is corrective job card
This commit is contained in:
parent
c878389050
commit
57307443f0
@ -11,7 +11,6 @@
|
|||||||
"workstation",
|
"workstation",
|
||||||
"description",
|
"description",
|
||||||
"col_break1",
|
"col_break1",
|
||||||
"skip_job_card",
|
|
||||||
"hour_rate",
|
"hour_rate",
|
||||||
"time_in_mins",
|
"time_in_mins",
|
||||||
"operating_cost",
|
"operating_cost",
|
||||||
@ -118,20 +117,13 @@
|
|||||||
"fieldname": "sequence_id",
|
"fieldname": "sequence_id",
|
||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"label": "Sequence ID"
|
"label": "Sequence ID"
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 1,
|
|
||||||
"default": "0",
|
|
||||||
"fieldname": "skip_job_card",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"label": "Skip Job Card"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-01-05 14:29:11.887888",
|
"modified": "2021-01-12 14:48:09.596843",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "BOM Operation",
|
"name": "BOM Operation",
|
||||||
|
|||||||
@ -41,6 +41,10 @@ frappe.ui.form.on('Job Card', {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (frm.doc.docstatus == 1 && !frm.doc.is_corrective_job_card) {
|
||||||
|
frm.trigger('setup_corrective_job_card')
|
||||||
|
}
|
||||||
|
|
||||||
frm.set_query("quality_inspection", function() {
|
frm.set_query("quality_inspection", function() {
|
||||||
return {
|
return {
|
||||||
query: "erpnext.stock.doctype.quality_inspection.quality_inspection.quality_inspection_query",
|
query: "erpnext.stock.doctype.quality_inspection.quality_inspection.quality_inspection_query",
|
||||||
@ -53,12 +57,50 @@ frappe.ui.form.on('Job Card', {
|
|||||||
|
|
||||||
frm.trigger("toggle_operation_number");
|
frm.trigger("toggle_operation_number");
|
||||||
|
|
||||||
if (frm.doc.docstatus == 0 && (frm.doc.for_quantity > frm.doc.total_completed_qty || !frm.doc.for_quantity)
|
if (frm.doc.docstatus == 0 && !frm.is_new() &&
|
||||||
|
(frm.doc.for_quantity > frm.doc.total_completed_qty || !frm.doc.for_quantity)
|
||||||
&& (frm.doc.items || !frm.doc.items.length || frm.doc.for_quantity == frm.doc.transferred_qty)) {
|
&& (frm.doc.items || !frm.doc.items.length || frm.doc.for_quantity == frm.doc.transferred_qty)) {
|
||||||
frm.trigger("prepare_timer_buttons");
|
frm.trigger("prepare_timer_buttons");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setup_corrective_job_card: function(frm) {
|
||||||
|
frm.add_custom_button(__('Corrective Job Card'), () => {
|
||||||
|
let operations = frm.doc.sub_operations.map(d => d.sub_operation).concat(frm.doc.operation);
|
||||||
|
|
||||||
|
let fields = [
|
||||||
|
{
|
||||||
|
fieldtype: 'Link', label: __('Corrective Operation'), options: 'Operation',
|
||||||
|
fieldname: 'operation', get_query() { return { filters: { "is_corrective_operation": 1 }}}
|
||||||
|
}, {
|
||||||
|
fieldtype: 'Link', label: __('For Operation'), options: 'Operation',
|
||||||
|
fieldname: 'for_operation', get_query() { return { filters: { "name": ["in", operations] }}}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
frappe.prompt(fields, d => {
|
||||||
|
frm.events.make_corrective_job_card(frm, d.operation, d.for_operation);
|
||||||
|
}, __("Select Corrective Operation"));
|
||||||
|
}, __('Make'));
|
||||||
|
},
|
||||||
|
|
||||||
|
make_corrective_job_card: function(frm, operation, for_operation) {
|
||||||
|
frappe.call({
|
||||||
|
method: 'erpnext.manufacturing.doctype.job_card.job_card.make_corrective_job_card',
|
||||||
|
args: {
|
||||||
|
source_name: frm.doc.name,
|
||||||
|
operation: operation,
|
||||||
|
for_operation: for_operation
|
||||||
|
},
|
||||||
|
callback: function(r) {
|
||||||
|
if (r.message) {
|
||||||
|
frappe.model.sync(r.message);
|
||||||
|
frappe.set_route("Form", r.message.doctype, r.message.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
operation: function(frm) {
|
operation: function(frm) {
|
||||||
frm.trigger("toggle_operation_number");
|
frm.trigger("toggle_operation_number");
|
||||||
|
|
||||||
@ -110,10 +152,9 @@ frappe.ui.form.on('Job Card', {
|
|||||||
|
|
||||||
if (!frm.doc.started_time && !frm.doc.current_time) {
|
if (!frm.doc.started_time && !frm.doc.current_time) {
|
||||||
frm.add_custom_button(__("Start Job"), () => {
|
frm.add_custom_button(__("Start Job"), () => {
|
||||||
frappe.prompt({fieldtype: 'Table MultiSelect', label: __('Employee'), options: "Job Card Time Log",
|
frappe.prompt({fieldtype: 'Table MultiSelect', label: __('Select Employees'),
|
||||||
fieldname: 'employee'}, d => {
|
options: "Job Card Time Log", fieldname: 'employees'}, d => {
|
||||||
debugger
|
frm.events.start_job(frm, "Work In Progress", d.employees);
|
||||||
frm.events.start_job(frm, "Work In Progress", d.employee);
|
|
||||||
}, __("Assign Job to Employee"));
|
}, __("Assign Job to Employee"));
|
||||||
}).addClass("btn-primary");
|
}).addClass("btn-primary");
|
||||||
} else if (frm.doc.status == "On Hold") {
|
} else if (frm.doc.status == "On Hold") {
|
||||||
@ -138,7 +179,7 @@ frappe.ui.form.on('Job Card', {
|
|||||||
const args = {
|
const args = {
|
||||||
job_card_id: frm.doc.name,
|
job_card_id: frm.doc.name,
|
||||||
start_time: frappe.datetime.now_datetime(),
|
start_time: frappe.datetime.now_datetime(),
|
||||||
employee: employee,
|
employees: employee,
|
||||||
status: status
|
status: status
|
||||||
};
|
};
|
||||||
frm.events.make_time_log(frm, args);
|
frm.events.make_time_log(frm, args);
|
||||||
|
|||||||
@ -33,9 +33,14 @@
|
|||||||
"total_completed_qty",
|
"total_completed_qty",
|
||||||
"column_break_15",
|
"column_break_15",
|
||||||
"total_time_in_mins",
|
"total_time_in_mins",
|
||||||
"hour_rate",
|
|
||||||
"section_break_8",
|
"section_break_8",
|
||||||
"items",
|
"items",
|
||||||
|
"corrective_operation_section",
|
||||||
|
"for_job_card",
|
||||||
|
"is_corrective_job_card",
|
||||||
|
"column_break_33",
|
||||||
|
"hour_rate",
|
||||||
|
"for_operation",
|
||||||
"more_information",
|
"more_information",
|
||||||
"operation_id",
|
"operation_id",
|
||||||
"sequence_id",
|
"sequence_id",
|
||||||
@ -331,14 +336,48 @@
|
|||||||
"hide_border": 1
|
"hide_border": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"depends_on": "is_corrective_job_card",
|
||||||
"fieldname": "hour_rate",
|
"fieldname": "hour_rate",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Hour Rate"
|
"label": "Hour Rate"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsible": 1,
|
||||||
|
"depends_on": "is_corrective_job_card",
|
||||||
|
"fieldname": "corrective_operation_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Corrective Operation"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "is_corrective_job_card",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Is Corrective Job Card",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_33",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "for_job_card",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "For Job Card",
|
||||||
|
"options": "Job Card",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "for_job_card.operation",
|
||||||
|
"fetch_if_empty": 1,
|
||||||
|
"fieldname": "for_operation",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "For Operation",
|
||||||
|
"options": "Operation"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-01-11 12:09:00.452032",
|
"modified": "2021-02-03 20:36:51.826944",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Job Card",
|
"name": "Job Card",
|
||||||
|
|||||||
@ -178,18 +178,27 @@ class JobCard(Document):
|
|||||||
|
|
||||||
self.reset_timer_value(args)
|
self.reset_timer_value(args)
|
||||||
if last_row and args.get("complete_time"):
|
if last_row and args.get("complete_time"):
|
||||||
last_row.update({
|
for row in self.time_logs:
|
||||||
"to_time": get_datetime(args.get("complete_time")),
|
if not row.to_time:
|
||||||
"operation": args.get("sub_operation"),
|
row.update({
|
||||||
"completed_qty": args.get("completed_qty") or 0.0
|
"to_time": get_datetime(args.get("complete_time")),
|
||||||
})
|
"operation": args.get("sub_operation"),
|
||||||
|
"completed_qty": args.get("completed_qty") or 0.0
|
||||||
|
})
|
||||||
elif args.get("start_time"):
|
elif args.get("start_time"):
|
||||||
self.append("time_logs", {
|
employees = args.employees
|
||||||
"from_time": get_datetime(args.get("start_time")),
|
print(args)
|
||||||
"employee": args.get("employee"),
|
if isinstance(employees, string_types):
|
||||||
"operation": args.get("sub_operation"),
|
employees = json.loads(employees)
|
||||||
"completed_qty": 0.0
|
|
||||||
})
|
for name in employees:
|
||||||
|
print(name.get('employee'))
|
||||||
|
self.append("time_logs", {
|
||||||
|
"from_time": get_datetime(args.get("start_time")),
|
||||||
|
"employee": name.get('employee'),
|
||||||
|
"operation": args.get("sub_operation"),
|
||||||
|
"completed_qty": 0.0
|
||||||
|
})
|
||||||
|
|
||||||
if self.status == "On Hold":
|
if self.status == "On Hold":
|
||||||
self.current_time = time_diff_in_seconds(last_row.to_time, last_row.from_time)
|
self.current_time = time_diff_in_seconds(last_row.to_time, last_row.from_time)
|
||||||
@ -300,10 +309,24 @@ class JobCard(Document):
|
|||||||
time_in_mins = flt(data[0].time_in_mins)
|
time_in_mins = flt(data[0].time_in_mins)
|
||||||
|
|
||||||
wo = frappe.get_doc('Work Order', self.work_order)
|
wo = frappe.get_doc('Work Order', self.work_order)
|
||||||
if self.operation_id:
|
|
||||||
|
if self.is_corrective_job_card:
|
||||||
|
self.update_corrective_in_work_order(wo)
|
||||||
|
|
||||||
|
elif self.operation_id:
|
||||||
self.validate_produced_quantity(for_quantity, wo)
|
self.validate_produced_quantity(for_quantity, wo)
|
||||||
self.update_work_order_data(for_quantity, time_in_mins, wo)
|
self.update_work_order_data(for_quantity, time_in_mins, wo)
|
||||||
|
|
||||||
|
def update_corrective_in_work_order(self, wo):
|
||||||
|
wo.corrective_operation_cost = 0.0
|
||||||
|
for row in frappe.get_all('Job Card', fields = ['total_time_in_mins', 'hour_rate'],
|
||||||
|
filters = {'is_corrective_job_card': 1, 'docstatus': 1, 'work_order': self.work_order}):
|
||||||
|
wo.corrective_operation_cost += flt(row.total_time_in_mins) * flt(row.hour_rate)
|
||||||
|
|
||||||
|
wo.calculate_operating_cost()
|
||||||
|
wo.flags.ignore_validate_update_after_submit = True
|
||||||
|
wo.save()
|
||||||
|
|
||||||
def validate_produced_quantity(self, for_quantity, wo):
|
def validate_produced_quantity(self, for_quantity, wo):
|
||||||
if self.docstatus < 2: return
|
if self.docstatus < 2: return
|
||||||
|
|
||||||
@ -346,7 +369,8 @@ class JobCard(Document):
|
|||||||
def get_current_operation_data(self):
|
def get_current_operation_data(self):
|
||||||
return frappe.get_all('Job Card',
|
return frappe.get_all('Job Card',
|
||||||
fields = ["sum(total_time_in_mins) as time_in_mins", "sum(total_completed_qty) as completed_qty"],
|
fields = ["sum(total_time_in_mins) as time_in_mins", "sum(total_completed_qty) as completed_qty"],
|
||||||
filters = {"docstatus": 1, "work_order": self.work_order, "operation_id": self.operation_id})
|
filters = {"docstatus": 1, "work_order": self.work_order, "operation_id": self.operation_id,
|
||||||
|
"is_corrective_job_card": 0})
|
||||||
|
|
||||||
def set_transferred_qty_in_job_card(self, ste_doc):
|
def set_transferred_qty_in_job_card(self, ste_doc):
|
||||||
for row in ste_doc.items:
|
for row in ste_doc.items:
|
||||||
@ -429,6 +453,8 @@ class JobCard(Document):
|
|||||||
.format(bold(self.operation), work_order), OperationMismatchError)
|
.format(bold(self.operation), work_order), OperationMismatchError)
|
||||||
|
|
||||||
def validate_sequence_id(self):
|
def validate_sequence_id(self):
|
||||||
|
if self.is_corrective_job_card: return
|
||||||
|
|
||||||
if not (self.work_order and self.sequence_id): return
|
if not (self.work_order and self.sequence_id): return
|
||||||
|
|
||||||
current_operation_qty = 0.0
|
current_operation_qty = 0.0
|
||||||
@ -440,8 +466,7 @@ class JobCard(Document):
|
|||||||
|
|
||||||
data = frappe.get_all("Work Order Operation",
|
data = frappe.get_all("Work Order Operation",
|
||||||
fields = ["operation", "status", "completed_qty"],
|
fields = ["operation", "status", "completed_qty"],
|
||||||
filters={"docstatus": 1, "parent": self.work_order, "sequence_id": ('<', self.sequence_id),
|
filters={"docstatus": 1, "parent": self.work_order, "sequence_id": ('<', self.sequence_id)},
|
||||||
"skip_job_card": 0},
|
|
||||||
order_by = "sequence_id, idx")
|
order_by = "sequence_id, idx")
|
||||||
|
|
||||||
message = "Job Card {0}: As per the sequence of the operations in the work order {1}".format(bold(self.name),
|
message = "Job Card {0}: As per the sequence of the operations in the work order {1}".format(bold(self.name),
|
||||||
@ -598,3 +623,26 @@ def get_job_details(start, end, filters=None):
|
|||||||
events.append(job_card_data)
|
events.append(job_card_data)
|
||||||
|
|
||||||
return events
|
return events
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def make_corrective_job_card(source_name, operation=None, for_operation=None, target_doc=None):
|
||||||
|
def set_missing_values(source, target):
|
||||||
|
target.is_corrective_job_card = 1
|
||||||
|
target.operation = operation
|
||||||
|
target.for_operation = for_operation
|
||||||
|
|
||||||
|
target.set('time_logs', [])
|
||||||
|
target.get_sub_operations()
|
||||||
|
target.get_required_items()
|
||||||
|
target.validate_time_logs()
|
||||||
|
|
||||||
|
doclist = get_mapped_doc("Job Card", source_name, {
|
||||||
|
"Job Card": {
|
||||||
|
"doctype": "Job Card",
|
||||||
|
"field_map": {
|
||||||
|
"name": "for_job_card",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}, target_doc, set_missing_values)
|
||||||
|
|
||||||
|
return doclist
|
||||||
@ -102,7 +102,7 @@
|
|||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"label": "Transferred Qty",
|
"label": "Transferred Qty",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"print_hide": 1,
|
"print_hide": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "rate",
|
"fieldname": "rate",
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
"field_order": [
|
"field_order": [
|
||||||
"workstation",
|
"workstation",
|
||||||
"data_2",
|
"data_2",
|
||||||
"cost_of_poor_quality_operation",
|
"is_corrective_operation",
|
||||||
"job_card_section",
|
"job_card_section",
|
||||||
"create_job_card_based_on_batch_size",
|
"create_job_card_based_on_batch_size",
|
||||||
"column_break_6",
|
"column_break_6",
|
||||||
@ -77,13 +77,6 @@
|
|||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Create Job Card based on Batch Size"
|
"label": "Create Job Card based on Batch Size"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"default": "0",
|
|
||||||
"description": "Cost of poor quality operation",
|
|
||||||
"fieldname": "cost_of_poor_quality_operation",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"label": "Is COPQ Operation"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"collapsible": 1,
|
"collapsible": 1,
|
||||||
"fieldname": "job_card_section",
|
"fieldname": "job_card_section",
|
||||||
@ -93,12 +86,18 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "column_break_6",
|
"fieldname": "column_break_6",
|
||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "is_corrective_operation",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Is Corrective Operation"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-wrench",
|
"icon": "fa fa-wrench",
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-12-24 14:25:03.428303",
|
"modified": "2021-01-12 15:09:23.593338",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Operation",
|
"name": "Operation",
|
||||||
|
|||||||
@ -242,13 +242,13 @@ frappe.ui.form.on("Work Order", {
|
|||||||
if(data.completed_qty != frm.doc.qty) {
|
if(data.completed_qty != frm.doc.qty) {
|
||||||
pending_qty = frm.doc.qty - flt(data.completed_qty);
|
pending_qty = frm.doc.qty - flt(data.completed_qty);
|
||||||
|
|
||||||
if (pending_qty && !data.skip_job_card) {
|
if (pending_qty) {
|
||||||
dialog.fields_dict.operations.df.data.push({
|
dialog.fields_dict.operations.df.data.push({
|
||||||
'name': data.name,
|
'name': data.name,
|
||||||
'operation': data.operation,
|
'operation': data.operation,
|
||||||
'workstation': data.workstation,
|
'workstation': data.workstation,
|
||||||
'qty': pending_qty,
|
'qty': pending_qty,
|
||||||
'pending_qty': pending_qty,
|
'pending_qty': pending_qty
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,6 +58,7 @@
|
|||||||
"actual_operating_cost",
|
"actual_operating_cost",
|
||||||
"additional_operating_cost",
|
"additional_operating_cost",
|
||||||
"column_break_24",
|
"column_break_24",
|
||||||
|
"corrective_operation_cost",
|
||||||
"total_operating_cost",
|
"total_operating_cost",
|
||||||
"more_info",
|
"more_info",
|
||||||
"description",
|
"description",
|
||||||
@ -534,6 +535,16 @@
|
|||||||
"fieldname": "batch_size",
|
"fieldname": "batch_size",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"label": "Batch Size"
|
"label": "Batch Size"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 1,
|
||||||
|
"description": "From Corrective Job Card",
|
||||||
|
"fieldname": "corrective_operation_cost",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Corrective Operation Cost",
|
||||||
|
"no_copy": 1,
|
||||||
|
"print_hide": 1,
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-cogs",
|
"icon": "fa fa-cogs",
|
||||||
|
|||||||
@ -130,7 +130,9 @@ class WorkOrder(Document):
|
|||||||
|
|
||||||
variable_cost = self.actual_operating_cost if self.actual_operating_cost \
|
variable_cost = self.actual_operating_cost if self.actual_operating_cost \
|
||||||
else self.planned_operating_cost
|
else self.planned_operating_cost
|
||||||
self.total_operating_cost = flt(self.additional_operating_cost) + flt(variable_cost)
|
|
||||||
|
self.total_operating_cost = (flt(self.additional_operating_cost)
|
||||||
|
+ flt(variable_cost) + flt(self.corrective_operation_cost))
|
||||||
|
|
||||||
def validate_work_order_against_so(self):
|
def validate_work_order_against_so(self):
|
||||||
# already ordered qty
|
# already ordered qty
|
||||||
@ -343,7 +345,6 @@ class WorkOrder(Document):
|
|||||||
plan_days = cint(manufacturing_settings_doc.capacity_planning_for_days) or 30
|
plan_days = cint(manufacturing_settings_doc.capacity_planning_for_days) or 30
|
||||||
|
|
||||||
for index, row in enumerate(self.operations):
|
for index, row in enumerate(self.operations):
|
||||||
if row.skip_job_card: continue
|
|
||||||
qty = self.qty
|
qty = self.qty
|
||||||
i=0
|
i=0
|
||||||
while qty > 0:
|
while qty > 0:
|
||||||
@ -357,6 +358,7 @@ class WorkOrder(Document):
|
|||||||
qty -= row.batch_size
|
qty -= row.batch_size
|
||||||
elif qty > 0:
|
elif qty > 0:
|
||||||
job_card_qty = qty
|
job_card_qty = qty
|
||||||
|
qty = 0
|
||||||
|
|
||||||
if job_card_qty > 0:
|
if job_card_qty > 0:
|
||||||
self.prepare_data_for_job_card(row, job_card_qty, index,
|
self.prepare_data_for_job_card(row, job_card_qty, index,
|
||||||
@ -496,7 +498,7 @@ class WorkOrder(Document):
|
|||||||
select
|
select
|
||||||
operation, description, workstation, idx,
|
operation, description, workstation, idx,
|
||||||
base_hour_rate as hour_rate, time_in_mins,
|
base_hour_rate as hour_rate, time_in_mins,
|
||||||
"Pending" as status, parent as bom, batch_size, sequence_id, skip_job_card
|
"Pending" as status, parent as bom, batch_size, sequence_id
|
||||||
from
|
from
|
||||||
`tabBOM Operation`
|
`tabBOM Operation`
|
||||||
where
|
where
|
||||||
|
|||||||
@ -9,7 +9,6 @@
|
|||||||
"operation",
|
"operation",
|
||||||
"bom",
|
"bom",
|
||||||
"column_break_4",
|
"column_break_4",
|
||||||
"skip_job_card",
|
|
||||||
"description",
|
"description",
|
||||||
"sequence_id",
|
"sequence_id",
|
||||||
"col_break1",
|
"col_break1",
|
||||||
@ -201,19 +200,12 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "column_break_4",
|
"fieldname": "column_break_4",
|
||||||
"fieldtype": "Column Break"
|
"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,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-01-08 17:42:05.372163",
|
"modified": "2021-01-12 14:48:31.061286",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Work Order Operation",
|
"name": "Work Order Operation",
|
||||||
|
|||||||
@ -4,6 +4,66 @@
|
|||||||
|
|
||||||
frappe.query_reports["Cost of Poor Quality Report"] = {
|
frappe.query_reports["Cost of Poor Quality Report"] = {
|
||||||
"filters": [
|
"filters": [
|
||||||
|
{
|
||||||
|
label: __("Company"),
|
||||||
|
fieldname: "company",
|
||||||
|
fieldtype: "Link",
|
||||||
|
options: "Company",
|
||||||
|
default: frappe.defaults.get_user_default("Company"),
|
||||||
|
reqd: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: __("From Date"),
|
||||||
|
fieldname:"from_date",
|
||||||
|
fieldtype: "Datetime",
|
||||||
|
default: frappe.datetime.convert_to_system_tz(frappe.datetime.add_months(frappe.datetime.now_datetime(), -1)),
|
||||||
|
reqd: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: __("To Date"),
|
||||||
|
fieldname:"to_date",
|
||||||
|
fieldtype: "Datetime",
|
||||||
|
default: frappe.datetime.now_datetime(),
|
||||||
|
reqd: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: __("Job Card"),
|
||||||
|
fieldname: "name",
|
||||||
|
fieldtype: "Link",
|
||||||
|
options: "Job Card",
|
||||||
|
get_query: function() {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
is_corrective_job_card: 1,
|
||||||
|
docstatus: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: __("Work Order"),
|
||||||
|
fieldname: "work_order",
|
||||||
|
fieldtype: "Link",
|
||||||
|
options: "Work Order"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: __("Operation"),
|
||||||
|
fieldname: "operation",
|
||||||
|
fieldtype: "Link",
|
||||||
|
options: "Operation",
|
||||||
|
get_query: function() {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
is_corrective_operation: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: __("Workstation"),
|
||||||
|
fieldname: "workstation",
|
||||||
|
fieldtype: "Link",
|
||||||
|
options: "Workstation"
|
||||||
|
},
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|||||||
@ -14,24 +14,34 @@ def execute(filters=None):
|
|||||||
|
|
||||||
return columns, data
|
return columns, data
|
||||||
|
|
||||||
def get_data(filters):
|
def get_data(report_filters):
|
||||||
data = []
|
data = []
|
||||||
operations = frappe.get_all("Operation", filters = {"cost_of_poor_quality_operation": 1})
|
operations = frappe.get_all("Operation", filters = {"is_corrective_operation": 1})
|
||||||
if operations:
|
if operations:
|
||||||
operations = [d.name for d in operations]
|
operations = [d.name for d in operations]
|
||||||
fields = ["production_item as item_code", "item_name", "work_order", "operation",
|
fields = ["production_item as item_code", "item_name", "work_order", "operation",
|
||||||
"workstation", "total_time_in_mins", "name", "hour_rate"]
|
"workstation", "total_time_in_mins", "name", "hour_rate"]
|
||||||
|
|
||||||
|
filters = get_filters(report_filters, operations)
|
||||||
|
|
||||||
job_cards = frappe.get_all("Job Card", fields = fields,
|
job_cards = frappe.get_all("Job Card", fields = fields,
|
||||||
filters = {"docstatus": 1, "operation": ("in", operations)})
|
filters = filters)
|
||||||
|
|
||||||
for row in job_cards:
|
for row in job_cards:
|
||||||
row.operating_cost = flt(row.hour_rate) * (flt(row.total_time_in_mins) / 60.0)
|
row.operating_cost = flt(row.hour_rate) * (flt(row.total_time_in_mins) / 60.0)
|
||||||
update_raw_material_cost(row, filters)
|
update_raw_material_cost(row, report_filters)
|
||||||
update_time_details(row, filters, data)
|
update_time_details(row, report_filters, data)
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
def get_filters(report_filters, operations):
|
||||||
|
filters = {"docstatus": 1, "operation": ("in", operations), "is_corrective_job_card": 1}
|
||||||
|
for field in ["name", "work_order", "operation", "workstation", "company"]:
|
||||||
|
if report_filters.get(field):
|
||||||
|
filters[field] = report_filters.get(field)
|
||||||
|
|
||||||
|
return filters
|
||||||
|
|
||||||
def update_raw_material_cost(row, filters):
|
def update_raw_material_cost(row, filters):
|
||||||
row.rm_cost = 0.0
|
row.rm_cost = 0.0
|
||||||
for data in frappe.get_all("Job Card Item", fields = ["amount"],
|
for data in frappe.get_all("Job Card Item", fields = ["amount"],
|
||||||
@ -43,8 +53,10 @@ def update_time_details(row, filters, data):
|
|||||||
"operation": "", "workstation":"", "operating_cost": "", "rm_cost": "", "total_time_in_mins": ""})
|
"operation": "", "workstation":"", "operating_cost": "", "rm_cost": "", "total_time_in_mins": ""})
|
||||||
|
|
||||||
i=0
|
i=0
|
||||||
for time_log in frappe.get_all("Job Card Time Log", fields = ["from_time", "to_time", "time_in_mins"],
|
for time_log in frappe.get_all("Job Card Time Log",
|
||||||
filters={"parent": row.name, "docstatus": 1}):
|
fields = ["from_time", "to_time", "time_in_mins"],
|
||||||
|
filters={"parent": row.name, "docstatus": 1,
|
||||||
|
"from_time": (">=", filters.from_date), "to_time": ("<=", filters.to_date)}):
|
||||||
|
|
||||||
if i==0:
|
if i==0:
|
||||||
i += 1
|
i += 1
|
||||||
|
|||||||
@ -365,7 +365,6 @@ class StockEntry(StockController):
|
|||||||
"overproduction_percentage_for_work_order"))
|
"overproduction_percentage_for_work_order"))
|
||||||
|
|
||||||
for d in prod_order.get("operations"):
|
for d in prod_order.get("operations"):
|
||||||
if d.skip_job_card: continue
|
|
||||||
total_completed_qty = flt(self.fg_completed_qty) + flt(prod_order.produced_qty)
|
total_completed_qty = flt(self.fg_completed_qty) + flt(prod_order.produced_qty)
|
||||||
completed_qty = d.completed_qty + (allowance_percentage/100 * d.completed_qty)
|
completed_qty = d.completed_qty + (allowance_percentage/100 * d.completed_qty)
|
||||||
if total_completed_qty > flt(completed_qty):
|
if total_completed_qty > flt(completed_qty):
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user