feat: Manufacturing : in BOM Operation time can be fix (#27063)
* feat: Operation time can be fixed * better coding without duplicate code * change modified date foir doctype * undo change * fix varmixing * fix varmixing * fix: remove f-string that's not required anymore * refactor: use ORM instead of raw query * fix: improve description * test: basic test for fixed time Co-authored-by: Ankush Menat <ankush@frappe.io>
This commit is contained in:
parent
66f516523f
commit
29f6852c13
@ -922,7 +922,7 @@ def validate_bom_no(item, bom_no):
|
|||||||
rm_item_exists = True
|
rm_item_exists = True
|
||||||
if bom.item.lower() == item.lower() or \
|
if bom.item.lower() == item.lower() or \
|
||||||
bom.item.lower() == cstr(frappe.db.get_value("Item", item, "variant_of")).lower():
|
bom.item.lower() == cstr(frappe.db.get_value("Item", item, "variant_of")).lower():
|
||||||
rm_item_exists = True
|
rm_item_exists = True
|
||||||
if not rm_item_exists:
|
if not rm_item_exists:
|
||||||
frappe.throw(_("BOM {0} does not belong to Item {1}").format(bom_no, item))
|
frappe.throw(_("BOM {0} does not belong to Item {1}").format(bom_no, item))
|
||||||
|
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
"col_break1",
|
"col_break1",
|
||||||
"workstation",
|
"workstation",
|
||||||
"time_in_mins",
|
"time_in_mins",
|
||||||
|
"fixed_time",
|
||||||
"costing_section",
|
"costing_section",
|
||||||
"hour_rate",
|
"hour_rate",
|
||||||
"base_hour_rate",
|
"base_hour_rate",
|
||||||
@ -79,6 +80,14 @@
|
|||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"description": "Operation time does not depend on quantity to produce",
|
||||||
|
"fieldname": "fixed_time",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Fixed Time"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "operating_cost",
|
"fieldname": "operating_cost",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
@ -177,12 +186,13 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-09-13 16:45:01.092868",
|
"modified": "2021-12-15 03:00:00.473173",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "BOM Operation",
|
"name": "BOM Operation",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC"
|
"sort_order": "DESC",
|
||||||
|
"states": []
|
||||||
}
|
}
|
||||||
@ -846,6 +846,45 @@ class TestWorkOrder(ERPNextTestCase):
|
|||||||
close_work_order(wo_order, "Closed")
|
close_work_order(wo_order, "Closed")
|
||||||
self.assertEqual(wo_order.get('status'), "Closed")
|
self.assertEqual(wo_order.get('status'), "Closed")
|
||||||
|
|
||||||
|
def test_fix_time_operations(self):
|
||||||
|
bom = frappe.get_doc({
|
||||||
|
"doctype": "BOM",
|
||||||
|
"item": "_Test FG Item 2",
|
||||||
|
"is_active": 1,
|
||||||
|
"is_default": 1,
|
||||||
|
"quantity": 1.0,
|
||||||
|
"with_operations": 1,
|
||||||
|
"operations": [
|
||||||
|
{
|
||||||
|
"operation": "_Test Operation 1",
|
||||||
|
"description": "_Test",
|
||||||
|
"workstation": "_Test Workstation 1",
|
||||||
|
"time_in_mins": 60,
|
||||||
|
"operating_cost": 140,
|
||||||
|
"fixed_time": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"amount": 5000.0,
|
||||||
|
"doctype": "BOM Item",
|
||||||
|
"item_code": "_Test Item",
|
||||||
|
"parentfield": "items",
|
||||||
|
"qty": 1.0,
|
||||||
|
"rate": 5000.0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
bom.save()
|
||||||
|
bom.submit()
|
||||||
|
|
||||||
|
|
||||||
|
wo1 = make_wo_order_test_record(item=bom.item, bom_no=bom.name, qty=1, skip_transfer=1, do_not_submit=1)
|
||||||
|
wo2 = make_wo_order_test_record(item=bom.item, bom_no=bom.name, qty=2, skip_transfer=1, do_not_submit=1)
|
||||||
|
|
||||||
|
self.assertEqual(wo1.operations[0].time_in_mins, wo2.operations[0].time_in_mins)
|
||||||
|
|
||||||
|
|
||||||
def update_job_card(job_card):
|
def update_job_card(job_card):
|
||||||
job_card_doc = frappe.get_doc('Job Card', job_card)
|
job_card_doc = frappe.get_doc('Job Card', job_card)
|
||||||
job_card_doc.set('scrap_items', [
|
job_card_doc.set('scrap_items', [
|
||||||
|
|||||||
@ -505,16 +505,19 @@ class WorkOrder(Document):
|
|||||||
"""Fetch operations from BOM and set in 'Work Order'"""
|
"""Fetch operations from BOM and set in 'Work Order'"""
|
||||||
|
|
||||||
def _get_operations(bom_no, qty=1):
|
def _get_operations(bom_no, qty=1):
|
||||||
return frappe.db.sql(
|
data = frappe.get_all("BOM Operation",
|
||||||
f"""select
|
filters={"parent": bom_no},
|
||||||
operation, description, workstation, idx,
|
fields=["operation", "description", "workstation", "idx",
|
||||||
base_hour_rate as hour_rate, time_in_mins * {qty} as time_in_mins,
|
"base_hour_rate as hour_rate", "time_in_mins", "parent as bom",
|
||||||
"Pending" as status, parent as bom, batch_size, sequence_id
|
"batch_size", "sequence_id", "fixed_time"],
|
||||||
from
|
order_by="idx")
|
||||||
`tabBOM Operation`
|
|
||||||
where
|
for d in data:
|
||||||
parent = %s order by idx
|
if not d.fixed_time:
|
||||||
""", bom_no, as_dict=1)
|
d.time_in_mins = flt(d.time_in_mins) * flt(qty)
|
||||||
|
d.status = "Pending"
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
self.set('operations', [])
|
self.set('operations', [])
|
||||||
@ -542,7 +545,8 @@ class WorkOrder(Document):
|
|||||||
|
|
||||||
def calculate_time(self):
|
def calculate_time(self):
|
||||||
for d in self.get("operations"):
|
for d in self.get("operations"):
|
||||||
d.time_in_mins = flt(d.time_in_mins) * (flt(self.qty) / flt(d.batch_size))
|
if not d.fixed_time:
|
||||||
|
d.time_in_mins = flt(d.time_in_mins) * (flt(self.qty) / flt(d.batch_size))
|
||||||
|
|
||||||
self.calculate_operating_cost()
|
self.calculate_operating_cost()
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user