Adds the daily membership renewal cron (_cron_process_membership_renewals):
sends a "renewal upcoming" reminder at each non-final configured offset,
flips state to renewal_due and sends a "renewal due" notice at the final
(smallest) offset, and on expiry flips to 'expired', sends an expiry notice,
and creates a draft renewal invoice for the member's tier product.
Email templates (renewal_upcoming, renewal_due, membership_expired) use
Odoo 19's current mail.template syntax ({{ }} subject/QWeb t-out body) -
the plan referenced the older ${object...} syntax, which v19 no longer
uses. Org name is pulled via a new non-stored res.partner.membership_org_name
compute field backed by ir.config_parameter, never hardcoded.
Also had to adapt the ir.cron data record: Odoo 19 removed 'numbercall'
entirely (ir.cron now delegates most fields to a linked ir.actions.server
under the hood, though name/model_id/state/code are still settable
directly on the record, per the core mail module's own cron definitions).
Verified against a live Odoo 19 + Postgres 16 container: module upgrades
clean, all 8 tests pass (4 from 1-A + 4 new: non-final-offset reminder,
final-offset state flip to renewal_due, expiry creates a draft invoice +
notice, no action outside any offset window).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
15 lines
586 B
XML
15 lines
586 B
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<odoo>
|
|
<data noupdate="1">
|
|
<record id="ir_cron_membership_renewals" model="ir.cron">
|
|
<field name="name">Membership: Process Renewals</field>
|
|
<field name="model_id" ref="base.model_res_partner"/>
|
|
<field name="state">code</field>
|
|
<field name="code">model._cron_process_membership_renewals()</field>
|
|
<field name="interval_number">1</field>
|
|
<field name="interval_type">days</field>
|
|
<field name="active" eval="True"/>
|
|
</record>
|
|
</data>
|
|
</odoo>
|