From 4e8fdf7b3fc2efea7d16398aa1dda11afdd2446d Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Thu, 22 Feb 2018 11:03:48 +0530 Subject: [PATCH] [Enhance] Quality Inspection Template (#12988) * [Enhance] Quality Inspection Template * Test case and patch * Update make_quality_inspection_template.py --- erpnext/config/stock.py | 4 + erpnext/controllers/stock_controller.py | 14 +- .../controllers/tests/test_item_variant.py | 35 ++-- erpnext/manufacturing/doctype/bom/bom.json | 64 +++++- .../production_order/production_order.py | 3 + erpnext/patches.txt | 1 + erpnext/patches/v11_0/__init__.py | 1 + .../v11_0/make_quality_inspection_template.py | 25 +++ erpnext/public/js/controllers/transaction.js | 1 + erpnext/stock/doctype/item/item.json | 62 +++--- .../quality_inspection/quality_inspection.js | 31 ++- .../quality_inspection.json | 44 ++++- .../quality_inspection/quality_inspection.py | 94 +++++---- .../test_quality_inspection.js | 23 +++ .../quality_inspection_template/__init__.py | 0 .../quality_inspection_template.js | 8 + .../quality_inspection_template.json | 186 ++++++++++++++++++ .../quality_inspection_template.py | 16 ++ .../test_quality_inspection_template.js | 23 +++ .../test_quality_inspection_template.py | 9 + .../stock/doctype/stock_entry/stock_entry.js | 39 +++- .../doctype/stock_entry/stock_entry.json | 33 +++- .../stock/doctype/stock_entry/stock_entry.py | 1 + .../doctype/stock_entry/test_stock_entry.py | 20 +- .../stock_entry_detail.json | 34 +++- 25 files changed, 678 insertions(+), 93 deletions(-) create mode 100644 erpnext/patches/v11_0/__init__.py create mode 100644 erpnext/patches/v11_0/make_quality_inspection_template.py create mode 100644 erpnext/stock/doctype/quality_inspection/test_quality_inspection.js create mode 100644 erpnext/stock/doctype/quality_inspection_template/__init__.py create mode 100644 erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.js create mode 100644 erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.json create mode 100644 erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.py create mode 100644 erpnext/stock/doctype/quality_inspection_template/test_quality_inspection_template.js create mode 100644 erpnext/stock/doctype/quality_inspection_template/test_quality_inspection_template.py diff --git a/erpnext/config/stock.py b/erpnext/config/stock.py index c5a372b945..e3b8d82c35 100644 --- a/erpnext/config/stock.py +++ b/erpnext/config/stock.py @@ -163,6 +163,10 @@ def get_data(): "type": "doctype", "name": "Quality Inspection", }, + { + "type": "doctype", + "name": "Quality Inspection Template", + }, { "type": "doctype", "name": "Landed Cost Voucher", diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 605881c839..b40b986ea5 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -320,14 +320,20 @@ class StockController(AccountsController): elif self.doctype in ["Delivery Note", "Sales Invoice"]: inspection_required_fieldname = "inspection_required_before_delivery" - if not inspection_required_fieldname or \ - (self.doctype in ["Sales Invoice", "Purchase Invoice"] and not self.update_stock): + if ((not inspection_required_fieldname and self.doctype != "Stock Entry") or + (self.doctype == "Stock Entry" and not self.inspection_required) or + (self.doctype in ["Sales Invoice", "Purchase Invoice"] and not self.update_stock)): return for d in self.get('items'): - if (frappe.db.get_value("Item", d.item_code, inspection_required_fieldname) - and not d.quality_inspection): + raise_exception = False + if (inspection_required_fieldname and not d.quality_inspection and + frappe.db.get_value("Item", d.item_code, inspection_required_fieldname)): + raise_exception = True + elif self.doctype == "Stock Entry" and not d.quality_inspection and d.t_warehouse: + raise_exception = True + if raise_exception: frappe.msgprint(_("Quality Inspection required for Item {0}").format(d.item_code)) if self.docstatus==1: raise frappe.ValidationError diff --git a/erpnext/controllers/tests/test_item_variant.py b/erpnext/controllers/tests/test_item_variant.py index dfd9f9de9e..d4b5dd2e1e 100644 --- a/erpnext/controllers/tests/test_item_variant.py +++ b/erpnext/controllers/tests/test_item_variant.py @@ -9,15 +9,22 @@ from erpnext.controllers.item_variant import copy_attributes_to_variant, make_va from six import string_types +class TestItemVariant(unittest.TestCase): + def test_tables_in_template_copied_to_variant(self): + fields = [{'field_name': 'quality_inspection_template'}] + set_item_variant_settings(fields) + variant = make_item_variant() + self.assertEqual(variant.get("quality_inspection_template"), "_Test QC Template") + def create_variant_with_tables(item, args): if isinstance(args, string_types): args = json.loads(args) + qc_name = make_quality_inspection_template() template = frappe.get_doc("Item", item) - template.quality_parameters.append({ - "specification": "Moisture", - "value": "< 5%", - }) + template.quality_inspection_template = qc_name + template.save() + variant = frappe.new_doc("Item") variant.variant_based_on = 'Item Attribute' variant_attributes = [] @@ -34,7 +41,6 @@ def create_variant_with_tables(item, args): return variant - def make_item_variant(): frappe.delete_doc_if_exists("Item", "_Test Variant Item-S", force=1) variant = create_variant_with_tables("_Test Variant Item", '{"Test Size": "Small"}') @@ -43,10 +49,17 @@ def make_item_variant(): variant.save() return variant +def make_quality_inspection_template(): + qc_template = "_Test QC Template" + if frappe.db.exists("Quality Inspection Template", qc_template): + return qc_template -class TestItemVariant(unittest.TestCase): - def test_tables_in_template_copied_to_variant(self): - fields = [{'field_name': 'quality_parameters'}] - set_item_variant_settings(fields) - variant = make_item_variant() - self.assertNotEqual(variant.get("quality_parameters"), []) + qc = frappe.new_doc("Quality Inspection Template") + qc.quality_inspection_template_name = qc_template + qc.append('item_quality_inspection_parameter', { + "specification": "Moisture", + "value": "< 5%", + }) + + qc.insert() + return qc.name diff --git a/erpnext/manufacturing/doctype/bom/bom.json b/erpnext/manufacturing/doctype/bom/bom.json index 85a3f7e9b1..30b9683638 100644 --- a/erpnext/manufacturing/doctype/bom/bom.json +++ b/erpnext/manufacturing/doctype/bom/bom.json @@ -108,6 +108,68 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "inspection_required", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Inspection Required", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "inspection_required", + "fieldname": "quality_inspection_template", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Quality Inspection Template", + "length": 0, + "no_copy": 0, + "options": "Quality Inspection Template", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -1671,7 +1733,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-10-23 14:56:21.991160", + "modified": "2018-02-16 13:43:55.485813", "modified_by": "Administrator", "module": "Manufacturing", "name": "BOM", diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py index 439659a5ca..c41260fa76 100644 --- a/erpnext/manufacturing/doctype/production_order/production_order.py +++ b/erpnext/manufacturing/doctype/production_order/production_order.py @@ -586,6 +586,9 @@ def make_stock_entry(production_order_id, purpose, qty=None): stock_entry.bom_no = production_order.bom_no stock_entry.use_multi_level_bom = production_order.use_multi_level_bom stock_entry.fg_completed_qty = qty or (flt(production_order.qty) - flt(production_order.produced_qty)) + if production_order.bom_no: + stock_entry.inspection_required = frappe.db.get_value('BOM', + production_order.bom_no, 'inspection_required') if purpose=="Material Transfer for Manufacture": stock_entry.to_warehouse = wip_warehouse diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 65c391eda2..b365e961b4 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -502,4 +502,5 @@ erpnext.patches.v10_0.update_translatable_fields erpnext.patches.v10_0.rename_offer_letter_to_job_offer execute:frappe.delete_doc('DocType', 'Production Planning Tool', ignore_missing=True) erpnext.patches.v10_0.migrate_daily_work_summary_settings_to_daily_work_summary_group +erpnext.patches.v11_0.make_quality_inspection_template erpnext.patches.v10_0.update_territory_and_customer_group diff --git a/erpnext/patches/v11_0/__init__.py b/erpnext/patches/v11_0/__init__.py new file mode 100644 index 0000000000..baffc48825 --- /dev/null +++ b/erpnext/patches/v11_0/__init__.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/erpnext/patches/v11_0/make_quality_inspection_template.py b/erpnext/patches/v11_0/make_quality_inspection_template.py new file mode 100644 index 0000000000..67755e8b44 --- /dev/null +++ b/erpnext/patches/v11_0/make_quality_inspection_template.py @@ -0,0 +1,25 @@ +# Copyright (c) 2017, Frappe and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + frappe.reload_doc('stock', 'doctype', 'item') + frappe.reload_doc('stock', 'doctype', 'quality_inspection_template') + + for data in frappe.get_all('Item Quality Inspection Parameter', + fields = ["distinct parent"], filters = {'parenttype': 'Item'}): + qc_doc = frappe.new_doc("Quality Inspection Template") + qc_doc.quality_inspection_template_name = 'QIT/%s' % data.parent + qc_doc.flags.ignore_mandatory = True + qc_doc.save(ignore_permissions=True) + + frappe.db.set_value('Item', data.parent, "quality_inspection_template", qc_doc.name, update_modified=False) + frappe.db.sql(""" update `tabItem Quality Inspection Parameter` + set parentfield = 'item_quality_inspection_parameter', parenttype = 'Quality Inspection Template', + parent = %s where parenttype = 'Item' and parent = %s""", (qc_doc.name, data.parent)) + + # update field in item variant settings + frappe.db.sql(""" update `tabVariant Field` set field_name = 'quality_inspection_template' + where field_name = 'quality_parameters'""") diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 274bb3e9ff..04e1bf3739 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -204,6 +204,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ filters: { docstatus: 1, inspection_type: inspection_type, + reference_name: doc.name, item_code: d.item_code } } diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json index 04f9df3dae..689089c74e 100644 --- a/erpnext/stock/doctype/item/item.json +++ b/erpnext/stock/doctype/item/item.json @@ -2694,37 +2694,35 @@ "unique": 0 }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:(doc.inspection_required_before_purchase || doc.inspection_required_before_delivery)", - "description": "Will also apply to variants", - "fieldname": "quality_parameters", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Quality Parameters", - "length": 0, - "no_copy": 0, - "oldfieldname": "item_specification_details", - "oldfieldtype": "Table", - "options": "Item Quality Inspection Parameter", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:(doc.inspection_required_before_purchase || doc.inspection_required_before_delivery)", + "fieldname": "quality_inspection_template", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Quality Inspection Template", + "length": 0, + "no_copy": 0, + "options": "Quality Inspection Template", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 }, { @@ -3545,7 +3543,7 @@ "issingle": 0, "istable": 0, "max_attachments": 1, - "modified": "2018-02-12 15:42:23.303090", + "modified": "2018-02-19 13:48:35.779089", "modified_by": "Administrator", "module": "Stock", "name": "Item", diff --git a/erpnext/stock/doctype/quality_inspection/quality_inspection.js b/erpnext/stock/doctype/quality_inspection/quality_inspection.js index 53579fb0ff..aa9854aee1 100644 --- a/erpnext/stock/doctype/quality_inspection/quality_inspection.js +++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.js @@ -3,13 +3,42 @@ cur_frm.cscript.refresh = cur_frm.cscript.inspection_type; +frappe.ui.form.on("Quality Inspection", { + item_code: function(frm) { + if (frm.doc.item_code) { + return frm.call({ + method: "get_quality_inspection_template", + doc: frm.doc, + callback: function() { + refresh_field(['quality_inspection_template', 'readings']); + } + }); + } + }, + + quality_inspection_template: function(frm) { + if (frm.doc.quality_inspection_template) { + return frm.call({ + method: "get_item_specification_details", + doc: frm.doc, + callback: function() { + refresh_field('readings'); + } + }); + } + } +}) + // item code based on GRN/DN cur_frm.fields_dict['item_code'].get_query = function(doc, cdt, cdn) { + const doctype = (doc.reference_type == "Stock Entry") ? + "Stock Entry Detail" : doc.reference_type + " Item"; + if (doc.reference_type && doc.reference_name) { return { query: "erpnext.stock.doctype.quality_inspection.quality_inspection.item_query", filters: { - "from": doc.reference_type + " Item", + "from": doctype, "parent": doc.reference_name } } diff --git a/erpnext/stock/doctype/quality_inspection/quality_inspection.json b/erpnext/stock/doctype/quality_inspection/quality_inspection.json index 4dd109c3b5..44d9a865ee 100644 --- a/erpnext/stock/doctype/quality_inspection/quality_inspection.json +++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.json @@ -154,7 +154,7 @@ "label": "Reference Type", "length": 0, "no_copy": 0, - "options": "\nPurchase Receipt\nPurchase Invoice\nDelivery Note\nSales Invoice", + "options": "\nPurchase Receipt\nPurchase Invoice\nDelivery Note\nSales Invoice\nStock Entry", "permlevel": 0, "precision": "", "print_hide": 0, @@ -541,6 +541,37 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "bom_no", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "BOM No", + "length": 0, + "no_copy": 0, + "options": "BOM", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -670,8 +701,8 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "get_specification_details", - "fieldtype": "Button", + "fieldname": "quality_inspection_template", + "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -679,11 +710,12 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Get Specification Details", + "label": "Quality Inspection Template", "length": 0, "no_copy": 0, - "options": "get_item_specification_details", + "options": "Quality Inspection Template", "permlevel": 0, + "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, @@ -738,7 +770,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-06-13 14:29:02.080120", + "modified": "2018-02-17 00:53:43.899395", "modified_by": "Administrator", "module": "Stock", "name": "Quality Inspection", diff --git a/erpnext/stock/doctype/quality_inspection/quality_inspection.py b/erpnext/stock/doctype/quality_inspection/quality_inspection.py index c3808f757e..36f6405ae4 100644 --- a/erpnext/stock/doctype/quality_inspection/quality_inspection.py +++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.py @@ -3,50 +3,78 @@ from __future__ import unicode_literals import frappe - - from frappe.model.document import Document +from erpnext.stock.doctype.quality_inspection_template.quality_inspection_template \ + import get_template_details class QualityInspection(Document): + def validate(self): + if not self.readings and self.item_code: + self.get_item_specification_details() + def get_item_specification_details(self): + if not self.quality_inspection_template: + self.quality_inspection_template = frappe.db.get_value('Item', + self.item_code, 'quality_inspection_template') + + if not self.quality_inspection_template: return + self.set('readings', []) - variant_of = frappe.db.get_value("Item", self.item_code, "variant_of") - if variant_of: - specification = frappe.db.sql("select specification, value from `tabItem Quality Inspection Parameter` \ - where parent in (%s, %s) order by idx", (self.item_code, variant_of)) - else: - specification = frappe.db.sql("select specification, value from `tabItem Quality Inspection Parameter` \ - where parent = %s order by idx", self.item_code) - for d in specification: + parameters = get_template_details(self.quality_inspection_template) + for d in parameters: child = self.append('readings', {}) - child.specification = d[0] - child.value = d[1] - child.status = 'Accepted' + child.specification = d.specification + child.value = d.value + child.status = "Accepted" + + def get_quality_inspection_template(self): + template = '' + if self.bom_no: + template = frappe.db.get_value('BOM', self.bom_no, 'quality_inspection_template') + + if not template: + template = frappe.db.get_value('BOM', self.item_code, 'quality_inspection_template') + + self.quality_inspection_template = template + self.get_item_specification_details() def on_submit(self): + self.update_qc_reference() + + def on_cancel(self): + self.update_qc_reference() + + def update_qc_reference(self): + quality_inspection = self.name if self.docstatus == 1 else "" + doctype = self.reference_type + ' Item' + if self.reference_type == 'Stock Entry': + doctype = 'Stock Entry Detail' + if self.reference_type and self.reference_name: - frappe.db.sql("""update `tab{doctype} Item` t1, `tab{doctype}` t2 + frappe.db.sql("""update `tab{child_doc}` t1, `tab{parent_doc}` t2 set t1.quality_inspection = %s, t2.modified = %s where t1.parent = %s and t1.item_code = %s and t1.parent = t2.name""" - .format(doctype=self.reference_type), - (self.name, self.modified, self.reference_name, self.item_code)) - - def on_cancel(self): - if self.reference_type and self.reference_name: - frappe.db.sql("""update `tab{doctype} Item` - set quality_inspection = null, modified=%s - where quality_inspection = %s""" - .format(doctype=self.reference_type), (self.modified, self.name)) - + .format(parent_doc=self.reference_type, child_doc=doctype), + (quality_inspection, self.modified, self.reference_name, self.item_code)) + def item_query(doctype, txt, searchfield, start, page_len, filters): if filters.get("from"): from frappe.desk.reportview import get_match_cond - filters.update({ - "txt": txt, - "mcond": get_match_cond(filters["from"]), - "start": start, - "page_len": page_len - }) - return frappe.db.sql("""select item_code from `tab%(from)s` - where parent='%(parent)s' and docstatus < 2 and item_code like '%%%(txt)s%%' %(mcond)s - order by item_code limit %(start)s, %(page_len)s""" % filters) + mcond = get_match_cond(filters["from"]) + cond = "" + + if filters.get('from') in ['Purchase Invoice Item', 'Purchase Receipt Item']: + cond = """and item_code in (select name from `tabItem` where + inspection_required_before_purchase = 1)""" + elif filters.get('from') in ['Sales Invoice Item', 'Delivery Note Item']: + cond = """and item_code in (select name from `tabItem` where + inspection_required_before_delivery = 1)""" + elif filters.get('from') == 'Stock Entry Detail': + cond = """and s_warehouse is null""" + + return frappe.db.sql(""" select item_code from `tab{doc}` + where parent=%(parent)s and docstatus < 2 and item_code like %(txt)s + and (quality_inspection is null or quality_inspection = '') + {cond} {mcond} order by item_code limit {start}, {page_len}""".format(doc=filters.get('from'), + parent=filters.get('parent'), cond=cond, mcond=mcond, start=start, page_len = page_len), + {'parent': filters.get('parent'), 'txt': "%%%s%%" % txt}) diff --git a/erpnext/stock/doctype/quality_inspection/test_quality_inspection.js b/erpnext/stock/doctype/quality_inspection/test_quality_inspection.js new file mode 100644 index 0000000000..327484e6cc --- /dev/null +++ b/erpnext/stock/doctype/quality_inspection/test_quality_inspection.js @@ -0,0 +1,23 @@ +/* eslint-disable */ +// rename this file from _test_[name] to test_[name] to activate +// and remove above this line + +QUnit.test("test: Quality Inspection", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Quality Inspection + () => frappe.tests.make('Quality Inspection', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/stock/doctype/quality_inspection_template/__init__.py b/erpnext/stock/doctype/quality_inspection_template/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.js b/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.js new file mode 100644 index 0000000000..fa57a3dcc3 --- /dev/null +++ b/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.js @@ -0,0 +1,8 @@ +// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Quality Inspection Template', { + refresh: function() { + + } +}); diff --git a/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.json b/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.json new file mode 100644 index 0000000000..eab08e2216 --- /dev/null +++ b/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.json @@ -0,0 +1,186 @@ +{ + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 1, + "allow_rename": 1, + "autoname": "field:quality_inspection_template_name", + "beta": 0, + "creation": "2018-01-24 16:23:41.691127", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "", + "editable_grid": 1, + "engine": "InnoDB", + "fields": [ + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "quality_inspection_template_name", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Quality Inspection Template Name", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "item_quality_inspection_parameter", + "fieldtype": "Table", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Item Quality Inspection Parameter", + "length": 0, + "no_copy": 0, + "options": "Item Quality Inspection Parameter", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + } + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 0, + "image_view": 0, + "in_create": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 0, + "max_attachments": 0, + "modified": "2018-02-21 12:05:29.304432", + "modified_by": "Administrator", + "module": "Stock", + "name": "Quality Inspection Template", + "name_case": "", + "owner": "Administrator", + "permissions": [ + { + "amend": 0, + "apply_user_permissions": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + }, + { + "amend": 0, + "apply_user_permissions": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Stock User", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + }, + { + "amend": 0, + "apply_user_permissions": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Quality Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + }, + { + "amend": 0, + "apply_user_permissions": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Manufacturing User", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + } + ], + "quick_entry": 0, + "read_only": 0, + "read_only_onload": 0, + "show_name_in_global_search": 0, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1, + "track_seen": 0 +} \ No newline at end of file diff --git a/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.py b/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.py new file mode 100644 index 0000000000..0d9a90312b --- /dev/null +++ b/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2018, 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 QualityInspectionTemplate(Document): + pass + +def get_template_details(template): + if not template: return [] + + return frappe.get_all('Item Quality Inspection Parameter', fields=["specification", "value"], + filters={'parenttype': 'Quality Inspection Template', 'parent': template}, order_by="idx") \ No newline at end of file diff --git a/erpnext/stock/doctype/quality_inspection_template/test_quality_inspection_template.js b/erpnext/stock/doctype/quality_inspection_template/test_quality_inspection_template.js new file mode 100644 index 0000000000..879c262ed2 --- /dev/null +++ b/erpnext/stock/doctype/quality_inspection_template/test_quality_inspection_template.js @@ -0,0 +1,23 @@ +/* eslint-disable */ +// rename this file from _test_[name] to test_[name] to activate +// and remove above this line + +QUnit.test("test: Quality Inspection Template", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Quality Inspection Template + () => frappe.tests.make('Quality Inspection Template', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/stock/doctype/quality_inspection_template/test_quality_inspection_template.py b/erpnext/stock/doctype/quality_inspection_template/test_quality_inspection_template.py new file mode 100644 index 0000000000..b16efa839d --- /dev/null +++ b/erpnext/stock/doctype/quality_inspection_template/test_quality_inspection_template.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import unittest + +class TestQualityInspectionTemplate(unittest.TestCase): + pass diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index 9093946d31..825b4cbeed 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -57,7 +57,42 @@ frappe.ui.form.on('Stock Entry', { } } }); + + frm.add_fetch("bom_no", "inspection_required", "inspection_required"); + frm.trigger("setup_quality_inspection"); }, + + setup_quality_inspection: function(frm) { + if (!frm.doc.inspection_required) { + return; + } + + let quality_inspection_field = frm.get_docfield("items", "quality_inspection"); + quality_inspection_field.get_route_options_for_new_doc = function(row) { + if (frm.is_new()) return; + return { + "inspection_type": "Incoming", + "reference_type": frm.doc.doctype, + "reference_name": frm.doc.name, + "item_code": row.doc.item_code, + "description": row.doc.description, + "item_serial_no": row.doc.serial_no ? row.doc.serial_no.split("\n")[0] : null, + "batch_no": row.doc.batch_no + } + } + + frm.set_query("quality_inspection", "items", function(doc, cdt, cdn) { + var d = locals[cdt][cdn]; + return { + filters: { + docstatus: 1, + item_code: d.item_code, + reference_name: doc.name + } + } + }); + }, + refresh: function(frm) { if(!frm.doc.docstatus) { frm.add_custom_button(__('Make Material Request'), function() { @@ -102,11 +137,11 @@ frappe.ui.form.on('Stock Entry', { }, __("Get items from")); } - if(frm.doc.company) { + if (frm.doc.company) { frm.trigger("toggle_display_account_head"); } - if(frm.doc.docstatus==1 && frm.doc.purpose == "Material Receipt") { + if (frm.doc.docstatus==1 && frm.doc.purpose == "Material Receipt") { frm.add_custom_button(__('Make Retention Stock Entry'), function () { frm.trigger("make_retention_stock_entry"); }); diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.json b/erpnext/stock/doctype/stock_entry/stock_entry.json index f68690cf8f..83bf92d8d2 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.json +++ b/erpnext/stock/doctype/stock_entry/stock_entry.json @@ -364,6 +364,37 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "inspection_required", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Inspection Required", + "length": 0, + "no_copy": 0, + "options": "", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -1739,7 +1770,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-06-13 14:28:47.818067", + "modified": "2018-02-17 10:32:24.111113", "modified_by": "Administrator", "module": "Stock", "name": "Stock Entry", diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 9bccfad50d..6cb81d8773 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -52,6 +52,7 @@ class StockEntry(StockController): self.validate_finished_goods() self.validate_with_material_request() self.validate_batch() + self.validate_inspection() if not self.from_bom: self.fg_completed_qty = 0.0 diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index 2da9f35ccc..8f287dd3fa 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -11,7 +11,7 @@ from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt \ from erpnext.stock.doctype.stock_ledger_entry.stock_ledger_entry import StockFreezeError from erpnext.stock.stock_ledger import get_previous_sle from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation -from erpnext.stock.doctype.item.test_item import set_item_variant_settings, make_item_variant +from erpnext.stock.doctype.item.test_item import set_item_variant_settings, make_item_variant, create_item from frappe.tests.test_permissions import set_user_permission_doctypes from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry from erpnext.accounts.doctype.account.test_account import get_inventory_account @@ -672,6 +672,24 @@ class TestStockEntry(unittest.TestCase): self.assertEquals(qty_in_usable_warehouse, 36) self.assertEquals(qty_in_retention_warehouse, 4) + def test_quality_check(self): + item_code = "_Test Item For QC" + if not frappe.db.exists('Item', item_code): + create_item(item_code) + + repack = frappe.copy_doc(test_records[3]) + repack.inspection_required = 1 + for d in repack.items: + if not d.s_warehouse and d.t_warehouse: + d.item_code = item_code + d.qty = 1 + d.uom = "Nos" + d.stock_uom = "Nos" + d.basic_rate = 5000 + + repack.insert() + self.assertRaises(frappe.ValidationError, repack.submit) + def make_serialized_item(item_code=None, serial_no=None, target_warehouse=None): se = frappe.copy_doc(test_records[0]) se.get("items")[0].item_code = item_code or "_Test Serialized Item With Series" diff --git a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json index c7566d9961..0f8bd17b10 100644 --- a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json +++ b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json @@ -988,6 +988,38 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:parent.inspection_required && doc.t_warehouse", + "fieldname": "quality_inspection", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Quality Inspection", + "length": 0, + "no_copy": 0, + "options": "Quality Inspection", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -1329,7 +1361,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-11-14 12:46:51.828176", + "modified": "2018-02-16 20:19:57.471380", "modified_by": "Administrator", "module": "Stock", "name": "Stock Entry Detail",