Files
Odoo-Modules/fusion_plating/fusion_plating_jobs/models/account_move.py
gsinghpal dd88afdf53 feat(jobs): add lifecycle hooks — portal/QC/delivery/invoice (Tasks 2.6-2.9)
- Task 2.6: fp.job.action_confirm auto-creates fusion.plating.portal.job
  with x_fc_job_id back-reference. Idempotent (skip if already linked).
- Task 2.7: fp.job.action_confirm checks customer.x_fc_requires_qc
  and best-effort creates a fusion.plating.quality.check (the model
  lives in bridge_mrp; runtime-detected to avoid dep cycle).
- Task 2.8: fp.job.button_mark_done sets state='done', date_finished,
  auto-creates draft fusion.plating.delivery and best-effort triggers
  fp.certificate generation.
- Task 2.9: account.move.action_post links invoice -> fp.job via SO
  origin lookup, updates portal_job state to complete and stamps
  invoice_ref.

5 new tests cover: portal job creation + idempotency, mark_done state
+ delivery, cancel-then-mark-done blocked.

Best-effort patterns (try/except + runtime model detection) used for
QC + cert because their target models are in dependent modules
that this module doesn't depend on by design.

qc_check_id field on fp.job still deferred — adding it here would
require depending on bridge_mrp.

Manifest 19.0.1.4.0 -> 19.0.1.5.0.

Part of: native job model migration (spec 2026-04-25)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 23:27:38 -04:00

48 lines
1.4 KiB
Python

# -*- coding: utf-8 -*-
# Copyright 2026 Nexa Systems Inc.
# License OPL-1 (Odoo Proprietary License v1.0)
#
# When an invoice is posted, find the linked fp.job (via origin) and
# update the portal job state to 'complete' + stamp invoice_ref.
import logging
from odoo import models
_logger = logging.getLogger(__name__)
class AccountMove(models.Model):
_inherit = 'account.move'
def action_post(self):
result = super().action_post()
for invoice in self.filtered(
lambda m: m.move_type in ('out_invoice', 'out_refund')
):
invoice._fp_link_to_job()
return result
def _fp_link_to_job(self):
self.ensure_one()
if not self.invoice_origin:
return
Job = self.env['fp.job'].sudo()
# Walk SO -> fp.job
SO = self.env['sale.order'].sudo()
so = SO.search([('name', '=', self.invoice_origin)], limit=1)
if not so:
return
job = Job.search([('sale_order_id', '=', so.id)], limit=1)
if not job or not job.portal_job_id:
return
portal = job.portal_job_id
if 'state' in portal._fields:
portal.state = 'complete'
if 'invoice_ref' in portal._fields:
portal.invoice_ref = self.name
_logger.info(
'Invoice %s linked to fp.job %s portal %s',
self.name, job.name, portal.name,
)