feat(configurator): C1+C3 - pricelist currency picker + Express SCSS (light + dark)

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.
This commit is contained in:
gsinghpal
2026-05-26 21:25:59 -04:00
parent 27af984f28
commit 43abb8ef25
6 changed files with 218 additions and 1 deletions

View File

@@ -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,

View File

@@ -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

View File

@@ -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}"

View File

@@ -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});

View File

@@ -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;
}

View File

@@ -131,6 +131,7 @@
<group string="Pricing &amp; Fulfilment">
<field name="pricelist_id"
string="Currency / Pricelist"
context="{'fp_express_currency_picker': True}"
options="{'no_create_edit': True}"/>
<field name="payment_term_id"
options="{'no_create': True}"/>