feat(fusion_repairs): Bundle 5 - M5 pre-paid service plans + burn-down
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>
This commit is contained in:
@@ -187,6 +187,14 @@ class RepairVisitReportWizard(models.TransientModel):
|
||||
if self.issue_inspection_cert:
|
||||
self._create_inspection_certificate(repair)
|
||||
|
||||
# M5: burn a pre-paid service plan visit if the client has one and
|
||||
# the repair is a maintenance visit. The wizard intentionally does NOT
|
||||
# zero out the client's invoice line - the office still posts the
|
||||
# invoice; the burn is informational + the office reconciles credits
|
||||
# in their accounting flow.
|
||||
if not repair.x_fc_is_quote_only:
|
||||
self._burn_service_plan_visit(repair)
|
||||
|
||||
# If a stub was spawned, open it directly so the tech can fill in details.
|
||||
# Otherwise, if a certificate was issued, jump to it so the tech can print.
|
||||
if stub:
|
||||
@@ -213,6 +221,14 @@ class RepairVisitReportWizard(models.TransientModel):
|
||||
'res_id': repair.id,
|
||||
}
|
||||
|
||||
def _burn_service_plan_visit(self, repair):
|
||||
"""M5: deduct one visit from the most-recently-active service plan
|
||||
covering this repair. Quietly no-ops if the client has no plan."""
|
||||
Plan = self.env['fusion.repair.service.plan.subscription'].sudo()
|
||||
sub = Plan.find_for_repair(repair)
|
||||
if sub:
|
||||
sub.burn_visit(repair)
|
||||
|
||||
def _create_inspection_certificate(self, repair):
|
||||
"""M1: create the inspection certificate. Requires a safety-critical
|
||||
equipment category - otherwise just logs to chatter and skips."""
|
||||
|
||||
Reference in New Issue
Block a user