From 95310c459d6c7c4d34dc7f0a2784e824b14007fe Mon Sep 17 00:00:00 2001 From: gsinghpal Date: Mon, 20 Apr 2026 20:30:47 -0400 Subject: [PATCH] =?UTF-8?q?chore(plating):=20retire=20fusion=5Fplating=5Fc?= =?UTF-8?q?ulture=20=E2=80=94=20not=20a=20priority?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Culture/values/recognitions framework was shipping zero data and zero workflow integration for this client. It's a people-ops concern (peer kudos, "Fundamental of the Week" rotations) with no overlap with the technical plating pipeline — no interaction with process recipes, quality holds, sensors, or compliance. Verified zero data on entech before uninstalling: fusion.plating.value 0 records fusion.plating.value.set 0 fusion.plating.value.recognition 0 fusion.plating.value.rotation 0 Clean uninstall on entech, module dir removed from disk. The Culture top-level menu disappears. If a future client wants it back, the module is easy to re-author — nothing we built on top of it depends on it. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../fusion_plating_culture/README.md | 53 ------ .../fusion_plating_culture/__init__.py | 6 - .../fusion_plating_culture/__manifest__.py | 74 -------- .../data/fp_demo_culture_data.xml | 72 -------- .../data/fp_sequence_data.xml | 18 -- .../fusion_plating_culture/models/__init__.py | 10 -- .../fusion_plating_culture/models/fp_value.py | 100 ----------- .../models/fp_value_recognition.py | 120 ------------- .../models/fp_value_rotation.py | 149 ----------------- .../models/fp_value_set.py | 111 ------------ .../models/hr_employee.py | 47 ------ .../security/fp_culture_security.xml | 47 ------ .../security/ir.model.access.csv | 13 -- .../src/scss/fusion_plating_culture.scss | 128 -------------- .../fusion_plating_culture/views/fp_menu.xml | 43 ----- .../views/fp_value_recognition_views.xml | 158 ------------------ .../views/fp_value_rotation_views.xml | 84 ---------- .../views/fp_value_set_views.xml | 106 ------------ .../views/fp_value_views.xml | 134 --------------- .../views/hr_employee_views.xml | 40 ----- 20 files changed, 1513 deletions(-) delete mode 100644 fusion_plating/fusion_plating_culture/README.md delete mode 100644 fusion_plating/fusion_plating_culture/__init__.py delete mode 100644 fusion_plating/fusion_plating_culture/__manifest__.py delete mode 100644 fusion_plating/fusion_plating_culture/data/fp_demo_culture_data.xml delete mode 100644 fusion_plating/fusion_plating_culture/data/fp_sequence_data.xml delete mode 100644 fusion_plating/fusion_plating_culture/models/__init__.py delete mode 100644 fusion_plating/fusion_plating_culture/models/fp_value.py delete mode 100644 fusion_plating/fusion_plating_culture/models/fp_value_recognition.py delete mode 100644 fusion_plating/fusion_plating_culture/models/fp_value_rotation.py delete mode 100644 fusion_plating/fusion_plating_culture/models/fp_value_set.py delete mode 100644 fusion_plating/fusion_plating_culture/models/hr_employee.py delete mode 100644 fusion_plating/fusion_plating_culture/security/fp_culture_security.xml delete mode 100644 fusion_plating/fusion_plating_culture/security/ir.model.access.csv delete mode 100644 fusion_plating/fusion_plating_culture/static/src/scss/fusion_plating_culture.scss delete mode 100644 fusion_plating/fusion_plating_culture/views/fp_menu.xml delete mode 100644 fusion_plating/fusion_plating_culture/views/fp_value_recognition_views.xml delete mode 100644 fusion_plating/fusion_plating_culture/views/fp_value_rotation_views.xml delete mode 100644 fusion_plating/fusion_plating_culture/views/fp_value_set_views.xml delete mode 100644 fusion_plating/fusion_plating_culture/views/fp_value_views.xml delete mode 100644 fusion_plating/fusion_plating_culture/views/hr_employee_views.xml diff --git a/fusion_plating/fusion_plating_culture/README.md b/fusion_plating/fusion_plating_culture/README.md deleted file mode 100644 index d2f44e80..00000000 --- a/fusion_plating/fusion_plating_culture/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# Fusion Plating — Culture & Values - -Part of the Fusion Plating product family by Nexa Systems Inc. - -A configurable culture / values / fundamentals framework for plating and -metal finishing shops. Each shop loads its own values — this module ships -with no client-specific seed data. - -## What it gives you - -- **Value Sets** — a named collection of a shop's values (e.g. "Our Way", - "The 24 Fundamentals", "Core Behaviours"). A company can have several - sets, but usually one is marked as primary. -- **Values** — individual fundamentals, core behaviours, or beliefs, each - with a short title, long-form description, stories/examples, icon, and - display number. -- **Rotations** — a schedule that surfaces a "Fundamental of the - Day/Week/Month". The shop admin decides whether to enable an ir.cron - (none ships in this module) to advance rotations automatically. -- **Recognitions** — peer shout-outs tied to a specific value. "I saw - Sarah living Value #3 today when she stayed late to finish a customer - order." Recognitions flow into an employee's Culture tab on their HR - record. - -## Installation - -1. Install `fusion_plating` (core) and `hr` first. -2. Install `fusion_plating_culture`. -3. Go to **Plating → Culture → Configuration → Value Sets** and create - your shop's set. -4. Add values to that set. -5. (Optional) Create a rotation schedule if you want a - fundamental-of-the-week rotation. - -## Design notes - -- **Not client-specific.** Nothing ships with Entech, Westin, or any - particular shop's language baked in. Each shop loads its own. -- **Reuses core groups.** No new security groups — operator reads, - supervisor creates recognitions, manager configures value sets. -- **Theme-aware.** SCSS uses Bootstrap CSS variables so kanban tiles and - recognition cards render cleanly in both light and dark mode. -- **hr.employee extension uses `x_fc_` prefix** per the Fusion Central - field-naming convention for base Odoo model extensions. - -## Dependencies - -- `fusion_plating` — core -- `hr` — for employee extension and recognition targeting - -## License - -OPL-1 (Odoo Proprietary License v1.0) — Copyright 2026 Nexa Systems Inc. diff --git a/fusion_plating/fusion_plating_culture/__init__.py b/fusion_plating/fusion_plating_culture/__init__.py deleted file mode 100644 index 3c90fa80..00000000 --- a/fusion_plating/fusion_plating_culture/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2026 Nexa Systems Inc. -# License OPL-1 (Odoo Proprietary License v1.0) -# Part of the Fusion Plating product family. - -from . import models diff --git a/fusion_plating/fusion_plating_culture/__manifest__.py b/fusion_plating/fusion_plating_culture/__manifest__.py deleted file mode 100644 index d0469821..00000000 --- a/fusion_plating/fusion_plating_culture/__manifest__.py +++ /dev/null @@ -1,74 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2026 Nexa Systems Inc. -# License OPL-1 (Odoo Proprietary License v1.0) -# Part of the Fusion Plating product family. - -{ - 'name': 'Fusion Plating — Culture & Values', - 'version': '19.0.1.0.0', - 'category': 'Manufacturing/Plating', - 'summary': 'Configurable culture framework for plating shops: values, fundamentals, peer recognitions, rotation schedules. Each shop loads its own values.', - 'description': """ -Fusion Plating — Culture & Values -================================= - -Part of the Fusion Plating product family by Nexa Systems Inc. - -A configurable culture / values / fundamentals framework for plating and -metal finishing shops. Every shop has a different way of talking about how -they expect their people to behave — this module gives each shop a place to -capture that language and put it to work in the daily flow of the plant. - -The module is intentionally generic. It ships with NO client-specific data. -Each shop loads its own value set: one shop may adopt the Entech "24 -Fundamentals", another may use a 10-value "Our Way" set, and another may -skip the module entirely. - -Concepts --------- -* Value Set — a named collection of values owned by a company -* Value — an individual fundamental, behaviour, or belief -* Rotation — a schedule that surfaces a value-of-the-day/week/month -* Recognition — a peer shout-out tied to a specific value - -Extensions ----------- -* hr.employee gains a recognition count and a Culture tab showing the - employee's recognition history. - -Copyright (c) 2026 Nexa Systems Inc. All rights reserved. - """, - 'author': 'Nexa Systems Inc.', - 'website': 'https://www.nexasystems.ca', - 'maintainer': 'Nexa Systems Inc.', - 'support': 'support@nexasystems.ca', - 'license': 'OPL-1', - 'price': 0.00, - 'currency': 'CAD', - 'depends': [ - 'fusion_plating', - 'hr', - ], - 'data': [ - 'security/fp_culture_security.xml', - 'security/ir.model.access.csv', - 'data/fp_sequence_data.xml', - 'views/fp_value_set_views.xml', - 'views/fp_value_views.xml', - 'views/fp_value_rotation_views.xml', - 'views/fp_value_recognition_views.xml', - 'views/hr_employee_views.xml', - 'views/fp_menu.xml', - ], - 'demo': [ - 'data/fp_demo_culture_data.xml', - ], - 'assets': { - 'web.assets_backend': [ - 'fusion_plating_culture/static/src/scss/fusion_plating_culture.scss', - ], - }, - 'installable': True, - 'application': False, - 'auto_install': False, -} diff --git a/fusion_plating/fusion_plating_culture/data/fp_demo_culture_data.xml b/fusion_plating/fusion_plating_culture/data/fp_demo_culture_data.xml deleted file mode 100644 index 6060afd1..00000000 --- a/fusion_plating/fusion_plating_culture/data/fp_demo_culture_data.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - Core Values - CORE - -

The five core values that guide how we work, treat each other, and serve our customers every day on the shop floor.

-
- - - - Safety First - 1 - 10 - - fa-shield - 1 -

Nothing we do is worth getting hurt over. Every person goes home safe, every day. We stop work when something is unsafe and speak up without hesitation.

-

A plater notices a leaking hose on the chrome line and immediately tags it out, even though it means pausing production for the shift.

-
- - - Quality Excellence - 2 - 20 - - fa-star - 2 -

We take pride in doing it right the first time. Our coatings protect critical parts — there is no room for "good enough." We own the spec, own the process, and own the result.

-

An operator catches a thickness reading at the low end of spec and voluntarily re-plates the part rather than shipping borderline work.

-
- - - Teamwork - 3 - 30 - - fa-users - 3 -

We win together or not at all. No one succeeds alone on a plating line — every station depends on the one before it. We help each other, share knowledge, and celebrate wins as a team.

-

The prep team stays late to help the EN line clear a rush order, even though it was not their line's work.

-
- - - Continuous Improvement - 4 - 40 - - fa-line-chart - 4 -

Good enough today is not good enough tomorrow. We look for small, practical improvements every day — in our processes, our tools, and ourselves.

-

A shift lead redesigns the rack loading sequence and cuts cycle time by 12% without any capital spend.

-
- - - Customer Focus - 5 - 50 - - fa-handshake-o - 5 -

Our customers trust us with their most critical parts. We honour that trust by delivering on time, communicating proactively, and treating every job like it matters — because it does.

-

The shipping coordinator calls a customer two days before the due date to confirm the delivery window, preventing a costly production delay on their end.

-
- -
diff --git a/fusion_plating/fusion_plating_culture/data/fp_sequence_data.xml b/fusion_plating/fusion_plating_culture/data/fp_sequence_data.xml deleted file mode 100644 index 00b95d9f..00000000 --- a/fusion_plating/fusion_plating_culture/data/fp_sequence_data.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - Fusion Plating: Recognition - fusion.plating.value.recognition - REC/%(year)s/ - 5 - - - - - diff --git a/fusion_plating/fusion_plating_culture/models/__init__.py b/fusion_plating/fusion_plating_culture/models/__init__.py deleted file mode 100644 index a6d8b143..00000000 --- a/fusion_plating/fusion_plating_culture/models/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2026 Nexa Systems Inc. -# License OPL-1 (Odoo Proprietary License v1.0) -# Part of the Fusion Plating product family. - -from . import fp_value_set -from . import fp_value -from . import fp_value_rotation -from . import fp_value_recognition -from . import hr_employee diff --git a/fusion_plating/fusion_plating_culture/models/fp_value.py b/fusion_plating/fusion_plating_culture/models/fp_value.py deleted file mode 100644 index eba93840..00000000 --- a/fusion_plating/fusion_plating_culture/models/fp_value.py +++ /dev/null @@ -1,100 +0,0 @@ -# -*- 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, fields, models - - -class FpValue(models.Model): - """A single value, fundamental, core behaviour, or belief. - - Values are grouped under a fusion.plating.value.set. Each value has a - short title, an optional display number (e.g. "Fundamental #3"), a - long-form description, stories / examples of living the value, and an - icon for display in kanban tiles. - """ - _name = 'fusion.plating.value' - _description = 'Fusion Plating — Value' - _order = 'set_id, sequence, number, name' - - name = fields.Char( - string='Title', - required=True, - help='Short, memorable title for the value, e.g. ' - '"Do What\'s Best for the Customer".', - ) - sequence = fields.Integer( - string='Sequence', - default=10, - help='Display order within the set.', - ) - number = fields.Integer( - string='Number', - help='Optional display number (e.g. 1, 2, 3). Shows on kanban ' - 'tiles and in rotation schedules.', - ) - set_id = fields.Many2one( - 'fusion.plating.value.set', - string='Value Set', - required=True, - ondelete='cascade', - index=True, - ) - company_id = fields.Many2one( - 'res.company', - string='Company', - related='set_id.company_id', - store=True, - readonly=True, - ) - description = fields.Html( - string='Description', - help='Long-form explanation of what this value means and how it ' - 'shows up in daily work.', - ) - examples = fields.Html( - string='Stories & Examples', - help='Stories, anecdotes, and concrete examples of people living ' - 'this value.', - ) - icon = fields.Char( - string='Icon', - default='fa-star', - help='Font Awesome icon class (without the "fa " prefix), ' - 'e.g. "fa-heart", "fa-bolt".', - ) - color = fields.Integer( - string='Color Index', - default=0, - help='Kanban colour index (0-11).', - ) - active = fields.Boolean( - string='Active', - default=True, - ) - recognition_ids = fields.One2many( - 'fusion.plating.value.recognition', - 'value_id', - string='Recognitions', - ) - recognition_count = fields.Integer( - string='Recognition Count', - compute='_compute_recognition_count', - ) - - @api.depends('recognition_ids', 'recognition_ids.state') - def _compute_recognition_count(self): - for rec in self: - rec.recognition_count = len(rec.recognition_ids.filtered( - lambda r: r.state == 'published' - )) - - def name_get(self): - result = [] - for rec in self: - if rec.number: - result.append((rec.id, f'#{rec.number} — {rec.name}')) - else: - result.append((rec.id, rec.name)) - return result diff --git a/fusion_plating/fusion_plating_culture/models/fp_value_recognition.py b/fusion_plating/fusion_plating_culture/models/fp_value_recognition.py deleted file mode 100644 index 65d2a194..00000000 --- a/fusion_plating/fusion_plating_culture/models/fp_value_recognition.py +++ /dev/null @@ -1,120 +0,0 @@ -# -*- 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, fields, models - - -class FpValueRecognition(models.Model): - """A peer recognition tied to a specific value. - - Example: "I saw Sarah living Value #3 yesterday when she stayed late - to re-mask a customer part after first-article inspection flagged a - nick." - - Recognitions start in draft, move to published, and can be archived - when they roll off a stand-up wall or a newsletter. - """ - _name = 'fusion.plating.value.recognition' - _description = 'Fusion Plating — Value Recognition' - _inherit = ['mail.thread', 'mail.activity.mixin'] - _order = 'nomination_date desc, id desc' - - name = fields.Char( - string='Title', - required=True, - tracking=True, - help='Short headline for the recognition, e.g. ' - '"Sarah stayed late for the customer".', - default=lambda self: _('New Recognition'), - ) - reference = fields.Char( - string='Reference', - readonly=True, - copy=False, - default=lambda self: _('New'), - ) - value_id = fields.Many2one( - 'fusion.plating.value', - string='Value', - required=True, - tracking=True, - ondelete='restrict', - ) - set_id = fields.Many2one( - 'fusion.plating.value.set', - string='Value Set', - related='value_id.set_id', - store=True, - readonly=True, - ) - recognized_employee_id = fields.Many2one( - 'hr.employee', - string='Recognized', - required=True, - tracking=True, - help='The person being recognized.', - ) - nominated_by_id = fields.Many2one( - 'res.users', - string='Nominated By', - default=lambda self: self.env.user, - tracking=True, - ) - nomination_date = fields.Datetime( - string='Nominated On', - default=fields.Datetime.now, - tracking=True, - ) - story = fields.Html( - string='Story', - help='What happened? Describe the moment you saw the value being ' - 'lived.', - ) - state = fields.Selection( - [ - ('draft', 'Draft'), - ('published', 'Published'), - ('archived', 'Archived'), - ], - string='Status', - default='draft', - required=True, - tracking=True, - ) - company_id = fields.Many2one( - 'res.company', - string='Company', - default=lambda self: self.env.company, - ) - color = fields.Integer( - string='Color Index', - default=0, - ) - - @api.model_create_multi - def create(self, vals_list): - for vals in vals_list: - if not vals.get('reference') or vals['reference'] == _('New'): - vals['reference'] = self.env['ir.sequence'].next_by_code( - 'fusion.plating.value.recognition' - ) or _('New') - return super().create(vals_list) - - def action_publish(self): - for rec in self: - rec.state = 'published' - rec.message_post(body=_('Recognition published.')) - return True - - def action_archive_recognition(self): - for rec in self: - rec.state = 'archived' - rec.message_post(body=_('Recognition archived.')) - return True - - def action_reset_to_draft(self): - for rec in self: - rec.state = 'draft' - return True diff --git a/fusion_plating/fusion_plating_culture/models/fp_value_rotation.py b/fusion_plating/fusion_plating_culture/models/fp_value_rotation.py deleted file mode 100644 index 785b89d8..00000000 --- a/fusion_plating/fusion_plating_culture/models/fp_value_rotation.py +++ /dev/null @@ -1,149 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2026 Nexa Systems Inc. -# License OPL-1 (Odoo Proprietary License v1.0) -# Part of the Fusion Plating product family. - -from datetime import timedelta - -from odoo import _, api, fields, models - - -class FpValueRotation(models.Model): - """A schedule that rotates a value to the front of the shop's attention. - - Used to drive "Fundamental of the Day/Week/Month" programs. The admin - creates a rotation, picks a set and a period, and enables it. This - module does NOT ship an ir.cron — the shop admin wires a cron to call - `_cron_advance_rotation` if they want automatic advancement. Many - shops prefer to advance the rotation manually at a weekly stand-up. - """ - _name = 'fusion.plating.value.rotation' - _description = 'Fusion Plating — Value Rotation Schedule' - _inherit = ['mail.thread'] - _order = 'name' - - name = fields.Char( - string='Name', - required=True, - tracking=True, - help='Display name of the rotation, e.g. "Weekly Fundamental".', - ) - set_id = fields.Many2one( - 'fusion.plating.value.set', - string='Value Set', - required=True, - ondelete='cascade', - tracking=True, - ) - rotation_period = fields.Selection( - [ - ('daily', 'Daily'), - ('weekly', 'Weekly'), - ('monthly', 'Monthly'), - ], - string='Rotation Period', - required=True, - default='weekly', - tracking=True, - ) - current_value_id = fields.Many2one( - 'fusion.plating.value', - string='Current Value', - readonly=True, - tracking=True, - help='The value currently surfaced by this rotation. Updated by ' - '_cron_advance_rotation.', - domain="[('set_id', '=', set_id)]", - ) - last_rotation_date = fields.Date( - string='Last Rotated On', - readonly=True, - ) - next_rotation_date = fields.Date( - string='Next Rotation', - compute='_compute_next_rotation_date', - ) - company_id = fields.Many2one( - 'res.company', - string='Company', - related='set_id.company_id', - store=True, - readonly=True, - ) - active = fields.Boolean( - string='Active', - default=True, - ) - - @api.depends('last_rotation_date', 'rotation_period') - def _compute_next_rotation_date(self): - for rec in self: - if not rec.last_rotation_date: - rec.next_rotation_date = fields.Date.context_today(rec) - continue - delta_days = { - 'daily': 1, - 'weekly': 7, - 'monthly': 30, - }.get(rec.rotation_period, 7) - rec.next_rotation_date = rec.last_rotation_date + timedelta( - days=delta_days - ) - - def action_advance(self): - """Manually advance the rotation to the next value. - - Wired to a form button so a shop that doesn't want cron-driven - rotation can move the fundamental forward at a stand-up meeting. - """ - for rec in self: - rec._advance_one() - return True - - def _advance_one(self): - """Move this rotation to the next value in the set, wrapping.""" - self.ensure_one() - values = self.set_id.value_ids.filtered('active').sorted( - key=lambda v: (v.sequence, v.number, v.id) - ) - if not values: - return False - if not self.current_value_id: - next_value = values[0] - else: - try: - idx = list(values).index(self.current_value_id) - next_idx = (idx + 1) % len(values) - next_value = values[next_idx] - except ValueError: - next_value = values[0] - self.write({ - 'current_value_id': next_value.id, - 'last_rotation_date': fields.Date.context_today(self), - }) - self.message_post( - body=_('Rotation advanced to %(value)s.') % { - 'value': next_value.display_name, - } - ) - return True - - @api.model - def _cron_advance_rotation(self): - """Cron entry point. - - A shop admin can wire an ir.cron to this method. The module - intentionally does not ship one — different shops want different - cadences. Only advances rotations whose next_rotation_date is - today or earlier. - """ - today = fields.Date.context_today(self) - rotations = self.search([('active', '=', True)]) - for rotation in rotations: - if ( - not rotation.last_rotation_date - or rotation.next_rotation_date - and rotation.next_rotation_date <= today - ): - rotation._advance_one() - return True diff --git a/fusion_plating/fusion_plating_culture/models/fp_value_set.py b/fusion_plating/fusion_plating_culture/models/fp_value_set.py deleted file mode 100644 index 96d729f9..00000000 --- a/fusion_plating/fusion_plating_culture/models/fp_value_set.py +++ /dev/null @@ -1,111 +0,0 @@ -# -*- 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, fields, models - - -class FpValueSet(models.Model): - """A named collection of values owned by a company. - - Each shop loads its own set. One shop might call theirs - "Entech Fundamentals" with 24 items, another "Our Way" with 10. A shop - may have several sets (historical, draft, archived) but usually only - one is marked primary. - - The module ships NO seed data — this is a generic framework. - """ - _name = 'fusion.plating.value.set' - _description = 'Fusion Plating — Value Set' - _inherit = ['mail.thread', 'mail.activity.mixin'] - _order = 'is_primary desc, name' - - name = fields.Char( - string='Name', - required=True, - tracking=True, - help='Display name of the set, e.g. "Entech Fundamentals", "Our Way".', - ) - code = fields.Char( - string='Code', - required=True, - tracking=True, - help='Unique slug identifier, e.g. "entech_fundamentals".', - ) - description = fields.Html( - string='Description', - help='Long-form description of what this set represents and how ' - 'the shop uses it.', - ) - company_id = fields.Many2one( - 'res.company', - string='Company', - required=True, - default=lambda self: self.env.company, - tracking=True, - ) - value_ids = fields.One2many( - 'fusion.plating.value', - 'set_id', - string='Values', - ) - value_count = fields.Integer( - string='Value Count', - compute='_compute_value_count', - ) - is_primary = fields.Boolean( - string='Primary Set', - default=False, - tracking=True, - help='Marks this as the shop\'s primary culture set. Only one set ' - 'per company should be primary at a time.', - ) - active = fields.Boolean( - string='Active', - default=True, - ) - - _sql_constraints = [ - ( - 'fp_value_set_code_company_uniq', - 'unique(code, company_id)', - 'Value set code must be unique within a company.', - ), - ] - - @api.depends('value_ids') - def _compute_value_count(self): - for rec in self: - rec.value_count = len(rec.value_ids) - - def write(self, vals): - """When flipping a set to primary, demote any other primary set in - the same company so there is only one primary per company. - """ - res = super().write(vals) - if vals.get('is_primary'): - for rec in self: - if rec.is_primary: - others = self.search([ - ('id', '!=', rec.id), - ('company_id', '=', rec.company_id.id), - ('is_primary', '=', True), - ]) - if others: - others.write({'is_primary': False}) - return res - - @api.model_create_multi - def create(self, vals_list): - recs = super().create(vals_list) - for rec in recs: - if rec.is_primary: - others = self.search([ - ('id', '!=', rec.id), - ('company_id', '=', rec.company_id.id), - ('is_primary', '=', True), - ]) - if others: - others.write({'is_primary': False}) - return recs diff --git a/fusion_plating/fusion_plating_culture/models/hr_employee.py b/fusion_plating/fusion_plating_culture/models/hr_employee.py deleted file mode 100644 index 49cb07f0..00000000 --- a/fusion_plating/fusion_plating_culture/models/hr_employee.py +++ /dev/null @@ -1,47 +0,0 @@ -# -*- 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, fields, models - - -class HrEmployee(models.Model): - """Extend hr.employee with culture recognition totals. - - Uses the x_fc_ prefix per the Fusion Central field-naming convention - for base Odoo model extensions. - """ - _inherit = 'hr.employee' - - x_fc_recognition_ids = fields.One2many( - 'fusion.plating.value.recognition', - 'recognized_employee_id', - string='Recognitions', - ) - x_fc_recognition_count = fields.Integer( - string='Recognition Count', - compute='_compute_x_fc_recognition_stats', - ) - x_fc_last_recognized_date = fields.Datetime( - string='Last Recognized', - compute='_compute_x_fc_recognition_stats', - ) - - @api.depends( - 'x_fc_recognition_ids', - 'x_fc_recognition_ids.state', - 'x_fc_recognition_ids.nomination_date', - ) - def _compute_x_fc_recognition_stats(self): - for rec in self: - published = rec.x_fc_recognition_ids.filtered( - lambda r: r.state == 'published' - ) - rec.x_fc_recognition_count = len(published) - if published: - rec.x_fc_last_recognized_date = max( - published.mapped('nomination_date') - ) - else: - rec.x_fc_last_recognized_date = False diff --git a/fusion_plating/fusion_plating_culture/security/fp_culture_security.xml b/fusion_plating/fusion_plating_culture/security/fp_culture_security.xml deleted file mode 100644 index c8500a27..00000000 --- a/fusion_plating/fusion_plating_culture/security/fp_culture_security.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - Fusion Plating: Value Set — multi-company - - - ['|', ('company_id', '=', False), ('company_id', 'in', company_ids)] - - - - Fusion Plating: Value — multi-company - - - ['|', ('company_id', '=', False), ('company_id', 'in', company_ids)] - - - - Fusion Plating: Value Rotation — multi-company - - - ['|', ('company_id', '=', False), ('company_id', 'in', company_ids)] - - - - Fusion Plating: Recognition — multi-company - - - ['|', ('company_id', '=', False), ('company_id', 'in', company_ids)] - - - diff --git a/fusion_plating/fusion_plating_culture/security/ir.model.access.csv b/fusion_plating/fusion_plating_culture/security/ir.model.access.csv deleted file mode 100644 index df4b01b8..00000000 --- a/fusion_plating/fusion_plating_culture/security/ir.model.access.csv +++ /dev/null @@ -1,13 +0,0 @@ -id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_fp_value_set_operator,fp.value.set.operator,model_fusion_plating_value_set,fusion_plating.group_fusion_plating_operator,1,0,0,0 -access_fp_value_set_supervisor,fp.value.set.supervisor,model_fusion_plating_value_set,fusion_plating.group_fusion_plating_supervisor,1,0,0,0 -access_fp_value_set_manager,fp.value.set.manager,model_fusion_plating_value_set,fusion_plating.group_fusion_plating_manager,1,1,1,1 -access_fp_value_operator,fp.value.operator,model_fusion_plating_value,fusion_plating.group_fusion_plating_operator,1,0,0,0 -access_fp_value_supervisor,fp.value.supervisor,model_fusion_plating_value,fusion_plating.group_fusion_plating_supervisor,1,0,0,0 -access_fp_value_manager,fp.value.manager,model_fusion_plating_value,fusion_plating.group_fusion_plating_manager,1,1,1,1 -access_fp_value_rotation_operator,fp.value.rotation.operator,model_fusion_plating_value_rotation,fusion_plating.group_fusion_plating_operator,1,0,0,0 -access_fp_value_rotation_supervisor,fp.value.rotation.supervisor,model_fusion_plating_value_rotation,fusion_plating.group_fusion_plating_supervisor,1,1,0,0 -access_fp_value_rotation_manager,fp.value.rotation.manager,model_fusion_plating_value_rotation,fusion_plating.group_fusion_plating_manager,1,1,1,1 -access_fp_value_recognition_operator,fp.value.recognition.operator,model_fusion_plating_value_recognition,fusion_plating.group_fusion_plating_operator,1,0,0,0 -access_fp_value_recognition_supervisor,fp.value.recognition.supervisor,model_fusion_plating_value_recognition,fusion_plating.group_fusion_plating_supervisor,1,1,1,0 -access_fp_value_recognition_manager,fp.value.recognition.manager,model_fusion_plating_value_recognition,fusion_plating.group_fusion_plating_manager,1,1,1,1 diff --git a/fusion_plating/fusion_plating_culture/static/src/scss/fusion_plating_culture.scss b/fusion_plating/fusion_plating_culture/static/src/scss/fusion_plating_culture.scss deleted file mode 100644 index 6a18e45d..00000000 --- a/fusion_plating/fusion_plating_culture/static/src/scss/fusion_plating_culture.scss +++ /dev/null @@ -1,128 +0,0 @@ -// ============================================================================= -// Fusion Plating — Culture & Values — backend styles -// Copyright 2026 Nexa Systems Inc. -// License OPL-1 (Odoo Proprietary License v1.0) -// -// THEME AWARENESS -// --------------- -// Like the core fusion_plating SCSS, this file uses ONLY Bootstrap / -// Odoo CSS custom properties so every surface adapts to light and dark -// mode automatically. No hardcoded hex colors anywhere. -// -// background: var(--bs-body-bg) -// surface: var(--o-view-background-color) -// foreground: var(--bs-body-color) -// muted text: var(--bs-secondary-color) -// border: var(--bs-border-color) -// primary: var(--o-action) -// -// Semantic tints use color-mix() so a green badge darkens on light mode -// and brightens on dark mode automatically. -// ============================================================================= - - -// ----------------------------------------------------------------------------- -// Value kanban tile — a colourful card showing number + name + icon -// ----------------------------------------------------------------------------- -.o_fp_value_card { - background-color: var(--o-view-background-color, var(--bs-body-bg)); - color: var(--bs-body-color); - border: 1px solid var(--bs-border-color); - border-radius: 12px; - padding: 16px 18px; - min-height: 140px; - transition: border-color 120ms ease, box-shadow 120ms ease, transform 120ms ease; - - &:hover { - border-color: color-mix(in srgb, var(--o-action) 50%, var(--bs-border-color)); - box-shadow: 0 4px 14px color-mix(in srgb, var(--bs-body-color) 10%, transparent); - transform: translateY(-1px); - } - - .o_fp_value_number { - font-size: 2.4rem; - font-weight: 700; - line-height: 1; - color: var(--o-action); - letter-spacing: -0.02em; - } - - .o_fp_value_icon { - font-size: 1.4rem; - opacity: 0.6; - } - - .o_fp_value_name { - font-size: 1rem; - line-height: 1.25; - color: var(--bs-body-color); - } - - .o_fp_value_meta { - color: var(--bs-secondary-color); - } -} - - -// ----------------------------------------------------------------------------- -// Recognition kanban card — badge-style card grouped by state -// ----------------------------------------------------------------------------- -.o_fp_recognition_card { - background-color: var(--o-view-background-color, var(--bs-body-bg)); - color: var(--bs-body-color); - border: 1px solid var(--bs-border-color); - border-left-width: 4px; - border-left-color: color-mix(in srgb, var(--o-action) 70%, var(--bs-border-color)); - border-radius: 10px; - padding: 12px 14px; - transition: border-color 120ms ease, box-shadow 120ms ease; - - &:hover { - border-color: color-mix(in srgb, var(--o-action) 50%, var(--bs-border-color)); - box-shadow: 0 2px 8px color-mix(in srgb, var(--bs-body-color) 8%, transparent); - } - - strong { - color: var(--bs-body-color); - font-size: 0.95rem; - line-height: 1.2; - } - - .text-muted { - color: var(--bs-secondary-color) !important; - } -} - - -// ----------------------------------------------------------------------------- -// Recognition kanban — state-based accent on the left border -// ----------------------------------------------------------------------------- -.o_fp_recognition_kanban { - - // Draft — subtle muted accent - .o_kanban_group[data-id$="draft"] .o_fp_recognition_card { - border-left-color: var(--bs-secondary-color); - } - - // Published — success accent - .o_kanban_group[data-id$="published"] .o_fp_recognition_card { - border-left-color: var(--bs-success); - } - - // Archived — dimmed - .o_kanban_group[data-id$="archived"] .o_fp_recognition_card { - border-left-color: color-mix(in srgb, var(--bs-secondary-color) 60%, transparent); - opacity: 0.75; - } -} - - -// ----------------------------------------------------------------------------- -// Value kanban — spacing for the grouped kanban columns -// ----------------------------------------------------------------------------- -.o_fp_value_kanban { - - .o_kanban_record { - margin-bottom: 8px; - } -} diff --git a/fusion_plating/fusion_plating_culture/views/fp_menu.xml b/fusion_plating/fusion_plating_culture/views/fp_menu.xml deleted file mode 100644 index 4dba06c7..00000000 --- a/fusion_plating/fusion_plating_culture/views/fp_menu.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/fusion_plating/fusion_plating_culture/views/fp_value_recognition_views.xml b/fusion_plating/fusion_plating_culture/views/fp_value_recognition_views.xml deleted file mode 100644 index cc17d6bd..00000000 --- a/fusion_plating/fusion_plating_culture/views/fp_value_recognition_views.xml +++ /dev/null @@ -1,158 +0,0 @@ - - - - - - fp.value.recognition.list - fusion.plating.value.recognition - - - - - - - - - - - - - - - fp.value.recognition.form - fusion.plating.value.recognition - -
-
-
- -
-
- - - - - - - - - - - - - - - - - -
- - -
-
- - - fp.value.recognition.kanban - fusion.plating.value.recognition - - - - - - - - - - - - -
-
- -