From 43abb8ef2599b2651351b2295eb06b74984d70a3 Mon Sep 17 00:00:00 2001 From: gsinghpal Date: Tue, 26 May 2026 21:25:59 -0400 Subject: [PATCH] feat(configurator): C1+C3 - pricelist currency picker + Express SCSS (light + dark) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit C1: product.pricelist._compute_display_name override gated by the 'fp_express_currency_picker' context flag (set on the Express form's pricelist_id field). When active, prefixes the dropdown label with the currency code: 'CAD — Public Pricelist (CAD)'. Elsewhere the standard display name is unchanged. C3: SCSS tokens + base styles for the Express form. Tokens use the compile-time @if $o-webclient-color-scheme branch per the project's 'Dark Mode' rule — same SCSS compiles into both bundles with different hex values. Token vars wrapped in CSS custom properties so downstream modules can override for per-shop branding without recompiling. Base styles: spreadsheet-feel table borders, bake-cell inset-pill, customer line ref bold/uppercase, accent section markers. --- .../__manifest__.py | 8 +- .../models/__init__.py | 1 + .../models/product_pricelist.py | 32 +++++++ .../static/src/scss/_express_tokens.scss | 84 +++++++++++++++++ .../static/src/scss/express_order.scss | 93 +++++++++++++++++++ .../views/fp_express_order_views.xml | 1 + 6 files changed, 218 insertions(+), 1 deletion(-) create mode 100644 fusion_plating/fusion_plating_configurator/models/product_pricelist.py create mode 100644 fusion_plating/fusion_plating_configurator/static/src/scss/_express_tokens.scss create mode 100644 fusion_plating/fusion_plating_configurator/static/src/scss/express_order.scss diff --git a/fusion_plating/fusion_plating_configurator/__manifest__.py b/fusion_plating/fusion_plating_configurator/__manifest__.py index 500bf3d7..ffa2b745 100644 --- a/fusion_plating/fusion_plating_configurator/__manifest__.py +++ b/fusion_plating/fusion_plating_configurator/__manifest__.py @@ -74,13 +74,19 @@ Provides: 'fusion_plating_configurator/static/src/scss/fp_part_process_composer.scss', 'fusion_plating_configurator/static/src/xml/fp_part_process_composer.xml', 'fusion_plating_configurator/static/src/js/fp_part_process_composer.js', + # Express Orders (2026-05-26) — tokens MUST load FIRST so + # $xpr-* vars are in scope for the consumer SCSS below. + 'fusion_plating_configurator/static/src/scss/_express_tokens.scss', + 'fusion_plating_configurator/static/src/scss/express_order.scss', ], - # Register the Job Status pill SCSS in both bundles so the + # Register colour-aware SCSS in both bundles so the # `@if $o-webclient-color-scheme == dark` branch compiles for # the dark variant (see CLAUDE.md "Dark Mode" — Odoo 19 has no # runtime DOM toggle, two pre-built bundles). 'web.assets_web_dark': [ 'fusion_plating_configurator/static/src/scss/fp_job_status_pill.scss', + 'fusion_plating_configurator/static/src/scss/_express_tokens.scss', + 'fusion_plating_configurator/static/src/scss/express_order.scss', ], }, 'installable': True, diff --git a/fusion_plating/fusion_plating_configurator/models/__init__.py b/fusion_plating/fusion_plating_configurator/models/__init__.py index c29ec608..1d830f33 100644 --- a/fusion_plating/fusion_plating_configurator/models/__init__.py +++ b/fusion_plating/fusion_plating_configurator/models/__init__.py @@ -17,3 +17,4 @@ from . import account_move_line from . import fp_sale_assembly from . import res_partner from . import fp_process_node +from . import product_pricelist diff --git a/fusion_plating/fusion_plating_configurator/models/product_pricelist.py b/fusion_plating/fusion_plating_configurator/models/product_pricelist.py new file mode 100644 index 00000000..c10e643f --- /dev/null +++ b/fusion_plating/fusion_plating_configurator/models/product_pricelist.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 Nexa Systems Inc. +# License OPL-1 (Odoo Proprietary License v1.0) +# Part of the Fusion Plating product family. + +from odoo import api, models + + +class ProductPricelist(models.Model): + """Express Orders currency-picker enhancement (C1 / 2026-05-26). + + When rendered with `fp_express_currency_picker=True` in context (set + by the Express Orders form's pricelist_id field), prefix the display + name with the currency code so the dropdown reads: + + CAD — Public Pricelist (CAD) + USD — Westin USA Pricelist + EUR — Public Pricelist (EUR) + + Elsewhere in Odoo (partner form, sale.order, settings), the standard + pricelist display name is unchanged. + """ + _inherit = 'product.pricelist' + + @api.depends('name', 'currency_id') + @api.depends_context('fp_express_currency_picker') + def _compute_display_name(self): + super()._compute_display_name() + if self.env.context.get('fp_express_currency_picker'): + for pl in self: + if pl.currency_id and pl.currency_id.name not in (pl.display_name or ''): + pl.display_name = f"{pl.currency_id.name} — {pl.name}" diff --git a/fusion_plating/fusion_plating_configurator/static/src/scss/_express_tokens.scss b/fusion_plating/fusion_plating_configurator/static/src/scss/_express_tokens.scss new file mode 100644 index 00000000..fc450dd5 --- /dev/null +++ b/fusion_plating/fusion_plating_configurator/static/src/scss/_express_tokens.scss @@ -0,0 +1,84 @@ +// Express Orders — colour tokens (C3 / 2026-05-26) +// +// Per the Odoo-Modules CLAUDE.md "Dark Mode" rule: branch on +// $o-webclient-color-scheme at SCSS compile time. Odoo compiles this +// SCSS into BOTH web.assets_backend (light) and web.assets_web_dark +// (dark); the @if below makes each bundle pick the right hex. +// +// Tokens are wrapped in CSS custom properties so a downstream module +// can override per-shop branding without recompiling — e.g. +// --xpr-accent: #d4af37; /* gold for premium plating shops */ +// on a global :root rule. + +$o-webclient-color-scheme: bright !default; + +// ---- Light defaults ---- +$_xpr-page-hex: #f3f4f6; +$_xpr-card-hex: #ffffff; +$_xpr-card-soft-hex: #fafafa; +$_xpr-row-hover-hex: #fafafa; +$_xpr-cell-focus-hex: #fef9e7; +$_xpr-table-head-hex: #f9fafb; +$_xpr-section-bg-hex: #f9fafb; +$_xpr-text-hex: #1f2937; +$_xpr-text-muted-hex: #6b7280; +$_xpr-text-dim-hex: #9ca3af; +$_xpr-border-hex: #e5e7eb; +$_xpr-border-strong-hex: #d1d5db; +$_xpr-border-table-hex: #e5e7eb; +$_xpr-accent-hex: #714b67; +$_xpr-accent-hover-hex: #875a7b; +$_xpr-accent-bg-hex: #faf5f8; +$_xpr-bake-bg-hex: #fff7ed; +$_xpr-bake-text-hex: #9a3412; +$_xpr-bake-border-hex: #fdba74; +$_xpr-good-hex: #059669; +$_xpr-bad-hex: #dc2626; + +// ---- Dark overrides (compile-time branch) ---- +@if $o-webclient-color-scheme == dark { + $_xpr-page-hex: #1a1d21 !global; + $_xpr-card-hex: #22262d !global; + $_xpr-card-soft-hex: #1e2128 !global; + $_xpr-row-hover-hex: #2a2f37 !global; + $_xpr-cell-focus-hex: #3d3920 !global; + $_xpr-table-head-hex: #1c1f25 !global; + $_xpr-section-bg-hex: #1c1f25 !global; + $_xpr-text-hex: #e5e7eb !global; + $_xpr-text-muted-hex: #9ca3af !global; + $_xpr-text-dim-hex: #6b7280 !global; + $_xpr-border-hex: #374151 !global; + $_xpr-border-strong-hex: #4b5563 !global; + $_xpr-border-table-hex: #2d333b !global; + $_xpr-accent-hex: #b88fb5 !global; + $_xpr-accent-hover-hex: #a07a9d !global; + $_xpr-accent-bg-hex: #2d2330 !global; + $_xpr-bake-bg-hex: #3d2818 !global; + $_xpr-bake-text-hex: #fed7aa !global; + $_xpr-bake-border-hex: #c2410c !global; + $_xpr-good-hex: #34d399 !global; + $_xpr-bad-hex: #f87171 !global; +} + +// ---- Token vars consumed by component partials ---- +$xpr-page: var(--xpr-page-bg, #{$_xpr-page-hex}); +$xpr-card: var(--xpr-card-bg, #{$_xpr-card-hex}); +$xpr-card-soft: var(--xpr-card-soft-bg, #{$_xpr-card-soft-hex}); +$xpr-row-hover: var(--xpr-row-hover, #{$_xpr-row-hover-hex}); +$xpr-cell-focus: var(--xpr-cell-focus, #{$_xpr-cell-focus-hex}); +$xpr-table-head: var(--xpr-table-head, #{$_xpr-table-head-hex}); +$xpr-section-bg: var(--xpr-section-bg, #{$_xpr-section-bg-hex}); +$xpr-text: var(--xpr-text, #{$_xpr-text-hex}); +$xpr-text-muted: var(--xpr-text-muted, #{$_xpr-text-muted-hex}); +$xpr-text-dim: var(--xpr-text-dim, #{$_xpr-text-dim-hex}); +$xpr-border: var(--xpr-border, #{$_xpr-border-hex}); +$xpr-border-strong: var(--xpr-border-strong, #{$_xpr-border-strong-hex}); +$xpr-border-table: var(--xpr-border-table, #{$_xpr-border-table-hex}); +$xpr-accent: var(--xpr-accent, #{$_xpr-accent-hex}); +$xpr-accent-hover: var(--xpr-accent-hover, #{$_xpr-accent-hover-hex}); +$xpr-accent-bg: var(--xpr-accent-bg, #{$_xpr-accent-bg-hex}); +$xpr-bake-bg: var(--xpr-bake-bg, #{$_xpr-bake-bg-hex}); +$xpr-bake-text: var(--xpr-bake-text, #{$_xpr-bake-text-hex}); +$xpr-bake-border: var(--xpr-bake-border, #{$_xpr-bake-border-hex}); +$xpr-good: var(--xpr-good, #{$_xpr-good-hex}); +$xpr-bad: var(--xpr-bad, #{$_xpr-bad-hex}); diff --git a/fusion_plating/fusion_plating_configurator/static/src/scss/express_order.scss b/fusion_plating/fusion_plating_configurator/static/src/scss/express_order.scss new file mode 100644 index 00000000..a98f43ac --- /dev/null +++ b/fusion_plating/fusion_plating_configurator/static/src/scss/express_order.scss @@ -0,0 +1,93 @@ +// Express Orders — base styles (C3 v1 / 2026-05-26) +// +// Tokens load FIRST via the manifest's web.assets_backend ordering; +// $xpr-* are CSS custom-property wrappers from _express_tokens.scss. + +.o_fp_express_order { + + // ---- Header banners — slightly tighter than stock alerts ---- + .alert { + margin-bottom: 8px; + } + + // ---- Table — spreadsheet feel ---- + .o_list_view { + table { + border-collapse: collapse; + } + thead th { + background: $xpr-table-head; + color: $xpr-text-muted; + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.3px; + font-weight: 600; + border-bottom: 1px solid $xpr-border-table; + border-right: 1px solid $xpr-border-table; + + &:last-child { border-right: none; } + } + tbody td { + border-bottom: 1px solid $xpr-border-table; + border-right: 1px solid $xpr-border-table; + + &:last-child { border-right: none; } + } + tbody tr:hover { + background: $xpr-row-hover; + } + } + + // ---- Mask toggle — make it pop a bit more in the list ---- + .o_list_view .o_field_boolean_toggle { + // Slightly larger so it reads at a glance in the column + .form-check-input { transform: scale(1.1); } + } + + // ---- Bake column (text input) — give the cell an inset pill feel ---- + // (Until C5 OWL widget lands, this is the simplest visual nudge.) + .o_list_view td[name="bake_instructions"] input[type="text"] { + background: $xpr-bake-bg; + color: $xpr-bake-text; + border: 1px solid $xpr-bake-border; + border-radius: 3px; + padding: 2px 8px; + font-size: 12px; + font-weight: 500; + + &::placeholder { + color: $xpr-text-dim; + font-style: italic; + font-weight: 400; + } + &:focus { + background: $xpr-cell-focus; + border-color: $xpr-accent; + } + } + + // ---- Customer Line Job # — narrow, bold, accent colour ---- + .o_list_view td[name="customer_line_ref"] input { + font-weight: 600; + letter-spacing: 0.5px; + text-transform: uppercase; + } + + // ---- Bullet section markers ---- + .o_group > .o_horizontal_separator { + font-size: 13px; + font-weight: 600; + color: $xpr-accent; + letter-spacing: 0.3px; + border-top: 1px solid $xpr-border; + padding-top: 6px; + } +} + +// ---- view_source badge column on drafts list ---- +// The Drafts list view shows a small EXPRESS/LEGACY chip. Stock Odoo +// badge widget styling is fine; this just bumps the Express variant +// a touch more visible via the accent colour. +.o_list_view .badge.text-bg-info { + background-color: $xpr-accent !important; +} diff --git a/fusion_plating/fusion_plating_configurator/views/fp_express_order_views.xml b/fusion_plating/fusion_plating_configurator/views/fp_express_order_views.xml index b8b732e0..df8b6847 100644 --- a/fusion_plating/fusion_plating_configurator/views/fp_express_order_views.xml +++ b/fusion_plating/fusion_plating_configurator/views/fp_express_order_views.xml @@ -131,6 +131,7 @@