fix: or condition filter in the get_all
diff --git a/erpnext/manufacturing/doctype/job_card/job_card.json b/erpnext/manufacturing/doctype/job_card/job_card.json
index c2fd8cc..0597cdb 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 5c157d4..b2d5667 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card.py
+++ b/erpnext/manufacturing/doctype/job_card/job_card.py
@@ -41,6 +41,7 @@
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 @@
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 @@
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 @@
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 100ef4c..60a2249 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 23cc090..06cafd2 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order.py
@@ -764,10 +764,10 @@
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 @@
'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 0000000..e69de29
--- /dev/null
+++ b/erpnext/manufacturing/report/cost_of_poor_quality_report/__init__.py
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 0000000..7f5bc48
--- /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 0000000..ee63bc1
--- /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 0000000..21e7be7
--- /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 dd0e33b..2b1fc43 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -288,4 +288,5 @@
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 0000000..d4e65c6
--- /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 83412c6..4cc721b 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -365,6 +365,7 @@
"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 @@
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