fix: skip job card
This commit is contained in:
parent
6e81489095
commit
fcab53b238
@ -11,6 +11,7 @@
|
||||
"workstation",
|
||||
"description",
|
||||
"col_break1",
|
||||
"skip_job_card",
|
||||
"hour_rate",
|
||||
"time_in_mins",
|
||||
"operating_cost",
|
||||
@ -117,13 +118,20 @@
|
||||
"fieldname": "sequence_id",
|
||||
"fieldtype": "Int",
|
||||
"label": "Sequence ID"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"default": "0",
|
||||
"fieldname": "skip_job_card",
|
||||
"fieldtype": "Check",
|
||||
"label": "Skip Job Card"
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-12-14 15:01:33.142869",
|
||||
"modified": "2021-01-05 14:29:11.887888",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "BOM Operation",
|
||||
|
@ -242,13 +242,15 @@ frappe.ui.form.on("Work Order", {
|
||||
if(data.completed_qty != frm.doc.qty) {
|
||||
pending_qty = frm.doc.qty - flt(data.completed_qty);
|
||||
|
||||
dialog.fields_dict.operations.df.data.push({
|
||||
'name': data.name,
|
||||
'operation': data.operation,
|
||||
'workstation': data.workstation,
|
||||
'qty': pending_qty,
|
||||
'pending_qty': pending_qty,
|
||||
});
|
||||
if (pending_qty && !data.skip_job_card) {
|
||||
dialog.fields_dict.operations.df.data.push({
|
||||
'name': data.name,
|
||||
'operation': data.operation,
|
||||
'workstation': data.workstation,
|
||||
'qty': pending_qty,
|
||||
'pending_qty': pending_qty,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
dialog.fields_dict.operations.grid.refresh();
|
||||
|
@ -27,7 +27,6 @@
|
||||
"column_break_17",
|
||||
"serial_no",
|
||||
"batch_size",
|
||||
"batches",
|
||||
"settings_section",
|
||||
"allow_alternative_item",
|
||||
"use_multi_level_bom",
|
||||
@ -535,14 +534,6 @@
|
||||
"fieldname": "batch_size",
|
||||
"fieldtype": "Float",
|
||||
"label": "Batch Size"
|
||||
},
|
||||
{
|
||||
"depends_on": "has_batch_no",
|
||||
"fieldname": "batches",
|
||||
"fieldtype": "Table",
|
||||
"label": "Batches",
|
||||
"options": "Work Order Batch",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-cogs",
|
||||
|
@ -27,6 +27,7 @@ class CapacityError(frappe.ValidationError): pass
|
||||
class StockOverProductionError(frappe.ValidationError): pass
|
||||
class OperationTooLongError(frappe.ValidationError): pass
|
||||
class ItemHasVariantError(frappe.ValidationError): pass
|
||||
class SerialNoQtyError(frappe.ValidationError): pass
|
||||
|
||||
from six import string_types
|
||||
|
||||
@ -42,7 +43,6 @@ class WorkOrder(Document):
|
||||
self.set_onload("overproduction_percentage", ms.overproduction_percentage_for_work_order)
|
||||
|
||||
def validate(self):
|
||||
self.set("batches", [])
|
||||
self.validate_production_item()
|
||||
if self.bom_no:
|
||||
validate_bom_no(self.production_item, self.bom_no)
|
||||
@ -281,10 +281,12 @@ class WorkOrder(Document):
|
||||
"make_serial_no_batch_from_work_order")): return
|
||||
|
||||
if self.has_batch_no:
|
||||
self.set("batches", [])
|
||||
self.create_batch_for_finished_good()
|
||||
|
||||
args = {"item_code": self.production_item}
|
||||
args = {
|
||||
"item_code": self.production_item,
|
||||
"work_order": self.name
|
||||
}
|
||||
|
||||
if self.has_serial_no:
|
||||
self.make_serial_nos(args)
|
||||
@ -305,29 +307,29 @@ class WorkOrder(Document):
|
||||
qty = total_qty
|
||||
total_qty = 0
|
||||
|
||||
batch = make_batch(self.production_item)
|
||||
self.append("batches", {
|
||||
"batch_no": batch,
|
||||
"qty": qty,
|
||||
})
|
||||
make_batch(frappe._dict({
|
||||
"item": self.production_item,
|
||||
"qty_to_produce": qty,
|
||||
"reference_doctype": self.doctype,
|
||||
"reference_name": self.name
|
||||
}))
|
||||
|
||||
def delete_auto_created_batch_and_serial_no(self):
|
||||
if self.serial_no:
|
||||
for d in get_serial_nos(self.serial_no):
|
||||
frappe.delete_doc("Serial No", d)
|
||||
for row in frappe.get_all("Serial No", filters = {"work_order": self.name}):
|
||||
frappe.delete_doc("Serial No", row.name)
|
||||
self.db_set("serial_no", "")
|
||||
|
||||
for row in self.batches:
|
||||
batch_no = row.batch_no
|
||||
row.db_set("batch_no", None)
|
||||
frappe.delete_doc("Batch", batch_no)
|
||||
for row in frappe.get_all("Batch", filters = {"reference_name": self.name}):
|
||||
frappe.delete_doc("Batch", row.name)
|
||||
|
||||
def make_serial_nos(self, args):
|
||||
serial_no_series = frappe.get_cached_value("Item", self.production_item, "serial_no_series")
|
||||
if serial_no_series:
|
||||
self.serial_no = get_auto_serial_nos(serial_no_series, self.qty)
|
||||
elif self.serial_no:
|
||||
args.update({"serial_no": self.serial_no, "actual_qty": self.qty, "batch_no": self.batch_no})
|
||||
self.serial_no = auto_make_serial_nos(args)
|
||||
|
||||
if self.serial_no:
|
||||
args.update({"serial_no": self.serial_no, "actual_qty": self.qty})
|
||||
auto_make_serial_nos(args)
|
||||
|
||||
serial_nos_length = len(get_serial_nos(self.serial_no))
|
||||
if serial_nos_length != self.qty:
|
||||
@ -341,6 +343,7 @@ class WorkOrder(Document):
|
||||
plan_days = cint(manufacturing_settings_doc.capacity_planning_for_days) or 30
|
||||
|
||||
for index, row in enumerate(self.operations):
|
||||
if row.skip_job_card: continue
|
||||
qty = self.qty
|
||||
i=0
|
||||
while qty > 0:
|
||||
@ -493,7 +496,7 @@ class WorkOrder(Document):
|
||||
select
|
||||
operation, description, workstation, idx,
|
||||
base_hour_rate as hour_rate, time_in_mins,
|
||||
"Pending" as status, parent as bom, batch_size, sequence_id
|
||||
"Pending" as status, parent as bom, batch_size, sequence_id, skip_job_card
|
||||
from
|
||||
`tabBOM Operation`
|
||||
where
|
||||
@ -755,14 +758,16 @@ class WorkOrder(Document):
|
||||
bom.set_bom_material_details()
|
||||
return bom
|
||||
|
||||
def update_batch_qty(self):
|
||||
if self.has_batch_no and self.batches:
|
||||
for row in self.batches:
|
||||
qty = frappe.get_all("Stock Entry Detail", fields = ["sum(transfer_qty)"],
|
||||
filters = {"docstatus": 1, "batch_no": row.batch_no, "is_finished_item": 1}, as_list=1)
|
||||
def update_batch_produced_qty(self, stock_entry_doc):
|
||||
if not cint(frappe.db.get_single_value("Manufacturing Settings",
|
||||
"make_serial_no_batch_from_work_order")): return
|
||||
|
||||
if qty:
|
||||
frappe.db.set_value("Work Order Batch", row.name, "produced_qty", flt(qty[0][0]))
|
||||
for row in stock_entry_doc.items:
|
||||
if row.batch_no and (row.is_finished_item or row.is_scrap_item):
|
||||
qty = frappe.get_all("Stock Entry Detail", filters = {"batch_no": row.batch_no},
|
||||
or_conditions= {"is_finished_item": 1, "is_scrap_item": 1}, fields = ["sum(qty)"])[0][0]
|
||||
|
||||
frappe.db.set_value("Batch", row.batch_no, "produced_qty", qty)
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
|
@ -4,10 +4,17 @@ from frappe import _
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'work_order',
|
||||
'non_standard_fieldnames': {
|
||||
'Batch': 'reference_name'
|
||||
},
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Transactions'),
|
||||
'items': ['Stock Entry', 'Job Card', 'Pick List']
|
||||
},
|
||||
{
|
||||
'label': _('Reference'),
|
||||
'items': ['Serial No', 'Batch']
|
||||
}
|
||||
]
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2021-01-04 16:42:39.347528",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"batch_no",
|
||||
"qty",
|
||||
"produced_qty"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "batch_no",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Batch No",
|
||||
"options": "Batch"
|
||||
},
|
||||
{
|
||||
"fieldname": "qty",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Qty",
|
||||
"non_negative": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "produced_qty",
|
||||
"fieldtype": "Float",
|
||||
"label": "Produced Qty",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-01-05 10:57:07.278399",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Work Order Batch",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class WorkOrderBatch(Document):
|
||||
pass
|
@ -8,8 +8,10 @@
|
||||
"details",
|
||||
"operation",
|
||||
"bom",
|
||||
"sequence_id",
|
||||
"column_break_4",
|
||||
"skip_job_card",
|
||||
"description",
|
||||
"sequence_id",
|
||||
"col_break1",
|
||||
"completed_qty",
|
||||
"status",
|
||||
@ -195,12 +197,23 @@
|
||||
"label": "Sequence ID",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"default": "0",
|
||||
"fieldname": "skip_job_card",
|
||||
"fieldtype": "Check",
|
||||
"label": "Skip Job Card"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-10-14 12:58:49.241252",
|
||||
"modified": "2021-01-08 17:42:05.372163",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Work Order Operation",
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"actions": [],
|
||||
"allow_import": 1,
|
||||
"autoname": "field:batch_id",
|
||||
"creation": "2013-03-05 14:50:38",
|
||||
@ -25,7 +26,11 @@
|
||||
"reference_doctype",
|
||||
"reference_name",
|
||||
"section_break_7",
|
||||
"description"
|
||||
"description",
|
||||
"manufacturing_section",
|
||||
"qty_to_produce",
|
||||
"column_break_23",
|
||||
"produced_qty"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@ -160,13 +165,35 @@
|
||||
"label": "Batch UOM",
|
||||
"options": "UOM",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "manufacturing_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Manufacturing"
|
||||
},
|
||||
{
|
||||
"fieldname": "qty_to_produce",
|
||||
"fieldtype": "Float",
|
||||
"label": "Qty To Produce",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_23",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "produced_qty",
|
||||
"fieldtype": "Float",
|
||||
"label": "Produced Qty",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-archive",
|
||||
"idx": 1,
|
||||
"image_field": "image",
|
||||
"links": [],
|
||||
"max_attachments": 5,
|
||||
"modified": "2020-09-18 17:26:09.703215",
|
||||
"modified": "2021-01-07 11:10:09.149170",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Batch",
|
||||
|
@ -310,9 +310,7 @@ def validate_serial_no_with_batch(serial_nos, item_code):
|
||||
frappe.throw(_("There is no batch found against the {0}: {1}")
|
||||
.format(message, serial_no_link))
|
||||
|
||||
def make_batch(item_code):
|
||||
if frappe.db.get_value("Item", item_code, "has_batch_no"):
|
||||
doc = frappe.new_doc("Batch")
|
||||
doc.item = item_code
|
||||
doc.save()
|
||||
return doc.name
|
||||
def make_batch(args):
|
||||
if frappe.db.get_value("Item", args.item, "has_batch_no"):
|
||||
args.doctype = "Batch"
|
||||
frappe.get_doc(args).insert().name
|
@ -57,7 +57,8 @@
|
||||
"more_info",
|
||||
"serial_no_details",
|
||||
"company",
|
||||
"status"
|
||||
"status",
|
||||
"work_order"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@ -422,12 +423,18 @@
|
||||
"label": "Status",
|
||||
"options": "\nActive\nInactive\nDelivered\nExpired",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "work_order",
|
||||
"fieldtype": "Link",
|
||||
"label": "Work Order",
|
||||
"options": "Work Order"
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-barcode",
|
||||
"idx": 1,
|
||||
"links": [],
|
||||
"modified": "2020-07-20 20:50:16.660433",
|
||||
"modified": "2021-01-08 14:31:15.375996",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Serial No",
|
||||
|
@ -473,16 +473,13 @@ def get_serial_nos(serial_no):
|
||||
if s.strip()]
|
||||
|
||||
def update_args_for_serial_no(serial_no_doc, serial_no, args, is_new=False):
|
||||
serial_no_doc.update({
|
||||
"item_code": args.get("item_code"),
|
||||
"company": args.get("company"),
|
||||
"batch_no": args.get("batch_no"),
|
||||
"via_stock_ledger": args.get("via_stock_ledger") or True,
|
||||
"supplier": args.get("supplier"),
|
||||
"location": args.get("location"),
|
||||
"warehouse": (args.get("warehouse")
|
||||
if args.get("actual_qty", 0) > 0 else None)
|
||||
})
|
||||
for field in ["item_code", "work_order", "company", "batch_no", "supplier", "location"]:
|
||||
if args.get(field):
|
||||
serial_no_doc.set(field, args.get(field))
|
||||
|
||||
serial_no_doc.via_stock_ledger = args.get("via_stock_ledger") or True
|
||||
serial_no_doc.warehouse = (args.get("warehouse")
|
||||
if args.get("actual_qty", 0) > 0 else None)
|
||||
|
||||
if is_new:
|
||||
serial_no_doc.serial_no = serial_no
|
||||
|
@ -855,7 +855,7 @@ class StockEntry(StockController):
|
||||
pro_doc.run_method("update_work_order_qty")
|
||||
if self.purpose == "Manufacture":
|
||||
pro_doc.run_method("update_planned_qty")
|
||||
pro_doc.update_batch_qty()
|
||||
pro_doc.update_batch_produced_qty(self)
|
||||
|
||||
if not pro_doc.operations:
|
||||
pro_doc.set_actual_dates()
|
||||
@ -1090,14 +1090,21 @@ class StockEntry(StockController):
|
||||
"is_finished_item": 1
|
||||
}
|
||||
|
||||
if self.work_order and self.pro_doc.batches:
|
||||
if self.work_order and self.pro_doc.has_batch_no:
|
||||
self.set_batchwise_finished_goods(args, item)
|
||||
else:
|
||||
self.add_finisged_goods(args, item)
|
||||
|
||||
def set_batchwise_finished_goods(self, args, item):
|
||||
qty = flt(self.fg_completed_qty)
|
||||
for row in self.pro_doc.batches:
|
||||
filters = {"reference_name": self.pro_doc.name,
|
||||
"reference_doctype": self.pro_doc.doctype,
|
||||
"qty_to_produce": (">", 0)
|
||||
}
|
||||
|
||||
fields = ["qty_to_produce as qty", "produced_qty", "name"]
|
||||
|
||||
for row in frappe.get_all("Batch", filters = filters, fields = fields):
|
||||
batch_qty = flt(row.qty) - flt(row.produced_qty)
|
||||
if not batch_qty: continue
|
||||
|
||||
@ -1110,7 +1117,7 @@ class StockEntry(StockController):
|
||||
|
||||
qty -= batch_qty
|
||||
args["qty"] = fg_qty
|
||||
args["batch_no"] = row.batch_no
|
||||
args["batch_no"] = row.name
|
||||
|
||||
self.add_finisged_goods(args, item)
|
||||
|
||||
@ -1555,7 +1562,7 @@ class StockEntry(StockController):
|
||||
|
||||
def set_serial_no_batch_for_finished_good(self):
|
||||
args = {}
|
||||
if self.pro_doc.serial_no or self.pro_doc.batch_no:
|
||||
if self.pro_doc.serial_no:
|
||||
self.get_serial_nos_for_fg(args)
|
||||
|
||||
for row in self.items:
|
||||
|
Loading…
x
Reference in New Issue
Block a user