chore(plating): de-dash shipped code + intake-neutral customer emails
Replace em-dashes and en-dashes with hyphens across 789 shipped source files (py/xml/js/scss) so the delivered module reads as human-written; em-dashes had become a recognizable AI-generated tell. Internal .md dev notes are excluded. The WO-sticker mojibake strippers keep their dash search targets (now written — / –). No logic changes: comments and display strings only; validated with py_compile + lxml parse. Rewrite the 7 customer notification emails to be intake-neutral (ship-in / drop-off / pickup) and repair-aware, and fix the Shipped email documents line (packing slip vs bill of lading; certificate only when issued). Subjects use a hyphen separator. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,14 +4,14 @@
|
||||
# Part of the Fusion Plating product family.
|
||||
|
||||
{
|
||||
'name': 'Fusion Plating — Safety (EHS)',
|
||||
'name': 'Fusion Plating - Safety (EHS)',
|
||||
'version': '19.0.1.3.2',
|
||||
'category': 'Manufacturing/Plating',
|
||||
'summary': 'Occupational health and safety for plating shops: SDS library, '
|
||||
'WHMIS/TDG training, exposure monitoring, JHSC, incidents, PPE, '
|
||||
'chemical inventory.',
|
||||
'description': """
|
||||
Fusion Plating — Safety (EHS)
|
||||
Fusion Plating - Safety (EHS)
|
||||
=============================
|
||||
|
||||
Part of the Fusion Plating product family by Nexa Systems Inc.
|
||||
@@ -24,23 +24,23 @@ regulatory pack.
|
||||
|
||||
Included workspaces
|
||||
-------------------
|
||||
* SDS Library — Safety Data Sheet repository with version, hazard class,
|
||||
* SDS Library - Safety Data Sheet repository with version, hazard class,
|
||||
GHS pictograms, language, expiry tracking and PDF attachment.
|
||||
* Chemical Inventory — physical chemical containers with storage location,
|
||||
* Chemical Inventory - physical chemical containers with storage location,
|
||||
on-hand quantity, reorder point and incompatibility relations.
|
||||
* Training Matrix — training type catalogue (WHMIS, TDG, first-aid, LOTO,
|
||||
* Training Matrix - training type catalogue (WHMIS, TDG, first-aid, LOTO,
|
||||
confined space, etc.) plus per-employee records with auto-computed
|
||||
expiry and current/expiring/expired status.
|
||||
* Exposure Monitoring — air sampling, biological, noise and vibration
|
||||
* Exposure Monitoring - air sampling, biological, noise and vibration
|
||||
monitoring events with OEL reference, percent-of-limit and result
|
||||
classification.
|
||||
* JHSC — Joint Health & Safety Committee with worker and management
|
||||
* JHSC - Joint Health & Safety Committee with worker and management
|
||||
representatives, plus a meeting register with agenda, minutes and
|
||||
action items.
|
||||
* Incident Register — injury, near-miss, first-aid, lost-time, medical,
|
||||
* Incident Register - injury, near-miss, first-aid, lost-time, medical,
|
||||
property damage and environmental events with investigation, root
|
||||
cause, corrective action, WSIB Form 7 flagging and lost-time tracking.
|
||||
* PPE Issuance — per-employee personal protective equipment issuance log
|
||||
* PPE Issuance - per-employee personal protective equipment issuance log
|
||||
with replacement scheduling.
|
||||
|
||||
Designed to slot in alongside jurisdiction-specific compliance packs
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2026 Nexa Systems Inc. — Demo safety data -->
|
||||
<!-- Copyright 2026 Nexa Systems Inc. - Demo safety data -->
|
||||
<odoo noupdate="1">
|
||||
|
||||
<!-- ================================================================== -->
|
||||
<!-- SDS — Safety Data Sheets -->
|
||||
<!-- SDS - Safety Data Sheets -->
|
||||
<!-- ================================================================== -->
|
||||
<record id="demo_sds_chromic_acid" model="fusion.plating.sds">
|
||||
<field name="name">SDS-CrO3-2025</field>
|
||||
@@ -58,10 +58,10 @@
|
||||
</record>
|
||||
|
||||
<!-- ================================================================== -->
|
||||
<!-- Chemicals — linked to SDS and facility -->
|
||||
<!-- Chemicals - linked to SDS and facility -->
|
||||
<!-- ================================================================== -->
|
||||
<record id="demo_chemical_chromic_acid" model="fusion.plating.chemical">
|
||||
<field name="name">Chromic Acid — Main Store</field>
|
||||
<field name="name">Chromic Acid - Main Store</field>
|
||||
<field name="sds_id" ref="demo_sds_chromic_acid"/>
|
||||
<field name="facility_id" ref="fusion_plating.demo_facility_main"/>
|
||||
<field name="location">Acid Cabinet 1</field>
|
||||
@@ -72,7 +72,7 @@
|
||||
</record>
|
||||
|
||||
<record id="demo_chemical_nickel_sulfate" model="fusion.plating.chemical">
|
||||
<field name="name">Nickel Sulfate — Main Store</field>
|
||||
<field name="name">Nickel Sulfate - Main Store</field>
|
||||
<field name="sds_id" ref="demo_sds_nickel_sulfate"/>
|
||||
<field name="facility_id" ref="fusion_plating.demo_facility_main"/>
|
||||
<field name="location">Chemical Storage Bay A</field>
|
||||
@@ -83,7 +83,7 @@
|
||||
</record>
|
||||
|
||||
<record id="demo_chemical_sulfuric_acid" model="fusion.plating.chemical">
|
||||
<field name="name">Sulfuric Acid — Main Store</field>
|
||||
<field name="name">Sulfuric Acid - Main Store</field>
|
||||
<field name="sds_id" ref="demo_sds_sulfuric_acid"/>
|
||||
<field name="facility_id" ref="fusion_plating.demo_facility_main"/>
|
||||
<field name="location">Acid Cabinet 2</field>
|
||||
@@ -134,7 +134,7 @@
|
||||
</record>
|
||||
|
||||
<!-- ================================================================== -->
|
||||
<!-- JHSC — Committee -->
|
||||
<!-- JHSC - Committee -->
|
||||
<!-- ================================================================== -->
|
||||
<record id="demo_jhsc_main" model="fusion.plating.jhsc">
|
||||
<field name="name">Main Plant JHSC</field>
|
||||
|
||||
@@ -11,8 +11,8 @@ from odoo.addons.fusion_plating.models._fp_uom_selection import FP_UOM_SELECTION
|
||||
class FpChemical(models.Model):
|
||||
"""Physical chemical container in the shop's chemical inventory.
|
||||
|
||||
A chemical record represents a managed container — drum, tote, jug,
|
||||
cylinder — of a specific product, stored in a specific facility and
|
||||
A chemical record represents a managed container - drum, tote, jug,
|
||||
cylinder - of a specific product, stored in a specific facility and
|
||||
location, with on-hand quantity and reorder thresholds. It links to the
|
||||
Safety Data Sheet that governs handling, and may optionally link to the
|
||||
Odoo product/stock record when the same chemistry is also tracked as
|
||||
@@ -23,7 +23,7 @@ class FpChemical(models.Model):
|
||||
a future workflow can warn on co-located storage.
|
||||
"""
|
||||
_name = 'fusion.plating.chemical'
|
||||
_description = 'Fusion Plating — Chemical'
|
||||
_description = 'Fusion Plating - Chemical'
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||
_order = 'name'
|
||||
|
||||
@@ -60,7 +60,7 @@ class FpChemical(models.Model):
|
||||
container_uom = fields.Selection(
|
||||
FP_UOM_SELECTION,
|
||||
string='Container UoM',
|
||||
help='Unit of measure for the container size — pick from the '
|
||||
help='Unit of measure for the container size - pick from the '
|
||||
'curated list to keep inventory consistent (L, kg, lb, gal).',
|
||||
)
|
||||
quantity_on_hand = fields.Float(
|
||||
|
||||
@@ -12,7 +12,7 @@ class FpExposureMonitoring(models.Model):
|
||||
"""An exposure monitoring sample.
|
||||
|
||||
A monitoring event captures one measurement of a worker's or area's
|
||||
exposure to a hazardous agent — air contaminant, biological marker,
|
||||
exposure to a hazardous agent - air contaminant, biological marker,
|
||||
noise or vibration. The result is compared against an Occupational
|
||||
Exposure Limit (OEL), most commonly the time-weighted average (TWA)
|
||||
or short-term exposure limit (STEL) published by the relevant
|
||||
@@ -23,7 +23,7 @@ class FpExposureMonitoring(models.Model):
|
||||
an early warning when controls need to be tightened.
|
||||
"""
|
||||
_name = 'fusion.plating.exposure.monitoring'
|
||||
_description = 'Fusion Plating — Exposure Monitoring'
|
||||
_description = 'Fusion Plating - Exposure Monitoring'
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||
_order = 'sample_date desc, id desc'
|
||||
_rec_name = 'name'
|
||||
|
||||
@@ -20,7 +20,7 @@ class FpIncident(models.Model):
|
||||
and whether the form has actually been filed.
|
||||
"""
|
||||
_name = 'fusion.plating.incident'
|
||||
_description = 'Fusion Plating — Incident'
|
||||
_description = 'Fusion Plating - Incident'
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||
_order = 'incident_date desc, id desc'
|
||||
_rec_name = 'name'
|
||||
|
||||
@@ -20,7 +20,7 @@ class FpJhsc(models.Model):
|
||||
members plus the specific worker and management representative subsets.
|
||||
"""
|
||||
_name = 'fusion.plating.jhsc'
|
||||
_description = 'Fusion Plating — JHSC'
|
||||
_description = 'Fusion Plating - JHSC'
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||
_order = 'name'
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ class FpJhscMeeting(models.Model):
|
||||
meetings still need minutes posted.
|
||||
"""
|
||||
_name = 'fusion.plating.jhsc.meeting'
|
||||
_description = 'Fusion Plating — JHSC Meeting'
|
||||
_description = 'Fusion Plating - JHSC Meeting'
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||
_order = 'meeting_date desc, id desc'
|
||||
_rec_name = 'name'
|
||||
|
||||
@@ -9,8 +9,8 @@ from odoo import api, fields, models
|
||||
class FpPpeIssuance(models.Model):
|
||||
"""Per-employee Personal Protective Equipment issuance log.
|
||||
|
||||
Each record captures one issuance of a piece of PPE — respirator,
|
||||
gloves, apron, face shield — to an employee, with the size, quantity,
|
||||
Each record captures one issuance of a piece of PPE - respirator,
|
||||
gloves, apron, face shield - to an employee, with the size, quantity,
|
||||
issue date and the date the equipment is next due for replacement.
|
||||
|
||||
A historical PPE log demonstrates that the employer is providing
|
||||
@@ -18,7 +18,7 @@ class FpPpeIssuance(models.Model):
|
||||
most occupational health and safety regulations.
|
||||
"""
|
||||
_name = 'fusion.plating.ppe.issuance'
|
||||
_description = 'Fusion Plating — PPE Issuance'
|
||||
_description = 'Fusion Plating - PPE Issuance'
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||
_order = 'issue_date desc, id desc'
|
||||
_rec_name = 'display_name'
|
||||
@@ -89,4 +89,4 @@ class FpPpeIssuance(models.Model):
|
||||
parts.append(ppe_label.get(rec.ppe_type, rec.ppe_type))
|
||||
if rec.issue_date:
|
||||
parts.append(fields.Date.to_string(rec.issue_date))
|
||||
rec.display_name = ' — '.join(parts) if parts else 'PPE Issuance'
|
||||
rec.display_name = ' - '.join(parts) if parts else 'PPE Issuance'
|
||||
|
||||
@@ -15,14 +15,14 @@ class FpSds(models.Model):
|
||||
manufacturer that describes the hazards, handling, storage, exposure
|
||||
controls and emergency information for a product. Under the WHMIS 2015 /
|
||||
GHS framework an SDS is considered current for three years from its
|
||||
issue date — after which a refresh from the supplier is required.
|
||||
issue date - after which a refresh from the supplier is required.
|
||||
|
||||
Each SDS in the library carries supplier metadata, hazard classification,
|
||||
GHS pictogram codes, language coverage and a link to the original PDF
|
||||
via ir.attachment.
|
||||
"""
|
||||
_name = 'fusion.plating.sds'
|
||||
_description = 'Fusion Plating — Safety Data Sheet'
|
||||
_description = 'Fusion Plating - Safety Data Sheet'
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||
_order = 'product_name, version desc, issue_date desc'
|
||||
_rec_name = 'name'
|
||||
|
||||
@@ -19,7 +19,7 @@ class FpTrainingRecord(models.Model):
|
||||
queried at a glance.
|
||||
"""
|
||||
_name = 'fusion.plating.training.record'
|
||||
_description = 'Fusion Plating — Training Record'
|
||||
_description = 'Fusion Plating - Training Record'
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||
_order = 'completion_date desc, id desc'
|
||||
_rec_name = 'display_name'
|
||||
@@ -123,4 +123,4 @@ class FpTrainingRecord(models.Model):
|
||||
parts.append(rec.training_type_id.name)
|
||||
if rec.completion_date:
|
||||
parts.append(fields.Date.to_string(rec.completion_date))
|
||||
rec.display_name = ' — '.join(parts) if parts else 'Training Record'
|
||||
rec.display_name = ' - '.join(parts) if parts else 'Training Record'
|
||||
|
||||
@@ -9,8 +9,8 @@ from odoo import fields, models
|
||||
class FpTrainingType(models.Model):
|
||||
"""Master catalogue of training courses required in the shop.
|
||||
|
||||
A training type defines a class of certification — WHMIS 2015, TDG Road,
|
||||
Standard First Aid / CPR, LOTO, Confined Space — together with how long
|
||||
A training type defines a class of certification - WHMIS 2015, TDG Road,
|
||||
Standard First Aid / CPR, LOTO, Confined Space - together with how long
|
||||
a completion remains valid before retraining is required. The validity
|
||||
window drives the per-employee training record's automatic expiry.
|
||||
|
||||
@@ -18,7 +18,7 @@ class FpTrainingType(models.Model):
|
||||
packs may add more.
|
||||
"""
|
||||
_name = 'fusion.plating.training.type'
|
||||
_description = 'Fusion Plating — Training Type'
|
||||
_description = 'Fusion Plating - Training Type'
|
||||
_order = 'category, name'
|
||||
|
||||
name = fields.Char(
|
||||
|
||||
@@ -12,56 +12,56 @@
|
||||
<!-- shop sees only its own data. -->
|
||||
<!-- ================================================================== -->
|
||||
<record id="fp_safety_sds_company_rule" model="ir.rule">
|
||||
<field name="name">Fusion Plating Safety: SDS — multi-company</field>
|
||||
<field name="name">Fusion Plating Safety: SDS - multi-company</field>
|
||||
<field name="model_id" ref="model_fusion_plating_sds"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
|
||||
<record id="fp_safety_chemical_company_rule" model="ir.rule">
|
||||
<field name="name">Fusion Plating Safety: Chemical — multi-company</field>
|
||||
<field name="name">Fusion Plating Safety: Chemical - multi-company</field>
|
||||
<field name="model_id" ref="model_fusion_plating_chemical"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
|
||||
<record id="fp_safety_training_record_company_rule" model="ir.rule">
|
||||
<field name="name">Fusion Plating Safety: Training Record — multi-company</field>
|
||||
<field name="name">Fusion Plating Safety: Training Record - multi-company</field>
|
||||
<field name="model_id" ref="model_fusion_plating_training_record"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
|
||||
<record id="fp_safety_exposure_company_rule" model="ir.rule">
|
||||
<field name="name">Fusion Plating Safety: Exposure — multi-company</field>
|
||||
<field name="name">Fusion Plating Safety: Exposure - multi-company</field>
|
||||
<field name="model_id" ref="model_fusion_plating_exposure_monitoring"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
|
||||
<record id="fp_safety_jhsc_company_rule" model="ir.rule">
|
||||
<field name="name">Fusion Plating Safety: JHSC — multi-company</field>
|
||||
<field name="name">Fusion Plating Safety: JHSC - multi-company</field>
|
||||
<field name="model_id" ref="model_fusion_plating_jhsc"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
|
||||
<record id="fp_safety_jhsc_meeting_company_rule" model="ir.rule">
|
||||
<field name="name">Fusion Plating Safety: JHSC Meeting — multi-company</field>
|
||||
<field name="name">Fusion Plating Safety: JHSC Meeting - multi-company</field>
|
||||
<field name="model_id" ref="model_fusion_plating_jhsc_meeting"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
|
||||
<record id="fp_safety_incident_company_rule" model="ir.rule">
|
||||
<field name="name">Fusion Plating Safety: Incident — multi-company</field>
|
||||
<field name="name">Fusion Plating Safety: Incident - multi-company</field>
|
||||
<field name="model_id" ref="model_fusion_plating_incident"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
|
||||
<record id="fp_safety_ppe_company_rule" model="ir.rule">
|
||||
<field name="name">Fusion Plating Safety: PPE — multi-company</field>
|
||||
<field name="name">Fusion Plating Safety: PPE - multi-company</field>
|
||||
<field name="model_id" ref="model_fusion_plating_ppe_issuance"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// =============================================================================
|
||||
// Fusion Plating — Safety (EHS) backend styles
|
||||
// Fusion Plating - Safety (EHS) backend styles
|
||||
// Copyright 2026 Nexa Systems Inc.
|
||||
// License OPL-1 (Odoo Proprietary License v1.0)
|
||||
//
|
||||
@@ -18,10 +18,10 @@
|
||||
//
|
||||
// Hazard / severity tints use color-mix() against the Bootstrap theme
|
||||
// tokens so a red badge is darker on light mode and brighter on dark mode
|
||||
// automatically — one rule, two looks.
|
||||
// automatically - one rule, two looks.
|
||||
//
|
||||
// We never target `.o_dark`, `html.dark`, or `@media (prefers-color-scheme)`
|
||||
// to override colours. If you find yourself needing that, it's a smell —
|
||||
// to override colours. If you find yourself needing that, it's a smell -
|
||||
// use a variable instead.
|
||||
// =============================================================================
|
||||
|
||||
@@ -37,12 +37,12 @@
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// SDS kanban — hazard-class tinted card
|
||||
// SDS kanban - hazard-class tinted card
|
||||
// -----------------------------------------------------------------------------
|
||||
.o_fp_sds_kanban {
|
||||
|
||||
.o_fp_sds_card {
|
||||
// Use a left border tint by hazard class — subtle, theme-aware.
|
||||
// Use a left border tint by hazard class - subtle, theme-aware.
|
||||
border-left-width: 4px;
|
||||
border-left-color: var(--bs-border-color);
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
border-left-color: var(--bs-info, var(--o-action));
|
||||
}
|
||||
|
||||
// Status overlay — expired wins over hazard tint.
|
||||
// Status overlay - expired wins over hazard tint.
|
||||
&[data-state="expired"] {
|
||||
border-left-color: var(--bs-danger);
|
||||
opacity: 0.85;
|
||||
@@ -102,7 +102,7 @@
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Training kanban — expiry indicator on the card
|
||||
// Training kanban - expiry indicator on the card
|
||||
// -----------------------------------------------------------------------------
|
||||
.o_fp_training_kanban {
|
||||
|
||||
@@ -141,7 +141,7 @@
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Incident kanban — severity tint by type
|
||||
// Incident kanban - severity tint by type
|
||||
// -----------------------------------------------------------------------------
|
||||
.o_fp_incident_kanban {
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@
|
||||
Log an incident, near-miss or first-aid event
|
||||
</p>
|
||||
<p>
|
||||
Capture every safety event — even close calls — and walk it
|
||||
Capture every safety event - even close calls - and walk it
|
||||
through investigation to closure with a documented root
|
||||
cause and corrective action.
|
||||
</p>
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
-->
|
||||
<odoo>
|
||||
|
||||
<!-- Phase 1 — re-parented under Plating → Compliance hub. -->
|
||||
<!-- Phase D (perms v2) — QM-only under compliance hub. -->
|
||||
<!-- Phase 1 - re-parented under Plating → Compliance hub. -->
|
||||
<!-- Phase D (perms v2) - QM-only under compliance hub. -->
|
||||
<menuitem id="menu_fp_safety_root"
|
||||
name="Safety / WHMIS"
|
||||
parent="fusion_plating.menu_fp_compliance_hub"
|
||||
@@ -56,7 +56,7 @@
|
||||
action="action_fp_ppe_issuance"
|
||||
sequence="60"/>
|
||||
|
||||
<!-- Phase 2 — Training Types → Workforce; Chemicals → Materials & Tanks -->
|
||||
<!-- Phase 2 - Training Types → Workforce; Chemicals → Materials & Tanks -->
|
||||
<menuitem id="menu_fp_safety_training_types"
|
||||
name="Training Types"
|
||||
parent="fusion_plating.menu_fp_config_workforce"
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
<p>
|
||||
Maintain a current SDS for every hazardous product on site.
|
||||
Under WHMIS / GHS each SDS is valid for three years from
|
||||
its issue date — refresh from the supplier before expiry.
|
||||
its issue date - refresh from the supplier before expiry.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
Reference in New Issue
Block a user