Add a Print Cylinder register for cylinder and plate readiness
Tooling was free text on the specification and a manual select on the Work Order. The register records each cylinder/plate with its specification, colour station, dimensions, ownership, location, condition and impressions. Work Order release now reads it: a job needing print tooling is blocked until every registered cylinder for its specification is Ready. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+9
-3
@@ -403,8 +403,14 @@
|
|||||||
"options": "Critical Acceptance Requirement"
|
"options": "Critical Acceptance Requirement"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"links": [],
|
"links": [
|
||||||
"modified": "2026-09-02 00:05:48.067955",
|
{
|
||||||
|
"group": "Tooling",
|
||||||
|
"link_doctype": "Print Cylinder",
|
||||||
|
"link_fieldname": "packaging_specification"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"modified": "2026-10-09 00:00:00",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "makap_backend",
|
"module": "makap_backend",
|
||||||
"name": "Packaging Specification",
|
"name": "Packaging Specification",
|
||||||
@@ -476,4 +482,4 @@
|
|||||||
"states": [],
|
"states": [],
|
||||||
"title_field": "specification_series",
|
"title_field": "specification_series",
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,337 @@
|
|||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"autoname": "field:cylinder_id",
|
||||||
|
"creation": "2026-10-09 00:00:00",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"identity_section",
|
||||||
|
"cylinder_id",
|
||||||
|
"tooling_type",
|
||||||
|
"status",
|
||||||
|
"identity_col",
|
||||||
|
"packaging_specification",
|
||||||
|
"item",
|
||||||
|
"customer",
|
||||||
|
"colour_station",
|
||||||
|
"colour_name",
|
||||||
|
"dimensions_section",
|
||||||
|
"circumference_mm",
|
||||||
|
"face_width_mm",
|
||||||
|
"dimensions_col",
|
||||||
|
"repeat_length_mm",
|
||||||
|
"engraving_reference",
|
||||||
|
"ownership_section",
|
||||||
|
"ownership",
|
||||||
|
"engraver",
|
||||||
|
"ownership_col",
|
||||||
|
"purchase_cost",
|
||||||
|
"customer_charge",
|
||||||
|
"condition_section",
|
||||||
|
"location",
|
||||||
|
"condition",
|
||||||
|
"last_used_on",
|
||||||
|
"last_used_work_order",
|
||||||
|
"condition_col",
|
||||||
|
"impression_count",
|
||||||
|
"impression_limit",
|
||||||
|
"retirement_reason",
|
||||||
|
"notes"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldname": "identity_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Identity"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "cylinder_id",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Cylinder / Plate ID",
|
||||||
|
"reqd": 1,
|
||||||
|
"unique": 1,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"description": "The number engraved or labelled on the cylinder, sleeve or plate."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "tooling_type",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"label": "Tooling Type",
|
||||||
|
"options": "Gravure Cylinder\nFlexo Plate\nFlexo Sleeve\nAnilox Roll\nCutting Die",
|
||||||
|
"reqd": 1,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "status",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"label": "Status",
|
||||||
|
"options": "Ordered\nIn Prepress\nReady\nIn Use\nUnder Repair\nRetired",
|
||||||
|
"default": "Ordered",
|
||||||
|
"reqd": 1,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "identity_col",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "packaging_specification",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Packaging Specification",
|
||||||
|
"options": "Packaging Specification",
|
||||||
|
"in_standard_filter": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "item",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Item",
|
||||||
|
"options": "Item",
|
||||||
|
"fetch_from": "packaging_specification.item",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "customer",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Customer",
|
||||||
|
"options": "Customer",
|
||||||
|
"fetch_from": "packaging_specification.customer",
|
||||||
|
"read_only": 1,
|
||||||
|
"in_standard_filter": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "colour_station",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"label": "Colour Station"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "colour_name",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Colour",
|
||||||
|
"in_list_view": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "dimensions_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Dimensions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "circumference_mm",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": "Circumference (mm)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "face_width_mm",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": "Face Width (mm)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "dimensions_col",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "repeat_length_mm",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": "Repeat Length (mm)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "engraving_reference",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Engraving / Screen Reference",
|
||||||
|
"description": "Screen ruling, cell depth or plate recipe reference."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "ownership_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Ownership and Cost"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "ownership",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"label": "Ownership",
|
||||||
|
"options": "Makap\nCustomer\nCharged to Customer",
|
||||||
|
"reqd": 1,
|
||||||
|
"default": "Makap"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "engraver",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Engraver / Supplier",
|
||||||
|
"options": "Supplier"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "ownership_col",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "purchase_cost",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Purchase Cost"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "customer_charge",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Charged to Customer",
|
||||||
|
"depends_on": "eval:doc.ownership=='Charged to Customer'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "condition_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Location and Condition"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "location",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Rack / Location",
|
||||||
|
"in_list_view": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "condition",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"label": "Condition",
|
||||||
|
"options": "New\nGood\nWorn\nNeeds Re-chrome\nDamaged",
|
||||||
|
"default": "New"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "last_used_on",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"label": "Last Used On"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "last_used_work_order",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Last Used On Work Order",
|
||||||
|
"options": "Work Order"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "condition_col",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "impression_count",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": "Impressions to Date",
|
||||||
|
"default": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "impression_limit",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": "Impression Limit",
|
||||||
|
"description": "Re-chrome or replace at this count. Leave empty if not tracked."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "retirement_reason",
|
||||||
|
"fieldtype": "Small Text",
|
||||||
|
"label": "Retirement Reason",
|
||||||
|
"depends_on": "eval:doc.status=='Retired'",
|
||||||
|
"mandatory_depends_on": "eval:doc.status=='Retired'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "notes",
|
||||||
|
"fieldtype": "Small Text",
|
||||||
|
"label": "Notes"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"links": [],
|
||||||
|
"modified": "2026-10-09 00:00:00",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "makap_backend",
|
||||||
|
"name": "Print Cylinder",
|
||||||
|
"naming_rule": "By fieldname",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"role": "System Manager",
|
||||||
|
"read": 1,
|
||||||
|
"write": 1,
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"print": 1,
|
||||||
|
"report": 1,
|
||||||
|
"export": 1,
|
||||||
|
"email": 1,
|
||||||
|
"share": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Manufacturing Manager",
|
||||||
|
"read": 1,
|
||||||
|
"write": 1,
|
||||||
|
"create": 1,
|
||||||
|
"delete": 0,
|
||||||
|
"print": 1,
|
||||||
|
"report": 1,
|
||||||
|
"export": 1,
|
||||||
|
"email": 1,
|
||||||
|
"share": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Technical Authority",
|
||||||
|
"read": 1,
|
||||||
|
"write": 1,
|
||||||
|
"create": 1,
|
||||||
|
"delete": 0,
|
||||||
|
"print": 1,
|
||||||
|
"report": 1,
|
||||||
|
"export": 1,
|
||||||
|
"email": 1,
|
||||||
|
"share": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Production Authority",
|
||||||
|
"read": 1,
|
||||||
|
"write": 1,
|
||||||
|
"create": 0,
|
||||||
|
"delete": 0,
|
||||||
|
"print": 1,
|
||||||
|
"report": 1,
|
||||||
|
"export": 1,
|
||||||
|
"email": 1,
|
||||||
|
"share": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Manufacturing User",
|
||||||
|
"read": 1,
|
||||||
|
"write": 0,
|
||||||
|
"create": 0,
|
||||||
|
"delete": 0,
|
||||||
|
"print": 1,
|
||||||
|
"report": 1,
|
||||||
|
"export": 0,
|
||||||
|
"email": 0,
|
||||||
|
"share": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Stock User",
|
||||||
|
"read": 1,
|
||||||
|
"write": 0,
|
||||||
|
"create": 0,
|
||||||
|
"delete": 0,
|
||||||
|
"print": 1,
|
||||||
|
"report": 1,
|
||||||
|
"export": 0,
|
||||||
|
"email": 0,
|
||||||
|
"share": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Sales User",
|
||||||
|
"read": 1,
|
||||||
|
"write": 0,
|
||||||
|
"create": 0,
|
||||||
|
"delete": 0,
|
||||||
|
"print": 1,
|
||||||
|
"report": 1,
|
||||||
|
"export": 0,
|
||||||
|
"email": 0,
|
||||||
|
"share": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"row_format": "Dynamic",
|
||||||
|
"search_fields": "colour_name,packaging_specification,customer",
|
||||||
|
"show_title_field_in_link": 0,
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
|
"title_field": "cylinder_id",
|
||||||
|
"track_changes": 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import frappe
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
UNFIT_CONDITIONS = {"Needs Re-chrome", "Damaged"}
|
||||||
|
|
||||||
|
|
||||||
|
class PrintCylinder(Document):
|
||||||
|
def validate(self):
|
||||||
|
# Work Order release reads "Ready" as fit to print, so a cylinder that
|
||||||
|
# isn't can't be marked Ready.
|
||||||
|
if self.status == "Ready" and self.condition in UNFIT_CONDITIONS:
|
||||||
|
frappe.throw(f"A cylinder in condition '{self.condition}' cannot be Ready. Send it for repair first.")
|
||||||
|
|
||||||
|
if self.impression_limit and (self.impression_count or 0) >= self.impression_limit:
|
||||||
|
frappe.msgprint(
|
||||||
|
f"{self.name} has reached its impression limit ({self.impression_limit:,.0f}). Plan a re-chrome or replacement.",
|
||||||
|
indicator="orange",
|
||||||
|
alert=True,
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user