changes
This commit is contained in:
@@ -0,0 +1,261 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2026 Nexa Systems Inc.
|
||||
License OPL-1 (Odoo Proprietary License v1.0)
|
||||
|
||||
Job Sorting:
|
||||
- Section model views (list/form) under Configuration → Sales.
|
||||
- Alternate SO list ("Sale Orders by Sorting") grouped by job sort
|
||||
with foldable sections and create-from-here support.
|
||||
-->
|
||||
<odoo>
|
||||
|
||||
<!-- ===== Section management (Configuration) ===== -->
|
||||
<record id="view_fp_so_job_sort_list" model="ir.ui.view">
|
||||
<field name="name">fp.so.job.sort.list</field>
|
||||
<field name="model">fp.so.job.sort</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Job Sorting" editable="bottom">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name"/>
|
||||
<field name="color" widget="color_picker"/>
|
||||
<field name="fold" widget="boolean_toggle"/>
|
||||
<field name="sale_order_count"/>
|
||||
<field name="active" widget="boolean_toggle" optional="hide"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_fp_so_job_sort_form" model="ir.ui.view">
|
||||
<field name="name">fp.so.job.sort.form</field>
|
||||
<field name="model">fp.so.job.sort</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Job Sorting">
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button name="action_view_sale_orders" type="object"
|
||||
class="oe_stat_button" icon="fa-shopping-cart">
|
||||
<field name="sale_order_count" widget="statinfo"
|
||||
string="Sale Orders"/>
|
||||
</button>
|
||||
</div>
|
||||
<div class="oe_title">
|
||||
<label for="name"/>
|
||||
<h1><field name="name" placeholder="e.g. Rush Orders"/></h1>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="sequence"/>
|
||||
<field name="color" widget="color_picker"/>
|
||||
<field name="fold"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="active"/>
|
||||
</group>
|
||||
</group>
|
||||
<field name="description"
|
||||
placeholder="What kinds of orders belong in this section?"/>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_fp_so_job_sort" model="ir.actions.act_window">
|
||||
<field name="name">Job Sorting</field>
|
||||
<field name="res_model">fp.so.job.sort</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_fp_so_job_sort"
|
||||
name="Job Sorting"
|
||||
parent="fusion_plating.menu_fp_config_pricing_billing"
|
||||
action="action_fp_so_job_sort"
|
||||
sequence="25"/>
|
||||
|
||||
<!-- ===== Kanban grouped by Job Sorting =====
|
||||
Groups SOs into foldable columns by x_fc_job_sort_id.
|
||||
Drag-drop between columns rewrites the bucket; quick-create on
|
||||
the column header creates a new fp.so.job.sort row. Wired into
|
||||
the existing Sale Orders action below so it shows up in the
|
||||
view-switcher next to the flat list. -->
|
||||
<record id="view_sale_order_kanban_fp_by_sorting" model="ir.ui.view">
|
||||
<field name="name">sale.order.kanban.fp.by_sorting</field>
|
||||
<field name="model">sale.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban default_group_by="x_fc_job_sort_id"
|
||||
group_create="true"
|
||||
group_edit="true"
|
||||
group_delete="true"
|
||||
quick_create="false"
|
||||
sample="1">
|
||||
<field name="name"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="amount_total"/>
|
||||
<field name="currency_id"/>
|
||||
<field name="x_fc_part_numbers_summary"/>
|
||||
<field name="x_fc_customer_job_number"/>
|
||||
<field name="x_fc_deadline_countdown"/>
|
||||
<field name="x_fc_deadline_urgency"/>
|
||||
<field name="x_fc_fp_job_status"/>
|
||||
<field name="state"/>
|
||||
<templates>
|
||||
<t t-name="card">
|
||||
<div class="o_kanban_card_content p-2">
|
||||
<div class="d-flex justify-content-between align-items-start mb-1">
|
||||
<strong><field name="name"/></strong>
|
||||
<span t-att-class="'badge ' + (
|
||||
record.x_fc_deadline_urgency.raw_value == 'overdue' and 'text-bg-danger' or
|
||||
record.x_fc_deadline_urgency.raw_value == 'urgent' and 'text-bg-warning' or
|
||||
record.x_fc_deadline_urgency.raw_value == 'safe' and 'text-bg-success' or
|
||||
'text-bg-light')"
|
||||
t-if="record.x_fc_deadline_countdown.raw_value">
|
||||
<field name="x_fc_deadline_countdown"/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-muted small mb-1">
|
||||
<field name="partner_id"/>
|
||||
</div>
|
||||
<div class="small mb-1" t-if="record.x_fc_part_numbers_summary.raw_value">
|
||||
<i class="fa fa-cube me-1"/>
|
||||
<field name="x_fc_part_numbers_summary"/>
|
||||
</div>
|
||||
<div class="small mb-2" t-if="record.x_fc_customer_job_number.raw_value">
|
||||
<i class="fa fa-hashtag me-1"/>
|
||||
<field name="x_fc_customer_job_number"/>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<field name="x_fc_fp_job_status" widget="html"/>
|
||||
<strong>
|
||||
<field name="amount_total" widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}"/>
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ===== Sale Orders by Sorting (alternate SO list) ===== -->
|
||||
<!-- Duplicate of view_sale_order_list_fp but renamed and intended
|
||||
to be opened with group_by=x_fc_job_sort_id by default so the
|
||||
user sees foldable sections per Job Sorting bucket. -->
|
||||
<record id="view_sale_order_list_fp_by_sorting" model="ir.ui.view">
|
||||
<field name="name">sale.order.list.fp.by_sorting</field>
|
||||
<field name="model">sale.order</field>
|
||||
<field name="priority">99</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Sale Orders by Sorting" create="0"
|
||||
decoration-info="state == 'draft'"
|
||||
decoration-muted="state == 'cancel'"
|
||||
decoration-danger="x_fc_is_late_forecast">
|
||||
<header>
|
||||
<button name="%(action_fp_direct_order_wizard)d"
|
||||
type="action"
|
||||
string="New Order"
|
||||
class="btn-primary"
|
||||
display="always"/>
|
||||
</header>
|
||||
<field name="name" optional="show"/>
|
||||
<field name="partner_id" optional="show"/>
|
||||
<field name="x_fc_po_number" optional="show"/>
|
||||
<field name="x_fc_customer_job_number" optional="show"/>
|
||||
<field name="x_fc_job_sort_id" optional="show"
|
||||
options="{'no_create_edit': False, 'no_open': True}"/>
|
||||
<field name="x_fc_internal_deadline" optional="show"/>
|
||||
<field name="commitment_date" string="Customer Deadline"
|
||||
optional="show"/>
|
||||
<field name="x_fc_order_completion_date" string="Completion"
|
||||
optional="show"/>
|
||||
<field name="x_fc_is_late_forecast" optional="hide"
|
||||
widget="boolean_toggle"/>
|
||||
<field name="x_fc_deadline_urgency" column_invisible="1"/>
|
||||
<field name="x_fc_deadline_countdown" optional="show"
|
||||
decoration-danger="x_fc_deadline_urgency == 'overdue'"
|
||||
decoration-warning="x_fc_deadline_urgency == 'urgent'"
|
||||
decoration-success="x_fc_deadline_urgency == 'safe'"/>
|
||||
<field name="x_fc_wo_completion" optional="show"/>
|
||||
<field name="x_fc_planned_start_date" optional="hide"/>
|
||||
<field name="x_fc_part_numbers_summary" string="Part"
|
||||
optional="show"/>
|
||||
<field name="amount_total" sum="Total" optional="show"/>
|
||||
<field name="x_fc_invoiced_amount" sum="Invoiced"
|
||||
optional="hide"
|
||||
widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}"/>
|
||||
<field name="x_fc_fp_job_status" widget="html"
|
||||
string="Job Status" optional="show" readonly="1"/>
|
||||
<field name="x_fc_receiving_status" widget="badge"
|
||||
optional="hide"
|
||||
decoration-warning="x_fc_receiving_status == 'not_received'"
|
||||
decoration-info="x_fc_receiving_status == 'partial'"
|
||||
decoration-success="x_fc_receiving_status == 'received'"/>
|
||||
<field name="x_fc_delivery_method" optional="hide"/>
|
||||
<field name="currency_id" column_invisible="1"/>
|
||||
<field name="state" widget="badge" optional="show"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Search view for the alternate list: surface "Group by Job
|
||||
Sorting" as a search-default filter. -->
|
||||
<record id="view_sale_order_search_fp_by_sorting" model="ir.ui.view">
|
||||
<field name="name">sale.order.search.fp.by_sorting</field>
|
||||
<field name="model">sale.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Sale Orders by Sorting">
|
||||
<field name="name"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="x_fc_part_numbers_summary" string="Part"/>
|
||||
<field name="x_fc_customer_job_number"/>
|
||||
<field name="x_fc_po_number"/>
|
||||
<field name="x_fc_job_sort_id"/>
|
||||
<filter name="late_forecast" string="Late Forecast"
|
||||
domain="[('x_fc_is_late_forecast','=',True)]"/>
|
||||
<filter name="cancelled" string="Cancelled"
|
||||
domain="[('state','=','cancel')]"/>
|
||||
<separator/>
|
||||
<group>
|
||||
<filter name="group_by_job_sort"
|
||||
string="Job Sorting"
|
||||
context="{'group_by': 'x_fc_job_sort_id'}"/>
|
||||
<filter name="group_by_customer"
|
||||
string="Customer"
|
||||
context="{'group_by': 'partner_id'}"/>
|
||||
<filter name="group_by_state"
|
||||
string="Status"
|
||||
context="{'group_by': 'state'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Append the kanban view to the existing Sale Orders action so
|
||||
users can switch from the flat list to the grouped-by-sorting
|
||||
kanban (foldable columns, drag-drop bucket reassignment) via
|
||||
the view-switcher icon in the top-right of the SO list. -->
|
||||
<record id="action_fp_sale_orders" model="ir.actions.act_window">
|
||||
<field name="view_mode">list,kanban,form</field>
|
||||
<field name="view_ids" eval="[(5, 0, 0),
|
||||
(0, 0, {'view_mode': 'list', 'view_id': ref('view_sale_order_list_fp')}),
|
||||
(0, 0, {'view_mode': 'kanban', 'view_id': ref('view_sale_order_kanban_fp_by_sorting')})]"/>
|
||||
</record>
|
||||
|
||||
<record id="action_fp_sale_orders_by_sorting" model="ir.actions.act_window">
|
||||
<field name="name">Sale Orders (by Sorting)</field>
|
||||
<field name="res_model">sale.order</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="view_id" ref="view_sale_order_list_fp_by_sorting"/>
|
||||
<field name="search_view_id" ref="view_sale_order_search_fp_by_sorting"/>
|
||||
<field name="domain">[('state', 'not in', ('draft', 'sent'))]</field>
|
||||
<field name="context">{'search_default_group_by_job_sort': 1}</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_fp_sale_orders_by_sorting"
|
||||
name="Sale Orders (by Sorting)"
|
||||
parent="fusion_plating_configurator.menu_fp_sales"
|
||||
action="action_fp_sale_orders_by_sorting"
|
||||
sequence="12"/>
|
||||
|
||||
</odoo>
|
||||
@@ -123,6 +123,15 @@
|
||||
<field name="commitment_date" string="Delivery Date"
|
||||
readonly="state in ('cancel',)"/>
|
||||
</xpath>
|
||||
|
||||
<!-- Job Sorting sits right under Payment Terms — a free-form
|
||||
bucket that groups the SO in the "Sale Orders by Sorting"
|
||||
list. Quick-create from the dropdown. -->
|
||||
<xpath expr="//group[@name='order_details']/field[@name='payment_term_id']" position="after">
|
||||
<field name="x_fc_job_sort_id"
|
||||
options="{'no_create_edit': False, 'no_open': True}"
|
||||
placeholder="Type to create a new bucket..."/>
|
||||
</xpath>
|
||||
<xpath expr="//notebook" position="inside">
|
||||
<page string="Plating" name="plating_tab">
|
||||
<!-- Multi-part summary: read-only list of every order line
|
||||
@@ -368,19 +377,29 @@
|
||||
class="btn-primary"
|
||||
display="always"/>
|
||||
</header>
|
||||
<field name="name"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="x_fc_po_number"/>
|
||||
<field name="name" optional="show"/>
|
||||
<field name="partner_id" optional="show"/>
|
||||
<field name="x_fc_po_number" optional="show"/>
|
||||
<field name="x_fc_customer_job_number" optional="show"/>
|
||||
<field name="x_fc_internal_deadline" optional="show"/>
|
||||
<field name="commitment_date" string="Customer Deadline" optional="show"/>
|
||||
<field name="x_fc_order_completion_date" string="Completion" optional="show"/>
|
||||
<field name="x_fc_is_late_forecast" optional="hide" widget="boolean_toggle"/>
|
||||
<field name="x_fc_deadline_countdown" optional="show"/>
|
||||
<field name="x_fc_deadline_urgency" column_invisible="1"/>
|
||||
<field name="x_fc_deadline_countdown" optional="show"
|
||||
decoration-danger="x_fc_deadline_urgency == 'overdue'"
|
||||
decoration-warning="x_fc_deadline_urgency == 'urgent'"
|
||||
decoration-success="x_fc_deadline_urgency == 'safe'"/>
|
||||
<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="amount_total" sum="Total"/>
|
||||
<!-- "Part" column — walks order_line.x_fc_part_catalog_id
|
||||
and shows a compact summary (e.g. "M1234, M5678
|
||||
(+3 more)"). The header x_fc_part_catalog_id field
|
||||
is rarely populated in the configurator flow; the
|
||||
line carries the authoritative part link. -->
|
||||
<field name="x_fc_part_numbers_summary" string="Part"
|
||||
optional="show"/>
|
||||
<field name="amount_total" sum="Total" optional="show"/>
|
||||
<field name="x_fc_invoiced_amount" sum="Invoiced" optional="hide"
|
||||
widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}"/>
|
||||
@@ -390,12 +409,21 @@
|
||||
<field name="x_fc_margin_percent" optional="hide"
|
||||
widget="percentage"/>
|
||||
<field name="x_fc_is_blanket_order" optional="hide"/>
|
||||
<!-- Single Job Status pill. Renders as HTML with a
|
||||
per-kind class (.fp-kind-*) so every phase carries
|
||||
its own distinct tint — see
|
||||
static/src/scss/fp_job_status_pill.scss. -->
|
||||
<field name="x_fc_fp_job_status" widget="html"
|
||||
string="Job Status" optional="show"
|
||||
readonly="1"/>
|
||||
<field name="x_fc_receiving_status" widget="badge"
|
||||
optional="hide"
|
||||
decoration-warning="x_fc_receiving_status == 'not_received'"
|
||||
decoration-info="x_fc_receiving_status == 'partial'"
|
||||
decoration-success="x_fc_receiving_status == 'received'"/>
|
||||
<field name="x_fc_delivery_method" optional="hide"/>
|
||||
<field name="currency_id" column_invisible="1"/>
|
||||
<field name="state" widget="badge"/>
|
||||
<field name="state" widget="badge" optional="show"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
@@ -465,8 +493,8 @@
|
||||
<field name="model">sale.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Quotations" decoration-muted="state == 'cancel'">
|
||||
<field name="name"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="name" optional="show"/>
|
||||
<field name="partner_id" optional="show"/>
|
||||
<field name="x_fc_part_numbers_summary" optional="show"/>
|
||||
<field name="x_fc_po_number" optional="hide"/>
|
||||
<field name="x_fc_customer_job_number" optional="hide"/>
|
||||
@@ -474,15 +502,16 @@
|
||||
<field name="validity_date" string="Expires" optional="show"/>
|
||||
<field name="x_fc_follow_up_date" optional="show"/>
|
||||
<field name="x_fc_follow_up_user_id" optional="show"/>
|
||||
<field name="amount_total" sum="Total"/>
|
||||
<field name="amount_total" sum="Total" optional="show"/>
|
||||
<field name="x_fc_is_signed" widget="boolean_toggle"
|
||||
string="Signed" optional="show"/>
|
||||
<field name="x_fc_email_status" widget="badge"
|
||||
optional="show"
|
||||
decoration-info="x_fc_email_status == 'sent'"
|
||||
decoration-warning="x_fc_email_status == 'opened'"
|
||||
decoration-success="x_fc_email_status == 'won'"/>
|
||||
<field name="currency_id" column_invisible="1"/>
|
||||
<field name="state" widget="badge"/>
|
||||
<field name="state" widget="badge" optional="show"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
@@ -582,7 +611,10 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ===== Window Action — Confirmed Sale Orders ===== -->
|
||||
<!-- ===== Window Action — Confirmed Sale Orders =====
|
||||
The kanban view_mode + kanban view_id are appended in
|
||||
fp_so_job_sort_views.xml after the kanban view is defined, so
|
||||
we don't hit a missing-ref at module load. -->
|
||||
<record id="action_fp_sale_orders" model="ir.actions.act_window">
|
||||
<field name="name">Sale Orders</field>
|
||||
<field name="res_model">sale.order</field>
|
||||
|
||||
Reference in New Issue
Block a user