mirror of
https://github.com/frappe/erpnext.git
synced 2026-04-17 13:55:10 +00:00
fix: Added validation for quality inspection in job card
(cherry picked from commit 46b4cf3add)
This commit is contained in:
@@ -23,6 +23,10 @@ from frappe.utils import (
|
|||||||
time_diff_in_hours,
|
time_diff_in_hours,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from erpnext.controllers.stock_controller import (
|
||||||
|
QualityInspectionNotSubmittedError,
|
||||||
|
QualityInspectionRejectedError,
|
||||||
|
)
|
||||||
from erpnext.manufacturing.doctype.bom.bom import add_additional_cost, get_bom_items_as_dict
|
from erpnext.manufacturing.doctype.bom.bom import add_additional_cost, get_bom_items_as_dict
|
||||||
from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import (
|
from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import (
|
||||||
get_mins_between_operations,
|
get_mins_between_operations,
|
||||||
@@ -751,6 +755,7 @@ class JobCard(Document):
|
|||||||
self.set_process_loss()
|
self.set_process_loss()
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
|
self.validate_inspection()
|
||||||
self.validate_transfer_qty()
|
self.validate_transfer_qty()
|
||||||
self.validate_job_card()
|
self.validate_job_card()
|
||||||
self.update_work_order()
|
self.update_work_order()
|
||||||
@@ -760,6 +765,66 @@ class JobCard(Document):
|
|||||||
self.update_work_order()
|
self.update_work_order()
|
||||||
self.set_transferred_qty()
|
self.set_transferred_qty()
|
||||||
|
|
||||||
|
def validate_inspection(self):
|
||||||
|
action_submit, action_reject = frappe.get_single_value(
|
||||||
|
"Stock Settings",
|
||||||
|
["action_if_quality_inspection_is_not_submitted", "action_if_quality_inspection_is_rejected"],
|
||||||
|
)
|
||||||
|
|
||||||
|
item = self.finished_good or self.production_item
|
||||||
|
bom_inspection_required = frappe.db.get_value(
|
||||||
|
"BOM", self.semi_fg_bom or self.bom_no, "inspection_required"
|
||||||
|
)
|
||||||
|
if bom_inspection_required:
|
||||||
|
if not self.quality_inspection:
|
||||||
|
frappe.throw(
|
||||||
|
_(
|
||||||
|
"Quality Inspection is required for the item {0} before completing the job card {1}"
|
||||||
|
).format(get_link_to_form("Item", item), bold(self.name))
|
||||||
|
)
|
||||||
|
qa_status, docstatus = frappe.db.get_value(
|
||||||
|
"Quality Inspection", self.quality_inspection, ["status", "docstatus"]
|
||||||
|
)
|
||||||
|
|
||||||
|
if docstatus != 1:
|
||||||
|
if action_submit == "Stop":
|
||||||
|
frappe.throw(
|
||||||
|
_("Quality Inspection {0} is not submitted for the item: {1}").format(
|
||||||
|
get_link_to_form("Quality Inspection", self.quality_inspection),
|
||||||
|
get_link_to_form("Item", item),
|
||||||
|
),
|
||||||
|
title=_("Inspection Submission"),
|
||||||
|
exc=QualityInspectionNotSubmittedError,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
frappe.msgprint(
|
||||||
|
_("Quality Inspection {0} is not submitted for the item: {1}").format(
|
||||||
|
get_link_to_form("Quality Inspection", self.quality_inspection),
|
||||||
|
get_link_to_form("Item", item),
|
||||||
|
),
|
||||||
|
alert=True,
|
||||||
|
indicator="orange",
|
||||||
|
)
|
||||||
|
elif qa_status == "Rejected":
|
||||||
|
if action_reject == "Stop":
|
||||||
|
frappe.throw(
|
||||||
|
_("Quality Inspection {0} is rejected for the item: {1}").format(
|
||||||
|
get_link_to_form("Quality Inspection", self.quality_inspection),
|
||||||
|
get_link_to_form("Item", item),
|
||||||
|
),
|
||||||
|
title=_("Inspection Rejected"),
|
||||||
|
exc=QualityInspectionRejectedError,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
frappe.msgprint(
|
||||||
|
_("Quality Inspection {0} is rejected for the item: {1}").format(
|
||||||
|
get_link_to_form("Quality Inspection", self.quality_inspection),
|
||||||
|
get_link_to_form("Item", item),
|
||||||
|
),
|
||||||
|
alert=True,
|
||||||
|
indicator="orange",
|
||||||
|
)
|
||||||
|
|
||||||
def validate_transfer_qty(self):
|
def validate_transfer_qty(self):
|
||||||
if (
|
if (
|
||||||
not self.finished_good
|
not self.finished_good
|
||||||
|
|||||||
@@ -20,8 +20,9 @@ from erpnext.manufacturing.doctype.job_card.job_card import (
|
|||||||
make_stock_entry as make_stock_entry_from_jc,
|
make_stock_entry as make_stock_entry_from_jc,
|
||||||
)
|
)
|
||||||
from erpnext.manufacturing.doctype.work_order.test_work_order import make_wo_order_test_record
|
from erpnext.manufacturing.doctype.work_order.test_work_order import make_wo_order_test_record
|
||||||
from erpnext.manufacturing.doctype.work_order.work_order import WorkOrder
|
from erpnext.manufacturing.doctype.work_order.work_order import WorkOrder, make_work_order
|
||||||
from erpnext.manufacturing.doctype.workstation.test_workstation import make_workstation
|
from erpnext.manufacturing.doctype.workstation.test_workstation import make_workstation
|
||||||
|
from erpnext.stock.doctype.item.test_item import create_item
|
||||||
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
|
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
|
||||||
from erpnext.tests.utils import ERPNextTestSuite
|
from erpnext.tests.utils import ERPNextTestSuite
|
||||||
|
|
||||||
@@ -73,6 +74,50 @@ class TestJobCard(ERPNextTestSuite):
|
|||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
frappe.db.rollback()
|
frappe.db.rollback()
|
||||||
|
|
||||||
|
def test_quality_inspection_mandatory_check(self):
|
||||||
|
from erpnext.manufacturing.doctype.operation.test_operation import make_operation
|
||||||
|
|
||||||
|
raw = create_item("Fabric-Raw")
|
||||||
|
cut_fg = create_item("Cut-Fabric-SFG")
|
||||||
|
stitch_fg = create_item("Stitched-TShirt-SFG")
|
||||||
|
final = create_item("Finished-TShirt")
|
||||||
|
|
||||||
|
row = {"operation": "Cutting", "workstation": "_Test Workstation 1"}
|
||||||
|
|
||||||
|
cutting = make_operation(row)
|
||||||
|
stitching = make_operation({"operation": "Stitching", "workstation": "_Test Workstation 1"})
|
||||||
|
ironing = make_operation({"operation": "Ironing", "workstation": "_Test Workstation 1"})
|
||||||
|
|
||||||
|
cut_bom = create_semi_fg_bom(cut_fg.name, raw.name, inspection_required=1)
|
||||||
|
stitch_bom = create_semi_fg_bom(stitch_fg.name, cut_fg.name, inspection_required=0)
|
||||||
|
final_bom = frappe.new_doc("BOM")
|
||||||
|
final_bom.item = final.name
|
||||||
|
final_bom.quantity = 1
|
||||||
|
final_bom.with_operations = 1
|
||||||
|
final_bom.track_semi_finished_goods = 1
|
||||||
|
final_bom.append("items", {"item_code": raw.name, "qty": 1})
|
||||||
|
final_bom.append(
|
||||||
|
"operations", {"operation": cutting.name, "workstation": "_Test Workstation 1", "bom_no": cut_bom}
|
||||||
|
)
|
||||||
|
final_bom.append(
|
||||||
|
"operations",
|
||||||
|
{"operation": stitching.name, "workstation": "_Test Workstation 1", "bom_no": stitch_bom},
|
||||||
|
)
|
||||||
|
final_bom.append("operations", {"operation": ironing.name, "workstation": "_Test Workstation 1"})
|
||||||
|
final_bom.insert()
|
||||||
|
final_bom.submit()
|
||||||
|
work_order = make_work_order(final_bom.name, final.name, 1, variant_items=[], use_multi_level_bom=0)
|
||||||
|
work_order.wip_warehouse = "Work In Progress - WP"
|
||||||
|
work_order.fg_warehouse = "Finished Goods - WP"
|
||||||
|
work_order.scrap_warehouse = "All Warehouses - WP"
|
||||||
|
for operation in work_order.operations:
|
||||||
|
operation.time_in_mins = 60
|
||||||
|
|
||||||
|
work_order.submit()
|
||||||
|
job_card = frappe.get_all("Job Card", filters={"work_order": work_order.name, "operation": "Cutting"})
|
||||||
|
job_card_doc = frappe.get_doc("Job Card", job_card[0].name)
|
||||||
|
self.assertRaises(frappe.ValidationError, job_card_doc.submit)
|
||||||
|
|
||||||
def test_job_card_operations(self):
|
def test_job_card_operations(self):
|
||||||
job_cards = frappe.get_all(
|
job_cards = frappe.get_all(
|
||||||
"Job Card", filters={"work_order": self.work_order.name}, fields=["operation_id", "name"]
|
"Job Card", filters={"work_order": self.work_order.name}, fields=["operation_id", "name"]
|
||||||
@@ -871,3 +916,13 @@ def make_wo_with_transfer_against_jc():
|
|||||||
work_order.submit()
|
work_order.submit()
|
||||||
|
|
||||||
return work_order
|
return work_order
|
||||||
|
|
||||||
|
|
||||||
|
def create_semi_fg_bom(semi_fg_item, raw_item, inspection_required):
|
||||||
|
bom = frappe.new_doc("BOM")
|
||||||
|
bom.item = semi_fg_item
|
||||||
|
bom.quantity = 1
|
||||||
|
bom.inspection_required = inspection_required
|
||||||
|
bom.append("items", {"item_code": raw_item, "qty": 1})
|
||||||
|
bom.submit()
|
||||||
|
return bom.name
|
||||||
|
|||||||
Reference in New Issue
Block a user