From c878389050a45fa6cdebf057da1752242db0ad3f Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Fri, 8 Jan 2021 19:47:38 +0530 Subject: [PATCH] fix: or condition filter in the get_all --- .../doctype/job_card/job_card.json | 8 +- .../doctype/job_card/job_card.py | 20 +-- .../doctype/job_card_item/job_card_item.json | 13 ++ .../doctype/work_order/work_order.py | 9 +- .../cost_of_poor_quality_report/__init__.py | 0 .../cost_of_poor_quality_report.js | 9 ++ .../cost_of_poor_quality_report.json | 33 +++++ .../cost_of_poor_quality_report.py | 136 ++++++++++++++++++ erpnext/patches.txt | 3 +- .../patches/v13_0/update_job_card_details.py | 16 +++ .../stock/doctype/stock_entry/stock_entry.py | 3 +- 11 files changed, 234 insertions(+), 16 deletions(-) create mode 100644 erpnext/manufacturing/report/cost_of_poor_quality_report/__init__.py create mode 100644 erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.js create mode 100644 erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.json create mode 100644 erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.py create mode 100644 erpnext/patches/v13_0/update_job_card_details.py diff --git a/erpnext/manufacturing/doctype/job_card/job_card.json b/erpnext/manufacturing/doctype/job_card/job_card.json index c2fd8cc3f9..0597cdb207 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.json +++ b/erpnext/manufacturing/doctype/job_card/job_card.json @@ -33,6 +33,7 @@ "total_completed_qty", "column_break_15", "total_time_in_mins", + "hour_rate", "section_break_8", "items", "more_information", @@ -328,11 +329,16 @@ "fieldname": "section_break_21", "fieldtype": "Section Break", "hide_border": 1 + }, + { + "fieldname": "hour_rate", + "fieldtype": "Currency", + "label": "Hour Rate" } ], "is_submittable": 1, "links": [], - "modified": "2020-12-14 15:14:05.566271", + "modified": "2021-01-11 12:09:00.452032", "modified_by": "Administrator", "module": "Manufacturing", "name": "Job Card", diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index 5c157d43ec..b2d5667368 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -41,6 +41,7 @@ class JobCard(Document): def validate_time_logs(self): self.total_time_in_mins = 0.0 + self.total_completed_qty = 0.0 if self.get('time_logs'): for d in self.get('time_logs'): @@ -58,8 +59,6 @@ class JobCard(Document): if d.completed_qty: self.total_completed_qty += d.completed_qty - else: - self.total_completed_qty = 0.0 self.total_completed_qty = flt(self.total_completed_qty, self.precision("total_completed_qty")) @@ -256,12 +255,14 @@ class JobCard(Document): if self.get('operation') == d.operation: self.append('items', { - 'item_code': d.item_code, - 'source_warehouse': d.source_warehouse, - 'uom': frappe.db.get_value("Item", d.item_code, 'stock_uom'), - 'item_name': d.item_name, - 'description': d.description, - 'required_qty': (d.required_qty * flt(self.for_quantity)) / doc.qty + "item_code": d.item_code, + "source_warehouse": d.source_warehouse, + "uom": frappe.db.get_value("Item", d.item_code, 'stock_uom'), + "item_name": d.item_name, + "description": d.description, + "required_qty": (d.required_qty * flt(self.for_quantity)) / doc.qty, + "rate": d.rate, + "amount": d.amount }) def on_submit(self): @@ -439,7 +440,8 @@ class JobCard(Document): data = frappe.get_all("Work Order Operation", 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") message = "Job Card {0}: As per the sequence of the operations in the work order {1}".format(bold(self.name), diff --git a/erpnext/manufacturing/doctype/job_card_item/job_card_item.json b/erpnext/manufacturing/doctype/job_card_item/job_card_item.json index 100ef4ca3a..60a2249442 100644 --- a/erpnext/manufacturing/doctype/job_card_item/job_card_item.json +++ b/erpnext/manufacturing/doctype/job_card_item/job_card_item.json @@ -17,6 +17,8 @@ "required_qty", "column_break_9", "transferred_qty", + "rate", + "amount", "allow_alternative_item" ], "fields": [ @@ -101,6 +103,17 @@ "label": "Transferred Qty", "no_copy": 1, "print_hide": 1, + }, + { + "fieldname": "rate", + "fieldtype": "Currency", + "label": "Rate", + "read_only": 1 + }, + { + "fieldname": "amount", + "fieldtype": "Currency", + "label": "Amount", "read_only": 1 } ], diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index 23cc090427..06cafd2d04 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -764,10 +764,10 @@ class WorkOrder(Document): 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] + qty = frappe.get_all("Stock Entry Detail", filters = {"batch_no": row.batch_no, "docstatus": 1}, + or_filters= {"is_finished_item": 1, "is_scrap_item": 1}, fields = ["sum(qty)"], as_list=1)[0][0] - frappe.db.set_value("Batch", row.batch_no, "produced_qty", qty) + frappe.db.set_value("Batch", row.batch_no, "produced_qty", flt(qty)) @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs @@ -1006,7 +1006,8 @@ def create_job_card(work_order, row, qty=0, enable_capacity_planning=False, auto 'project': work_order.project, 'company': work_order.company, 'sequence_id': row.get("sequence_id"), - 'wip_warehouse': work_order.wip_warehouse + 'wip_warehouse': work_order.wip_warehouse, + "hour_rate": row.get("hour_rate") }) if work_order.transfer_material_against == 'Job Card' and not work_order.skip_transfer: diff --git a/erpnext/manufacturing/report/cost_of_poor_quality_report/__init__.py b/erpnext/manufacturing/report/cost_of_poor_quality_report/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.js b/erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.js new file mode 100644 index 0000000000..7f5bc48f18 --- /dev/null +++ b/erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.js @@ -0,0 +1,9 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.query_reports["Cost of Poor Quality Report"] = { + "filters": [ + + ] +}; diff --git a/erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.json b/erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.json new file mode 100644 index 0000000000..ee63bc1c28 --- /dev/null +++ b/erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.json @@ -0,0 +1,33 @@ +{ + "add_total_row": 0, + "columns": [], + "creation": "2021-01-11 11:10:58.292896", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "filters": [], + "idx": 0, + "is_standard": "Yes", + "json": "{}", + "modified": "2021-01-11 11:11:03.594242", + "modified_by": "Administrator", + "module": "Manufacturing", + "name": "Cost of Poor Quality Report", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Job Card", + "report_name": "Cost of Poor Quality Report", + "report_type": "Script Report", + "roles": [ + { + "role": "System Manager" + }, + { + "role": "Manufacturing User" + }, + { + "role": "Manufacturing Manager" + } + ] +} \ No newline at end of file diff --git a/erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.py b/erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.py new file mode 100644 index 0000000000..21e7be7478 --- /dev/null +++ b/erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.py @@ -0,0 +1,136 @@ +# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +from frappe import _ +from frappe.utils import flt + +def execute(filters=None): + columns, data = [], [] + + columns = get_columns(filters) + data = get_data(filters) + + return columns, data + +def get_data(filters): + data = [] + operations = frappe.get_all("Operation", filters = {"cost_of_poor_quality_operation": 1}) + if operations: + operations = [d.name for d in operations] + fields = ["production_item as item_code", "item_name", "work_order", "operation", + "workstation", "total_time_in_mins", "name", "hour_rate"] + + job_cards = frappe.get_all("Job Card", fields = fields, + filters = {"docstatus": 1, "operation": ("in", operations)}) + + for row in job_cards: + row.operating_cost = flt(row.hour_rate) * (flt(row.total_time_in_mins) / 60.0) + update_raw_material_cost(row, filters) + update_time_details(row, filters, data) + + return data + +def update_raw_material_cost(row, filters): + row.rm_cost = 0.0 + for data in frappe.get_all("Job Card Item", fields = ["amount"], + filters={"parent": row.name, "docstatus": 1}): + row.rm_cost += data.amount + +def update_time_details(row, filters, data): + args = frappe._dict({"item_code": "", "item_name": "", "name": "", "work_order":"", + "operation": "", "workstation":"", "operating_cost": "", "rm_cost": "", "total_time_in_mins": ""}) + + i=0 + for time_log in frappe.get_all("Job Card Time Log", fields = ["from_time", "to_time", "time_in_mins"], + filters={"parent": row.name, "docstatus": 1}): + + if i==0: + i += 1 + row.update(time_log) + data.append(row) + else: + args.update(time_log) + data.append(args) + +def get_columns(filters): + return [ + { + "label": _("Job Card"), + "fieldtype": "Link", + "fieldname": "name", + "options": "Job Card", + "width": "100" + }, + { + "label": _("Work Order"), + "fieldtype": "Link", + "fieldname": "work_order", + "options": "Work Order", + "width": "100" + }, + { + "label": _("Item Code"), + "fieldtype": "Link", + "fieldname": "item_code", + "options": "Item", + "width": "100" + }, + { + "label": _("Item Name"), + "fieldtype": "Data", + "fieldname": "item_name", + "width": "100" + }, + { + "label": _("Operation"), + "fieldtype": "Link", + "fieldname": "operation", + "options": "Operation", + "width": "100" + }, + { + "label": _("Workstation"), + "fieldtype": "Link", + "fieldname": "workstation", + "options": "Workstation", + "width": "100" + }, + { + "label": _("Operating Cost"), + "fieldtype": "Currency", + "fieldname": "operating_cost", + "width": "100" + }, + { + "label": _("Raw Material Cost"), + "fieldtype": "Currency", + "fieldname": "rm_cost", + "width": "100" + }, + { + "label": _("Total Time (in Mins)"), + "fieldtype": "Float", + "fieldname": "total_time_in_mins", + "width": "100" + }, + { + "label": _("From Time"), + "fieldtype": "Datetime", + "fieldname": "from_time", + "width": "100" + }, + { + "label": _("To Time"), + "fieldtype": "Datetime", + "fieldname": "to_time", + "width": "100" + }, + { + "label": _("Time in Mins"), + "fieldtype": "Float", + "fieldname": "time_in_mins", + "width": "100" + }, + ] \ No newline at end of file diff --git a/erpnext/patches.txt b/erpnext/patches.txt index dd0e33beba..2b1fc43a1c 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -288,4 +288,5 @@ execute:frappe.rename_doc("Workspace", "Loan Management", "Loans", force=True) erpnext.patches.v13_0.update_timesheet_changes erpnext.patches.v13_0.set_training_event_attendance erpnext.patches.v13_0.rename_issue_status_hold_to_on_hold -erpnext.patches.v13_0.bill_for_rejected_quantity_in_purchase_invoice \ No newline at end of file +erpnext.patches.v13_0.bill_for_rejected_quantity_in_purchase_invoice +erpnext.patches.v13_0.update_job_card_details diff --git a/erpnext/patches/v13_0/update_job_card_details.py b/erpnext/patches/v13_0/update_job_card_details.py new file mode 100644 index 0000000000..d4e65c6f2f --- /dev/null +++ b/erpnext/patches/v13_0/update_job_card_details.py @@ -0,0 +1,16 @@ +# Copyright (c) 2019, Frappe and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + frappe.reload_doc("manufacturing", "doctype", "job_card") + frappe.reload_doc("manufacturing", "doctype", "job_card_item") + frappe.reload_doc("manufacturing", "doctype", "work_order_operation") + + frappe.db.sql(""" update `tabJob Card` jc, `tabWork Order Operation` wo + SET jc.hour_rate = wo.hour_rate + WHERE + jc.operation_id = wo.name and jc.docstatus < 2 and wo.hour_rate > 0 + """) \ No newline at end of file diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 83412c61d9..4cc721badf 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -365,6 +365,7 @@ class StockEntry(StockController): "overproduction_percentage_for_work_order")) 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) completed_qty = d.completed_qty + (allowance_percentage/100 * d.completed_qty) if total_completed_qty > flt(completed_qty): @@ -1104,7 +1105,7 @@ class StockEntry(StockController): fields = ["qty_to_produce as qty", "produced_qty", "name"] - for row in frappe.get_all("Batch", filters = filters, fields = fields): + for row in frappe.get_all("Batch", filters = filters, fields = fields, order_by="creation asc"): batch_qty = flt(row.qty) - flt(row.produced_qty) if not batch_qty: continue