feat(configurator): Phase E — SO list view uplift
E1/E2/E3/E4: list view gets new togglable columns for - x_fc_wo_completion (e.g. '3/5'): count of completed vs total WOs - x_fc_invoiced_amount (Monetary): sum of posted customer invoices minus credit notes - x_fc_margin_amount + x_fc_margin_percent: reuses Phase D8 computes - x_fc_is_blanket_order toggle New sale.order.search view (sale.order.search.fp) with preset filters: My Orders / Open / Confirmed / Done / Blanket / Has Rush / Overdue, plus group-bys for Customer / Status / Customer Deadline. Bumped to 19.0.7.1.0. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
|
||||
{
|
||||
'name': 'Fusion Plating — Configurator',
|
||||
'version': '19.0.7.0.0',
|
||||
'version': '19.0.7.1.0',
|
||||
'category': 'Manufacturing/Plating',
|
||||
'summary': 'Quotation configurator with part catalog, coating configs, and formula-based pricing engine.',
|
||||
'description': """
|
||||
|
||||
@@ -119,6 +119,46 @@ class SaleOrder(models.Model):
|
||||
compute='_compute_workorder_count',
|
||||
)
|
||||
|
||||
# ---- Phase E: list view helpers ----
|
||||
x_fc_wo_completion = fields.Char(
|
||||
string='WO Progress',
|
||||
compute='_compute_wo_completion',
|
||||
help='Ratio of completed work orders, shown as "3/5 done".',
|
||||
)
|
||||
x_fc_invoiced_amount = fields.Monetary(
|
||||
string='Invoiced',
|
||||
compute='_compute_invoiced_amount',
|
||||
currency_field='currency_id',
|
||||
)
|
||||
|
||||
def _compute_wo_completion(self):
|
||||
WO = self.env['mrp.workorder'].sudo()
|
||||
for rec in self:
|
||||
if not rec.name:
|
||||
rec.x_fc_wo_completion = '0/0'
|
||||
continue
|
||||
total = WO.search_count([('production_id.origin', '=', rec.name)])
|
||||
done = WO.search_count([
|
||||
('production_id.origin', '=', rec.name),
|
||||
('state', '=', 'done'),
|
||||
])
|
||||
rec.x_fc_wo_completion = '%d/%d' % (done, total) if total else '0/0'
|
||||
|
||||
@api.depends('invoice_ids.amount_total', 'invoice_ids.state',
|
||||
'invoice_ids.move_type')
|
||||
def _compute_invoiced_amount(self):
|
||||
for rec in self:
|
||||
posted = rec.invoice_ids.filtered(
|
||||
lambda m: m.state == 'posted' and m.move_type == 'out_invoice'
|
||||
)
|
||||
refunds = rec.invoice_ids.filtered(
|
||||
lambda m: m.state == 'posted' and m.move_type == 'out_refund'
|
||||
)
|
||||
rec.x_fc_invoiced_amount = (
|
||||
sum(posted.mapped('amount_total'))
|
||||
- sum(refunds.mapped('amount_total'))
|
||||
)
|
||||
|
||||
def _compute_workorder_count(self):
|
||||
WO = self.env['mrp.workorder'].sudo()
|
||||
for rec in self:
|
||||
|
||||
@@ -153,19 +153,68 @@
|
||||
<field name="x_fc_internal_deadline" optional="show"/>
|
||||
<field name="commitment_date" string="Customer Deadline" optional="show"/>
|
||||
<field name="x_fc_deadline_countdown" optional="show"/>
|
||||
<field name="x_fc_wo_completion" optional="show"/>
|
||||
<field name="x_fc_planned_start_date" optional="hide"/>
|
||||
<field name="x_fc_part_catalog_id" optional="hide"/>
|
||||
<field name="x_fc_coating_config_id" optional="hide"/>
|
||||
<field name="amount_total" sum="Total"/>
|
||||
<field name="x_fc_invoiced_amount" sum="Invoiced" optional="hide"
|
||||
widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}"/>
|
||||
<field name="x_fc_margin_amount" sum="Margin" optional="hide"
|
||||
widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}"/>
|
||||
<field name="x_fc_margin_percent" optional="hide"
|
||||
widget="percentage"/>
|
||||
<field name="x_fc_is_blanket_order" optional="hide"/>
|
||||
<field name="x_fc_receiving_status" widget="badge"
|
||||
decoration-warning="x_fc_receiving_status == 'not_received'"
|
||||
decoration-success="x_fc_receiving_status in ('received','inspected')"/>
|
||||
<field name="x_fc_delivery_method" optional="hide"/>
|
||||
<field name="currency_id" column_invisible="1"/>
|
||||
<field name="state" widget="badge"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ===== Search view for Fusion Plating SO list ===== -->
|
||||
<record id="view_sale_order_search_fp" model="ir.ui.view">
|
||||
<field name="name">sale.order.search.fp</field>
|
||||
<field name="model">sale.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Sales Orders">
|
||||
<field name="name"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="x_fc_po_number" string="Customer PO #"/>
|
||||
<field name="x_fc_customer_job_number" string="Customer Job #"/>
|
||||
<filter name="my_orders" string="My Orders"
|
||||
domain="[('user_id', '=', uid)]"/>
|
||||
<separator/>
|
||||
<filter name="open_orders" string="Open"
|
||||
domain="[('state', 'in', ('draft', 'sent', 'sale'))]"/>
|
||||
<filter name="confirmed" string="Confirmed"
|
||||
domain="[('state', '=', 'sale')]"/>
|
||||
<filter name="done" string="Done"
|
||||
domain="[('state', '=', 'done')]"/>
|
||||
<separator/>
|
||||
<filter name="blanket_orders" string="Blanket Orders"
|
||||
domain="[('x_fc_is_blanket_order', '=', True)]"/>
|
||||
<filter name="rush_lines" string="Has Rush Line"
|
||||
domain="[('order_line.x_fc_rush_order', '=', True)]"/>
|
||||
<filter name="overdue" string="Overdue"
|
||||
domain="[('commitment_date', '<', context_today()), ('state', 'in', ('sale',))]"/>
|
||||
<group>
|
||||
<filter string="Customer" name="group_partner"
|
||||
context="{'group_by': 'partner_id'}"/>
|
||||
<filter string="Status" name="group_state"
|
||||
context="{'group_by': 'state'}"/>
|
||||
<filter string="Customer Deadline" name="group_deadline"
|
||||
context="{'group_by': 'commitment_date'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ===== Window Action — Quotations (for Fusion Plating menu) ===== -->
|
||||
<record id="action_fp_quotations" model="ir.actions.act_window">
|
||||
<field name="name">Quotations</field>
|
||||
|
||||
Reference in New Issue
Block a user