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:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}"
|
||||
@@ -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});
|
||||
@@ -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;
|
||||
}
|
||||
@@ -131,6 +131,7 @@
|
||||
<group string="Pricing & 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}"/>
|
||||
|
||||
Reference in New Issue
Block a user