New models - fusion.repair.service.plan.subscription Tracks pre-paid maintenance packages: partner, plan product, optional category restriction, visits_included / visits_used / visits_remaining, start_date / end_date, computed state (active/exhausted/expired/cancelled), burn_history One2many. PLAN-NNNNN sequence. - fusion.repair.service.plan.burn One row per maintenance visit that consumed a plan visit - feeds the Burn History tab on the subscription form. product.template extensions - x_fc_is_service_plan boolean toggle - x_fc_plan_visits_included (default 4) - x_fc_plan_duration_months (default 12) - x_fc_plan_category_id - if set, only burns for repairs in that category (e.g. an Annual Stairlift Maintenance plan does not burn for wheelchair repairs) sale.order.action_confirm() override - For each order line whose product has x_fc_is_service_plan=True, spawns one fusion.repair.service.plan.subscription per qty unit. - Start date = today; end date = today + plan_duration_months (relativedelta - correct month boundaries). Visit report wizard - New _burn_service_plan_visit(repair) call from action_confirm() finds the matching active subscription and burns one visit + posts a chatter note "Visit burned for repair X. N of M remaining." on the subscription. - Skips quote-only repairs. - The wizard does NOT zero out the invoice - the burn is informational; the office reconciles plan credits in their accounting workflow. Backend - Service Plans menu under Fusion Repairs root. - List view colour-coded by state. - Form with statusbar + cancel button + Burn History notebook. - Service Plan tab added to product.template form (manager only). - ACL: User read; Dispatcher write/create; Manager full + unlink. Verified end-to-end on local westin-v19: Created plan product 'Annual Stairlift Maintenance - 4 Visits' Sold it via sale.order -> PLAN-00001 auto-created (visits_included=4, end_date=2027-05-21) Submitted visit-report on a stairlift repair -> visits_used=1 remaining=3 (correctly category-matched). Bumped to 19.0.1.5.0. Co-authored-by: Cursor <cursoragent@cursor.com>
109 lines
5.0 KiB
XML
109 lines
5.0 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<odoo>
|
|
|
|
<!-- Service plan toggle on the product template -->
|
|
<record id="view_product_template_form_service_plan" model="ir.ui.view">
|
|
<field name="name">product.template.form.service.plan.fusion_repairs</field>
|
|
<field name="model">product.template</field>
|
|
<field name="inherit_id" ref="product.product_template_only_form_view"/>
|
|
<field name="arch" type="xml">
|
|
<xpath expr="//notebook" position="inside">
|
|
<page string="Service Plan" name="fusion_repairs_plan"
|
|
groups="fusion_repairs.group_fusion_repairs_manager">
|
|
<group>
|
|
<field name="x_fc_is_service_plan"/>
|
|
<field name="x_fc_plan_visits_included"
|
|
invisible="not x_fc_is_service_plan"/>
|
|
<field name="x_fc_plan_duration_months"
|
|
invisible="not x_fc_is_service_plan"/>
|
|
<field name="x_fc_plan_category_id"
|
|
invisible="not x_fc_is_service_plan"
|
|
options="{'no_create': True}"/>
|
|
</group>
|
|
</page>
|
|
</xpath>
|
|
</field>
|
|
</record>
|
|
|
|
<!-- Subscription list -->
|
|
<record id="view_service_plan_subscription_list" model="ir.ui.view">
|
|
<field name="name">fusion.repair.service.plan.subscription.list</field>
|
|
<field name="model">fusion.repair.service.plan.subscription</field>
|
|
<field name="arch" type="xml">
|
|
<list string="Service Plan Subscriptions"
|
|
decoration-success="state == 'active'"
|
|
decoration-warning="state == 'exhausted'"
|
|
decoration-muted="state == 'expired' or state == 'cancelled'">
|
|
<field name="name"/>
|
|
<field name="partner_id"/>
|
|
<field name="product_id"/>
|
|
<field name="category_id" optional="show"/>
|
|
<field name="visits_used"/>
|
|
<field name="visits_included"/>
|
|
<field name="visits_remaining"/>
|
|
<field name="start_date"/>
|
|
<field name="end_date"/>
|
|
<field name="state" widget="badge"/>
|
|
</list>
|
|
</field>
|
|
</record>
|
|
|
|
<!-- Subscription form -->
|
|
<record id="view_service_plan_subscription_form" model="ir.ui.view">
|
|
<field name="name">fusion.repair.service.plan.subscription.form</field>
|
|
<field name="model">fusion.repair.service.plan.subscription</field>
|
|
<field name="arch" type="xml">
|
|
<form string="Service Plan Subscription">
|
|
<header>
|
|
<button name="action_cancel" type="object" string="Cancel Plan"
|
|
invisible="state == 'cancelled'"
|
|
confirm="Cancel this service plan? Remaining visits will be forfeited."/>
|
|
<field name="state" widget="statusbar"
|
|
statusbar_visible="active,exhausted,expired,cancelled"/>
|
|
</header>
|
|
<sheet>
|
|
<div class="oe_title">
|
|
<h1>
|
|
<field name="name" readonly="1"/>
|
|
</h1>
|
|
</div>
|
|
<group>
|
|
<group>
|
|
<field name="partner_id" options="{'no_create': True}"/>
|
|
<field name="product_id" options="{'no_create': True}"/>
|
|
<field name="category_id" readonly="1"/>
|
|
<field name="sale_order_id" readonly="1"/>
|
|
</group>
|
|
<group>
|
|
<field name="start_date"/>
|
|
<field name="end_date"/>
|
|
<field name="visits_included"/>
|
|
<field name="visits_used" readonly="1"/>
|
|
<field name="visits_remaining" readonly="1"/>
|
|
<field name="company_id" groups="base.group_multi_company"/>
|
|
</group>
|
|
</group>
|
|
<notebook>
|
|
<page string="Burn History" name="burn_history">
|
|
<field name="burn_history_ids" readonly="1">
|
|
<list>
|
|
<field name="burned_on"/>
|
|
<field name="repair_order_id"/>
|
|
</list>
|
|
</field>
|
|
</page>
|
|
</notebook>
|
|
</sheet>
|
|
<chatter/>
|
|
</form>
|
|
</field>
|
|
</record>
|
|
|
|
<record id="action_service_plan_subscription" model="ir.actions.act_window">
|
|
<field name="name">Service Plans</field>
|
|
<field name="res_model">fusion.repair.service.plan.subscription</field>
|
|
<field name="view_mode">list,form</field>
|
|
</record>
|
|
|
|
</odoo>
|