diff --git a/fusion-plating/fusion_plating/controllers/recipe_controller.py b/fusion-plating/fusion_plating/controllers/recipe_controller.py index 8c762732..131ed2a8 100644 --- a/fusion-plating/fusion_plating/controllers/recipe_controller.py +++ b/fusion-plating/fusion_plating/controllers/recipe_controller.py @@ -85,7 +85,7 @@ class FpRecipeController(http.Controller): 'description', 'notes', 'estimated_duration', 'auto_complete', 'customer_visible', 'is_manual', - 'requires_signoff', 'sequence', 'version', + 'requires_signoff', 'opt_in_out', 'sequence', 'version', } safe_vals = {k: v for k, v in vals.items() if k in allowed} if not safe_vals: diff --git a/fusion-plating/fusion_plating/models/fp_process_node.py b/fusion-plating/fusion_plating/models/fp_process_node.py index 6edf91d2..78f2e5bb 100644 --- a/fusion-plating/fusion_plating/models/fp_process_node.py +++ b/fusion-plating/fusion_plating/models/fp_process_node.py @@ -143,6 +143,17 @@ class FpProcessNode(models.Model): default=False, help='Quality hold point — requires operator sign-off.', ) + opt_in_out = fields.Selection( + [ + ('disabled', 'Disabled'), + ('opt_in', 'Opt-In'), + ('opt_out', 'Opt-Out'), + ], + string='Opt In/Out', + default='disabled', + help='Controls whether this step is optional for a given job.', + tracking=True, + ) # ---- Lifecycle ----------------------------------------------------------- @@ -274,7 +285,12 @@ class FpProcessNode(models.Model): 'requires_signoff': self.requires_signoff, 'version': self.version, 'child_count': len(children), + 'opt_in_out': self.opt_in_out or 'disabled', 'input_count': len(self.input_ids), + 'create_date': self.create_date.isoformat() if self.create_date else '', + 'create_uid_name': self.create_uid.name if self.create_uid else '', + 'write_date': self.write_date.isoformat() if self.write_date else '', + 'write_uid_name': self.write_uid.name if self.write_uid else '', 'children': children, } diff --git a/fusion-plating/fusion_plating/static/src/js/recipe_tree_editor.js b/fusion-plating/fusion_plating/static/src/js/recipe_tree_editor.js index d976e7b8..a1ff0024 100644 --- a/fusion-plating/fusion_plating/static/src/js/recipe_tree_editor.js +++ b/fusion-plating/fusion_plating/static/src/js/recipe_tree_editor.js @@ -453,6 +453,29 @@ export class RecipeTreeEditor extends Component { return ICON_OPTIONS; } + formatTimeAgo(isoStr) { + if (!isoStr) return ""; + const date = new Date(isoStr); + const now = new Date(); + let diff = Math.floor((now - date) / 1000); // seconds + if (diff < 0) diff = 0; + const parts = []; + const weeks = Math.floor(diff / 604800); + diff %= 604800; + const days = Math.floor(diff / 86400); + diff %= 86400; + const hours = Math.floor(diff / 3600); + diff %= 3600; + const minutes = Math.floor(diff / 60); + const seconds = diff % 60; + if (weeks) parts.push(`${weeks}w`); + if (days) parts.push(`${days}d`); + if (hours) parts.push(`${hours}h`); + if (minutes) parts.push(`${minutes}m`); + parts.push(`${seconds}s`); + return parts.join(" ") + " ago"; + } + formatDuration(minutes) { if (!minutes) return ""; if (minutes < 60) return `${Math.round(minutes)}m`; diff --git a/fusion-plating/fusion_plating/static/src/scss/recipe_tree_editor.scss b/fusion-plating/fusion_plating/static/src/scss/recipe_tree_editor.scss index cec9e216..1c386735 100644 --- a/fusion-plating/fusion_plating/static/src/scss/recipe_tree_editor.scss +++ b/fusion-plating/fusion_plating/static/src/scss/recipe_tree_editor.scss @@ -372,6 +372,12 @@ } } +// ---- Tracking section ------------------------------------------------------- + +.o_fp_recipe_tracking { + border-top: 1px solid $border-color; +} + // ---- Icon picker ------------------------------------------------------------ .o_fp_recipe_icon_picker { diff --git a/fusion-plating/fusion_plating/static/src/xml/recipe_tree_editor.xml b/fusion-plating/fusion_plating/static/src/xml/recipe_tree_editor.xml index effd3b78..065927ed 100644 --- a/fusion-plating/fusion_plating/static/src/xml/recipe_tree_editor.xml +++ b/fusion-plating/fusion_plating/static/src/xml/recipe_tree_editor.xml @@ -144,20 +144,49 @@ +