From b6dc0efa27bd3196f01e2bb1a5ade2422073ac00 Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Tue, 22 Jun 2021 16:53:35 +0530 Subject: [PATCH 01/54] feat: add provision for process loss in manufac --- erpnext/manufacturing/doctype/bom/bom.py | 7 +- .../bom_scrap_item/bom_scrap_item.json | 429 ++++-------------- .../stock/doctype/stock_entry/stock_entry.py | 23 +- .../stock_entry_detail.json | 9 +- 4 files changed, 133 insertions(+), 335 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 0ba85078ea..6bd2a985e2 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -808,8 +808,11 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite items = frappe.db.sql(query, { "parent": bom, "qty": qty, "bom": bom, "company": company }, as_dict=True) elif fetch_scrap_items: - query = query.format(table="BOM Scrap Item", where_conditions="", - select_columns=", bom_item.idx, item.description", is_stock_item=is_stock_item, qty_field="stock_qty") + query = query.format( + table="BOM Scrap Item", where_conditions="", + select_columns=", bom_item.idx, item.description, is_process_loss", + is_stock_item=is_stock_item, qty_field="stock_qty" + ) items = frappe.db.sql(query, { "qty": qty, "bom": bom, "company": company }, as_dict=True) else: diff --git a/erpnext/manufacturing/doctype/bom_scrap_item/bom_scrap_item.json b/erpnext/manufacturing/doctype/bom_scrap_item/bom_scrap_item.json index 9f7091dd8d..7018082e40 100644 --- a/erpnext/manufacturing/doctype/bom_scrap_item/bom_scrap_item.json +++ b/erpnext/manufacturing/doctype/bom_scrap_item/bom_scrap_item.json @@ -1,345 +1,112 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2016-09-26 02:19:21.642081", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, + "actions": [], + "creation": "2016-09-26 02:19:21.642081", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "item_code", + "column_break_2", + "item_name", + "is_process_loss", + "quantity_and_rate", + "stock_qty", + "rate", + "amount", + "column_break_6", + "stock_uom", + "base_rate", + "base_amount" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "item_code", - "fieldtype": "Link", - "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": "Item Code", - "length": 0, - "no_copy": 0, - "options": "Item", - "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, - "unique": 0 - }, + "fieldname": "item_code", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Item Code", + "options": "Item", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "item_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": "Item 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": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, + "fieldname": "item_name", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Item Name" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "quantity_and_rate", - "fieldtype": "Section Break", - "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": "Quantity and Rate", - "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 - }, + "fieldname": "quantity_and_rate", + "fieldtype": "Section Break", + "label": "Quantity and Rate" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "stock_qty", - "fieldtype": "Float", - "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": "Qty", - "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, - "unique": 0 - }, + "fieldname": "stock_qty", + "fieldtype": "Float", + "in_list_view": 1, + "label": "Qty", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "rate", - "fieldtype": "Currency", - "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": "Rate", - "length": 0, - "no_copy": 0, - "options": "currency", - "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 - }, + "fieldname": "rate", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Rate", + "options": "currency" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "amount", - "fieldtype": "Currency", - "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": "Amount", - "length": 0, - "no_copy": 0, - "options": "currency", - "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 - }, + "fieldname": "amount", + "fieldtype": "Currency", + "label": "Amount", + "options": "currency", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_6", - "fieldtype": "Column Break", - "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, - "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 - }, + "fieldname": "column_break_6", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "stock_uom", - "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": "Stock UOM", - "length": 0, - "no_copy": 0, - "options": "UOM", - "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 - }, + "fieldname": "stock_uom", + "fieldtype": "Link", + "label": "Stock UOM", + "options": "UOM", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "base_rate", - "fieldtype": "Currency", - "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": "Basic Rate (Company Currency)", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 - }, + "fieldname": "base_rate", + "fieldtype": "Currency", + "label": "Basic Rate (Company Currency)", + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "base_amount", - "fieldtype": "Currency", - "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": "Basic Amount (Company Currency)", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 + "fieldname": "base_amount", + "fieldtype": "Currency", + "label": "Basic Amount (Company Currency)", + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "column_break_2", + "fieldtype": "Column Break" + }, + { + "default": "0", + "fieldname": "is_process_loss", + "fieldtype": "Check", + "label": "Is Process Loss" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 1, - "max_attachments": 0, - "modified": "2017-07-04 16:04:32.442287", - "modified_by": "Administrator", - "module": "Manufacturing", - "name": "BOM Scrap Item", - "name_case": "", - "owner": "Administrator", - "permissions": [], - "quick_entry": 1, - "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 + ], + "istable": 1, + "links": [], + "modified": "2021-06-22 16:46:12.153311", + "modified_by": "Administrator", + "module": "Manufacturing", + "name": "BOM Scrap Item", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 } \ 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 7b31d2fdf2..478d5b2e0f 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -463,7 +463,7 @@ class StockEntry(StockController): """ # Set rate for outgoing items outgoing_items_cost = self.set_rate_for_outgoing_items(reset_outgoing_rate, raise_error_if_no_rate) - finished_item_qty = sum(d.transfer_qty for d in self.items if d.is_finished_item) + finished_item_qty = sum(d.transfer_qty for d in self.items if d.is_finished_item or d.is_process_loss) # Set basic rate for incoming items for d in self.get('items'): @@ -484,6 +484,8 @@ class StockEntry(StockController): raise_error_if_no_rate=raise_error_if_no_rate) d.basic_rate = flt(d.basic_rate, d.precision("basic_rate")) + if d.is_process_loss: + d.basic_rate = flt(0.) d.basic_amount = flt(flt(d.transfer_qty) * flt(d.basic_rate), d.precision("basic_amount")) def set_rate_for_outgoing_items(self, reset_outgoing_rate=True, raise_error_if_no_rate=True): @@ -1041,6 +1043,7 @@ class StockEntry(StockController): self.set_scrap_items() self.set_actual_qty() + self.adjust_qty_for_process_loss() self.validate_customer_provided_item() self.calculate_rate_and_amount() @@ -1398,6 +1401,7 @@ class StockEntry(StockController): get_default_cost_center(item_dict[d], company = self.company)) se_child.is_finished_item = item_dict[d].get("is_finished_item", 0) se_child.is_scrap_item = item_dict[d].get("is_scrap_item", 0) + se_child.is_process_loss = item_dict[d].get("is_process_loss", 0) for field in ["idx", "po_detail", "original_item", "expense_account", "description", "item_name", "serial_no", "batch_no"]: @@ -1576,6 +1580,23 @@ class StockEntry(StockController): if material_request and material_request not in material_requests: material_requests.append(material_request) frappe.db.set_value('Material Request', material_request, 'transfer_status', status) + + def adjust_qty_for_process_loss(self): + process_loss_dict = {} + for d in self.get("items"): + if not d.is_process_loss: + continue + if d.item_code not in process_loss_dict: + process_loss_dict[d.item_code] = [flt(0), flt(0)] + process_loss_dict[d.item_code][0] += flt(d.transfer_qty) + process_loss_dict[d.item_code][1] += flt(d.qty) + + for d in self.get("items"): + if not d.is_finished_item or d.item_code not in process_loss_dict: + continue + # Assumption: 1 FG has 1 row. + d.transfer_qty -= process_loss_dict[d.item_code][0] + d.qty -= process_loss_dict[d.item_code][1] def set_serial_no_batch_for_finished_good(self): args = {} 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 22f412a298..df65706c39 100644 --- a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json +++ b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json @@ -19,6 +19,7 @@ "is_finished_item", "is_scrap_item", "quality_inspection", + "is_process_loss", "subcontracted_item", "section_break_8", "description", @@ -543,13 +544,19 @@ "no_copy": 1, "print_hide": 1, "read_only": 1 + }, + { + "default": "0", + "fieldname": "is_process_loss", + "fieldtype": "Check", + "label": "Is Process Loss" } ], "idx": 1, "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2021-06-21 16:03:18.834880", + "modified": "2021-06-22 16:47:11.268975", "modified_by": "Administrator", "module": "Stock", "name": "Stock Entry Detail", From 984c97ed4ee80c72edf8f12776ab3a8d99605424 Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Wed, 23 Jun 2021 15:06:00 +0530 Subject: [PATCH 02/54] feat: add is process loss autoset and validation --- erpnext/manufacturing/doctype/bom/bom.js | 15 +++++++++++++++ erpnext/manufacturing/doctype/bom/bom.py | 10 ++++++++++ 2 files changed, 25 insertions(+) diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js index 3f50b41be1..a5ce8c6195 100644 --- a/erpnext/manufacturing/doctype/bom/bom.js +++ b/erpnext/manufacturing/doctype/bom/bom.js @@ -379,6 +379,9 @@ erpnext.bom.BomController = class BomController extends erpnext.TransactionContr child.bom_no = ''; } + if (scrap_items) { + set_is_process_loss(doc, cdt, cdn) + } get_bom_material_detail(doc, cdt, cdn, scrap_items); } @@ -446,6 +449,10 @@ var get_bom_material_detail = function(doc, cdt, cdn, scrap_items) { }, callback: function(r) { d = locals[cdt][cdn]; + if (d.is_process_loss) { + r.message.rate = 0 + r.message.base_rate = 0 + } $.extend(d, r.message); refresh_field("items"); refresh_field("scrap_items"); @@ -655,3 +662,11 @@ frappe.ui.form.on("BOM", "with_operations", function(frm) { frm.set_value("operations", []); } }); + +function set_is_process_loss(doc, cdt, cdn) { + const row = locals[cdt][cdn] + if (row.item_code === doc.item) { + row.is_process_loss = 1 + frappe.msgprint(__("Item:") + ` ${row.item_code} ` + __("set as process loss.")) + } +} diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 6bd2a985e2..de0c521cf5 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -155,6 +155,7 @@ class BOM(WebsiteGenerator): self.update_stock_qty() self.update_cost(update_parent=False, from_child_bom=True, update_hour_rate = False, save=False) self.set_bom_level() + self.validate_scrap_items() def get_context(self, context): context.parents = [{'name': 'boms', 'title': _('All BOMs') }] @@ -691,6 +692,15 @@ class BOM(WebsiteGenerator): if update: self.db_set("bom_level", self.bom_level) + def validate_scrap_items(self): + for item in self.scrap_items: + if item.item_code == self.item and not item.is_process_loss: + frappe.throw(_('Item:') + f' {item.item_code} ' +\ + _('in Scrap/Loss Items table should have Is Process Loss checked.')) + elif item.item_code != self.item and item.is_process_loss: + frappe.throw(_('Item:') + f' {item.item_code} ' +\ + _('in Scrap/Loss Items table should not have Is Process Loss checked.')) + def get_bom_item_rate(args, bom_doc): if bom_doc.rm_cost_as_per == 'Valuation Rate': rate = get_valuation_rate(args) * (args.get("conversion_factor") or 1) From 3df8d0cdf0f00e78c64ac3044f13e6e50f0010d5 Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Wed, 23 Jun 2021 15:30:48 +0530 Subject: [PATCH 03/54] fix: add warehouse and unset is scrap for process loss items --- erpnext/stock/doctype/stock_entry/stock_entry.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 478d5b2e0f..4f724ec637 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -1043,7 +1043,7 @@ class StockEntry(StockController): self.set_scrap_items() self.set_actual_qty() - self.adjust_qty_for_process_loss() + self.update_items_for_process_loss() self.validate_customer_provided_item() self.calculate_rate_and_amount() @@ -1581,11 +1581,17 @@ class StockEntry(StockController): material_requests.append(material_request) frappe.db.set_value('Material Request', material_request, 'transfer_status', status) - def adjust_qty_for_process_loss(self): + def update_items_for_process_loss(self): process_loss_dict = {} for d in self.get("items"): if not d.is_process_loss: continue + + scrap_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_scrap_warehouse") + if scrap_warehouse is not None: + d.t_warehouse = scrap_warehouse + d.is_scrap_item = 0 + if d.item_code not in process_loss_dict: process_loss_dict[d.item_code] = [flt(0), flt(0)] process_loss_dict[d.item_code][0] += flt(d.transfer_qty) @@ -1594,7 +1600,7 @@ class StockEntry(StockController): for d in self.get("items"): if not d.is_finished_item or d.item_code not in process_loss_dict: continue - # Assumption: 1 FG has 1 row. + # Assumption: 1 finished item has 1 row. d.transfer_qty -= process_loss_dict[d.item_code][0] d.qty -= process_loss_dict[d.item_code][1] From 7433b971060a671971af0c23e64efd4dab951799 Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Thu, 24 Jun 2021 15:05:52 +0530 Subject: [PATCH 04/54] refactor: shift auto entry of is process loss check, update validations --- erpnext/manufacturing/doctype/bom/bom.js | 45 ++++++++++++++++++------ erpnext/manufacturing/doctype/bom/bom.py | 22 +++++++++--- 2 files changed, 52 insertions(+), 15 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js index a5ce8c6195..dd437dd555 100644 --- a/erpnext/manufacturing/doctype/bom/bom.js +++ b/erpnext/manufacturing/doctype/bom/bom.js @@ -379,9 +379,6 @@ erpnext.bom.BomController = class BomController extends erpnext.TransactionContr child.bom_no = ''; } - if (scrap_items) { - set_is_process_loss(doc, cdt, cdn) - } get_bom_material_detail(doc, cdt, cdn, scrap_items); } @@ -450,9 +447,10 @@ var get_bom_material_detail = function(doc, cdt, cdn, scrap_items) { callback: function(r) { d = locals[cdt][cdn]; if (d.is_process_loss) { - r.message.rate = 0 - r.message.base_rate = 0 + r.message.rate = 0; + r.message.base_rate = 0; } + $.extend(d, r.message); refresh_field("items"); refresh_field("scrap_items"); @@ -661,12 +659,37 @@ frappe.ui.form.on("BOM", "with_operations", function(frm) { if(!cint(frm.doc.with_operations)) { frm.set_value("operations", []); } + toggle_operations(frm); }); -function set_is_process_loss(doc, cdt, cdn) { - const row = locals[cdt][cdn] - if (row.item_code === doc.item) { - row.is_process_loss = 1 - frappe.msgprint(__("Item:") + ` ${row.item_code} ` + __("set as process loss.")) - } +frappe.ui.form.on("BOM Scrap Item", { + item_code(frm, cdt, cdn) { + const { item_code } = locals[cdt][cdn]; + if (item_code === frm.doc.item) { + locals[cdt][cdn].is_process_loss = 1; + trigger_process_loss_qty_prompt(frm, cdt, cdn, item_code) + } + }, +}); + +function trigger_process_loss_qty_prompt(frm, cdt, cdn, item_code) { + frappe.prompt( + { + fieldname: "percent", + fieldtype: "Percent", + label: __("% Finished Item Quantity"), + description: + __("Set quantity of process loss item:") + + ` ${item_code} ` + + __("as a percentage of finished item quantity"), + }, + (data) => { + const row = locals[cdt][cdn]; + row.stock_qty = (frm.doc.quantity * data.percent) / 100; + row.qty = row.stock_qty / (row.conversion_factor ?? 1); + refresh_field("scrap_items"); + }, + __("Set Process Loss Item Quantity"), + __("Set Quantity") + ); } diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index de0c521cf5..b90d54dea5 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -695,11 +695,25 @@ class BOM(WebsiteGenerator): def validate_scrap_items(self): for item in self.scrap_items: if item.item_code == self.item and not item.is_process_loss: - frappe.throw(_('Item:') + f' {item.item_code} ' +\ - _('in Scrap/Loss Items table should have Is Process Loss checked.')) + frappe.throw(_('Scrap/Loss Item:') + f' {frappe.bold(item.item_code)} ' +\ + _('should have') + ' ' + frappe.bold(_('Is Process Loss')) + ' ' + ('checked.')) elif item.item_code != self.item and item.is_process_loss: - frappe.throw(_('Item:') + f' {item.item_code} ' +\ - _('in Scrap/Loss Items table should not have Is Process Loss checked.')) + frappe.throw(_('Scrap/Loss Item:') + f' {frappe.bold(item.item_code)} ' +\ + _('should not have') + ' ' + frappe.bold(_('Is Process Loss')) + ' ' + ('checked.')) + + stock_uom = item.stock_uom + must_be_whole_number = frappe.get_value("UOM", stock_uom, "must_be_whole_number") + if item.is_process_loss and must_be_whole_number: + frappe.throw(_('Item:') + f' {frappe.bold(item.item_code)} ' +\ + _('with Stock UOM:') + f' {frappe.bold(stock_uom)} '+\ + _('cannot be a Scrap/Loss Item.')) + + if item.is_process_loss and (item.stock_qty >= self.quantity): + frappe.throw(_('Scrap/Loss Item:') + f' {item.item_code} ' +\ + _('should have') +' '+frappe.bold(_('Qty')) +\ + ' ' + _('less than finished goods') + ' ' +\ + frappe.bold(_('Quantity.'))) + def get_bom_item_rate(args, bom_doc): if bom_doc.rm_cost_as_per == 'Valuation Rate': From 8ecb14623175e8a789bd82a9bbeb1738787046f2 Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Fri, 25 Jun 2021 14:20:22 +0530 Subject: [PATCH 05/54] test: add bom tests for process loss val, add se test for qty calc --- erpnext/manufacturing/doctype/bom/test_bom.py | 73 +++++++++++++++++++ .../tests/test_stock_entry_for_manufacture.js | 27 +++++++ 2 files changed, 100 insertions(+) create mode 100644 erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_manufacture.js diff --git a/erpnext/manufacturing/doctype/bom/test_bom.py b/erpnext/manufacturing/doctype/bom/test_bom.py index c89f7d66fd..e61bb52592 100644 --- a/erpnext/manufacturing/doctype/bom/test_bom.py +++ b/erpnext/manufacturing/doctype/bom/test_bom.py @@ -280,6 +280,38 @@ class TestBOM(unittest.TestCase): self.assertEqual(reqd_item.qty, created_item.qty) self.assertEqual(reqd_item.exploded_qty, created_item.exploded_qty) + def test_bom_with_process_loss_item(self): + fg_item_non_whole, fg_item_whole, bom_item = create_process_loss_bom_items() + + if frappe.db.exists("BOM", f"BOM-{fg_item_non_whole.item_code}-001") is None: + bom_doc = create_bom_with_process_loss_item( + fg_item_non_whole, bom_item, 0.25, 0, 1 + ) + bom_doc.submit() + + bom_doc = create_bom_with_process_loss_item( + fg_item_non_whole, bom_item, 2, 0 + ) + # PL Item qty can't be >= FG Item qty + self.assertRaises(frappe.ValidationError, bom_doc.submit) + + bom_doc = create_bom_with_process_loss_item( + fg_item_non_whole, bom_item, 1, 100 + ) + # PL Item rate has to be 0 + self.assertRaises(frappe.ValidationError, bom_doc.submit) + + bom_doc = create_bom_with_process_loss_item( + fg_item_whole, bom_item, 0.25, 0 + ) + # Items with whole UOMs can't be PL Items + self.assertRaises(frappe.ValidationError, bom_doc.submit) + + bom_doc = create_bom_with_process_loss_item( + fg_item_non_whole, bom_item, 0.25, 0, is_process_loss=0 + ) + # FG Items in Scrap/Loss Table should have Is Process Loss set + self.assertRaises(frappe.ValidationError, bom_doc.submit) def get_default_bom(item_code="_Test FG Item 2"): return frappe.db.get_value("BOM", {"item": item_code, "is_active": 1, "is_default": 1}) @@ -353,3 +385,44 @@ def reset_item_valuation_rate(item_code, warehouse_list=None, qty=None, rate=Non for warehouse in warehouse_list: create_stock_reconciliation(item_code=item_code, warehouse=warehouse, qty=qty, rate=rate) + +def create_bom_with_process_loss_item( + fg_item, bom_item, scrap_qty, scrap_rate, fg_qty=2, is_process_loss=1): + bom_doc = frappe.new_doc("BOM") + bom_doc.item = fg_item.item_code + bom_doc.quantity = fg_qty + bom_doc.append("items", { + "item_code": bom_item.item_code, + "qty": 1, + "uom": bom_item.stock_uom, + "stock_uom": bom_item.stock_uom, + "rate": 100.0 + }) + bom_doc.append("scrap_items", { + "item_code": fg_item.item_code, + "qty": scrap_qty, + "stock_qty": scrap_qty, + "uom": fg_item.stock_uom, + "stock_uom": fg_item.stock_uom, + "rate": scrap_rate, + "is_process_loss": is_process_loss + }) + return bom_doc + +def create_process_loss_bom_items(): + item_list = [ + ("_Test Item - Non Whole UOM", "Kg"), + ("_Test Item - Whole UOM", "Unit"), + ( "_Test PL BOM Item", "Unit") + ] + return [create_process_loss_bom_item(it) for it in item_list] + +def create_process_loss_bom_item(item_tuple): + item_code, stock_uom = item_tuple + if frappe.db.exists("Item", item_code) is None: + return make_item( + item_code, + {'stock_uom':stock_uom, 'valuation_rate':100} + ) + else: + return frappe.get_doc("Item", item_code) diff --git a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_manufacture.js b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_manufacture.js new file mode 100644 index 0000000000..d74f31672d --- /dev/null +++ b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_manufacture.js @@ -0,0 +1,27 @@ +QUnit.module('Stock'); + +QUnit.test("test manufacture from bom", function(assert) { + assert.expect(2); + let done = assert.async(); + frappe.run_serially([ + () => { + return frappe.tests.make("Stock Entry", [ + {purpose:"Manufacture"}, + {from_bom:1}, + {bom_no:"BOM-_Test Item - Non Whole UOM-001"}, + {fg_completed_qty:2} + ]); + }, + () => cur_frm.save(), + () => frappe.click_button("Update Rate and Availability"), + () => { + assert.ok(cur_frm.doc.items[1] === 0.75, " Finished Item Qty correct"); + assert.ok(cur_frm.doc.items[2] === 0.25, " Process Loss Item Qty correct"); + }, + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), + () => done() + ]); +}); + From cdf253aeb4b248846c2979ed41f2f239ab75c804 Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Fri, 25 Jun 2021 14:21:12 +0530 Subject: [PATCH 06/54] fix: add more validations, remove source wh req for pl item --- erpnext/manufacturing/doctype/bom/bom.py | 29 ++++++++++--------- .../stock/doctype/stock_entry/stock_entry.py | 2 +- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index b90d54dea5..8f01edd0e2 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -695,25 +695,28 @@ class BOM(WebsiteGenerator): def validate_scrap_items(self): for item in self.scrap_items: if item.item_code == self.item and not item.is_process_loss: - frappe.throw(_('Scrap/Loss Item:') + f' {frappe.bold(item.item_code)} ' +\ - _('should have') + ' ' + frappe.bold(_('Is Process Loss')) + ' ' + ('checked.')) + frappe.throw(_('Scrap/Loss Item:') + f' {frappe.bold(item.item_code)} ' + + _('should have') + ' ' + frappe.bold(_('Is Process Loss')) + ' ' + ('checked')) elif item.item_code != self.item and item.is_process_loss: - frappe.throw(_('Scrap/Loss Item:') + f' {frappe.bold(item.item_code)} ' +\ - _('should not have') + ' ' + frappe.bold(_('Is Process Loss')) + ' ' + ('checked.')) + frappe.throw(_('Scrap/Loss Item:') + f' {frappe.bold(item.item_code)} ' + + _('should not have') + ' ' + frappe.bold(_('Is Process Loss')) + ' ' + ('checked')) - stock_uom = item.stock_uom - must_be_whole_number = frappe.get_value("UOM", stock_uom, "must_be_whole_number") + must_be_whole_number = frappe.get_value("UOM", item.stock_uom, "must_be_whole_number") if item.is_process_loss and must_be_whole_number: - frappe.throw(_('Item:') + f' {frappe.bold(item.item_code)} ' +\ - _('with Stock UOM:') + f' {frappe.bold(stock_uom)} '+\ - _('cannot be a Scrap/Loss Item.')) + frappe.throw(_('Item:') + f' {frappe.bold(item.item_code)} ' + + _('with Stock UOM:') + f' {frappe.bold(item.stock_uom)} ' + + _('cannot be a Scrap/Loss Item')) if item.is_process_loss and (item.stock_qty >= self.quantity): - frappe.throw(_('Scrap/Loss Item:') + f' {item.item_code} ' +\ - _('should have') +' '+frappe.bold(_('Qty')) +\ - ' ' + _('less than finished goods') + ' ' +\ - frappe.bold(_('Quantity.'))) + frappe.throw(_('Scrap/Loss Item:') + f' {item.item_code} ' + + _('should have') +' '+frappe.bold(_('Qty')) + ' ' + + _('less than finished goods') + ' ' + frappe.bold(_('Quantity'))) + if item.is_process_loss and (item.rate > 0): + frappe.throw(_('Scrap/Loss Item:') + f' {item.item_code} ' + + _('should have') + ' ' + frappe.bold(_('Rate')) + + ' ' + _('set to 0 because') + ' ' + + frappe.bold(_('Is Process Loss')) + ' ' + _('is checked')) def get_bom_item_rate(args, bom_doc): if bom_doc.rm_cost_as_per == 'Valuation Rate': diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 4f724ec637..21c0e75393 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -334,7 +334,7 @@ class StockEntry(StockController): if self.purpose == "Manufacture": if validate_for_manufacture: - if d.is_finished_item or d.is_scrap_item: + if d.is_finished_item or d.is_scrap_item or d.is_process_loss: d.s_warehouse = None if not d.t_warehouse: frappe.throw(_("Target warehouse is mandatory for row {0}").format(d.idx)) From 55acb2e8434747658ea6cfd319840a55e11c0380 Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Fri, 25 Jun 2021 14:46:08 +0530 Subject: [PATCH 07/54] fix: sider --- erpnext/manufacturing/doctype/bom/test_bom.py | 2 +- .../stock_entry/tests/test_stock_entry_for_manufacture.js | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/test_bom.py b/erpnext/manufacturing/doctype/bom/test_bom.py index e61bb52592..fe7a8f151b 100644 --- a/erpnext/manufacturing/doctype/bom/test_bom.py +++ b/erpnext/manufacturing/doctype/bom/test_bom.py @@ -413,7 +413,7 @@ def create_process_loss_bom_items(): item_list = [ ("_Test Item - Non Whole UOM", "Kg"), ("_Test Item - Whole UOM", "Unit"), - ( "_Test PL BOM Item", "Unit") + ("_Test PL BOM Item", "Unit") ] return [create_process_loss_bom_item(it) for it in item_list] diff --git a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_manufacture.js b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_manufacture.js index d74f31672d..285ae4f59e 100644 --- a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_manufacture.js +++ b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_manufacture.js @@ -6,10 +6,10 @@ QUnit.test("test manufacture from bom", function(assert) { frappe.run_serially([ () => { return frappe.tests.make("Stock Entry", [ - {purpose:"Manufacture"}, - {from_bom:1}, - {bom_no:"BOM-_Test Item - Non Whole UOM-001"}, - {fg_completed_qty:2} + { purpose: "Manufacture" }, + { from_bom: 1 }, + { bom_no: "BOM-_Test Item - Non Whole UOM-001" }, + { fg_completed_qty: 2 } ]); }, () => cur_frm.save(), From 47a4a3d88898fc13800d90ce9e9b7f62f0b7e272 Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Fri, 25 Jun 2021 15:14:55 +0530 Subject: [PATCH 08/54] refactor: polyfill ?? --- erpnext/manufacturing/doctype/bom/bom.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js index dd437dd555..7e755d424c 100644 --- a/erpnext/manufacturing/doctype/bom/bom.js +++ b/erpnext/manufacturing/doctype/bom/bom.js @@ -686,7 +686,7 @@ function trigger_process_loss_qty_prompt(frm, cdt, cdn, item_code) { (data) => { const row = locals[cdt][cdn]; row.stock_qty = (frm.doc.quantity * data.percent) / 100; - row.qty = row.stock_qty / (row.conversion_factor ?? 1); + row.qty = row.stock_qty / (row.conversion_factor || 1); refresh_field("scrap_items"); }, __("Set Process Loss Item Quantity"), From 23ef51a9819eda14c89b963b1e64a4555b2f95a7 Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Fri, 25 Jun 2021 15:48:28 +0530 Subject: [PATCH 09/54] fix: sider --- erpnext/manufacturing/doctype/bom/bom.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js index 7e755d424c..7de7e17abc 100644 --- a/erpnext/manufacturing/doctype/bom/bom.js +++ b/erpnext/manufacturing/doctype/bom/bom.js @@ -667,7 +667,7 @@ frappe.ui.form.on("BOM Scrap Item", { const { item_code } = locals[cdt][cdn]; if (item_code === frm.doc.item) { locals[cdt][cdn].is_process_loss = 1; - trigger_process_loss_qty_prompt(frm, cdt, cdn, item_code) + trigger_process_loss_qty_prompt(frm, cdt, cdn, item_code); } }, }); From ad73d3fbfb7894c74a259a489da5cba72d95f15f Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Mon, 9 Aug 2021 17:37:17 +0530 Subject: [PATCH 10/54] refactor: validation error message formatting --- erpnext/manufacturing/doctype/bom/bom.py | 28 ++++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 8f01edd0e2..8d9b10ddc1 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -694,29 +694,29 @@ class BOM(WebsiteGenerator): def validate_scrap_items(self): for item in self.scrap_items: + msg = "" if item.item_code == self.item and not item.is_process_loss: - frappe.throw(_('Scrap/Loss Item:') + f' {frappe.bold(item.item_code)} ' + - _('should have') + ' ' + frappe.bold(_('Is Process Loss')) + ' ' + ('checked')) + msg = _('Scrap/Loss Item: {0} should have Is Process Loss checked') \ + .format(frappe.bold(item.item_code)) elif item.item_code != self.item and item.is_process_loss: - frappe.throw(_('Scrap/Loss Item:') + f' {frappe.bold(item.item_code)} ' + - _('should not have') + ' ' + frappe.bold(_('Is Process Loss')) + ' ' + ('checked')) + msg = _('Scrap/Loss Item: {0} should not have Is Process Loss checked') \ + .format(frappe.bold(item.item_code)) must_be_whole_number = frappe.get_value("UOM", item.stock_uom, "must_be_whole_number") if item.is_process_loss and must_be_whole_number: - frappe.throw(_('Item:') + f' {frappe.bold(item.item_code)} ' + - _('with Stock UOM:') + f' {frappe.bold(item.stock_uom)} ' + - _('cannot be a Scrap/Loss Item')) + msg = _("Item: {0} with Stock UOM: {1} cannot be a Scrap/Loss Item") \ + .format(frappe.bold(item.item_code), frappe.bold(item.stock_uom)) if item.is_process_loss and (item.stock_qty >= self.quantity): - frappe.throw(_('Scrap/Loss Item:') + f' {item.item_code} ' + - _('should have') +' '+frappe.bold(_('Qty')) + ' ' + - _('less than finished goods') + ' ' + frappe.bold(_('Quantity'))) + msg = _("Scrap/Loss Item: {0} should have Qty less than finished goods Quantity") \ + .format(frappe.bold(item.item_code)) if item.is_process_loss and (item.rate > 0): - frappe.throw(_('Scrap/Loss Item:') + f' {item.item_code} ' + - _('should have') + ' ' + frappe.bold(_('Rate')) + - ' ' + _('set to 0 because') + ' ' + - frappe.bold(_('Is Process Loss')) + ' ' + _('is checked')) + msg = _("Scrap/Loss Item: {0} should have Rate set to 0 because Is Process Loss is checked") \ + .format(frappe.bold(item.item_code)) + + if msg: + frappe.throw(msg, title=_("Note")) def get_bom_item_rate(args, bom_doc): if bom_doc.rm_cost_as_per == 'Valuation Rate': From 2670adc0c00a1ea48e19285156f65a0c23b4a42c Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Tue, 10 Aug 2021 12:23:19 +0530 Subject: [PATCH 11/54] test: check manufacture completion qty in se and wo --- erpnext/manufacturing/doctype/bom/test_bom.py | 2 +- .../doctype/work_order/test_work_order.py | 58 +++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/bom/test_bom.py b/erpnext/manufacturing/doctype/bom/test_bom.py index fe7a8f151b..6e17f2a831 100644 --- a/erpnext/manufacturing/doctype/bom/test_bom.py +++ b/erpnext/manufacturing/doctype/bom/test_bom.py @@ -283,7 +283,7 @@ class TestBOM(unittest.TestCase): def test_bom_with_process_loss_item(self): fg_item_non_whole, fg_item_whole, bom_item = create_process_loss_bom_items() - if frappe.db.exists("BOM", f"BOM-{fg_item_non_whole.item_code}-001") is None: + if not frappe.db.exists("BOM", f"BOM-{fg_item_non_whole.item_code}-001"): bom_doc = create_bom_with_process_loss_item( fg_item_non_whole, bom_item, 0.25, 0, 1 ) diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index bf1ccb7159..7f943d9cbb 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -690,6 +690,64 @@ class TestWorkOrder(unittest.TestCase): self.assertRaises(frappe.ValidationError, make_stock_entry, wo.name, 'Material Transfer for Manufacture') + def test_wo_completion_with_pl_bom(self): + from erpnext.manufacturing.doctype.bom.test_bom import create_process_loss_bom_items + from erpnext.manufacturing.doctype.bom.test_bom import create_bom_with_process_loss_item + + qty = fg_qty = 4 + scrap_qty = 0.25 # bom item qty = 1, consider as 25% of FG + source_warehouse = "Stores - _TC" + wip_warehouse = "_Test Warehouse - _TC" + fg_item_non_whole, _, bom_item = create_process_loss_bom_items() + + test_stock_entry.make_stock_entry(item_code=bom_item.item_code, + target=source_warehouse, qty=4, basic_rate=100) + + bom_no = f"BOM-{fg_item_non_whole.item_code}-001" + if not frappe.db.exists("BOM", bom_no): + bom_doc = create_bom_with_process_loss_item( + fg_item_non_whole, bom_item, scrap_qty=scrap_qty, + scrap_rate=0, fg_qty=fg_qty, is_process_loss=1 + ) + bom_doc.submit() + + wo = make_wo_order_test_record( + production_item=fg_item_non_whole.item_code, + bom_no=bom_no, + wip_warehouse=wip_warehouse, + qty=qty, + skip_transfer=1, + stock_uom=fg_item_non_whole.stock_uom, + ) + + se = frappe.get_doc( + make_stock_entry(wo.name, "Material Transfer for Manufacture", 4) + ) + se.get("items")[0].s_warehouse = "Stores - _TC" + se.insert() + se.submit() + + se = frappe.get_doc( + make_stock_entry(wo.name, "Manufacture", 4) + ) + se.insert() + se.submit() + + # Testing stock entry values + items = se.get("items") + self.assertEqual(len(items), 3, "There should be 3 items including process loss.") + + source_item, fg_item, pl_item = items + + total_pl_qty = scrap_qty * fg_qty + actual_fg_qty = fg_qty - total_pl_qty + + self.assertEqual(pl_item.qty, total_pl_qty) + self.assertEqual(fg_item.qty, actual_fg_qty) + + # Testing Work Order values + self.assertEqual( frappe.db.get_value("Work Order", wo.name, "produced_qty"), actual_fg_qty) + def get_scrap_item_details(bom_no): scrap_items = {} for item in frappe.db.sql("""select item_code, stock_qty from `tabBOM Scrap Item` From cc177f34158d3ffabdbfbb2ace500fa17a7b7c9d Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Tue, 10 Aug 2021 14:42:39 +0530 Subject: [PATCH 12/54] fix: wo tests, sider, account for pl in se validation --- .../doctype/work_order/test_work_order.py | 16 ++++++++-------- erpnext/stock/doctype/stock_entry/stock_entry.py | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index 7f943d9cbb..d6a20df0c8 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -694,7 +694,7 @@ class TestWorkOrder(unittest.TestCase): from erpnext.manufacturing.doctype.bom.test_bom import create_process_loss_bom_items from erpnext.manufacturing.doctype.bom.test_bom import create_bom_with_process_loss_item - qty = fg_qty = 4 + qty = 4 scrap_qty = 0.25 # bom item qty = 1, consider as 25% of FG source_warehouse = "Stores - _TC" wip_warehouse = "_Test Warehouse - _TC" @@ -707,7 +707,7 @@ class TestWorkOrder(unittest.TestCase): if not frappe.db.exists("BOM", bom_no): bom_doc = create_bom_with_process_loss_item( fg_item_non_whole, bom_item, scrap_qty=scrap_qty, - scrap_rate=0, fg_qty=fg_qty, is_process_loss=1 + scrap_rate=0, fg_qty=1, is_process_loss=1 ) bom_doc.submit() @@ -721,32 +721,32 @@ class TestWorkOrder(unittest.TestCase): ) se = frappe.get_doc( - make_stock_entry(wo.name, "Material Transfer for Manufacture", 4) + make_stock_entry(wo.name, "Material Transfer for Manufacture", qty) ) se.get("items")[0].s_warehouse = "Stores - _TC" se.insert() se.submit() se = frappe.get_doc( - make_stock_entry(wo.name, "Manufacture", 4) + make_stock_entry(wo.name, "Manufacture", qty) ) se.insert() se.submit() # Testing stock entry values items = se.get("items") - self.assertEqual(len(items), 3, "There should be 3 items including process loss.") + self.assertEqual(len(items), 4, "There should be 3 items including process loss.") source_item, fg_item, pl_item = items - total_pl_qty = scrap_qty * fg_qty - actual_fg_qty = fg_qty - total_pl_qty + total_pl_qty = qty * scrap_qty + actual_fg_qty = qty - total_pl_qty self.assertEqual(pl_item.qty, total_pl_qty) self.assertEqual(fg_item.qty, actual_fg_qty) # Testing Work Order values - self.assertEqual( frappe.db.get_value("Work Order", wo.name, "produced_qty"), actual_fg_qty) + self.assertEqual(frappe.db.get_value("Work Order", wo.name, "produced_qty"), actual_fg_qty) def get_scrap_item_details(bom_no): scrap_items = {} diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 21c0e75393..8ea1275283 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -271,7 +271,7 @@ class StockEntry(StockController): item_wise_qty = {} if self.purpose == "Manufacture" and self.work_order: for d in self.items: - if d.is_finished_item: + if d.is_finished_item or d.is_process_loss: item_wise_qty.setdefault(d.item_code, []).append(d.qty) for item_code, qty_list in iteritems(item_wise_qty): From dddc29fdc1a6bb634ed12cc9ea6b364784ebb7c6 Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Thu, 19 Aug 2021 17:55:24 +0530 Subject: [PATCH 13/54] feat: initialize party link for customer & suppliers --- .../accounts/doctype/party_link/__init__.py | 0 .../accounts/doctype/party_link/party_link.js | 41 ++++++++++ .../doctype/party_link/party_link.json | 78 +++++++++++++++++++ .../accounts/doctype/party_link/party_link.py | 12 +++ .../doctype/party_link/test_party_link.py | 8 ++ 5 files changed, 139 insertions(+) create mode 100644 erpnext/accounts/doctype/party_link/__init__.py create mode 100644 erpnext/accounts/doctype/party_link/party_link.js create mode 100644 erpnext/accounts/doctype/party_link/party_link.json create mode 100644 erpnext/accounts/doctype/party_link/party_link.py create mode 100644 erpnext/accounts/doctype/party_link/test_party_link.py diff --git a/erpnext/accounts/doctype/party_link/__init__.py b/erpnext/accounts/doctype/party_link/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/accounts/doctype/party_link/party_link.js b/erpnext/accounts/doctype/party_link/party_link.js new file mode 100644 index 0000000000..966a5f5d30 --- /dev/null +++ b/erpnext/accounts/doctype/party_link/party_link.js @@ -0,0 +1,41 @@ +// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Party Link', { + refresh: function(frm) { + frm.set_query('party_type', 'links', () => { + return { + filters: { + name: ['in', party_types] + } + }; + }); + + frm.set_query('primary_role', () => { + return { + filters: { + name: ['in', ['Customer', 'Supplier']] + } + }; + }); + + frm.set_query('secondary_role', () => { + let party_types = Object.keys(frappe.boot.party_account_types) + .filter(p => p != frm.doc.primary_role); + return { + filters: { + name: ['in', party_types] + } + }; + }); + }, + + primary_role(frm) { + frm.set_value('primary_party', ''); + frm.set_value('secondary_role', ''); + }, + + secondary_role(frm) { + frm.set_value('secondary_party', ''); + } +}); diff --git a/erpnext/accounts/doctype/party_link/party_link.json b/erpnext/accounts/doctype/party_link/party_link.json new file mode 100644 index 0000000000..2053dc0f00 --- /dev/null +++ b/erpnext/accounts/doctype/party_link/party_link.json @@ -0,0 +1,78 @@ +{ + "actions": [], + "autoname": "ACC-PT-LNK-.###.", + "creation": "2021-08-18 21:06:53.027695", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "primary_role", + "secondary_role", + "column_break_2", + "primary_party", + "secondary_party" + ], + "fields": [ + { + "fieldname": "primary_role", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Primary Role", + "options": "DocType", + "reqd": 1 + }, + { + "fieldname": "column_break_2", + "fieldtype": "Column Break" + }, + { + "depends_on": "primary_role", + "fieldname": "secondary_role", + "fieldtype": "Link", + "label": "Secondary Role", + "mandatory_depends_on": "primary_role", + "options": "DocType" + }, + { + "depends_on": "primary_role", + "fieldname": "primary_party", + "fieldtype": "Dynamic Link", + "label": "Primary Party", + "mandatory_depends_on": "primary_role", + "options": "primary_role" + }, + { + "depends_on": "secondary_role", + "fieldname": "secondary_party", + "fieldtype": "Dynamic Link", + "label": "Secondary Party", + "mandatory_depends_on": "secondary_role", + "options": "secondary_role" + } + ], + "index_web_pages_for_search": 1, + "links": [], + "modified": "2021-08-19 17:53:43.456752", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Party Link", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "title_field": "primary_party", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/accounts/doctype/party_link/party_link.py b/erpnext/accounts/doctype/party_link/party_link.py new file mode 100644 index 0000000000..80f86e75a0 --- /dev/null +++ b/erpnext/accounts/doctype/party_link/party_link.py @@ -0,0 +1,12 @@ +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +import frappe +from frappe import _ +from frappe.model.document import Document + +class PartyLink(Document): + def validate(self): + if self.primary_role not in ['Customer', 'Supplier']: + frappe.throw(_("Allowed primary roles are 'Customer' and 'Supplier'. Please select one of these roles only."), + title=_("Invalid Primary Role")) diff --git a/erpnext/accounts/doctype/party_link/test_party_link.py b/erpnext/accounts/doctype/party_link/test_party_link.py new file mode 100644 index 0000000000..a3ea3959ba --- /dev/null +++ b/erpnext/accounts/doctype/party_link/test_party_link.py @@ -0,0 +1,8 @@ +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt + +# import frappe +import unittest + +class TestPartyLink(unittest.TestCase): + pass From cad08bc428346f1f09c0f6b8eaf59a9bf95ca3df Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Thu, 19 Aug 2021 17:56:04 +0530 Subject: [PATCH 14/54] feat: toggle to enable common party accounting --- .../doctype/accounts_settings/accounts_settings.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json index a246ae51a4..7d0ecfbafd 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json @@ -19,6 +19,7 @@ "delete_linked_ledger_entries", "book_asset_depreciation_entry_automatically", "unlink_advance_payment_on_cancelation_of_order", + "enable_common_party_accounting", "post_change_gl_entries", "enable_discount_accounting", "tax_settings_section", @@ -268,6 +269,12 @@ "fieldname": "enable_discount_accounting", "fieldtype": "Check", "label": "Enable Discount Accounting" + }, + { + "default": "0", + "fieldname": "enable_common_party_accounting", + "fieldtype": "Check", + "label": "Enable Common Party Accounting" } ], "icon": "icon-cog", @@ -275,7 +282,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2021-08-09 13:08:04.335416", + "modified": "2021-08-19 11:17:38.788054", "modified_by": "Administrator", "module": "Accounts", "name": "Accounts Settings", From 977b09b6ba35eeb0295c8397bfb982824355c699 Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Thu, 19 Aug 2021 17:57:30 +0530 Subject: [PATCH 15/54] feat: auto create advance entry on invoice submission --- .../purchase_invoice/purchase_invoice.py | 2 + .../doctype/sales_invoice/sales_invoice.py | 2 + erpnext/controllers/accounts_controller.py | 62 ++++++++++++++++++- 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index a16795e628..e2f02f37ee 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -415,6 +415,8 @@ class PurchaseInvoice(BuyingController): self.update_project() update_linked_doc(self.doctype, self.name, self.inter_company_invoice_reference) + self.process_common_party_accounting() + def make_gl_entries(self, gl_entries=None, from_repost=False): if not gl_entries: gl_entries = self.get_gl_entries() diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 5fa622856b..f29f7bef22 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -253,6 +253,8 @@ class SalesInvoice(SellingController): if "Healthcare" in active_domains: manage_invoice_submit_cancel(self, "on_submit") + self.process_common_party_accounting() + def validate_pos_return(self): if self.is_pos and self.is_return: diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 4c243d0cc4..1b23289062 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -14,7 +14,7 @@ from erpnext.accounts.utils import get_fiscal_years, validate_fiscal_year, get_a from erpnext.utilities.transaction_base import TransactionBase from erpnext.buying.utils import update_last_purchase_rate from erpnext.controllers.sales_and_purchase_return import validate_return -from erpnext.accounts.party import get_party_account_currency, validate_party_frozen_disabled +from erpnext.accounts.party import get_party_account_currency, validate_party_frozen_disabled, get_party_account from erpnext.accounts.doctype.pricing_rule.utils import (apply_pricing_rule_on_transaction, apply_pricing_rule_for_free_items, get_applied_pricing_rules) from erpnext.exceptions import InvalidCurrency @@ -1367,6 +1367,66 @@ class AccountsController(TransactionBase): return False + def process_common_party_accounting(self): + is_invoice = self.doctype in ['Sales Invoice', 'Purchase Invoice'] + if not is_invoice: + return + + if frappe.db.get_single_value('Accounts Settings', 'enable_common_party_accounting'): + party_link = self.get_common_party_link() + if party_link and self.outstanding_amount: + self.create_advance_and_reconcile(party_link) + + def get_common_party_link(self): + party_type, party = self.get_party() + party_link = frappe.db.exists('Party Link', {'secondary_role': party_type, 'secondary_party': party}) + if party_link: + return frappe.db.get_value('Party Link', party_link, ['primary_role', 'primary_party'], as_dict=True) + + def create_advance_and_reconcile(self, party_link): + secondary_party_type, secondary_party = self.get_party() + primary_party_type, primary_party = party_link.primary_role, party_link.primary_party + + primary_account = get_party_account(primary_party_type, primary_party, self.company) + secondary_account = get_party_account(secondary_party_type, secondary_party, self.company) + + jv = frappe.new_doc('Journal Entry') + jv.voucher_type = 'Journal Entry' + jv.naming_series = 'ACC-JV-.YYYY.-' + jv.posting_date = self.posting_date + jv.company = self.company + jv.remark = 'Adjustment for {} {}'.format(self.doctype, self.name) + + reconcilation_entry = frappe._dict() + advance_entry = frappe._dict() + cost_center = erpnext.get_default_cost_center(self.company) + + reconcilation_entry.account = secondary_account + reconcilation_entry.party_type = secondary_party_type + reconcilation_entry.party = secondary_party + reconcilation_entry.reference_type = self.doctype + reconcilation_entry.reference_name = self.name + reconcilation_entry.cost_center = cost_center + + advance_entry.account = primary_account + advance_entry.party_type = primary_party_type + advance_entry.party = primary_party + advance_entry.cost_center = cost_center + advance_entry.is_advance = 'Yes' + + if self.doctype == 'Sales Invoice': + reconcilation_entry.credit_in_account_currency = self.outstanding_amount + advance_entry.debit_in_account_currency = self.outstanding_amount + else: + advance_entry.credit_in_account_currency = self.outstanding_amount + reconcilation_entry.debit_in_account_currency = self.outstanding_amount + + jv.append('accounts', reconcilation_entry) + jv.append('accounts', advance_entry) + + jv.save() + jv.submit() + @frappe.whitelist() def get_tax_rate(account_head): return frappe.db.get_value("Account", account_head, ["tax_rate", "account_name"], as_dict=True) From 71e72541846f6294bd0ccee3f76fb2448d8cfa9b Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Thu, 19 Aug 2021 17:57:54 +0530 Subject: [PATCH 16/54] test: creation of advance entry on invoice submission --- .../sales_invoice/test_sales_invoice.py | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 4d1e0c3e06..8bb25dc663 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -2174,6 +2174,50 @@ class TestSalesInvoice(unittest.TestCase): self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount) self.assertTrue(schedule.journal_entry) + def test_sales_invoice_against_supplier(self): + from erpnext.accounts.doctype.opening_invoice_creation_tool.test_opening_invoice_creation_tool import make_customer + from erpnext.buying.doctype.supplier.test_supplier import create_supplier + + # create a customer + customer = make_customer(customer="_Test Common Supplier") + # create a supplier + supplier = create_supplier(supplier_name="_Test Common Supplier").name + + # create a party link between customer & supplier + # set primary role as supplier + party_link = frappe.new_doc("Party Link") + party_link.primary_role = "Supplier" + party_link.primary_party = supplier + party_link.secondary_role = "Customer" + party_link.secondary_party = customer + party_link.save() + + # enable common party accounting + frappe.db.set_value('Accounts Settings', None, 'enable_common_party_accounting', 1) + + # create a sales invoice + si = create_sales_invoice(customer=customer) + + # check outstanding of sales invoice + si.reload() + self.assertEqual(si.status, 'Paid') + self.assertEqual(flt(si.outstanding_amount), 0.0) + + # check creation of journal entry + jv = frappe.get_all('Journal Entry Account', { + 'account': si.debit_to, + 'party_type': 'Customer', + 'party': si.customer, + 'reference_type': si.doctype, + 'reference_name': si.name + }, pluck='credit_in_account_currency') + + self.assertTrue(jv) + self.assertEqual(jv[0], si.grand_total) + + party_link.delete() + frappe.db.set_value('Accounts Settings', None, 'enable_common_party_accounting', 0) + def get_sales_invoice_for_e_invoice(): si = make_sales_invoice_for_ewaybill() si.naming_series = 'INV-2020-.#####' From 8e79c48db87da4bb180f4e67333d73501e88b9dd Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Thu, 19 Aug 2021 18:10:02 +0530 Subject: [PATCH 17/54] fix: remove unwanted filter query --- erpnext/accounts/doctype/party_link/party_link.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/erpnext/accounts/doctype/party_link/party_link.js b/erpnext/accounts/doctype/party_link/party_link.js index 966a5f5d30..6da9291d64 100644 --- a/erpnext/accounts/doctype/party_link/party_link.js +++ b/erpnext/accounts/doctype/party_link/party_link.js @@ -3,14 +3,6 @@ frappe.ui.form.on('Party Link', { refresh: function(frm) { - frm.set_query('party_type', 'links', () => { - return { - filters: { - name: ['in', party_types] - } - }; - }); - frm.set_query('primary_role', () => { return { filters: { From 7fb08173b54b67a67aac03102a6327cc3c9b475b Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Tue, 17 Aug 2021 16:03:04 +0530 Subject: [PATCH 18/54] fix: reword error messages, fix test values --- erpnext/manufacturing/doctype/bom/bom.py | 10 +++++----- .../doctype/work_order/test_work_order.py | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 8d9b10ddc1..8d105789d0 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -696,23 +696,23 @@ class BOM(WebsiteGenerator): for item in self.scrap_items: msg = "" if item.item_code == self.item and not item.is_process_loss: - msg = _('Scrap/Loss Item: {0} should have Is Process Loss checked') \ + msg = _('Scrap/Loss Item: {0} should have Is Process Loss checked as it is the same as the item to be manufactured or repacked.') \ .format(frappe.bold(item.item_code)) elif item.item_code != self.item and item.is_process_loss: - msg = _('Scrap/Loss Item: {0} should not have Is Process Loss checked') \ + msg = _('Scrap/Loss Item: {0} should not have Is Process Loss checked as it is different from the item to be manufactured or repacked') \ .format(frappe.bold(item.item_code)) must_be_whole_number = frappe.get_value("UOM", item.stock_uom, "must_be_whole_number") if item.is_process_loss and must_be_whole_number: - msg = _("Item: {0} with Stock UOM: {1} cannot be a Scrap/Loss Item") \ + msg = _("Item: {0} with Stock UOM: {1} cannot be a Scrap/Loss Item as {1} is a whole UOM.") \ .format(frappe.bold(item.item_code), frappe.bold(item.stock_uom)) if item.is_process_loss and (item.stock_qty >= self.quantity): - msg = _("Scrap/Loss Item: {0} should have Qty less than finished goods Quantity") \ + msg = _("Scrap/Loss Item: {0} should have Qty less than finished goods Quantity.") \ .format(frappe.bold(item.item_code)) if item.is_process_loss and (item.rate > 0): - msg = _("Scrap/Loss Item: {0} should have Rate set to 0 because Is Process Loss is checked") \ + msg = _("Scrap/Loss Item: {0} should have Rate set to 0 because Is Process Loss is checked.") \ .format(frappe.bold(item.item_code)) if msg: diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index d6a20df0c8..0569092f88 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -735,7 +735,7 @@ class TestWorkOrder(unittest.TestCase): # Testing stock entry values items = se.get("items") - self.assertEqual(len(items), 4, "There should be 3 items including process loss.") + self.assertEqual(len(items), 3, "There should be 3 items including process loss.") source_item, fg_item, pl_item = items @@ -746,7 +746,7 @@ class TestWorkOrder(unittest.TestCase): self.assertEqual(fg_item.qty, actual_fg_qty) # Testing Work Order values - self.assertEqual(frappe.db.get_value("Work Order", wo.name, "produced_qty"), actual_fg_qty) + self.assertEqual(frappe.db.get_value("Work Order", wo.name, "produced_qty"), qty) def get_scrap_item_details(bom_no): scrap_items = {} From b58853e89d9a7a149972cac7de32e5577ac0c16b Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Tue, 24 Aug 2021 16:11:29 +0530 Subject: [PATCH 19/54] feat: add procss_loss_qty field in work order --- .../doctype/work_order/test_work_order.py | 9 +++++- .../doctype/work_order/work_order.json | 30 +++++++++++-------- .../doctype/work_order/work_order.py | 16 ++++++++++ 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index 0569092f88..a00520f6a1 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -746,7 +746,14 @@ class TestWorkOrder(unittest.TestCase): self.assertEqual(fg_item.qty, actual_fg_qty) # Testing Work Order values - self.assertEqual(frappe.db.get_value("Work Order", wo.name, "produced_qty"), qty) + self.assertEqual( + frappe.db.get_value("Work Order", wo.name, "produced_qty"), + qty + ) + self.assertEqual( + frappe.db.get_value("Work Order", wo.name, "process_loss_qty"), + actual_fg_qty + ) def get_scrap_item_details(bom_no): scrap_items = {} diff --git a/erpnext/manufacturing/doctype/work_order/work_order.json b/erpnext/manufacturing/doctype/work_order/work_order.json index 3b56854aaf..913fc85af6 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.json +++ b/erpnext/manufacturing/doctype/work_order/work_order.json @@ -19,6 +19,7 @@ "qty", "material_transferred_for_manufacturing", "produced_qty", + "process_loss_qty", "sales_order", "project", "serial_no_and_batch_for_finished_good_section", @@ -64,16 +65,12 @@ "description", "stock_uom", "column_break2", - "references_section", "material_request", "material_request_item", "sales_order_item", - "column_break_61", "production_plan", "production_plan_item", "production_plan_sub_assembly_item", - "parent_work_order", - "bom_level", "product_bundle_item", "amended_from" ], @@ -553,20 +550,29 @@ "read_only": 1 }, { - "fieldname": "production_plan_sub_assembly_item", - "fieldtype": "Data", - "label": "Production Plan Sub-assembly Item", - "no_copy": 1, - "print_hide": 1, - "read_only": 1 - } + "fieldname": "production_plan_sub_assembly_item", + "fieldtype": "Data", + "label": "Production Plan Sub-assembly Item", + "no_copy": 1, + "print_hide": 1, + "read_only": 1 + }, + { + "depends_on": "eval: doc.process_loss_qty", + "fieldname": "process_loss_qty", + "fieldtype": "Float", + "label": "Process Loss Qty", + "no_copy": 1, + "non_negative": 1, + "read_only": 1 + } ], "icon": "fa fa-cogs", "idx": 1, "image_field": "image", "is_submittable": 1, "links": [], - "modified": "2021-06-28 16:19:14.902699", + "modified": "2021-08-24 15:14:03.844937", "modified_by": "Administrator", "module": "Manufacturing", "name": "Work Order", diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index 282b5d0afe..c37a1c9e5a 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -214,6 +214,7 @@ class WorkOrder(Document): self.meta.get_label(fieldname), qty, completed_qty, self.name), StockOverProductionError) self.db_set(fieldname, qty) + self.set_process_loss_qty() from erpnext.selling.doctype.sales_order.sales_order import update_produced_qty_in_so_item @@ -223,6 +224,21 @@ class WorkOrder(Document): if self.production_plan: self.update_production_plan_status() + def set_process_loss_qty(self): + process_loss_qty = flt(frappe.db.sql(""" + SELECT sum(qty) FROM `tabStock Entry Detail` + WHERE + is_process_loss=1 + AND parent IN ( + SELECT name FROM `tabStock Entry` + WHERE + work_order=%s + AND docstatus=1 + ) + """, (self.name, ))[0][0]) + if process_loss_qty is not None: + self.db_set('process_loss_qty', process_loss_qty) + def update_production_plan_status(self): production_plan = frappe.get_doc('Production Plan', self.production_plan) produced_qty = 0 From 8f73d587f92473419301fa6b88b2c1562e5ff31a Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Tue, 24 Aug 2021 18:23:49 +0530 Subject: [PATCH 20/54] feat: process loss report, fix set pl query condition --- .../doctype/work_order/work_order.py | 1 + .../report/process_loss_report/__init__.py | 0 .../process_loss_report.js | 37 +++++ .../process_loss_report.json | 29 ++++ .../process_loss_report.py | 132 ++++++++++++++++++ 5 files changed, 199 insertions(+) create mode 100644 erpnext/stock/report/process_loss_report/__init__.py create mode 100644 erpnext/stock/report/process_loss_report/process_loss_report.js create mode 100644 erpnext/stock/report/process_loss_report/process_loss_report.json create mode 100644 erpnext/stock/report/process_loss_report/process_loss_report.py diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index c37a1c9e5a..1cdbc5f0e1 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -233,6 +233,7 @@ class WorkOrder(Document): SELECT name FROM `tabStock Entry` WHERE work_order=%s + AND purpose='Manufacture' AND docstatus=1 ) """, (self.name, ))[0][0]) diff --git a/erpnext/stock/report/process_loss_report/__init__.py b/erpnext/stock/report/process_loss_report/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/stock/report/process_loss_report/process_loss_report.js b/erpnext/stock/report/process_loss_report/process_loss_report.js new file mode 100644 index 0000000000..078b9e11ce --- /dev/null +++ b/erpnext/stock/report/process_loss_report/process_loss_report.js @@ -0,0 +1,37 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.query_reports["Process Loss Report"] = { + filters: [ + { + label: __("Company"), + fieldname: "company", + fieldtype: "Link", + options: "Company", + mandatory: true, + default: frappe.defaults.get_user_default("Company"), + }, + { + label: __("Item"), + fieldname: "item", + fieldtype: "Link", + options: "Item", + mandatory: false, + }, + { + label: __("From Date"), + fieldname: "from_date", + fieldtype: "Date", + mandatory: true, + default: frappe.datetime.year_start(), + }, + { + label: __("To Date"), + fieldname: "to_date", + fieldtype: "Date", + mandatory: true, + default: frappe.datetime.get_today(), + }, + ] +}; diff --git a/erpnext/stock/report/process_loss_report/process_loss_report.json b/erpnext/stock/report/process_loss_report/process_loss_report.json new file mode 100644 index 0000000000..afe4aff7f1 --- /dev/null +++ b/erpnext/stock/report/process_loss_report/process_loss_report.json @@ -0,0 +1,29 @@ +{ + "add_total_row": 0, + "columns": [], + "creation": "2021-08-24 16:38:15.233395", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "filters": [], + "idx": 0, + "is_standard": "Yes", + "modified": "2021-08-24 16:38:15.233395", + "modified_by": "Administrator", + "module": "Stock", + "name": "Process Loss Report", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Work Order", + "report_name": "Process Loss Report", + "report_type": "Script Report", + "roles": [ + { + "role": "Manufacturing User" + }, + { + "role": "Stock User" + } + ] +} \ No newline at end of file diff --git a/erpnext/stock/report/process_loss_report/process_loss_report.py b/erpnext/stock/report/process_loss_report/process_loss_report.py new file mode 100644 index 0000000000..be0f0151d4 --- /dev/null +++ b/erpnext/stock/report/process_loss_report/process_loss_report.py @@ -0,0 +1,132 @@ +# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +import frappe +from typing import Dict, List, Tuple + +Filters = frappe._dict +Row = frappe._dict +Data = List[Row] +Columns = List[Dict[str, str]] +QueryArgs = Dict[str, str] + +def execute(filters: Filters) -> Tuple[Columns, Data]: + columns = get_columns() + data = get_data(filters) + return columns, data + +def get_data(filters: Filters) -> Data: + query_args = get_query_args(filters) + data = run_query(query_args) + update_data_with_total_pl_value(data) + return data + +def get_columns() -> Columns: + return [ + { + 'label': 'Work Order', + 'fieldname': 'name', + 'fieldtype': 'Link', + 'options': 'Work Order', + 'width': '200' + }, + { + 'label': 'Item', + 'fieldname': 'production_item', + 'fieldtype': 'Link', + 'options': 'Item', + 'width': '100' + }, + { + 'label': 'Status', + 'fieldname': 'status', + 'fieldtype': 'Data', + 'width': '100' + }, + { + 'label': 'Qty To Manufacture', + 'fieldname': 'qty', + 'fieldtype': 'Float', + 'width': '150' + }, + { + 'label': 'Manufactured Qty', + 'fieldname': 'produced_qty', + 'fieldtype': 'Float', + 'width': '150' + }, + { + 'label': 'Process Loss Qty', + 'fieldname': 'process_loss_qty', + 'fieldtype': 'Float', + 'width': '150' + }, + { + 'label': 'Actual Manufactured Qty', + 'fieldname': 'actual_produced_qty', + 'fieldtype': 'Float', + 'width': '150' + }, + { + 'label': 'Total FG Value', + 'fieldname': 'total_fg_value', + 'fieldtype': 'Float', + 'width': '150' + }, + { + 'label': 'Total Raw Material Value', + 'fieldname': 'total_rm_value', + 'fieldtype': 'Float', + 'width': '150' + }, + { + 'label': 'Total Process Loss Value', + 'fieldname': 'total_pl_value', + 'fieldtype': 'Float', + 'width': '150' + }, + ] + +def get_query_args(filters: Filters) -> QueryArgs: + query_args = {} + query_args.update(filters) + query_args.update( + get_filter_conditions(filters) + ) + return query_args + +def run_query(query_args: QueryArgs) -> Data: + return frappe.db.sql(""" + SELECT + wo.name, wo.status, wo.production_item, wo.qty, + wo.produced_qty, wo.process_loss_qty, + (wo.produced_qty - wo.process_loss_qty) as actual_produced_qty, + sum(se.total_incoming_value) as total_fg_value, + sum(se.total_outgoing_value) as total_rm_value + FROM + `tabWork Order` wo INNER JOIN `tabStock Entry` se + ON wo.name=se.work_order + WHERE + process_loss_qty > 0 + AND wo.company = %(company)s + AND se.docstatus = 1 + AND se.posting_date BETWEEN %(from_date)s AND %(to_date)s + %(item_filter)s + GROUP BY + se.work_order + """, query_args, as_dict=1) + +def update_data_with_total_pl_value(data: Data) -> None: + for row in data: + value_per_unit_fg = row['total_fg_value'] / row['actual_produced_qty'] + row['total_pl_value'] = row['process_loss_qty'] * value_per_unit_fg + +def get_filter_conditions(filters: Filters) -> QueryArgs: + filter_conditions = dict(item_filter="") + if "item" in filters: + production_item = filters.get("item") + filter_conditions.update( + {"item_filter": f"wo.production_item='{production_item}'"} + ) + return filter_conditions + From c3ce3f918dbe3d871244750de05aa0a59afcfce3 Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Tue, 24 Aug 2021 20:15:19 +0530 Subject: [PATCH 21/54] fix: remove spurious function 'toggle_operations' --- erpnext/manufacturing/doctype/bom/bom.js | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js index 7de7e17abc..5afda7028a 100644 --- a/erpnext/manufacturing/doctype/bom/bom.js +++ b/erpnext/manufacturing/doctype/bom/bom.js @@ -659,7 +659,6 @@ frappe.ui.form.on("BOM", "with_operations", function(frm) { if(!cint(frm.doc.with_operations)) { frm.set_value("operations", []); } - toggle_operations(frm); }); frappe.ui.form.on("BOM Scrap Item", { From 95a2565d86f76858f1e436a871f50862e9874a61 Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Tue, 24 Aug 2021 20:18:53 +0530 Subject: [PATCH 22/54] fix: correct value in test --- erpnext/manufacturing/doctype/work_order/test_work_order.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index a00520f6a1..3a334a530c 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -752,7 +752,7 @@ class TestWorkOrder(unittest.TestCase): ) self.assertEqual( frappe.db.get_value("Work Order", wo.name, "process_loss_qty"), - actual_fg_qty + total_pl_qty ) def get_scrap_item_details(bom_no): From c7e11c89ff6636ec9c8aa4a3c3ed1ba5f71e3206 Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Wed, 25 Aug 2021 18:58:56 +0530 Subject: [PATCH 23/54] fix: get filters to work - reorder and rename columns - add work order filter --- .../process_loss_report.js | 7 ++++ .../process_loss_report.py | 40 +++++++++---------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/erpnext/stock/report/process_loss_report/process_loss_report.js b/erpnext/stock/report/process_loss_report/process_loss_report.js index 078b9e11ce..b0c2b94a25 100644 --- a/erpnext/stock/report/process_loss_report/process_loss_report.js +++ b/erpnext/stock/report/process_loss_report/process_loss_report.js @@ -17,6 +17,13 @@ frappe.query_reports["Process Loss Report"] = { fieldname: "item", fieldtype: "Link", options: "Item", + mandatory: false, + }, + { + label: __("Work Order"), + fieldname: "work_order", + fieldtype: "Link", + options: "Work Order", mandatory: false, }, { diff --git a/erpnext/stock/report/process_loss_report/process_loss_report.py b/erpnext/stock/report/process_loss_report/process_loss_report.py index be0f0151d4..7494328ab4 100644 --- a/erpnext/stock/report/process_loss_report/process_loss_report.py +++ b/erpnext/stock/report/process_loss_report/process_loss_report.py @@ -43,12 +43,6 @@ def get_columns() -> Columns: 'fieldtype': 'Data', 'width': '100' }, - { - 'label': 'Qty To Manufacture', - 'fieldname': 'qty', - 'fieldtype': 'Float', - 'width': '150' - }, { 'label': 'Manufactured Qty', 'fieldname': 'produced_qty', @@ -56,7 +50,7 @@ def get_columns() -> Columns: 'width': '150' }, { - 'label': 'Process Loss Qty', + 'label': 'Loss Qty', 'fieldname': 'process_loss_qty', 'fieldtype': 'Float', 'width': '150' @@ -68,23 +62,23 @@ def get_columns() -> Columns: 'width': '150' }, { - 'label': 'Total FG Value', + 'label': 'Loss Value', + 'fieldname': 'total_pl_value', + 'fieldtype': 'Float', + 'width': '150' + }, + { + 'label': 'FG Value', 'fieldname': 'total_fg_value', 'fieldtype': 'Float', 'width': '150' }, { - 'label': 'Total Raw Material Value', + 'label': 'Raw Material Value', 'fieldname': 'total_rm_value', 'fieldtype': 'Float', 'width': '150' - }, - { - 'label': 'Total Process Loss Value', - 'fieldname': 'total_pl_value', - 'fieldtype': 'Float', - 'width': '150' - }, + } ] def get_query_args(filters: Filters) -> QueryArgs: @@ -111,10 +105,11 @@ def run_query(query_args: QueryArgs) -> Data: AND wo.company = %(company)s AND se.docstatus = 1 AND se.posting_date BETWEEN %(from_date)s AND %(to_date)s - %(item_filter)s + {item_filter} + {work_order_filter} GROUP BY se.work_order - """, query_args, as_dict=1) + """.format(**query_args), query_args, as_dict=1, debug=1) def update_data_with_total_pl_value(data: Data) -> None: for row in data: @@ -122,11 +117,16 @@ def update_data_with_total_pl_value(data: Data) -> None: row['total_pl_value'] = row['process_loss_qty'] * value_per_unit_fg def get_filter_conditions(filters: Filters) -> QueryArgs: - filter_conditions = dict(item_filter="") + filter_conditions = dict(item_filter="", work_order_filter="") if "item" in filters: production_item = filters.get("item") filter_conditions.update( - {"item_filter": f"wo.production_item='{production_item}'"} + {"item_filter": f"AND wo.production_item='{production_item}'"} + ) + if "work_order" in filters: + work_order_name = filters.get("work_order") + filter_conditions.update( + {"work_order_filter": f"AND wo.name='{work_order_name}'"} ) return filter_conditions From c101b42d4a086c1e328fcdd442d4af33bde1f9c0 Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Wed, 25 Aug 2021 20:08:28 +0530 Subject: [PATCH 24/54] feat: validate multiple links --- erpnext/accounts/doctype/party_link/party_link.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/erpnext/accounts/doctype/party_link/party_link.py b/erpnext/accounts/doctype/party_link/party_link.py index 80f86e75a0..7d58506ce7 100644 --- a/erpnext/accounts/doctype/party_link/party_link.py +++ b/erpnext/accounts/doctype/party_link/party_link.py @@ -10,3 +10,17 @@ class PartyLink(Document): if self.primary_role not in ['Customer', 'Supplier']: frappe.throw(_("Allowed primary roles are 'Customer' and 'Supplier'. Please select one of these roles only."), title=_("Invalid Primary Role")) + + existing_party_link = frappe.get_all('Party Link', { + 'primary_party': self.secondary_party + }, pluck="primary_role") + if existing_party_link: + frappe.throw(_('{} {} is already linked with another {}') + .format(self.secondary_role, self.secondary_party, existing_party_link[0])) + + existing_party_link = frappe.get_all('Party Link', { + 'secondary_party': self.primary_party + }, pluck="primary_role") + if existing_party_link: + frappe.throw(_('{} {} is already linked with another {}') + .format(self.primary_role, self.primary_party, existing_party_link[0])) From a2f8d6c31acbfeac4cc3abfedbaf59375f6fe962 Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Wed, 25 Aug 2021 20:10:19 +0530 Subject: [PATCH 25/54] fix: party link permissions --- .../doctype/party_link/party_link.json | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/party_link/party_link.json b/erpnext/accounts/doctype/party_link/party_link.json index 2053dc0f00..a1bb15f0d6 100644 --- a/erpnext/accounts/doctype/party_link/party_link.json +++ b/erpnext/accounts/doctype/party_link/party_link.json @@ -52,7 +52,7 @@ ], "index_web_pages_for_search": 1, "links": [], - "modified": "2021-08-19 17:53:43.456752", + "modified": "2021-08-25 20:08:56.761150", "modified_by": "Administrator", "module": "Accounts", "name": "Party Link", @@ -69,6 +69,30 @@ "role": "System Manager", "share": 1, "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts Manager", + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts User", + "share": 1, + "write": 1 } ], "sort_field": "modified", From 7254368fc52dd9f828dfe3c3d9570ba3274f0ade Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Wed, 25 Aug 2021 20:15:23 +0530 Subject: [PATCH 26/54] perf: reduce number of queries to get party link --- erpnext/controllers/accounts_controller.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 55e6f0482c..798b994920 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1375,9 +1375,12 @@ class AccountsController(TransactionBase): def get_common_party_link(self): party_type, party = self.get_party() - party_link = frappe.db.exists('Party Link', {'secondary_role': party_type, 'secondary_party': party}) - if party_link: - return frappe.db.get_value('Party Link', party_link, ['primary_role', 'primary_party'], as_dict=True) + return frappe.db.get_value( + doctype='Party Link', + filters={'secondary_role': party_type, 'secondary_party': party}, + fieldname=['primary_role', 'primary_party'], + as_dict=True + ) def create_advance_and_reconcile(self, party_link): secondary_party_type, secondary_party = self.get_party() From c6c7a8b5cf182b9314aa726296a1e34767450939 Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Wed, 25 Aug 2021 20:17:04 +0530 Subject: [PATCH 27/54] fix: cost center & naming series --- erpnext/controllers/accounts_controller.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 798b994920..f4af8932b6 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1391,26 +1391,24 @@ class AccountsController(TransactionBase): jv = frappe.new_doc('Journal Entry') jv.voucher_type = 'Journal Entry' - jv.naming_series = 'ACC-JV-.YYYY.-' jv.posting_date = self.posting_date jv.company = self.company jv.remark = 'Adjustment for {} {}'.format(self.doctype, self.name) reconcilation_entry = frappe._dict() advance_entry = frappe._dict() - cost_center = erpnext.get_default_cost_center(self.company) reconcilation_entry.account = secondary_account reconcilation_entry.party_type = secondary_party_type reconcilation_entry.party = secondary_party reconcilation_entry.reference_type = self.doctype reconcilation_entry.reference_name = self.name - reconcilation_entry.cost_center = cost_center + reconcilation_entry.cost_center = self.cost_center advance_entry.account = primary_account advance_entry.party_type = primary_party_type advance_entry.party = primary_party - advance_entry.cost_center = cost_center + advance_entry.cost_center = self.cost_center advance_entry.is_advance = 'Yes' if self.doctype == 'Sales Invoice': From be7a38b662b82aac11a6a085f02eeffecd10872f Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Wed, 25 Aug 2021 21:35:32 +0530 Subject: [PATCH 28/54] fix: cost center in test_sales_invoice_against_supplier --- erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index b48dc924f7..83f0222026 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -2185,7 +2185,7 @@ class TestSalesInvoice(unittest.TestCase): frappe.db.set_value('Accounts Settings', None, 'enable_common_party_accounting', 1) # create a sales invoice - si = create_sales_invoice(customer=customer) + si = create_sales_invoice(customer=customer, parent_cost_center="_Test Cost Center - _TC") # check outstanding of sales invoice si.reload() From c8f22e5524980996eec998566d2cea19be1f2b93 Mon Sep 17 00:00:00 2001 From: Anupam Kumar Date: Thu, 26 Aug 2021 10:46:55 +0530 Subject: [PATCH 29/54] fix: removing toggle_display for address and contact HTML (#27152) --- erpnext/selling/doctype/customer/customer.js | 1 - erpnext/selling/doctype/customer/customer.json | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/selling/doctype/customer/customer.js b/erpnext/selling/doctype/customer/customer.js index 2f06e98880..cb00019cf5 100644 --- a/erpnext/selling/doctype/customer/customer.js +++ b/erpnext/selling/doctype/customer/customer.js @@ -111,7 +111,6 @@ frappe.ui.form.on("Customer", { } frappe.dynamic_link = {doc: frm.doc, fieldname: 'name', doctype: 'Customer'} - frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal); if(!frm.doc.__islocal) { frappe.contacts.render_address_and_contact(frm); diff --git a/erpnext/selling/doctype/customer/customer.json b/erpnext/selling/doctype/customer/customer.json index 0d839fc822..2acc64cb43 100644 --- a/erpnext/selling/doctype/customer/customer.json +++ b/erpnext/selling/doctype/customer/customer.json @@ -268,6 +268,7 @@ "options": "fa fa-map-marker" }, { + "depends_on": "eval: !doc.__islocal", "fieldname": "address_html", "fieldtype": "HTML", "label": "Address HTML", @@ -284,6 +285,7 @@ "width": "50%" }, { + "depends_on": "eval: !doc.__islocal", "fieldname": "contact_html", "fieldtype": "HTML", "label": "Contact HTML", From 1a919773d795f607142992fc4a373d5ab9d2e725 Mon Sep 17 00:00:00 2001 From: Brian Pond Date: Wed, 25 Aug 2021 23:27:28 -0700 Subject: [PATCH 30/54] fix: Customers 'primary_address' not updated automatically (#26798) (#26799) * Fix for Issue #26798 This PR is a fix for GitHub Issue 26798: https://github.com/frappe/erpnext/issues/26798 TLDR: When an Address is updated, and that Address is a Customer's Primary Address, update the Read Only field `customer.primary_address` * Update address.py Co-authored-by: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> --- erpnext/accounts/custom/address.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/custom/address.py b/erpnext/accounts/custom/address.py index c417a493c6..834227bb58 100644 --- a/erpnext/accounts/custom/address.py +++ b/erpnext/accounts/custom/address.py @@ -1,7 +1,7 @@ import frappe from frappe import _ from frappe.contacts.doctype.address.address import Address -from frappe.contacts.doctype.address.address import get_address_templates +from frappe.contacts.doctype.address.address import get_address_templates, get_address_display class ERPNextAddress(Address): def validate(self): @@ -22,6 +22,16 @@ class ERPNextAddress(Address): frappe.throw(_("Address needs to be linked to a Company. Please add a row for Company in the Links table."), title=_("Company Not Linked")) + def on_update(self): + """ + After Address is updated, update the related 'Primary Address' on Customer. + """ + address_display = get_address_display(self.as_dict()) + filters = { "customer_primary_address": self.name } + customers = frappe.db.get_all("Customer", filters=filters, as_list=True) + for customer_name in customers: + frappe.db.set_value("Customer", customer_name[0], "primary_address", address_display) + @frappe.whitelist() def get_shipping_address(company, address = None): filters = [ From 642b4c805cdf912fdc07de5b998df70091a8c8ac Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Thu, 26 Aug 2021 12:15:49 +0530 Subject: [PATCH 31/54] fix: Fee Validity fixes (#27156) * chore: update Fee Validity form labels * fix: first appointment should not be considered for Fee Validity * fix: Fee Validity test cases * fix: appointment test case --- .../doctype/fee_validity/fee_validity.json | 6 +++--- .../doctype/fee_validity/fee_validity.py | 14 ++------------ .../doctype/fee_validity/test_fee_validity.py | 4 ++-- .../patient_appointment/patient_appointment.py | 6 +++++- .../test_patient_appointment.py | 9 ++++++--- 5 files changed, 18 insertions(+), 21 deletions(-) diff --git a/erpnext/healthcare/doctype/fee_validity/fee_validity.json b/erpnext/healthcare/doctype/fee_validity/fee_validity.json index b001bf024c..d76b42e683 100644 --- a/erpnext/healthcare/doctype/fee_validity/fee_validity.json +++ b/erpnext/healthcare/doctype/fee_validity/fee_validity.json @@ -46,13 +46,13 @@ { "fieldname": "visited", "fieldtype": "Int", - "label": "Visited yet", + "label": "Visits Completed", "read_only": 1 }, { "fieldname": "valid_till", "fieldtype": "Date", - "label": "Valid till", + "label": "Valid Till", "read_only": 1 }, { @@ -106,7 +106,7 @@ ], "in_create": 1, "links": [], - "modified": "2020-03-17 20:25:06.487418", + "modified": "2021-08-26 10:51:05.609349", "modified_by": "Administrator", "module": "Healthcare", "name": "Fee Validity", diff --git a/erpnext/healthcare/doctype/fee_validity/fee_validity.py b/erpnext/healthcare/doctype/fee_validity/fee_validity.py index 5b9c17934f..59586e0c31 100644 --- a/erpnext/healthcare/doctype/fee_validity/fee_validity.py +++ b/erpnext/healthcare/doctype/fee_validity/fee_validity.py @@ -11,7 +11,6 @@ import datetime class FeeValidity(Document): def validate(self): self.update_status() - self.set_start_date() def update_status(self): if self.visited >= self.max_visits: @@ -19,13 +18,6 @@ class FeeValidity(Document): else: self.status = 'Pending' - def set_start_date(self): - self.start_date = getdate() - for appointment in self.ref_appointments: - appointment_date = frappe.db.get_value('Patient Appointment', appointment.appointment, 'appointment_date') - if getdate(appointment_date) < self.start_date: - self.start_date = getdate(appointment_date) - def create_fee_validity(appointment): if not check_is_new_patient(appointment): @@ -36,11 +28,9 @@ def create_fee_validity(appointment): fee_validity.patient = appointment.patient fee_validity.max_visits = frappe.db.get_single_value('Healthcare Settings', 'max_visits') or 1 valid_days = frappe.db.get_single_value('Healthcare Settings', 'valid_days') or 1 - fee_validity.visited = 1 + fee_validity.visited = 0 + fee_validity.start_date = getdate(appointment.appointment_date) fee_validity.valid_till = getdate(appointment.appointment_date) + datetime.timedelta(days=int(valid_days)) - fee_validity.append('ref_appointments', { - 'appointment': appointment.name - }) fee_validity.save(ignore_permissions=True) return fee_validity diff --git a/erpnext/healthcare/doctype/fee_validity/test_fee_validity.py b/erpnext/healthcare/doctype/fee_validity/test_fee_validity.py index 82e7136d6b..4a178723a0 100644 --- a/erpnext/healthcare/doctype/fee_validity/test_fee_validity.py +++ b/erpnext/healthcare/doctype/fee_validity/test_fee_validity.py @@ -22,14 +22,14 @@ class TestFeeValidity(unittest.TestCase): item = create_healthcare_service_items() healthcare_settings = frappe.get_single("Healthcare Settings") healthcare_settings.enable_free_follow_ups = 1 - healthcare_settings.max_visits = 2 + healthcare_settings.max_visits = 1 healthcare_settings.valid_days = 7 healthcare_settings.automate_appointment_invoicing = 1 healthcare_settings.op_consulting_charge_item = item healthcare_settings.save(ignore_permissions=True) patient, medical_department, practitioner = create_healthcare_docs() - # For first appointment, invoice is generated + # For first appointment, invoice is generated. First appointment not considered in fee validity appointment = create_appointment(patient, practitioner, nowdate()) invoiced = frappe.db.get_value("Patient Appointment", appointment.name, "invoiced") self.assertEqual(invoiced, 1) diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py index 05e2cd30df..7db4fa616a 100755 --- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py +++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py @@ -109,9 +109,13 @@ class PatientAppointment(Document): frappe.db.set_value('Patient Appointment', self.name, 'notes', comments) def update_fee_validity(self): + if not frappe.db.get_single_value('Healthcare Settings', 'enable_free_follow_ups'): + return + fee_validity = manage_fee_validity(self) if fee_validity: - frappe.msgprint(_('{0} has fee validity till {1}').format(self.patient, fee_validity.valid_till)) + frappe.msgprint(_('{0}: {1} has fee validity till {2}').format(self.patient, + frappe.bold(self.patient_name), fee_validity.valid_till)) @frappe.whitelist() def get_therapy_types(self): diff --git a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py index 9c3392cd5b..157b3e1162 100644 --- a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py +++ b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py @@ -107,14 +107,17 @@ class TestPatientAppointment(unittest.TestCase): patient, medical_department, practitioner = create_healthcare_docs() frappe.db.set_value('Healthcare Settings', None, 'enable_free_follow_ups', 1) appointment = create_appointment(patient, practitioner, nowdate()) - fee_validity = frappe.db.get_value('Fee Validity Reference', {'appointment': appointment.name}, 'parent') + fee_validity = frappe.db.get_value('Fee Validity', {'patient': patient, 'practitioner': practitioner}) # fee validity created self.assertTrue(fee_validity) - visited = frappe.db.get_value('Fee Validity', fee_validity, 'visited') + # first follow up appointment + appointment = create_appointment(patient, practitioner, nowdate()) + self.assertEqual(frappe.db.get_value('Fee Validity', fee_validity, 'visited'), 1) + update_status(appointment.name, 'Cancelled') # check fee validity updated - self.assertEqual(frappe.db.get_value('Fee Validity', fee_validity, 'visited'), visited - 1) + self.assertEqual(frappe.db.get_value('Fee Validity', fee_validity, 'visited'), 0) frappe.db.set_value('Healthcare Settings', None, 'enable_free_follow_ups', 0) frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 1) From baa548a3dfec3167555c7a20252d6fc72b78a213 Mon Sep 17 00:00:00 2001 From: Anuja Pawar <60467153+Anuja-pawar@users.noreply.github.com> Date: Thu, 26 Aug 2021 12:48:43 +0530 Subject: [PATCH 32/54] fix(regional): minor fixes and test for South Africa VAT report (#26933) * fix: added test and minor fixes * fix: sider fixes * fix: sider * fix: test fixes Co-authored-by: Afshan <33727827+AfshanKhan@users.noreply.github.com> Co-authored-by: Saqib --- .../vat_audit_report/test_vat_audit_report.py | 193 ++++++++++++++++++ .../vat_audit_report/vat_audit_report.py | 11 +- 2 files changed, 199 insertions(+), 5 deletions(-) create mode 100644 erpnext/regional/report/vat_audit_report/test_vat_audit_report.py diff --git a/erpnext/regional/report/vat_audit_report/test_vat_audit_report.py b/erpnext/regional/report/vat_audit_report/test_vat_audit_report.py new file mode 100644 index 0000000000..dea17a66fd --- /dev/null +++ b/erpnext/regional/report/vat_audit_report/test_vat_audit_report.py @@ -0,0 +1,193 @@ +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +from unittest import TestCase +from frappe.utils import today + +from erpnext.accounts.doctype.account.test_account import create_account +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice +from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice + +from erpnext.regional.report.vat_audit_report.vat_audit_report import execute + +class TestVATAuditReport(TestCase): + def setUp(self): + frappe.set_user("Administrator") + make_company("_Test Company SA VAT", "_TCSV") + + create_account(account_name="VAT - 0%", account_type="Tax", + parent_account="Duties and Taxes - _TCSV", company="_Test Company SA VAT") + create_account(account_name="VAT - 15%", account_type="Tax", + parent_account="Duties and Taxes - _TCSV", company="_Test Company SA VAT") + set_sa_vat_accounts() + + make_item("_Test SA VAT Item") + make_item("_Test SA VAT Zero Rated Item", properties = {"is_zero_rated": 1}) + + make_customer() + make_supplier() + + make_sales_invoices() + create_purchase_invoices() + + def tearDown(self): + frappe.db.sql("delete from `tabSales Invoice` where company='_Test Company SA VAT'") + frappe.db.sql("delete from `tabPurchase Invoice` where company='_Test Company SA VAT'") + + def test_vat_audit_report(self): + filters = { + "company": "_Test Company SA VAT", + "from_date": today(), + "to_date": today() + } + columns, data = execute(filters) + total_tax_amount = 0 + total_row_tax = 0 + for row in data: + keys = row.keys() + # skips total row tax_amount in if.. and skips section header in elif.. + if 'voucher_no' in keys: + total_tax_amount = total_tax_amount + row['tax_amount'] + elif 'tax_amount' in keys: + total_row_tax = total_row_tax + row['tax_amount'] + + self.assertEqual(total_tax_amount, total_row_tax) + +def make_company(company_name, abbr): + if not frappe.db.exists("Company", company_name): + company = frappe.get_doc({ + "doctype": "Company", + "company_name": company_name, + "abbr": abbr, + "default_currency": "ZAR", + "country": "South Africa", + "create_chart_of_accounts_based_on": "Standard Template" + }) + company.insert() + else: + company = frappe.get_doc("Company", company_name) + + company.create_default_warehouses() + + if not frappe.db.get_value("Cost Center", {"is_group": 0, "company": company.name}): + company.create_default_cost_center() + + company.save() + + return company + +def set_sa_vat_accounts(): + if not frappe.db.exists("South Africa VAT Settings", "_Test Company SA VAT"): + vat_accounts = frappe.get_all( + "Account", + fields=["name"], + filters = { + "company": "_Test Company SA VAT", + "is_group": 0, + "account_type": "Tax" + } + ) + + sa_vat_accounts = [] + for account in vat_accounts: + sa_vat_accounts.append({ + "doctype": "South Africa VAT Account", + "account": account.name + }) + + frappe.get_doc({ + "company": "_Test Company SA VAT", + "vat_accounts": sa_vat_accounts, + "doctype": "South Africa VAT Settings", + }).insert() + +def make_customer(): + if not frappe.db.exists("Customer", "_Test SA Customer"): + frappe.get_doc({ + "doctype": "Customer", + "customer_name": "_Test SA Customer", + "customer_type": "Company", + }).insert() + +def make_supplier(): + if not frappe.db.exists("Supplier", "_Test SA Supplier"): + frappe.get_doc({ + "doctype": "Supplier", + "supplier_name": "_Test SA Supplier", + "supplier_type": "Company", + "supplier_group":"All Supplier Groups" + }).insert() + +def make_item(item_code, properties=None): + if not frappe.db.exists("Item", item_code): + item = frappe.get_doc({ + "doctype": "Item", + "item_code": item_code, + "item_name": item_code, + "description": item_code, + "item_group": "Products" + }) + + if properties: + item.update(properties) + + item.insert() + +def make_sales_invoices(): + def make_sales_invoices_wrapper(item, rate, tax_account, tax_rate, tax=True): + si = create_sales_invoice( + company="_Test Company SA VAT", + customer = "_Test SA Customer", + currency = "ZAR", + item=item, + rate=rate, + warehouse = "Finished Goods - _TCSV", + debit_to = "Debtors - _TCSV", + income_account = "Sales - _TCSV", + expense_account = "Cost of Goods Sold - _TCSV", + cost_center = "Main - _TCSV", + do_not_save=1 + ) + if tax: + si.append("taxes", { + "charge_type": "On Net Total", + "account_head": tax_account, + "cost_center": "Main - _TCSV", + "description": "VAT 15% @ 15.0", + "rate": tax_rate + }) + + si.submit() + + test_item = "_Test SA VAT Item" + test_zero_rated_item = "_Test SA VAT Zero Rated Item" + + make_sales_invoices_wrapper(test_item, 100.0, "VAT - 15% - _TCSV", 15.0) + make_sales_invoices_wrapper(test_zero_rated_item, 100.0, "VAT - 0% - _TCSV", 0.0) + +def create_purchase_invoices(): + pi = make_purchase_invoice( + company = "_Test Company SA VAT", + supplier = "_Test SA Supplier", + supplier_warehouse = "Finished Goods - _TCSV", + warehouse = "Finished Goods - _TCSV", + currency = "ZAR", + cost_center = "Main - _TCSV", + expense_account = "Cost of Goods Sold - _TCSV", + item = "_Test SA VAT Item", + qty = 1, + rate = 100, + uom = "Nos", + do_not_save = 1 + ) + pi.append("taxes", { + "charge_type": "On Net Total", + "account_head": "VAT - 15% - _TCSV", + "cost_center": "Main - _TCSV", + "description": "VAT 15% @ 15.0", + "rate": 15.0 + }) + + pi.submit() diff --git a/erpnext/regional/report/vat_audit_report/vat_audit_report.py b/erpnext/regional/report/vat_audit_report/vat_audit_report.py index 17aca17afd..88f6b923e6 100644 --- a/erpnext/regional/report/vat_audit_report/vat_audit_report.py +++ b/erpnext/regional/report/vat_audit_report/vat_audit_report.py @@ -1,11 +1,11 @@ -# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt from __future__ import unicode_literals import frappe import json from frappe import _ -from frappe.utils import formatdate +from frappe.utils import formatdate, get_link_to_form def execute(filters=None): return VATAuditReport(filters).run() @@ -42,7 +42,8 @@ class VATAuditReport(object): self.sa_vat_accounts = frappe.get_list("South Africa VAT Account", filters = {"parent": self.filters.company}, pluck="account") if not self.sa_vat_accounts and not frappe.flags.in_test and not frappe.flags.in_migrate: - frappe.throw(_("Please set VAT Accounts in South Africa VAT Settings")) + link_to_settings = get_link_to_form("South Africa VAT Settings", "", label="South Africa VAT Settings") + frappe.throw(_("Please set VAT Accounts in {0}").format(link_to_settings)) def get_invoice_data(self, doctype): conditions = self.get_conditions() @@ -69,7 +70,7 @@ class VATAuditReport(object): items = frappe.db.sql(""" SELECT - item_code, parent, taxable_value, base_net_amount, is_zero_rated + item_code, parent, base_net_amount, is_zero_rated FROM `tab%s Item` WHERE @@ -79,7 +80,7 @@ class VATAuditReport(object): if d.item_code not in self.invoice_items.get(d.parent, {}): self.invoice_items.setdefault(d.parent, {}).setdefault(d.item_code, { 'net_amount': 0.0}) - self.invoice_items[d.parent][d.item_code]['net_amount'] += d.get('taxable_value', 0) or d.get('base_net_amount', 0) + self.invoice_items[d.parent][d.item_code]['net_amount'] += d.get('base_net_amount', 0) self.invoice_items[d.parent][d.item_code]['is_zero_rated'] = d.is_zero_rated def get_items_based_on_tax_rate(self, doctype): From fe4540d74d0dfda170c2a781347d745fb9f86fb6 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Thu, 26 Aug 2021 12:52:36 +0530 Subject: [PATCH 33/54] fix: allow to change rate manually in case of stand-alone credit note (#27036) Co-authored-by: Marica --- .../sales_invoice/test_sales_invoice.py | 15 ++++++++- .../sales_invoice_item.json | 10 +++--- .../controllers/sales_and_purchase_return.py | 32 +++++++++++-------- erpnext/controllers/selling_controller.py | 27 ++++++++-------- erpnext/stock/stock_ledger.py | 1 + 5 files changed, 52 insertions(+), 33 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index c3d83c7d74..053d42ee53 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -1140,6 +1140,18 @@ class TestSalesInvoice(unittest.TestCase): self.assertEqual(loss_for_si['credit'], loss_for_return_si['debit']) self.assertEqual(loss_for_si['debit'], loss_for_return_si['credit']) + def test_incoming_rate_for_stand_alone_credit_note(self): + return_si = create_sales_invoice(is_return=1, update_stock=1, qty=-1, rate=90000, incoming_rate=10, + company='_Test Company with perpetual inventory', warehouse='Stores - TCP1', debit_to='Debtors - TCP1', + income_account='Sales - TCP1', expense_account='Cost of Goods Sold - TCP1', cost_center='Main - TCP1') + + incoming_rate = frappe.db.get_value('Stock Ledger Entry', {'voucher_no': return_si.name}, 'incoming_rate') + debit_amount = frappe.db.get_value('GL Entry', + {'voucher_no': return_si.name, 'account': 'Stock In Hand - TCP1'}, 'debit') + + self.assertEqual(debit_amount, 10.0) + self.assertEqual(incoming_rate, 10.0) + def test_discount_on_net_total(self): si = frappe.copy_doc(test_records[2]) si.apply_discount_on = "Net Total" @@ -2375,7 +2387,8 @@ def create_sales_invoice(**args): "asset": args.asset or None, "cost_center": args.cost_center or "_Test Cost Center - _TC", "serial_no": args.serial_no, - "conversion_factor": 1 + "conversion_factor": 1, + "incoming_rate": args.incoming_rate or 0 }) if not args.do_not_save: diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json index c77076cb90..b90f3f0904 100644 --- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json +++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json @@ -53,7 +53,6 @@ "column_break_24", "base_net_rate", "base_net_amount", - "incoming_rate", "drop_ship", "delivered_by_supplier", "accounting", @@ -81,6 +80,7 @@ "target_warehouse", "quality_inspection", "batch_no", + "incoming_rate", "col_break5", "allow_zero_valuation_rate", "serial_no", @@ -807,12 +807,12 @@ "read_only": 1 }, { + "depends_on": "eval:parent.is_return && parent.update_stock && !parent.return_against", "fieldname": "incoming_rate", "fieldtype": "Currency", - "label": "Incoming Rate", + "label": "Incoming Rate (Costing)", "no_copy": 1, - "print_hide": 1, - "read_only": 1 + "print_hide": 1 }, { "depends_on": "eval: doc.uom != doc.stock_uom", @@ -833,7 +833,7 @@ "idx": 1, "istable": 1, "links": [], - "modified": "2021-08-12 20:15:47.668399", + "modified": "2021-08-19 13:41:53.435827", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice Item", diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py index 5ee1f2f7fb..01486fcd65 100644 --- a/erpnext/controllers/sales_and_purchase_return.py +++ b/erpnext/controllers/sales_and_purchase_return.py @@ -394,19 +394,6 @@ def get_rate_for_return(voucher_type, voucher_no, item_code, return_against=None if not return_against: return_against = frappe.get_cached_value(voucher_type, voucher_no, "return_against") - if not return_against and voucher_type == 'Sales Invoice' and sle: - return get_incoming_rate({ - "item_code": sle.item_code, - "warehouse": sle.warehouse, - "posting_date": sle.get('posting_date'), - "posting_time": sle.get('posting_time'), - "qty": sle.actual_qty, - "serial_no": sle.get('serial_no'), - "company": sle.company, - "voucher_type": sle.voucher_type, - "voucher_no": sle.voucher_no - }, raise_error_if_no_rate=False) - return_against_item_field = get_return_against_item_fields(voucher_type) filters = get_filters(voucher_type, voucher_no, voucher_detail_no, @@ -417,7 +404,24 @@ def get_rate_for_return(voucher_type, voucher_no, item_code, return_against=None else: select_field = "abs(stock_value_difference / actual_qty)" - return flt(frappe.db.get_value("Stock Ledger Entry", filters, select_field)) + rate = flt(frappe.db.get_value("Stock Ledger Entry", filters, select_field)) + if not (rate and return_against) and voucher_type in ['Sales Invoice', 'Delivery Note']: + rate = frappe.db.get_value(f'{voucher_type} Item', voucher_detail_no, 'incoming_rate') + + if not rate and sle: + rate = get_incoming_rate({ + "item_code": sle.item_code, + "warehouse": sle.warehouse, + "posting_date": sle.get('posting_date'), + "posting_time": sle.get('posting_time'), + "qty": sle.actual_qty, + "serial_no": sle.get('serial_no'), + "company": sle.company, + "voucher_type": sle.voucher_type, + "voucher_no": sle.voucher_no + }, raise_error_if_no_rate=False) + + return rate def get_return_against_item_fields(voucher_type): return_against_item_fields = { diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index fc2cc97e0a..4ea0e114b4 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -362,7 +362,7 @@ class SellingController(StockController): sales_order.update_reserved_qty(so_item_rows) def set_incoming_rate(self): - if self.doctype not in ("Delivery Note", "Sales Invoice", "Sales Order"): + if self.doctype not in ("Delivery Note", "Sales Invoice"): return items = self.get("items") + (self.get("packed_items") or []) @@ -371,18 +371,19 @@ class SellingController(StockController): # Get incoming rate based on original item cost based on valuation method qty = flt(d.get('stock_qty') or d.get('actual_qty')) - d.incoming_rate = get_incoming_rate({ - "item_code": d.item_code, - "warehouse": d.warehouse, - "posting_date": self.get('posting_date') or self.get('transaction_date'), - "posting_time": self.get('posting_time') or nowtime(), - "qty": qty if cint(self.get("is_return")) else (-1 * qty), - "serial_no": d.get('serial_no'), - "company": self.company, - "voucher_type": self.doctype, - "voucher_no": self.name, - "allow_zero_valuation": d.get("allow_zero_valuation") - }, raise_error_if_no_rate=False) + if not d.incoming_rate: + d.incoming_rate = get_incoming_rate({ + "item_code": d.item_code, + "warehouse": d.warehouse, + "posting_date": self.get('posting_date') or self.get('transaction_date'), + "posting_time": self.get('posting_time') or nowtime(), + "qty": qty if cint(self.get("is_return")) else (-1 * qty), + "serial_no": d.get('serial_no'), + "company": self.company, + "voucher_type": self.doctype, + "voucher_no": self.name, + "allow_zero_valuation": d.get("allow_zero_valuation") + }, raise_error_if_no_rate=False) # For internal transfers use incoming rate as the valuation rate if self.is_internal_transfer(): diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index eddd048c74..27feec1d15 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -332,6 +332,7 @@ class update_entries_after(object): where item_code = %(item_code)s and warehouse = %(warehouse)s + and is_cancelled = 0 and timestamp(posting_date, time_format(posting_time, %(time_format)s)) = timestamp(%(posting_date)s, time_format(%(posting_time)s, %(time_format)s)) order by From f4dc9ee2aa57d82a0be747a89e1ca573940da959 Mon Sep 17 00:00:00 2001 From: Marica Date: Thu, 26 Aug 2021 13:12:51 +0530 Subject: [PATCH 34/54] fix: Don't create inward SLE against SI unless is internal customer enabled (#27086) * fix: Dont create inward SLE against SI unless is internal customer enabled - Check if is internal customer enabled apart from target warehouse - Test to check if inward SLE is made if target warehouse is accidentally set but customer is not internal * test: Use internal customer for delivery of bundle items to target warehouse - created `create_internal_customer` util - reused it in delivery note and sales invoice tests - use internal customer for target warehouse test in delivery note --- .../sales_invoice/test_sales_invoice.py | 56 +++++++++++++------ erpnext/controllers/selling_controller.py | 2 +- .../selling/doctype/customer/test_customer.py | 25 +++++++++ .../delivery_note/test_delivery_note.py | 25 +++++++-- 4 files changed, 85 insertions(+), 23 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 5a19426eb0..43a5f5e2f6 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -151,7 +151,7 @@ class TestSalesInvoice(unittest.TestCase): si1 = create_sales_invoice(rate=1000) si2 = create_sales_invoice(rate=300) si3 = create_sales_invoice(qty=-1, rate=300, is_return=1) - + pe = get_payment_entry("Sales Invoice", si1.name, bank_account="_Test Bank - _TC") pe.append('references', { @@ -1828,23 +1828,12 @@ class TestSalesInvoice(unittest.TestCase): acc_settings.save() def test_inter_company_transaction(self): + from erpnext.selling.doctype.customer.test_customer import create_internal_customer - if not frappe.db.exists("Customer", "_Test Internal Customer"): - customer = frappe.get_doc({ - "customer_group": "_Test Customer Group", - "customer_name": "_Test Internal Customer", - "customer_type": "Individual", - "doctype": "Customer", - "territory": "_Test Territory", - "is_internal_customer": 1, - "represents_company": "_Test Company 1" - }) - - customer.append("companies", { - "company": "Wind Power LLC" - }) - - customer.insert() + create_internal_customer( + customer_name="_Test Internal Customer", + represents_company="_Test Company 1" + ) if not frappe.db.exists("Supplier", "_Test Internal Supplier"): supplier = frappe.get_doc({ @@ -1970,6 +1959,39 @@ class TestSalesInvoice(unittest.TestCase): frappe.local.enable_perpetual_inventory['_Test Company 1'] = old_perpetual_inventory frappe.db.set_value("Stock Settings", None, "allow_negative_stock", old_negative_stock) + def test_sle_if_target_warehouse_exists_accidentally(self): + """ + Check if inward entry exists if Target Warehouse accidentally exists + but Customer is not an internal customer. + """ + se = make_stock_entry( + item_code="138-CMS Shoe", + target="Finished Goods - _TC", + company = "_Test Company", + qty=1, + basic_rate=500 + ) + + si = frappe.copy_doc(test_records[0]) + si.update_stock = 1 + si.set_warehouse = "Finished Goods - _TC" + si.set_target_warehouse = "Stores - _TC" + si.get("items")[0].warehouse = "Finished Goods - _TC" + si.get("items")[0].target_warehouse = "Stores - _TC" + si.insert() + si.submit() + + sles = frappe.get_all("Stock Ledger Entry", filters={"voucher_no": si.name}, + fields=["name", "actual_qty"]) + + # check if only one SLE for outward entry is created + self.assertEqual(len(sles), 1) + self.assertEqual(sles[0].actual_qty, -1) + + # tear down + si.cancel() + se.cancel() + def test_internal_transfer_gl_entry(self): ## Create internal transfer account account = create_account(account_name="Unrealized Profit", diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index 4ea0e114b4..844c40c8a6 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -423,7 +423,7 @@ class SellingController(StockController): or (cint(self.is_return) and self.docstatus==2)): sl_entries.append(self.get_sle_for_source_warehouse(d)) - if d.target_warehouse: + if d.target_warehouse and self.get("is_internal_customer"): sl_entries.append(self.get_sle_for_target_warehouse(d)) if d.warehouse and ((not cint(self.is_return) and self.docstatus==2) diff --git a/erpnext/selling/doctype/customer/test_customer.py b/erpnext/selling/doctype/customer/test_customer.py index b1a5b52f96..908ba270b0 100644 --- a/erpnext/selling/doctype/customer/test_customer.py +++ b/erpnext/selling/doctype/customer/test_customer.py @@ -352,3 +352,28 @@ def set_credit_limit(customer, company, credit_limit): 'credit_limit': credit_limit }) customer.credit_limits[-1].db_insert() + +def create_internal_customer(**args): + args = frappe._dict(args) + + customer_name = args.get("customer_name") or "_Test Internal Customer" + + if not frappe.db.exists("Customer", customer_name): + customer = frappe.get_doc({ + "doctype": "Customer", + "customer_group": args.customer_group or "_Test Customer Group", + "customer_name": customer_name, + "customer_type": args.customer_type or "Individual", + "territory": args.territory or "_Test Territory", + "is_internal_customer": 1, + "represents_company": args.represents_company or "_Test Company with perpetual inventory" + }) + + customer.append("companies", { + "company": args.allowed_company or "Wind Power LLC" + }) + customer.insert() + + return customer + else: + return frappe.get_cached_doc("Customer", customer_name) \ No newline at end of file diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index 91e7c006ee..dffc73020d 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -430,12 +430,18 @@ class TestDeliveryNote(unittest.TestCase): }) def test_delivery_of_bundled_items_to_target_warehouse(self): + from erpnext.selling.doctype.customer.test_customer import create_internal_customer + company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') + customer = create_internal_customer( + customer_name="_Test Internal Customer 2", + allowed_company="_Test Company with perpetual inventory" + ) set_valuation_method("_Test Item", "FIFO") set_valuation_method("_Test Item Home Desktop 100", "FIFO") - target_warehouse=get_warehouse(company=company, abbr="TCP1", + target_warehouse = get_warehouse(company=company, abbr="TCP1", warehouse_name="_Test Customer Warehouse").name for warehouse in ("Stores - TCP1", target_warehouse): @@ -444,10 +450,16 @@ class TestDeliveryNote(unittest.TestCase): create_stock_reconciliation(item_code="_Test Item Home Desktop 100", company = company, expense_account = "Stock Adjustment - TCP1", warehouse=warehouse, qty=500, rate=100) - dn = create_delivery_note(item_code="_Test Product Bundle Item", - company='_Test Company with perpetual inventory', cost_center = 'Main - TCP1', - expense_account = "Cost of Goods Sold - TCP1", do_not_submit=True, qty=5, rate=500, - warehouse="Stores - TCP1", target_warehouse=target_warehouse) + dn = create_delivery_note( + item_code="_Test Product Bundle Item", + company="_Test Company with perpetual inventory", + customer=customer.name, + cost_center = 'Main - TCP1', + expense_account = "Cost of Goods Sold - TCP1", + do_not_submit=True, + qty=5, rate=500, + warehouse="Stores - TCP1", + target_warehouse=target_warehouse) dn.submit() @@ -487,6 +499,9 @@ class TestDeliveryNote(unittest.TestCase): for i, gle in enumerate(gl_entries): self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account)) + # tear down + frappe.db.rollback() + def test_closed_delivery_note(self): from erpnext.stock.doctype.delivery_note.delivery_note import update_delivery_note_status From b389b8c3ad945f0192c58151e525d9c077ceb1d0 Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Thu, 26 Aug 2021 13:15:57 +0530 Subject: [PATCH 35/54] fix: prevent over riding scrap table values, name kwargs, set currency --- erpnext/manufacturing/doctype/bom/bom.py | 2 +- erpnext/manufacturing/doctype/bom/test_bom.py | 15 +++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index ed1e259c3c..24f84e63b3 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -231,7 +231,7 @@ class BOM(WebsiteGenerator): } ret = self.get_bom_material_detail(args) for key, value in ret.items(): - if not item.get(key): + if item.get(key) is None: item.set(key, value) @frappe.whitelist() diff --git a/erpnext/manufacturing/doctype/bom/test_bom.py b/erpnext/manufacturing/doctype/bom/test_bom.py index 6e17f2a831..b8f0db0de2 100644 --- a/erpnext/manufacturing/doctype/bom/test_bom.py +++ b/erpnext/manufacturing/doctype/bom/test_bom.py @@ -285,30 +285,30 @@ class TestBOM(unittest.TestCase): if not frappe.db.exists("BOM", f"BOM-{fg_item_non_whole.item_code}-001"): bom_doc = create_bom_with_process_loss_item( - fg_item_non_whole, bom_item, 0.25, 0, 1 + fg_item_non_whole, bom_item, scrap_qty=0.25, scrap_rate=0, fg_qty=1 ) bom_doc.submit() bom_doc = create_bom_with_process_loss_item( - fg_item_non_whole, bom_item, 2, 0 + fg_item_non_whole, bom_item, scrap_qty=2, scrap_rate=0 ) # PL Item qty can't be >= FG Item qty self.assertRaises(frappe.ValidationError, bom_doc.submit) bom_doc = create_bom_with_process_loss_item( - fg_item_non_whole, bom_item, 1, 100 + fg_item_non_whole, bom_item, scrap_qty=1, scrap_rate=100 ) # PL Item rate has to be 0 self.assertRaises(frappe.ValidationError, bom_doc.submit) bom_doc = create_bom_with_process_loss_item( - fg_item_whole, bom_item, 0.25, 0 + fg_item_whole, bom_item, scrap_qty=0.25, scrap_rate=0 ) # Items with whole UOMs can't be PL Items self.assertRaises(frappe.ValidationError, bom_doc.submit) bom_doc = create_bom_with_process_loss_item( - fg_item_non_whole, bom_item, 0.25, 0, is_process_loss=0 + fg_item_non_whole, bom_item, scrap_qty=0.25, scrap_rate=0, is_process_loss=0 ) # FG Items in Scrap/Loss Table should have Is Process Loss set self.assertRaises(frappe.ValidationError, bom_doc.submit) @@ -316,9 +316,6 @@ class TestBOM(unittest.TestCase): def get_default_bom(item_code="_Test FG Item 2"): return frappe.db.get_value("BOM", {"item": item_code, "is_active": 1, "is_default": 1}) - - - def level_order_traversal(node): traversal = [] q = deque() @@ -364,6 +361,7 @@ def create_nested_bom(tree, prefix="_Test bom "): bom = frappe.get_doc(doctype="BOM", item=bom_item_code) for child_item in child_items.keys(): bom.append("items", {"item_code": prefix + child_item}) + bom.currency = "INR" bom.insert() bom.submit() @@ -407,6 +405,7 @@ def create_bom_with_process_loss_item( "rate": scrap_rate, "is_process_loss": is_process_loss }) + bom_doc.currency = "INR" return bom_doc def create_process_loss_bom_items(): From 8ed63383366728ae7650f6858feaba7ee1f832cd Mon Sep 17 00:00:00 2001 From: Saqib Date: Thu, 26 Aug 2021 13:27:16 +0530 Subject: [PATCH 36/54] refactor!: remove e_invoice utils (#27167) --- erpnext/regional/india/e_invoice/utils.py | 1131 --------------------- 1 file changed, 1131 deletions(-) delete mode 100644 erpnext/regional/india/e_invoice/utils.py diff --git a/erpnext/regional/india/e_invoice/utils.py b/erpnext/regional/india/e_invoice/utils.py deleted file mode 100644 index 765b51f435..0000000000 --- a/erpnext/regional/india/e_invoice/utils.py +++ /dev/null @@ -1,1131 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - -from __future__ import unicode_literals -import os -import re -import jwt -import sys -import json -import base64 -import frappe -import six -import traceback -import io -from frappe import _, bold -from pyqrcode import create as qrcreate -from frappe.utils.background_jobs import enqueue -from frappe.utils.scheduler import is_scheduler_inactive -from frappe.core.page.background_jobs.background_jobs import get_info -from frappe.integrations.utils import make_post_request, make_get_request -from erpnext.regional.india.utils import get_gst_accounts, get_place_of_supply -from frappe.utils.data import cstr, cint, format_date, flt, time_diff_in_seconds, now_datetime, add_to_date, get_link_to_form, getdate, time_diff_in_hours - -@frappe.whitelist() -def validate_eligibility(doc): - if isinstance(doc, six.string_types): - doc = json.loads(doc) - - invalid_doctype = doc.get('doctype') != 'Sales Invoice' - if invalid_doctype: - return False - - einvoicing_enabled = cint(frappe.db.get_single_value('E Invoice Settings', 'enable')) - if not einvoicing_enabled: - return False - - einvoicing_eligible_from = frappe.db.get_single_value('E Invoice Settings', 'applicable_from') or '2021-04-01' - if getdate(doc.get('posting_date')) < getdate(einvoicing_eligible_from): - return False - - invalid_company = not frappe.db.get_value('E Invoice User', { 'company': doc.get('company') }) - invalid_supply_type = doc.get('gst_category') not in ['Registered Regular', 'SEZ', 'Overseas', 'Deemed Export'] - company_transaction = doc.get('billing_address_gstin') == doc.get('company_gstin') - - # if export invoice, then taxes can be empty - # invoice can only be ineligible if no taxes applied and is not an export invoice - no_taxes_applied = not doc.get('taxes') and not doc.get('gst_category') == 'Overseas' - has_non_gst_item = any(d for d in doc.get('items', []) if d.get('is_non_gst')) - - if invalid_company or invalid_supply_type or company_transaction or no_taxes_applied or has_non_gst_item: - return False - - return True - -def validate_einvoice_fields(doc): - invoice_eligible = validate_eligibility(doc) - - if not invoice_eligible: - return - - if doc.docstatus == 0 and doc._action == 'save': - if doc.irn: - frappe.throw(_('You cannot edit the invoice after generating IRN'), title=_('Edit Not Allowed')) - if len(doc.name) > 16: - raise_document_name_too_long_error() - - doc.einvoice_status = 'Pending' - - elif doc.docstatus == 1 and doc._action == 'submit' and not doc.irn: - frappe.throw(_('You must generate IRN before submitting the document.'), title=_('Missing IRN')) - - elif doc.irn and doc.docstatus == 2 and doc._action == 'cancel' and not doc.irn_cancelled: - frappe.throw(_('You must cancel IRN before cancelling the document.'), title=_('Cancel Not Allowed')) - -def raise_document_name_too_long_error(): - title = _('Document ID Too Long') - msg = _('As you have E-Invoicing enabled, to be able to generate IRN for this invoice') - msg += ', ' - msg += _('document id {} exceed 16 letters.').format(bold(_('should not'))) - msg += '

' - msg += _('You must {} your {} in order to have document id of {} length 16.').format( - bold(_('modify')), bold(_('naming series')), bold(_('maximum')) - ) - msg += _('Please account for ammended documents too.') - frappe.throw(msg, title=title) - -def read_json(name): - file_path = os.path.join(os.path.dirname(__file__), '{name}.json'.format(name=name)) - with open(file_path, 'r') as f: - return cstr(f.read()) - -def get_transaction_details(invoice): - supply_type = '' - if invoice.gst_category == 'Registered Regular': supply_type = 'B2B' - elif invoice.gst_category == 'SEZ': supply_type = 'SEZWOP' - elif invoice.gst_category == 'Overseas': supply_type = 'EXPWOP' - elif invoice.gst_category == 'Deemed Export': supply_type = 'DEXP' - - if not supply_type: - rr, sez, overseas, export = bold('Registered Regular'), bold('SEZ'), bold('Overseas'), bold('Deemed Export') - frappe.throw(_('GST category should be one of {}, {}, {}, {}').format(rr, sez, overseas, export), - title=_('Invalid Supply Type')) - - return frappe._dict(dict( - tax_scheme='GST', - supply_type=supply_type, - reverse_charge=invoice.reverse_charge - )) - -def get_doc_details(invoice): - if getdate(invoice.posting_date) < getdate('2021-01-01'): - frappe.throw(_('IRN generation is not allowed for invoices dated before 1st Jan 2021'), title=_('Not Allowed')) - - invoice_type = 'CRN' if invoice.is_return else 'INV' - - invoice_name = invoice.name - invoice_date = format_date(invoice.posting_date, 'dd/mm/yyyy') - - return frappe._dict(dict( - invoice_type=invoice_type, - invoice_name=invoice_name, - invoice_date=invoice_date - )) - -def validate_address_fields(address, is_shipping_address): - if ((not address.gstin and not is_shipping_address) - or not address.city - or not address.pincode - or not address.address_title - or not address.address_line1 - or not address.gst_state_number): - - frappe.throw( - msg=_('Address Lines, City, Pincode, GSTIN are mandatory for address {}. Please set them and try again.').format(address.name), - title=_('Missing Address Fields') - ) - -def get_party_details(address_name, is_shipping_address=False): - addr = frappe.get_doc('Address', address_name) - - validate_address_fields(addr, is_shipping_address) - - if addr.gst_state_number == 97: - # according to einvoice standard - addr.pincode = 999999 - - party_address_details = frappe._dict(dict( - legal_name=sanitize_for_json(addr.address_title), - location=sanitize_for_json(addr.city), - pincode=addr.pincode, gstin=addr.gstin, - state_code=addr.gst_state_number, - address_line1=sanitize_for_json(addr.address_line1), - address_line2=sanitize_for_json(addr.address_line2) - )) - - return party_address_details - -def get_overseas_address_details(address_name): - address_title, address_line1, address_line2, city = frappe.db.get_value( - 'Address', address_name, ['address_title', 'address_line1', 'address_line2', 'city'] - ) - - if not address_title or not address_line1 or not city: - frappe.throw( - msg=_('Address lines and city is mandatory for address {}. Please set them and try again.').format( - get_link_to_form('Address', address_name) - ), - title=_('Missing Address Fields') - ) - - return frappe._dict(dict( - gstin='URP', - legal_name=sanitize_for_json(address_title), - location=city, - address_line1=sanitize_for_json(address_line1), - address_line2=sanitize_for_json(address_line2), - pincode=999999, state_code=96, place_of_supply=96 - )) - -def get_item_list(invoice): - item_list = [] - - for d in invoice.items: - einvoice_item_schema = read_json('einv_item_template') - item = frappe._dict({}) - item.update(d.as_dict()) - - item.sr_no = d.idx - item.description = sanitize_for_json(d.item_name) - - item.qty = abs(item.qty) - if flt(item.qty) != 0.0: - item.unit_rate = abs(item.taxable_value / item.qty) - else: - item.unit_rate = abs(item.taxable_value) - item.gross_amount = abs(item.taxable_value) - item.taxable_value = abs(item.taxable_value) - item.discount_amount = 0 - - item.batch_expiry_date = frappe.db.get_value('Batch', d.batch_no, 'expiry_date') if d.batch_no else None - item.batch_expiry_date = format_date(item.batch_expiry_date, 'dd/mm/yyyy') if item.batch_expiry_date else None - item.is_service_item = 'Y' if item.gst_hsn_code and item.gst_hsn_code[:2] == "99" else 'N' - item.serial_no = "" - - item = update_item_taxes(invoice, item) - - item.total_value = abs( - item.taxable_value + item.igst_amount + item.sgst_amount + - item.cgst_amount + item.cess_amount + item.cess_nadv_amount + item.other_charges - ) - einv_item = einvoice_item_schema.format(item=item) - item_list.append(einv_item) - - return ', '.join(item_list) - -def update_item_taxes(invoice, item): - gst_accounts = get_gst_accounts(invoice.company) - gst_accounts_list = [d for accounts in gst_accounts.values() for d in accounts if d] - - for attr in [ - 'tax_rate', 'cess_rate', 'cess_nadv_amount', - 'cgst_amount', 'sgst_amount', 'igst_amount', - 'cess_amount', 'cess_nadv_amount', 'other_charges' - ]: - item[attr] = 0 - - for t in invoice.taxes: - is_applicable = t.tax_amount and t.account_head in gst_accounts_list - if is_applicable: - # this contains item wise tax rate & tax amount (incl. discount) - item_tax_detail = json.loads(t.item_wise_tax_detail).get(item.item_code or item.item_name) - - item_tax_rate = item_tax_detail[0] - # item tax amount excluding discount amount - item_tax_amount = (item_tax_rate / 100) * item.taxable_value - - if t.account_head in gst_accounts.cess_account: - item_tax_amount_after_discount = item_tax_detail[1] - if t.charge_type == 'On Item Quantity': - item.cess_nadv_amount += abs(item_tax_amount_after_discount) - else: - item.cess_rate += item_tax_rate - item.cess_amount += abs(item_tax_amount_after_discount) - - for tax_type in ['igst', 'cgst', 'sgst']: - if t.account_head in gst_accounts[f'{tax_type}_account']: - item.tax_rate += item_tax_rate - item[f'{tax_type}_amount'] += abs(item_tax_amount) - else: - # TODO: other charges per item - pass - - return item - -def get_invoice_value_details(invoice): - invoice_value_details = frappe._dict(dict()) - invoice_value_details.base_total = abs(sum([i.taxable_value for i in invoice.get('items')])) - invoice_value_details.invoice_discount_amt = 0 - - invoice_value_details.round_off = invoice.base_rounding_adjustment - invoice_value_details.base_grand_total = abs(invoice.base_rounded_total) or abs(invoice.base_grand_total) - invoice_value_details.grand_total = abs(invoice.rounded_total) or abs(invoice.grand_total) - - invoice_value_details = update_invoice_taxes(invoice, invoice_value_details) - - return invoice_value_details - -def update_invoice_taxes(invoice, invoice_value_details): - gst_accounts = get_gst_accounts(invoice.company) - gst_accounts_list = [d for accounts in gst_accounts.values() for d in accounts if d] - - invoice_value_details.total_cgst_amt = 0 - invoice_value_details.total_sgst_amt = 0 - invoice_value_details.total_igst_amt = 0 - invoice_value_details.total_cess_amt = 0 - invoice_value_details.total_other_charges = 0 - considered_rows = [] - - for t in invoice.taxes: - tax_amount = t.base_tax_amount_after_discount_amount - if t.account_head in gst_accounts_list: - if t.account_head in gst_accounts.cess_account: - # using after discount amt since item also uses after discount amt for cess calc - invoice_value_details.total_cess_amt += abs(t.base_tax_amount_after_discount_amount) - - for tax_type in ['igst', 'cgst', 'sgst']: - if t.account_head in gst_accounts[f'{tax_type}_account']: - - invoice_value_details[f'total_{tax_type}_amt'] += abs(tax_amount) - update_other_charges(t, invoice_value_details, gst_accounts_list, invoice, considered_rows) - else: - invoice_value_details.total_other_charges += abs(tax_amount) - - return invoice_value_details - -def update_other_charges(tax_row, invoice_value_details, gst_accounts_list, invoice, considered_rows): - prev_row_id = cint(tax_row.row_id) - 1 - if tax_row.account_head in gst_accounts_list and prev_row_id not in considered_rows: - if tax_row.charge_type == 'On Previous Row Amount': - amount = invoice.get('taxes')[prev_row_id].tax_amount_after_discount_amount - invoice_value_details.total_other_charges -= abs(amount) - considered_rows.append(prev_row_id) - if tax_row.charge_type == 'On Previous Row Total': - amount = invoice.get('taxes')[prev_row_id].base_total - invoice.base_net_total - invoice_value_details.total_other_charges -= abs(amount) - considered_rows.append(prev_row_id) - -def get_payment_details(invoice): - payee_name = invoice.company - mode_of_payment = ', '.join([d.mode_of_payment for d in invoice.payments]) - paid_amount = invoice.base_paid_amount - outstanding_amount = invoice.outstanding_amount - - return frappe._dict(dict( - payee_name=payee_name, mode_of_payment=mode_of_payment, - paid_amount=paid_amount, outstanding_amount=outstanding_amount - )) - -def get_return_doc_reference(invoice): - invoice_date = frappe.db.get_value('Sales Invoice', invoice.return_against, 'posting_date') - return frappe._dict(dict( - invoice_name=invoice.return_against, invoice_date=format_date(invoice_date, 'dd/mm/yyyy') - )) - -def get_eway_bill_details(invoice): - if invoice.is_return: - frappe.throw(_('E-Way Bill cannot be generated for Credit Notes & Debit Notes. Please clear fields in the Transporter Section of the invoice.'), - title=_('Invalid Fields')) - - - mode_of_transport = { '': '', 'Road': '1', 'Air': '2', 'Rail': '3', 'Ship': '4' } - vehicle_type = { 'Regular': 'R', 'Over Dimensional Cargo (ODC)': 'O' } - - return frappe._dict(dict( - gstin=invoice.gst_transporter_id, - name=invoice.transporter_name, - mode_of_transport=mode_of_transport[invoice.mode_of_transport], - distance=invoice.distance or 0, - document_name=invoice.lr_no, - document_date=format_date(invoice.lr_date, 'dd/mm/yyyy'), - vehicle_no=invoice.vehicle_no, - vehicle_type=vehicle_type[invoice.gst_vehicle_type] - )) - -def validate_mandatory_fields(invoice): - if not invoice.company_address: - frappe.throw( - _('Company Address is mandatory to fetch company GSTIN details. Please set Company Address and try again.'), - title=_('Missing Fields') - ) - if not invoice.customer_address: - frappe.throw( - _('Customer Address is mandatory to fetch customer GSTIN details. Please set Company Address and try again.'), - title=_('Missing Fields') - ) - if not frappe.db.get_value('Address', invoice.company_address, 'gstin'): - frappe.throw( - _('GSTIN is mandatory to fetch company GSTIN details. Please enter GSTIN in selected company address.'), - title=_('Missing Fields') - ) - if invoice.gst_category != 'Overseas' and not frappe.db.get_value('Address', invoice.customer_address, 'gstin'): - frappe.throw( - _('GSTIN is mandatory to fetch customer GSTIN details. Please enter GSTIN in selected customer address.'), - title=_('Missing Fields') - ) - -def validate_totals(einvoice): - item_list = einvoice['ItemList'] - value_details = einvoice['ValDtls'] - - total_item_ass_value = 0 - total_item_cgst_value = 0 - total_item_sgst_value = 0 - total_item_igst_value = 0 - total_item_value = 0 - for item in item_list: - total_item_ass_value += flt(item['AssAmt']) - total_item_cgst_value += flt(item['CgstAmt']) - total_item_sgst_value += flt(item['SgstAmt']) - total_item_igst_value += flt(item['IgstAmt']) - total_item_value += flt(item['TotItemVal']) - - if abs(flt(item['AssAmt']) * flt(item['GstRt']) / 100) - (flt(item['CgstAmt']) + flt(item['SgstAmt']) + flt(item['IgstAmt'])) > 1: - frappe.throw(_('Row #{}: GST rate is invalid. Please remove tax rows with zero tax amount from taxes table.').format(item.idx)) - - if abs(flt(value_details['AssVal']) - total_item_ass_value) > 1: - frappe.throw(_('Total Taxable Value of the items is not equal to the Invoice Net Total. Please check item taxes / discounts for any correction.')) - - if abs( - flt(value_details['TotInvVal']) + flt(value_details['Discount']) - - flt(value_details['OthChrg']) - flt(value_details['RndOffAmt']) - - total_item_value) > 1: - frappe.throw(_('Total Value of the items is not equal to the Invoice Grand Total. Please check item taxes / discounts for any correction.')) - - calculated_invoice_value = \ - flt(value_details['AssVal']) + flt(value_details['CgstVal']) \ - + flt(value_details['SgstVal']) + flt(value_details['IgstVal']) \ - + flt(value_details['OthChrg']) + flt(value_details['RndOffAmt']) - flt(value_details['Discount']) - - if abs(flt(value_details['TotInvVal']) - calculated_invoice_value) > 1: - frappe.throw(_('Total Item Value + Taxes - Discount is not equal to the Invoice Grand Total. Please check taxes / discounts for any correction.')) - -def make_einvoice(invoice): - validate_mandatory_fields(invoice) - - schema = read_json('einv_template') - - transaction_details = get_transaction_details(invoice) - item_list = get_item_list(invoice) - doc_details = get_doc_details(invoice) - invoice_value_details = get_invoice_value_details(invoice) - seller_details = get_party_details(invoice.company_address) - - if invoice.gst_category == 'Overseas': - buyer_details = get_overseas_address_details(invoice.customer_address) - else: - buyer_details = get_party_details(invoice.customer_address) - place_of_supply = get_place_of_supply(invoice, invoice.doctype) - if place_of_supply: - place_of_supply = place_of_supply.split('-')[0] - else: - place_of_supply = sanitize_for_json(invoice.billing_address_gstin)[:2] - buyer_details.update(dict(place_of_supply=place_of_supply)) - - seller_details.update(dict(legal_name=invoice.company)) - buyer_details.update(dict(legal_name=invoice.customer_name or invoice.customer)) - - shipping_details = payment_details = prev_doc_details = eway_bill_details = frappe._dict({}) - if invoice.shipping_address_name and invoice.customer_address != invoice.shipping_address_name: - if invoice.gst_category == 'Overseas': - shipping_details = get_overseas_address_details(invoice.shipping_address_name) - else: - shipping_details = get_party_details(invoice.shipping_address_name, is_shipping_address=True) - - if invoice.is_pos and invoice.base_paid_amount: - payment_details = get_payment_details(invoice) - - if invoice.is_return and invoice.return_against: - prev_doc_details = get_return_doc_reference(invoice) - - if invoice.transporter and not invoice.is_return: - eway_bill_details = get_eway_bill_details(invoice) - - # not yet implemented - dispatch_details = period_details = export_details = frappe._dict({}) - - einvoice = schema.format( - transaction_details=transaction_details, doc_details=doc_details, dispatch_details=dispatch_details, - seller_details=seller_details, buyer_details=buyer_details, shipping_details=shipping_details, - item_list=item_list, invoice_value_details=invoice_value_details, payment_details=payment_details, - period_details=period_details, prev_doc_details=prev_doc_details, - export_details=export_details, eway_bill_details=eway_bill_details - ) - - try: - einvoice = safe_json_load(einvoice) - einvoice = santize_einvoice_fields(einvoice) - except Exception: - show_link_to_error_log(invoice, einvoice) - - validate_totals(einvoice) - - return einvoice - -def show_link_to_error_log(invoice, einvoice): - err_log = log_error(einvoice) - link_to_error_log = get_link_to_form('Error Log', err_log.name, 'Error Log') - frappe.throw( - _('An error occurred while creating e-invoice for {}. Please check {} for more information.').format( - invoice.name, link_to_error_log), - title=_('E Invoice Creation Failed') - ) - -def log_error(data=None): - if isinstance(data, six.string_types): - data = json.loads(data) - - seperator = "--" * 50 - err_tb = traceback.format_exc() - err_msg = str(sys.exc_info()[1]) - data = json.dumps(data, indent=4) - - message = "\n".join([ - "Error", err_msg, seperator, - "Data:", data, seperator, - "Exception:", err_tb - ]) - frappe.log_error(title=_('E Invoice Request Failed'), message=message) - -def santize_einvoice_fields(einvoice): - int_fields = ["Pin","Distance","CrDay"] - float_fields = ["Qty","FreeQty","UnitPrice","TotAmt","Discount","PreTaxVal","AssAmt","GstRt","IgstAmt","CgstAmt","SgstAmt","CesRt","CesAmt","CesNonAdvlAmt","StateCesRt","StateCesAmt","StateCesNonAdvlAmt","OthChrg","TotItemVal","AssVal","CgstVal","SgstVal","IgstVal","CesVal","StCesVal","Discount","OthChrg","RndOffAmt","TotInvVal","TotInvValFc","PaidAmt","PaymtDue","ExpDuty",] - copy = einvoice.copy() - for key, value in copy.items(): - if isinstance(value, list): - for idx, d in enumerate(value): - santized_dict = santize_einvoice_fields(d) - if santized_dict: - einvoice[key][idx] = santized_dict - else: - einvoice[key].pop(idx) - - if not einvoice[key]: - einvoice.pop(key, None) - - elif isinstance(value, dict): - santized_dict = santize_einvoice_fields(value) - if santized_dict: - einvoice[key] = santized_dict - else: - einvoice.pop(key, None) - - elif not value or value == "None": - einvoice.pop(key, None) - - elif key in float_fields: - einvoice[key] = flt(value, 2) - - elif key in int_fields: - einvoice[key] = cint(value) - - return einvoice - -def safe_json_load(json_string): - try: - return json.loads(json_string) - except json.JSONDecodeError as e: - # print a snippet of 40 characters around the location where error occured - pos = e.pos - start, end = max(0, pos-20), min(len(json_string)-1, pos+20) - snippet = json_string[start:end] - frappe.throw(_("Error in input data. Please check for any special characters near following input:
{}").format(snippet)) - -class RequestFailed(Exception): - pass -class CancellationNotAllowed(Exception): - pass - -class GSPConnector(): - def __init__(self, doctype=None, docname=None): - self.doctype = doctype - self.docname = docname - - self.set_invoice() - self.set_credentials() - - # authenticate url is same for sandbox & live - self.authenticate_url = 'https://gsp.adaequare.com/gsp/authenticate?grant_type=token' - self.base_url = 'https://gsp.adaequare.com' if not self.e_invoice_settings.sandbox_mode else 'https://gsp.adaequare.com/test' - - self.cancel_irn_url = self.base_url + '/enriched/ei/api/invoice/cancel' - self.irn_details_url = self.base_url + '/enriched/ei/api/invoice/irn' - self.generate_irn_url = self.base_url + '/enriched/ei/api/invoice' - self.gstin_details_url = self.base_url + '/enriched/ei/api/master/gstin' - self.cancel_ewaybill_url = self.base_url + '/enriched/ewb/ewayapi?action=CANEWB' - self.generate_ewaybill_url = self.base_url + '/enriched/ei/api/ewaybill' - - def set_invoice(self): - self.invoice = None - if self.doctype and self.docname: - self.invoice = frappe.get_cached_doc(self.doctype, self.docname) - - def set_credentials(self): - self.e_invoice_settings = frappe.get_cached_doc('E Invoice Settings') - - if not self.e_invoice_settings.enable: - frappe.throw(_("E-Invoicing is disabled. Please enable it from {} to generate e-invoices.").format(get_link_to_form("E Invoice Settings", "E Invoice Settings"))) - - if self.invoice: - gstin = self.get_seller_gstin() - credentials_for_gstin = [d for d in self.e_invoice_settings.credentials if d.gstin == gstin] - if credentials_for_gstin: - self.credentials = credentials_for_gstin[0] - else: - frappe.throw(_('Cannot find e-invoicing credentials for selected Company GSTIN. Please check E-Invoice Settings')) - else: - self.credentials = self.e_invoice_settings.credentials[0] if self.e_invoice_settings.credentials else None - - def get_seller_gstin(self): - gstin = frappe.db.get_value('Address', self.invoice.company_address, 'gstin') - if not gstin: - frappe.throw(_('Cannot retrieve Company GSTIN. Please select company address with valid GSTIN.')) - return gstin - - def get_auth_token(self): - if time_diff_in_seconds(self.e_invoice_settings.token_expiry, now_datetime()) < 150.0: - self.fetch_auth_token() - - return self.e_invoice_settings.auth_token - - def make_request(self, request_type, url, headers=None, data=None): - if request_type == 'post': - res = make_post_request(url, headers=headers, data=data) - else: - res = make_get_request(url, headers=headers, data=data) - - self.log_request(url, headers, data, res) - return res - - def log_request(self, url, headers, data, res): - headers.update({ 'password': self.credentials.password }) - request_log = frappe.get_doc({ - "doctype": "E Invoice Request Log", - "user": frappe.session.user, - "reference_invoice": self.invoice.name if self.invoice else None, - "url": url, - "headers": json.dumps(headers, indent=4) if headers else None, - "data": json.dumps(data, indent=4) if isinstance(data, dict) else data, - "response": json.dumps(res, indent=4) if res else None - }) - request_log.save(ignore_permissions=True) - frappe.db.commit() - - def fetch_auth_token(self): - headers = { - 'gspappid': frappe.conf.einvoice_client_id, - 'gspappsecret': frappe.conf.einvoice_client_secret - } - res = {} - try: - res = self.make_request('post', self.authenticate_url, headers) - self.e_invoice_settings.auth_token = "{} {}".format(res.get('token_type'), res.get('access_token')) - self.e_invoice_settings.token_expiry = add_to_date(None, seconds=res.get('expires_in')) - self.e_invoice_settings.save(ignore_permissions=True) - self.e_invoice_settings.reload() - - except Exception: - log_error(res) - self.raise_error(True) - - def get_headers(self): - return { - 'content-type': 'application/json', - 'user_name': self.credentials.username, - 'password': self.credentials.get_password(), - 'gstin': self.credentials.gstin, - 'authorization': self.get_auth_token(), - 'requestid': str(base64.b64encode(os.urandom(18))), - } - - def fetch_gstin_details(self, gstin): - headers = self.get_headers() - - try: - params = '?gstin={gstin}'.format(gstin=gstin) - res = self.make_request('get', self.gstin_details_url + params, headers) - if res.get('success'): - return res.get('result') - else: - log_error(res) - raise RequestFailed - - except RequestFailed: - self.raise_error() - - except Exception: - log_error() - self.raise_error(True) - @staticmethod - def get_gstin_details(gstin): - '''fetch and cache GSTIN details''' - if not hasattr(frappe.local, 'gstin_cache'): - frappe.local.gstin_cache = {} - - key = gstin - gsp_connector = GSPConnector() - details = gsp_connector.fetch_gstin_details(gstin) - - frappe.local.gstin_cache[key] = details - frappe.cache().hset('gstin_cache', key, details) - return details - - def generate_irn(self): - data = {} - try: - headers = self.get_headers() - einvoice = make_einvoice(self.invoice) - data = json.dumps(einvoice, indent=4) - res = self.make_request('post', self.generate_irn_url, headers, data) - - if res.get('success'): - self.set_einvoice_data(res.get('result')) - - elif '2150' in res.get('message'): - # IRN already generated but not updated in invoice - # Extract the IRN from the response description and fetch irn details - irn = res.get('result')[0].get('Desc').get('Irn') - irn_details = self.get_irn_details(irn) - if irn_details: - self.set_einvoice_data(irn_details) - else: - raise RequestFailed('IRN has already been generated for the invoice but cannot fetch details for the it. \ - Contact ERPNext support to resolve the issue.') - - else: - raise RequestFailed - - except RequestFailed: - errors = self.sanitize_error_message(res.get('message')) - self.set_failed_status(errors=errors) - self.raise_error(errors=errors) - - except Exception as e: - self.set_failed_status(errors=str(e)) - log_error(data) - self.raise_error(True) - - @staticmethod - def bulk_generate_irn(invoices): - gsp_connector = GSPConnector() - gsp_connector.doctype = 'Sales Invoice' - - failed = [] - - for invoice in invoices: - try: - gsp_connector.docname = invoice - gsp_connector.set_invoice() - gsp_connector.set_credentials() - gsp_connector.generate_irn() - - except Exception as e: - failed.append({ - 'docname': invoice, - 'message': str(e) - }) - - return failed - - def get_irn_details(self, irn): - headers = self.get_headers() - - try: - params = '?irn={irn}'.format(irn=irn) - res = self.make_request('get', self.irn_details_url + params, headers) - if res.get('success'): - return res.get('result') - else: - raise RequestFailed - - except RequestFailed: - errors = self.sanitize_error_message(res.get('message')) - self.raise_error(errors=errors) - - except Exception: - log_error() - self.raise_error(True) - - def cancel_irn(self, irn, reason, remark): - data, res = {}, {} - try: - # validate cancellation - if time_diff_in_hours(now_datetime(), self.invoice.ack_date) > 24: - frappe.throw(_('E-Invoice cannot be cancelled after 24 hours of IRN generation.'), title=_('Not Allowed'), exc=CancellationNotAllowed) - if not irn: - frappe.throw(_('IRN not found. You must generate IRN before cancelling.'), title=_('Not Allowed'), exc=CancellationNotAllowed) - - headers = self.get_headers() - data = json.dumps({ - 'Irn': irn, - 'Cnlrsn': reason, - 'Cnlrem': remark - }, indent=4) - - res = self.make_request('post', self.cancel_irn_url, headers, data) - if res.get('success') or '9999' in res.get('message'): - self.invoice.irn_cancelled = 1 - self.invoice.irn_cancel_date = res.get('result')['CancelDate'] if res.get('result') else "" - self.invoice.einvoice_status = 'Cancelled' - self.invoice.flags.updater_reference = { - 'doctype': self.invoice.doctype, - 'docname': self.invoice.name, - 'label': _('IRN Cancelled - {}').format(remark) - } - self.update_invoice() - - else: - raise RequestFailed - - except RequestFailed: - errors = self.sanitize_error_message(res.get('message')) - self.set_failed_status(errors=errors) - self.raise_error(errors=errors) - - except CancellationNotAllowed as e: - self.set_failed_status(errors=str(e)) - self.raise_error(errors=str(e)) - - except Exception as e: - self.set_failed_status(errors=str(e)) - log_error(data) - self.raise_error(True) - - @staticmethod - def bulk_cancel_irn(invoices, reason, remark): - gsp_connector = GSPConnector() - gsp_connector.doctype = 'Sales Invoice' - - failed = [] - - for invoice in invoices: - try: - gsp_connector.docname = invoice - gsp_connector.set_invoice() - gsp_connector.set_credentials() - irn = gsp_connector.invoice.irn - gsp_connector.cancel_irn(irn, reason, remark) - - except Exception as e: - failed.append({ - 'docname': invoice, - 'message': str(e) - }) - - return failed - - def generate_eway_bill(self, **kwargs): - args = frappe._dict(kwargs) - - headers = self.get_headers() - eway_bill_details = get_eway_bill_details(args) - data = json.dumps({ - 'Irn': args.irn, - 'Distance': cint(eway_bill_details.distance), - 'TransMode': eway_bill_details.mode_of_transport, - 'TransId': eway_bill_details.gstin, - 'TransName': eway_bill_details.transporter, - 'TrnDocDt': eway_bill_details.document_date, - 'TrnDocNo': eway_bill_details.document_name, - 'VehNo': eway_bill_details.vehicle_no, - 'VehType': eway_bill_details.vehicle_type - }, indent=4) - - try: - res = self.make_request('post', self.generate_ewaybill_url, headers, data) - if res.get('success'): - self.invoice.ewaybill = res.get('result').get('EwbNo') - self.invoice.eway_bill_validity = res.get('result').get('EwbValidTill') - self.invoice.eway_bill_cancelled = 0 - self.invoice.update(args) - self.invoice.flags.updater_reference = { - 'doctype': self.invoice.doctype, - 'docname': self.invoice.name, - 'label': _('E-Way Bill Generated') - } - self.update_invoice() - - else: - raise RequestFailed - - except RequestFailed: - errors = self.sanitize_error_message(res.get('message')) - self.raise_error(errors=errors) - - except Exception: - log_error(data) - self.raise_error(True) - - def cancel_eway_bill(self, eway_bill, reason, remark): - headers = self.get_headers() - data = json.dumps({ - 'ewbNo': eway_bill, - 'cancelRsnCode': reason, - 'cancelRmrk': remark - }, indent=4) - headers["username"] = headers["user_name"] - del headers["user_name"] - try: - res = self.make_request('post', self.cancel_ewaybill_url, headers, data) - if res.get('success'): - self.invoice.ewaybill = '' - self.invoice.eway_bill_cancelled = 1 - self.invoice.flags.updater_reference = { - 'doctype': self.invoice.doctype, - 'docname': self.invoice.name, - 'label': _('E-Way Bill Cancelled - {}').format(remark) - } - self.update_invoice() - - else: - raise RequestFailed - - except RequestFailed: - errors = self.sanitize_error_message(res.get('message')) - self.raise_error(errors=errors) - - except Exception: - log_error(data) - self.raise_error(True) - - def sanitize_error_message(self, message): - ''' - On validation errors, response message looks something like this: - message = '2174 : For inter-state transaction, CGST and SGST amounts are not applicable; only IGST amount is applicable, - 3095 : Supplier GSTIN is inactive' - we search for string between ':' to extract the error messages - errors = [ - ': For inter-state transaction, CGST and SGST amounts are not applicable; only IGST amount is applicable, 3095 ', - ': Test' - ] - then we trim down the message by looping over errors - ''' - if not message: - return [] - - errors = re.findall(': [^:]+', message) - for idx, e in enumerate(errors): - # remove colons - errors[idx] = errors[idx].replace(':', '').strip() - # if not last - if idx != len(errors) - 1: - # remove last 7 chars eg: ', 3095 ' - errors[idx] = errors[idx][:-6] - - return errors - - def raise_error(self, raise_exception=False, errors=[]): - title = _('E Invoice Request Failed') - if errors: - frappe.throw(errors, title=title, as_list=1) - else: - link_to_error_list = 'Error Log' - frappe.msgprint( - _('An error occurred while making e-invoicing request. Please check {} for more information.').format(link_to_error_list), - title=title, - raise_exception=raise_exception, - indicator='red' - ) - - def set_einvoice_data(self, res): - enc_signed_invoice = res.get('SignedInvoice') - dec_signed_invoice = jwt.decode(enc_signed_invoice, options={"verify_signature": False})['data'] - - self.invoice.irn = res.get('Irn') - self.invoice.ewaybill = res.get('EwbNo') - self.invoice.eway_bill_validity = res.get('EwbValidTill') - self.invoice.ack_no = res.get('AckNo') - self.invoice.ack_date = res.get('AckDt') - self.invoice.signed_einvoice = dec_signed_invoice - self.invoice.ack_no = res.get('AckNo') - self.invoice.ack_date = res.get('AckDt') - self.invoice.signed_qr_code = res.get('SignedQRCode') - self.invoice.einvoice_status = 'Generated' - - self.attach_qrcode_image() - - self.invoice.flags.updater_reference = { - 'doctype': self.invoice.doctype, - 'docname': self.invoice.name, - 'label': _('IRN Generated') - } - self.update_invoice() - - def attach_qrcode_image(self): - qrcode = self.invoice.signed_qr_code - doctype = self.invoice.doctype - docname = self.invoice.name - filename = 'QRCode_{}.png'.format(docname).replace(os.path.sep, "__") - - qr_image = io.BytesIO() - url = qrcreate(qrcode, error='L') - url.png(qr_image, scale=2, quiet_zone=1) - _file = frappe.get_doc({ - "doctype": "File", - "file_name": filename, - "attached_to_doctype": doctype, - "attached_to_name": docname, - "attached_to_field": "qrcode_image", - "is_private": 0, - "content": qr_image.getvalue()}) - _file.save() - frappe.db.commit() - self.invoice.qrcode_image = _file.file_url - - def update_invoice(self): - self.invoice.flags.ignore_validate_update_after_submit = True - self.invoice.flags.ignore_validate = True - self.invoice.save() - - def set_failed_status(self, errors=None): - frappe.db.rollback() - self.invoice.einvoice_status = 'Failed' - self.invoice.failure_description = self.get_failure_message(errors) if errors else "" - self.update_invoice() - frappe.db.commit() - - def get_failure_message(self, errors): - if isinstance(errors, list): - errors = ', '.join(errors) - return errors - -def sanitize_for_json(string): - """Escape JSON specific characters from a string.""" - - # json.dumps adds double-quotes to the string. Indexing to remove them. - return json.dumps(string)[1:-1] - -@frappe.whitelist() -def get_einvoice(doctype, docname): - invoice = frappe.get_doc(doctype, docname) - return make_einvoice(invoice) - -@frappe.whitelist() -def generate_irn(doctype, docname): - gsp_connector = GSPConnector(doctype, docname) - gsp_connector.generate_irn() - -@frappe.whitelist() -def cancel_irn(doctype, docname, irn, reason, remark): - gsp_connector = GSPConnector(doctype, docname) - gsp_connector.cancel_irn(irn, reason, remark) - -@frappe.whitelist() -def generate_eway_bill(doctype, docname, **kwargs): - gsp_connector = GSPConnector(doctype, docname) - gsp_connector.generate_eway_bill(**kwargs) - -@frappe.whitelist() -def cancel_eway_bill(doctype, docname): - # TODO: uncomment when eway_bill api from Adequare is enabled - # gsp_connector = GSPConnector(doctype, docname) - # gsp_connector.cancel_eway_bill(eway_bill, reason, remark) - - frappe.db.set_value(doctype, docname, 'ewaybill', '') - frappe.db.set_value(doctype, docname, 'eway_bill_cancelled', 1) - -@frappe.whitelist() -def generate_einvoices(docnames): - docnames = json.loads(docnames) or [] - - if len(docnames) < 10: - failures = GSPConnector.bulk_generate_irn(docnames) - frappe.local.message_log = [] - - if failures: - show_bulk_action_failure_message(failures) - - success = len(docnames) - len(failures) - frappe.msgprint( - _('{} e-invoices generated successfully').format(success), - title=_('Bulk E-Invoice Generation Complete') - ) - - else: - enqueue_bulk_action(schedule_bulk_generate_irn, docnames=docnames) - -def schedule_bulk_generate_irn(docnames): - failures = GSPConnector.bulk_generate_irn(docnames) - frappe.local.message_log = [] - - frappe.publish_realtime("bulk_einvoice_generation_complete", { - "user": frappe.session.user, - "failures": failures, - "invoices": docnames - }) - -def show_bulk_action_failure_message(failures): - for doc in failures: - docname = '{0}'.format(doc.get('docname')) - message = doc.get('message').replace("'", '"') - if message[0] == '[': - errors = json.loads(message) - error_list = ''.join(['
  • {}
  • '.format(err) for err in errors]) - message = '''{} has following errors:
    -
      {}
    '''.format(docname, error_list) - else: - message = '{} - {}'.format(docname, message) - - frappe.msgprint( - message, - title=_('Bulk E-Invoice Generation Complete'), - indicator='red' - ) - -@frappe.whitelist() -def cancel_irns(docnames, reason, remark): - docnames = json.loads(docnames) or [] - - if len(docnames) < 10: - failures = GSPConnector.bulk_cancel_irn(docnames, reason, remark) - frappe.local.message_log = [] - - if failures: - show_bulk_action_failure_message(failures) - - success = len(docnames) - len(failures) - frappe.msgprint( - _('{} e-invoices cancelled successfully').format(success), - title=_('Bulk E-Invoice Cancellation Complete') - ) - else: - enqueue_bulk_action(schedule_bulk_cancel_irn, docnames=docnames, reason=reason, remark=remark) - -def schedule_bulk_cancel_irn(docnames, reason, remark): - failures = GSPConnector.bulk_cancel_irn(docnames, reason, remark) - frappe.local.message_log = [] - - frappe.publish_realtime("bulk_einvoice_cancellation_complete", { - "user": frappe.session.user, - "failures": failures, - "invoices": docnames - }) - -def enqueue_bulk_action(job, **kwargs): - check_scheduler_status() - - enqueue( - job, - **kwargs, - queue="long", - timeout=10000, - event="processing_bulk_einvoice_action", - now=frappe.conf.developer_mode or frappe.flags.in_test, - ) - - if job == schedule_bulk_generate_irn: - msg = _('E-Invoices will be generated in a background process.') - else: - msg = _('E-Invoices will be cancelled in a background process.') - - frappe.msgprint(msg, alert=1) - -def check_scheduler_status(): - if is_scheduler_inactive() and not frappe.flags.in_test: - frappe.throw(_("Scheduler is inactive. Cannot enqueue job."), title=_("Scheduler Inactive")) - -def job_already_enqueued(job_name): - enqueued_jobs = [d.get("job_name") for d in get_info()] - if job_name in enqueued_jobs: - return True From 45edfd9d50f6d2f86d268b94cad86abbfa815d2a Mon Sep 17 00:00:00 2001 From: marination Date: Thu, 26 Aug 2021 15:53:52 +0530 Subject: [PATCH 37/54] fix: Remove duplicate `create_internal_customer` util - Introduced via https://github.com/frappe/erpnext/pull/27086 --- .../sales_invoice/test_sales_invoice.py | 28 +++---------------- .../selling/doctype/customer/test_customer.py | 24 ++++++++-------- .../delivery_note/test_delivery_note.py | 3 +- 3 files changed, 17 insertions(+), 38 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 43a5f5e2f6..e06a3bb5b1 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -1832,7 +1832,8 @@ class TestSalesInvoice(unittest.TestCase): create_internal_customer( customer_name="_Test Internal Customer", - represents_company="_Test Company 1" + represents_company="_Test Company 1", + allowed_to_interact_with="Wind Power LLC" ) if not frappe.db.exists("Supplier", "_Test Internal Supplier"): @@ -1994,6 +1995,8 @@ class TestSalesInvoice(unittest.TestCase): def test_internal_transfer_gl_entry(self): ## Create internal transfer account + from erpnext.selling.doctype.customer.test_customer import create_internal_customer + account = create_account(account_name="Unrealized Profit", parent_account="Current Liabilities - TCP1", company="_Test Company with perpetual inventory") @@ -2551,29 +2554,6 @@ def get_taxes_and_charges(): "row_id": 1 }] -def create_internal_customer(customer_name, represents_company, allowed_to_interact_with): - if not frappe.db.exists("Customer", customer_name): - customer = frappe.get_doc({ - "customer_group": "_Test Customer Group", - "customer_name": customer_name, - "customer_type": "Individual", - "doctype": "Customer", - "territory": "_Test Territory", - "is_internal_customer": 1, - "represents_company": represents_company - }) - - customer.append("companies", { - "company": allowed_to_interact_with - }) - - customer.insert() - customer_name = customer.name - else: - customer_name = frappe.db.get_value("Customer", customer_name) - - return customer_name - def create_internal_supplier(supplier_name, represents_company, allowed_to_interact_with): if not frappe.db.exists("Supplier", supplier_name): supplier = frappe.get_doc({ diff --git a/erpnext/selling/doctype/customer/test_customer.py b/erpnext/selling/doctype/customer/test_customer.py index 908ba270b0..5b337313d3 100644 --- a/erpnext/selling/doctype/customer/test_customer.py +++ b/erpnext/selling/doctype/customer/test_customer.py @@ -353,27 +353,25 @@ def set_credit_limit(customer, company, credit_limit): }) customer.credit_limits[-1].db_insert() -def create_internal_customer(**args): - args = frappe._dict(args) - - customer_name = args.get("customer_name") or "_Test Internal Customer" - +def create_internal_customer(customer_name, represents_company, allowed_to_interact_with): if not frappe.db.exists("Customer", customer_name): customer = frappe.get_doc({ "doctype": "Customer", - "customer_group": args.customer_group or "_Test Customer Group", + "customer_group": "_Test Customer Group", "customer_name": customer_name, - "customer_type": args.customer_type or "Individual", - "territory": args.territory or "_Test Territory", + "customer_type": "Individual", + "territory": "_Test Territory", "is_internal_customer": 1, - "represents_company": args.represents_company or "_Test Company with perpetual inventory" + "represents_company": represents_company }) customer.append("companies", { - "company": args.allowed_company or "Wind Power LLC" + "company": allowed_to_interact_with }) - customer.insert() - return customer + customer.insert() + customer_name = customer.name else: - return frappe.get_cached_doc("Customer", customer_name) \ No newline at end of file + customer_name = frappe.db.get_value("Customer", customer_name) + + return customer_name \ No newline at end of file diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index dffc73020d..e6736b2bab 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -435,7 +435,8 @@ class TestDeliveryNote(unittest.TestCase): company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') customer = create_internal_customer( customer_name="_Test Internal Customer 2", - allowed_company="_Test Company with perpetual inventory" + represents_company="_Test Company with perpetual inventory", + allowed_to_interact_with="_Test Company with perpetual inventory" ) set_valuation_method("_Test Item", "FIFO") From 501b91a608a5da4f03c43751d5af3d05aa9f1352 Mon Sep 17 00:00:00 2001 From: marination Date: Thu, 26 Aug 2021 16:18:23 +0530 Subject: [PATCH 38/54] fix: internal customer util returns str not doc object --- erpnext/stock/doctype/delivery_note/test_delivery_note.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index e6736b2bab..b333a6b57e 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -433,7 +433,7 @@ class TestDeliveryNote(unittest.TestCase): from erpnext.selling.doctype.customer.test_customer import create_internal_customer company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') - customer = create_internal_customer( + customer_name = create_internal_customer( customer_name="_Test Internal Customer 2", represents_company="_Test Company with perpetual inventory", allowed_to_interact_with="_Test Company with perpetual inventory" @@ -454,7 +454,7 @@ class TestDeliveryNote(unittest.TestCase): dn = create_delivery_note( item_code="_Test Product Bundle Item", company="_Test Company with perpetual inventory", - customer=customer.name, + customer=customer_name, cost_center = 'Main - TCP1', expense_account = "Cost of Goods Sold - TCP1", do_not_submit=True, From e7109c18db6df4ffce80c936911b6c98327cdd0f Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Thu, 26 Aug 2021 16:40:45 +0530 Subject: [PATCH 39/54] fix: negative qty validation on stock reco cancellation (#27170) * test: negative stock validation on SR cancel * fix: negative stock setting ignored in stock reco In stock reconcilation cancellation negative stock setting is ignored as `db.get_value` is returning string `'0'` which is not casted to int/bool for further logic. This causes negative qty, which evantually gets caught by reposting but by design this should stop cancellation. * test: typo and minor refactor --- .../stock_reconciliation.py | 2 +- .../test_stock_reconciliation.py | 45 +++++++++++++++++-- erpnext/stock/stock_ledger.py | 6 +-- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index cda7c1d31a..24b7b9aeb6 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -390,7 +390,7 @@ class StockReconciliation(StockController): sl_entries = self.merge_similar_item_serial_nos(sl_entries) sl_entries.reverse() - allow_negative_stock = frappe.db.get_value("Stock Settings", None, "allow_negative_stock") + allow_negative_stock = cint(frappe.db.get_single_value("Stock Settings", "allow_negative_stock")) self.make_sl_entries(sl_entries, allow_negative_stock=allow_negative_stock) diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py index 94b006c894..e4381271ed 100644 --- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py @@ -15,6 +15,7 @@ from erpnext.stock.doctype.item.test_item import create_item from erpnext.stock.utils import get_incoming_rate, get_stock_value_on, get_valuation_method from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt +from erpnext.tests.utils import change_settings class TestStockReconciliation(unittest.TestCase): @@ -310,6 +311,7 @@ class TestStockReconciliation(unittest.TestCase): pr2.cancel() pr1.cancel() + @change_settings("Stock Settings", {"allow_negative_stock": 0}) def test_backdated_stock_reco_future_negative_stock(self): """ Test if a backdated stock reco causes future negative stock and is blocked. @@ -327,8 +329,6 @@ class TestStockReconciliation(unittest.TestCase): warehouse = "_Test Warehouse - _TC" create_item(item_code) - negative_stock_setting = frappe.db.get_single_value("Stock Settings", "allow_negative_stock") - frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 0) pr1 = make_purchase_receipt(item_code=item_code, warehouse=warehouse, qty=10, rate=100, posting_date=add_days(nowdate(), -2)) @@ -348,11 +348,50 @@ class TestStockReconciliation(unittest.TestCase): self.assertRaises(NegativeStockError, sr3.submit) # teardown - frappe.db.set_value("Stock Settings", None, "allow_negative_stock", negative_stock_setting) sr3.cancel() dn2.cancel() pr1.cancel() + + @change_settings("Stock Settings", {"allow_negative_stock": 0}) + def test_backdated_stock_reco_cancellation_future_negative_stock(self): + """ + Test if a backdated stock reco cancellation that causes future negative stock is blocked. + ------------------------------------------- + Var | Doc | Qty | Balance + ------------------------------------------- + SR | Reco | 100 | 100 (posting date: today-1) (shouldn't be cancelled after DN) + DN | DN | 100 | 0 (posting date: today) + """ + from erpnext.stock.stock_ledger import NegativeStockError + from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note + frappe.db.commit() + + item_code = "Backdated-Reco-Cancellation-Item" + warehouse = "_Test Warehouse - _TC" + create_item(item_code) + + + sr = create_stock_reconciliation(item_code=item_code, warehouse=warehouse, qty=100, rate=100, + posting_date=add_days(nowdate(), -1)) + + dn = create_delivery_note(item_code=item_code, warehouse=warehouse, qty=100, rate=120, + posting_date=nowdate()) + + dn_balance = frappe.db.get_value("Stock Ledger Entry", {"voucher_no": dn.name, "is_cancelled": 0}, + "qty_after_transaction") + self.assertEqual(dn_balance, 0) + + # check if cancellation of stock reco is blocked + self.assertRaises(NegativeStockError, sr.cancel) + + repost_exists = bool(frappe.db.exists("Repost Item Valuation", {"voucher_no": sr.name})) + self.assertFalse(repost_exists, msg="Negative stock validation not working on reco cancellation") + + # teardown + frappe.db.rollback() + + def test_valid_batch(self): create_batch_item_with_batch("Testing Batch Item 1", "001") create_batch_item_with_batch("Testing Batch Item 2", "002") diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index 27feec1d15..48fd7d3d26 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -955,7 +955,7 @@ def get_valuation_rate(item_code, warehouse, voucher_type, voucher_no, return valuation_rate -def update_qty_in_future_sle(args, allow_negative_stock=None): +def update_qty_in_future_sle(args, allow_negative_stock=False): """Recalculate Qty after Transaction in future SLEs based on current SLE.""" datetime_limit_condition = "" qty_shift = args.actual_qty @@ -1044,8 +1044,8 @@ def get_datetime_limit_condition(detail): ) )""" -def validate_negative_qty_in_future_sle(args, allow_negative_stock=None): - allow_negative_stock = allow_negative_stock \ +def validate_negative_qty_in_future_sle(args, allow_negative_stock=False): + allow_negative_stock = cint(allow_negative_stock) \ or cint(frappe.db.get_single_value("Stock Settings", "allow_negative_stock")) if (args.actual_qty < 0 or args.voucher_type == "Stock Reconciliation") and not allow_negative_stock: From c07dce940e31f84fb38ea6fd8d2d41bef619f904 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Thu, 26 Aug 2021 18:33:42 +0530 Subject: [PATCH 40/54] fix: don't allow BOM's item code at any level of child items (#27157) * refactor: bom recursion checking * fix: dont allow bom recursion if same item_code is added in child items at any level, it shouldn't be allowed. * test: add test for bom recursion * test: fix broken prodplan test using recursive bom * test: fix recursive bom in tests --- erpnext/manufacturing/doctype/bom/bom.py | 30 ++++++++------ erpnext/manufacturing/doctype/bom/test_bom.py | 40 +++++++++++++++++++ .../production_plan/test_production_plan.py | 9 +++-- .../doctype/work_order/test_work_order.py | 7 +++- 4 files changed, 68 insertions(+), 18 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 24f84e63b3..1d7d451cc8 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -447,25 +447,29 @@ class BOM(WebsiteGenerator): frappe.throw(_("Quantity required for Item {0} in row {1}").format(m.item_code, m.idx)) check_list.append(m) - def check_recursion(self, bom_list=[]): + def check_recursion(self, bom_list=None): """ Check whether recursion occurs in any bom""" + def _throw_error(bom_name): + frappe.throw(_("BOM recursion: {0} cannot be parent or child of {0}").format(bom_name)) + bom_list = self.traverse_tree() - bom_nos = frappe.get_all('BOM Item', fields=["bom_no"], - filters={'parent': ('in', bom_list), 'parenttype': 'BOM'}) + child_items = frappe.get_all('BOM Item', fields=["bom_no", "item_code"], + filters={'parent': ('in', bom_list), 'parenttype': 'BOM'}) or [] - raise_exception = False - if bom_nos and self.name in [d.bom_no for d in bom_nos]: - raise_exception = True + child_bom = {d.bom_no for d in child_items} + child_items_codes = {d.item_code for d in child_items} - if not raise_exception: - bom_nos = frappe.get_all('BOM Item', fields=["parent"], - filters={'bom_no': self.name, 'parenttype': 'BOM'}) + if self.name in child_bom: + _throw_error(self.name) - if self.name in [d.parent for d in bom_nos]: - raise_exception = True + if self.item in child_items_codes: + _throw_error(self.item) - if raise_exception: - frappe.throw(_("BOM recursion: {0} cannot be parent or child of {1}").format(self.name, self.name)) + bom_nos = frappe.get_all('BOM Item', fields=["parent"], + filters={'bom_no': self.name, 'parenttype': 'BOM'}) or [] + + if self.name in {d.parent for d in bom_nos}: + _throw_error(self.name) def traverse_tree(self, bom_list=None): def _get_children(bom_no): diff --git a/erpnext/manufacturing/doctype/bom/test_bom.py b/erpnext/manufacturing/doctype/bom/test_bom.py index b8f0db0de2..8408f10b18 100644 --- a/erpnext/manufacturing/doctype/bom/test_bom.py +++ b/erpnext/manufacturing/doctype/bom/test_bom.py @@ -280,6 +280,46 @@ class TestBOM(unittest.TestCase): self.assertEqual(reqd_item.qty, created_item.qty) self.assertEqual(reqd_item.exploded_qty, created_item.exploded_qty) + def test_bom_recursion_1st_level(self): + """BOM should not allow BOM item again in child""" + item_code = "_Test BOM Recursion" + make_item(item_code, {'is_stock_item': 1}) + + bom = frappe.new_doc("BOM") + bom.item = item_code + bom.append("items", frappe._dict(item_code=item_code)) + with self.assertRaises(frappe.ValidationError) as err: + bom.save() + + self.assertTrue("recursion" in str(err.exception).lower()) + frappe.delete_doc("BOM", bom.name, ignore_missing=True) + + def test_bom_recursion_transitive(self): + item1 = "_Test BOM Recursion" + item2 = "_Test BOM Recursion 2" + make_item(item1, {'is_stock_item': 1}) + make_item(item2, {'is_stock_item': 1}) + + bom1 = frappe.new_doc("BOM") + bom1.item = item1 + bom1.append("items", frappe._dict(item_code=item2)) + bom1.save() + bom1.submit() + + bom2 = frappe.new_doc("BOM") + bom2.item = item2 + bom2.append("items", frappe._dict(item_code=item1)) + + with self.assertRaises(frappe.ValidationError) as err: + bom2.save() + bom2.submit() + + self.assertTrue("recursion" in str(err.exception).lower()) + + bom1.cancel() + frappe.delete_doc("BOM", bom1.name, ignore_missing=True, force=True) + frappe.delete_doc("BOM", bom2.name, ignore_missing=True, force=True) + def test_bom_with_process_loss_item(self): fg_item_non_whole, fg_item_whole, bom_item = create_process_loss_bom_items() diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py index a5b9ff845f..78028039c4 100644 --- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py @@ -288,6 +288,7 @@ class TestProductionPlan(unittest.TestCase): self.assertEqual(warehouses, expected_warehouses) def test_get_sales_order_with_variant(self): + rm_item = create_item('PIV_RM', valuation_rate = 100) if not frappe.db.exists('Item', {"item_code": 'PIV'}): item = create_item('PIV', valuation_rate = 100) variant_settings = { @@ -300,20 +301,20 @@ class TestProductionPlan(unittest.TestCase): } item.update(variant_settings) item.save() - parent_bom = make_bom(item = 'PIV', raw_materials = ['PIV']) + parent_bom = make_bom(item = 'PIV', raw_materials = [rm_item.item_code]) if not frappe.db.exists('BOM', {"item": 'PIV'}): - parent_bom = make_bom(item = 'PIV', raw_materials = ['PIV']) + parent_bom = make_bom(item = 'PIV', raw_materials = [rm_item.item_code]) else: parent_bom = frappe.get_doc('BOM', {"item": 'PIV'}) if not frappe.db.exists('Item', {"item_code": 'PIV-RED'}): variant = create_variant("PIV", {"Colour": "Red"}) variant.save() - variant_bom = make_bom(item = variant.item_code, raw_materials = [variant.item_code]) + variant_bom = make_bom(item = variant.item_code, raw_materials = [rm_item.item_code]) else: variant = frappe.get_doc('Item', 'PIV-RED') if not frappe.db.exists('BOM', {"item": 'PIV-RED'}): - variant_bom = make_bom(item = variant.item_code, raw_materials = [variant.item_code]) + variant_bom = make_bom(item = variant.item_code, raw_materials = [rm_item.item_code]) """Testing when item variant has a BOM""" so = make_sales_order(item_code="PIV-RED", qty=5) diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index 3a334a530c..c0ed611534 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -675,13 +675,18 @@ class TestWorkOrder(unittest.TestCase): def test_valuation_rate_missing_on_make_stock_entry(self): item_name = 'Test Valuation Rate Missing' + rm_item = '_Test raw material item' make_item(item_name, { "is_stock_item": 1, "include_item_in_manufacturing": 1, }) + make_item('_Test raw material item', { + "is_stock_item": 1, + "include_item_in_manufacturing": 1, + }) if not frappe.db.get_value('BOM', {'item': item_name}): - make_bom(item=item_name, raw_materials=[item_name], rm_qty=1) + make_bom(item=item_name, raw_materials=[rm_item], rm_qty=1) company = "_Test Company with perpetual inventory" source_warehouse = create_warehouse("Test Valuation Rate Missing Warehouse", company=company) From 4b1f16542952563f13f9eb716604d763a35bf54c Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Thu, 26 Aug 2021 18:34:15 +0530 Subject: [PATCH 41/54] fix: Use reverse debit and credit to get net amount in GL Entries (#27174) * fix: Use reverse debit and credit to get net amount in GL Entries * fix: Remove unused import --- erpnext/accounts/doctype/payment_entry/payment_entry.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index abacee985c..5a183e2e51 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -755,9 +755,11 @@ class PaymentEntry(AccountsController): if self.payment_type in ('Pay', 'Internal Transfer'): dr_or_cr = "debit" if d.add_deduct_tax == "Add" else "credit" + rev_dr_or_cr = "credit" if dr_or_cr == "debit" else "debit" against = self.party or self.paid_from elif self.payment_type == 'Receive': dr_or_cr = "credit" if d.add_deduct_tax == "Add" else "debit" + rev_dr_or_cr = "credit" if dr_or_cr == "debit" else "debit" against = self.party or self.paid_to payment_or_advance_account = self.get_party_account_for_taxes() @@ -779,14 +781,13 @@ class PaymentEntry(AccountsController): "cost_center": d.cost_center }, account_currency, item=d)) - #Intentionally use -1 to get net values in party account if not d.included_in_paid_amount or self.advance_tax_account: gl_entries.append( self.get_gl_dict({ "account": payment_or_advance_account, "against": against, - dr_or_cr: -1 * tax_amount, - dr_or_cr + "_in_account_currency": -1 * base_tax_amount + rev_dr_or_cr: tax_amount, + rev_dr_or_cr + "_in_account_currency": -1 * base_tax_amount if account_currency==self.company_currency else d.tax_amount, "cost_center": self.cost_center, From a9852a54830a68f388956b972933dfac8aec78f9 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Thu, 26 Aug 2021 20:02:51 +0530 Subject: [PATCH 42/54] fix(ux): hide irrelevant fields for asset items (#26274) --- erpnext/stock/doctype/item/item.js | 3 +-- erpnext/stock/doctype/item/item.json | 25 ++++++++++++++++++------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js index c587dd5c7e..3de35e6062 100644 --- a/erpnext/stock/doctype/item/item.js +++ b/erpnext/stock/doctype/item/item.js @@ -141,9 +141,8 @@ frappe.ui.form.on("Item", { is_fixed_asset: function(frm) { // set serial no to false & toggles its visibility frm.set_value('has_serial_no', 0); + frm.set_value('has_batch_no', 0); frm.toggle_enable(['has_serial_no', 'serial_no_series'], !frm.doc.is_fixed_asset); - frm.toggle_reqd(['asset_category'], frm.doc.is_fixed_asset); - frm.toggle_display(['has_serial_no', 'serial_no_series'], !frm.doc.is_fixed_asset); frm.call({ method: "set_asset_naming_series", diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json index f662bbd1c7..db5caf9164 100644 --- a/erpnext/stock/doctype/item/item.json +++ b/erpnext/stock/doctype/item/item.json @@ -204,6 +204,7 @@ }, { "default": "0", + "depends_on": "eval:!doc.is_fixed_asset", "fieldname": "is_item_from_hub", "fieldtype": "Check", "label": "Is Item from Hub", @@ -238,6 +239,7 @@ { "bold": 1, "default": "1", + "depends_on": "eval:!doc.is_fixed_asset", "fieldname": "is_stock_item", "fieldtype": "Check", "label": "Maintain Stock", @@ -246,6 +248,7 @@ }, { "default": "1", + "depends_on": "eval:!doc.is_fixed_asset", "fieldname": "include_item_in_manufacturing", "fieldtype": "Check", "label": "Include Item In Manufacturing" @@ -282,6 +285,7 @@ "fieldname": "asset_category", "fieldtype": "Link", "label": "Asset Category", + "mandatory_depends_on": "is_fixed_asset", "options": "Asset Category" }, { @@ -434,8 +438,8 @@ }, { "collapsible": 1, - "collapsible_depends_on": "eval:doc.has_batch_no || doc.has_serial_no || doc.is_fixed_asset", - "depends_on": "eval:doc.is_stock_item || doc.is_fixed_asset", + "collapsible_depends_on": "eval:doc.has_batch_no || doc.has_serial_no", + "depends_on": "eval:doc.is_stock_item", "fieldname": "serial_nos_and_batches", "fieldtype": "Section Break", "label": "Serial Nos and Batches" @@ -492,7 +496,7 @@ }, { "default": "0", - "depends_on": "eval:doc.is_stock_item || doc.is_fixed_asset", + "depends_on": "eval:doc.is_stock_item", "fieldname": "has_serial_no", "fieldtype": "Check", "label": "Has Serial No", @@ -510,6 +514,7 @@ { "collapsible": 1, "collapsible_depends_on": "attributes", + "depends_on": "eval:!doc.is_fixed_asset", "fieldname": "variants_section", "fieldtype": "Section Break", "label": "Variants" @@ -540,6 +545,7 @@ "options": "Item Variant Attribute" }, { + "depends_on": "eval:!doc.is_fixed_asset", "fieldname": "defaults", "fieldtype": "Section Break", "label": "Sales, Purchase, Accounting Defaults" @@ -621,6 +627,7 @@ }, { "collapsible": 1, + "depends_on": "eval:!doc.is_fixed_asset", "fieldname": "supplier_details", "fieldtype": "Section Break", "label": "Supplier Details" @@ -668,6 +675,7 @@ }, { "collapsible": 1, + "default": "eval:!doc.is_fixed_asset", "fieldname": "sales_details", "fieldtype": "Section Break", "label": "Sales Details", @@ -761,6 +769,7 @@ }, { "collapsible": 1, + "depends_on": "eval:!doc.is_fixed_asset", "fieldname": "customer_details", "fieldtype": "Section Break", "label": "Customer Details" @@ -791,6 +800,7 @@ }, { "collapsible": 1, + "depends_on": "eval:!doc.is_fixed_asset", "fieldname": "inspection_criteria", "fieldtype": "Section Break", "label": "Inspection Criteria", @@ -861,6 +871,7 @@ }, { "collapsible": 1, + "depends_on": "eval:!doc.is_fixed_asset", "fieldname": "website_section", "fieldtype": "Section Break", "label": "Website", @@ -987,7 +998,7 @@ }, { "collapsible": 1, - "depends_on": "eval:(!doc.is_item_from_hub)", + "depends_on": "eval:(!doc.is_item_from_hub && !doc.is_fixed_asset)", "fieldname": "hub_publishing_sb", "fieldtype": "Section Break", "label": "Hub Publishing Details" @@ -1021,7 +1032,7 @@ "read_only": 1 }, { - "depends_on": "eval:!doc.__islocal", + "depends_on": "eval:!doc.__islocal && !doc.is_fixed_asset", "fieldname": "over_delivery_receipt_allowance", "fieldtype": "Float", "label": "Over Delivery/Receipt Allowance (%)", @@ -1029,7 +1040,7 @@ "oldfieldtype": "Currency" }, { - "depends_on": "eval:!doc.__islocal", + "depends_on": "eval:!doc.__islocal && !doc.is_fixed_asset", "fieldname": "over_billing_allowance", "fieldtype": "Float", "label": "Over Billing Allowance (%)" @@ -1067,7 +1078,7 @@ "index_web_pages_for_search": 1, "links": [], "max_attachments": 1, - "modified": "2021-07-13 01:29:06.071827", + "modified": "2021-08-26 12:23:07.277077", "modified_by": "Administrator", "module": "Stock", "name": "Item", From ae55eab599094ff45f7d495f4a3ef3f00bd9e00e Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Thu, 26 Aug 2021 20:43:06 +0530 Subject: [PATCH 43/54] chore: remove deprecated and empty QUnit tests (#27179) * chore: remove deprecated and empty QUnit tests * ci: fix UI test config Testing library was added on Frappe, in order to reuse command testing library has to be installed during setup process. --- .github/workflows/ui-tests.yml | 2 +- .../test_accounting_period.js | 23 ------------------- erpnext/accounts/doctype/bank/test_bank.js | 23 ------------------- .../doctype/bank_account/test_bank_account.js | 23 ------------------- .../test_bank_account_subtype.js | 23 ------------------- .../bank_guarantee/test_bank_guarantee.js | 23 ------------------- .../bank_transaction/test_bank_transaction.js | 23 ------------------- .../cash_flow_mapper/test_cash_flow_mapper.js | 23 ------------------- .../test_cash_flow_mapping.js | 23 ------------------- .../test_cash_flow_mapping_template.js | 23 ------------------- ...test_cash_flow_mapping_template_details.js | 23 ------------------- .../cashier_closing/test_cashier_closing.js | 23 ------------------- .../test_chart_of_accounts_importer.js | 23 ------------------- .../doctype/coupon_code/test_coupon_code.js | 23 ------------------- .../test_exchange_rate_revaluation.js | 23 ------------------- .../doctype/finance_book/test_finance_book.js | 23 ------------------- .../doctype/gl_entry/test_gl_entry.js | 23 ------------------- .../test_item_tax_template.js | 23 ------------------- .../test_loyalty_point_entry.js | 23 ------------------- .../loyalty_program/test_loyalty_program.js | 23 ------------------- .../test_opening_invoice_creation_tool.js | 23 ------------------- .../payment_order/test_payment_order.js | 23 ------------------- .../payment_request/test_payment_request.js | 23 ------------------- .../doctype/payment_term/test_payment_term.js | 23 ------------------- .../test_payment_terms_template.js | 23 ------------------- .../test_pos_closing_entry.js | 23 ------------------- .../doctype/pos_profile/test_pos_profile.js | 23 ------------------- .../pos_profile_user/test_pos_profile_user.js | 23 ------------------- .../doctype/pos_settings/test_pos_settings.js | 23 ------------------- .../share_transfer/test_share_transfer.js | 23 ------------------- .../doctype/share_type/test_share_type.js | 23 ------------------- .../doctype/shareholder/test_shareholder.js | 23 ------------------- .../test_subscription_invoice.js | 23 ------------------- .../test_subscription_plan.js | 23 ------------------- .../test_subscription_settings.js | 23 ------------------- .../doctype/tax_category/test_tax_category.js | 23 ------------------- .../doctype/tax_rule/test_tax_rule.js | 23 ------------------- .../test_tax_withholding_category.js | 23 ------------------- .../test_agriculture_analysis_criteria.js | 23 ------------------- .../agriculture_task/test_agriculture_task.js | 23 ------------------- .../plant_analysis/test_plant_analysis.js | 23 ------------------- .../soil_analysis/test_soil_analysis.js | 23 ------------------- .../doctype/weather/test_weather.js | 23 ------------------- erpnext/assets/doctype/asset/test_asset.js | 23 ------------------- .../asset_category/test_asset_category.js | 23 ------------------- .../test_asset_maintenance.js | 23 ------------------- .../test_asset_maintenance_log.js | 23 ------------------- .../test_asset_maintenance_team.js | 23 ------------------- .../asset_movement/test_asset_movement.js | 23 ------------------- .../doctype/asset_repair/test_asset_repair.js | 23 ------------------- .../test_asset_value_adjustment.js | 23 ------------------- .../assets/doctype/location/test_location.js | 23 ------------------- .../test_maintenance_team_member.js | 23 ------------------- erpnext/crm/doctype/contract/test_contract.js | 23 ------------------- .../test_contract_fulfilment_checklist.js | 23 ------------------- .../test_contract_template.js | 23 ------------------- .../market_segment/test_market_segment.js | 23 ------------------- .../opportunity_type/test_opportunity_type.js | 23 ------------------- .../doctype/sales_stage/test_sales_stage.js | 23 ------------------- .../academic_year/test_academic_year.js | 23 ------------------- .../education/doctype/article/test_article.js | 23 ------------------- .../content_question/test_content_question.js | 23 ------------------- .../course_activity/test_course_activity.js | 23 ------------------- .../course_content/test_course_content.js | 23 ------------------- .../test_course_enrollment.js | 23 ------------------- .../course_schedule/test_course_schedule.js | 23 ------------------- .../test_course_scheduling_tool.js | 23 ------------------- .../doctype/course_topic/test_course_topic.js | 23 ------------------- .../doctype/fee_category/test_fee_category.js | 23 ------------------- .../doctype/fee_schedule/test_fee_schedule.js | 23 ------------------- .../fee_structure/test_fee_structure.js | 23 ------------------- .../test_program_enrollment.js | 23 ------------------- .../test_program_enrollment_tool.js | 23 ------------------- .../doctype/question/test_question.js | 23 ------------------- erpnext/education/doctype/quiz/test_quiz.js | 23 ------------------- .../quiz_activity/test_quiz_activity.js | 23 ------------------- .../doctype/quiz_result/test_quiz_result.js | 23 ------------------- .../doctype/school_house/test_school_house.js | 23 ------------------- .../education/doctype/student/test_student.js | 23 ------------------- .../student_language/test_student_language.js | 23 ------------------- .../test_student_report_generation_tool.js | 23 ------------------- erpnext/education/doctype/topic/test_topic.js | 23 ------------------- .../topic_content/test_topic_content.js | 23 ------------------- .../test_amazon_mws_settings.js | 23 ------------------- .../test_gocardless_mandate.js | 23 ------------------- .../test_gocardless_settings.js | 23 ------------------- .../plaid_settings/test_plaid_settings.js | 23 ------------------- .../test_quickbooks_migrator.js | 23 ------------------- .../tally_migration/test_tally_migration.js | 23 ------------------- .../test_woocommerce_settings.js | 23 ------------------- .../doctype/antibiotic/test_antibiotic.js | 23 ------------------- .../appointment_type/test_appointment_type.js | 23 ------------------- .../test_clinical_procedure.js | 23 ------------------- .../test_clinical_procedure_template.js | 23 ------------------- .../doctype/complaint/test_complaint.js | 23 ------------------- .../doctype/diagnosis/test_diagnosis.js | 23 ------------------- .../doctype/dosage_form/test_dosage_form.js | 23 ------------------- .../doctype/fee_validity/test_fee_validity.js | 23 ------------------- .../test_healthcare_practitioner.js | 23 ------------------- .../test_healthcare_service_unit.js | 23 ------------------- .../test_healthcare_service_unit_type.js | 23 ------------------- .../test_healthcare_settings.js | 23 ------------------- .../inpatient_record/test_inpatient_record.js | 23 ------------------- .../doctype/lab_test/test_lab_test.js | 23 ------------------- .../lab_test_sample/test_lab_test_sample.js | 23 ------------------- .../test_lab_test_template.js | 23 ------------------- .../doctype/lab_test_uom/test_lab_test_uom.js | 23 ------------------- .../doctype/medical_code/test_medical_code.js | 23 ------------------- .../test_medical_code_standard.js | 23 ------------------- .../test_medical_department.js | 23 ------------------- .../doctype/organism/test_organism.js | 23 ------------------- .../doctype/patient/test_patient.js | 23 ------------------- .../test_patient_appointment.js | 23 ------------------- .../test_patient_encounter.js | 23 ------------------- .../test_patient_medical_record.js | 23 ------------------- .../test_practitioner_schedule.js | 23 ------------------- .../test_prescription_dosage.js | 23 ------------------- .../test_prescription_duration.js | 23 ------------------- .../test_sample_collection.js | 23 ------------------- .../doctype/sensitivity/test_sensitivity.js | 23 ------------------- .../doctype/vital_signs/test_vital_signs.js | 23 ------------------- .../doctype/hotel_room/test_hotel_room.js | 23 ------------------- .../test_hotel_room_package.js | 23 ------------------- .../test_hotel_room_pricing.js | 23 ------------------- .../test_hotel_room_pricing_package.js | 23 ------------------- .../test_hotel_room_reservation.js | 23 ------------------- .../hotel_room_type/test_hotel_room_type.js | 23 ------------------- .../hotel_settings/test_hotel_settings.js | 23 ------------------- .../test_attendance_request.js | 23 ------------------- erpnext/hr/doctype/branch/test_branch.js | 23 ------------------- .../test_compensatory_leave_request.js | 23 ------------------- .../test_daily_work_summary.js | 23 ------------------- .../hr/doctype/department/test_department.js | 23 ------------------- .../doctype/designation/test_designation.js | 23 ------------------- erpnext/hr/doctype/driver/test_driver.js | 23 ------------------- .../employee_advance/test_employee_advance.js | 23 ------------------- .../employee_grade/test_employee_grade.js | 23 ------------------- .../test_employee_health_insurance.js | 23 ------------------- .../test_employee_onboarding.js | 23 ------------------- .../test_employee_onboarding_template.js | 23 ------------------- .../test_employee_promotion.js | 23 ------------------- .../test_employee_separation.js | 23 ------------------- .../test_employee_separation_template.js | 23 ------------------- .../test_employee_transfer.js | 23 ------------------- .../test_employee_transfer_property.js | 23 ------------------- .../doctype/hr_settings/test_hr_settings.js | 23 ------------------- .../test_identification_document_type.js | 23 ------------------- .../test_job_applicant_source.js | 23 ------------------- .../leave_encashment/test_leave_encashment.js | 23 ------------------- .../doctype/leave_period/test_leave_period.js | 23 ------------------- .../doctype/leave_policy/test_leave_policy.js | 23 ------------------- .../test_leave_policy_detail.js | 23 ------------------- .../test_purpose_of_travel.js | 23 ------------------- .../shift_assignment/test_shift_assignment.js | 23 ------------------- .../shift_request/test_shift_request.js | 23 ------------------- .../hr/doctype/shift_type/test_shift_type.js | 23 ------------------- .../staffing_plan/test_staffing_plan.js | 23 ------------------- .../training_program/test_training_program.js | 23 ------------------- .../training_result/test_training_result.js | 23 ------------------- .../travel_request/test_travel_request.js | 23 ------------------- erpnext/hr/doctype/vehicle/test_vehicle.js | 23 ------------------- .../test_marketplace_settings.js | 23 ------------------- .../test_maintenance_schedule.js | 23 ------------------- .../blanket_order/test_blanket_order.js | 23 ------------------- .../bom_update_tool/test_bom_update_tool.js | 23 ------------------- .../doctype/job_card/test_job_card.js | 23 ------------------- .../test_manufacturing_settings.js | 23 ------------------- .../test_material_request_plan_item.js | 23 ------------------- .../production_plan/test_production_plan.js | 23 ------------------- .../doctype/routing/test_routing.js | 23 ------------------- .../test_certification_application.js | 23 ------------------- .../test_certified_consultant.js | 23 ------------------- .../doctype/chapter/test_chapter.js | 23 ------------------- .../doctype/donor_type/test_donor_type.js | 23 ------------------- .../doctype/membership/test_membership.js | 23 ------------------- .../test_additional_salary.js | 23 ------------------- .../test_employee_benefit_application.js | 23 ------------------- .../test_employee_benefit_claim.js | 23 ------------------- .../test_employee_incentive.js | 23 ------------------- .../test_employee_tax_exemption_category.js | 23 ------------------- ...test_employee_tax_exemption_declaration.js | 23 ------------------- ...employee_tax_exemption_proof_submission.js | 23 ------------------- ...est_employee_tax_exemption_sub_category.js | 23 ------------------- .../payroll_period/test_payroll_period.js | 23 ------------------- .../retention_bonus/test_retention_bonus.js | 23 ------------------- .../salary_component/test_salary_component.js | 23 ------------------- .../test_salary_structure_assignment.js | 23 ------------------- .../test_products_settings.js | 23 ------------------- .../projects/doctype/project/test_project.js | 23 ------------------- .../doctype/project_type/test_project_type.js | 23 ------------------- .../project_update/test_project_update.js | 23 ------------------- .../test_projects_settings.js | 23 ------------------- .../doctype/timesheet/test_timesheet.js | 23 ------------------- .../doctype/gst_hsn_code/test_gst_hsn_code.js | 23 ------------------- .../doctype/gst_settings/test_gst_settings.js | 23 ------------------- .../selling/doctype/customer/test_customer.js | 23 ------------------- .../doctype/sales_order/test_sales_order.js | 23 ------------------- .../test_sales_partner_type.js | 23 ------------------- .../test_currency_exchange.js | 23 ------------------- .../global_defaults/test_global_defaults.js | 23 ------------------- .../doctype/item_group/test_item_group.js | 23 ------------------- .../naming_series/test_naming_series.js | 23 ------------------- .../doctype/party_type/test_party_type.js | 23 ------------------- .../supplier_group/test_supplier_group.js | 23 ------------------- .../test_uom_conversion_factor.js | 23 ------------------- .../test_shopping_cart_settings.js | 23 ------------------- .../test_customs_tariff_number.js | 23 ------------------- .../test_delivery_settings.js | 23 ------------------- .../delivery_trip/test_delivery_trip.js | 23 ------------------- erpnext/stock/doctype/item/test_item.js | 23 ------------------- .../item_alternative/test_item_alternative.js | 23 ------------------- .../test_item_variant_settings.js | 23 ------------------- .../doctype/manufacturer/test_manufacturer.js | 23 ------------------- .../material_request/test_material_request.js | 23 ------------------- .../doctype/price_list/test_price_list.js | 23 ------------------- .../test_quality_inspection.js | 23 ------------------- .../test_quality_inspection_template.js | 23 ------------------- .../stock/doctype/serial_no/test_serial_no.js | 23 ------------------- .../stock_settings/test_stock_settings.js | 23 ------------------- .../doctype/uom_category/test_uom_category.js | 23 ------------------- .../variant_field/test_variant_field.js | 23 ------------------- .../support_settings/test_support_settings.js | 23 ------------------- 222 files changed, 1 insertion(+), 5084 deletions(-) delete mode 100644 erpnext/accounts/doctype/accounting_period/test_accounting_period.js delete mode 100644 erpnext/accounts/doctype/bank/test_bank.js delete mode 100644 erpnext/accounts/doctype/bank_account/test_bank_account.js delete mode 100644 erpnext/accounts/doctype/bank_account_subtype/test_bank_account_subtype.js delete mode 100644 erpnext/accounts/doctype/bank_guarantee/test_bank_guarantee.js delete mode 100644 erpnext/accounts/doctype/bank_transaction/test_bank_transaction.js delete mode 100644 erpnext/accounts/doctype/cash_flow_mapper/test_cash_flow_mapper.js delete mode 100644 erpnext/accounts/doctype/cash_flow_mapping/test_cash_flow_mapping.js delete mode 100644 erpnext/accounts/doctype/cash_flow_mapping_template/test_cash_flow_mapping_template.js delete mode 100644 erpnext/accounts/doctype/cash_flow_mapping_template_details/test_cash_flow_mapping_template_details.js delete mode 100644 erpnext/accounts/doctype/cashier_closing/test_cashier_closing.js delete mode 100644 erpnext/accounts/doctype/chart_of_accounts_importer/test_chart_of_accounts_importer.js delete mode 100644 erpnext/accounts/doctype/coupon_code/test_coupon_code.js delete mode 100644 erpnext/accounts/doctype/exchange_rate_revaluation/test_exchange_rate_revaluation.js delete mode 100644 erpnext/accounts/doctype/finance_book/test_finance_book.js delete mode 100644 erpnext/accounts/doctype/gl_entry/test_gl_entry.js delete mode 100644 erpnext/accounts/doctype/item_tax_template/test_item_tax_template.js delete mode 100644 erpnext/accounts/doctype/loyalty_point_entry/test_loyalty_point_entry.js delete mode 100644 erpnext/accounts/doctype/loyalty_program/test_loyalty_program.js delete mode 100644 erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.js delete mode 100644 erpnext/accounts/doctype/payment_order/test_payment_order.js delete mode 100644 erpnext/accounts/doctype/payment_request/test_payment_request.js delete mode 100644 erpnext/accounts/doctype/payment_term/test_payment_term.js delete mode 100644 erpnext/accounts/doctype/payment_terms_template/test_payment_terms_template.js delete mode 100644 erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.js delete mode 100644 erpnext/accounts/doctype/pos_profile/test_pos_profile.js delete mode 100644 erpnext/accounts/doctype/pos_profile_user/test_pos_profile_user.js delete mode 100644 erpnext/accounts/doctype/pos_settings/test_pos_settings.js delete mode 100644 erpnext/accounts/doctype/share_transfer/test_share_transfer.js delete mode 100644 erpnext/accounts/doctype/share_type/test_share_type.js delete mode 100644 erpnext/accounts/doctype/shareholder/test_shareholder.js delete mode 100644 erpnext/accounts/doctype/subscription_invoice/test_subscription_invoice.js delete mode 100644 erpnext/accounts/doctype/subscription_plan/test_subscription_plan.js delete mode 100644 erpnext/accounts/doctype/subscription_settings/test_subscription_settings.js delete mode 100644 erpnext/accounts/doctype/tax_category/test_tax_category.js delete mode 100644 erpnext/accounts/doctype/tax_rule/test_tax_rule.js delete mode 100644 erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.js delete mode 100644 erpnext/agriculture/doctype/agriculture_analysis_criteria/test_agriculture_analysis_criteria.js delete mode 100644 erpnext/agriculture/doctype/agriculture_task/test_agriculture_task.js delete mode 100644 erpnext/agriculture/doctype/plant_analysis/test_plant_analysis.js delete mode 100644 erpnext/agriculture/doctype/soil_analysis/test_soil_analysis.js delete mode 100644 erpnext/agriculture/doctype/weather/test_weather.js delete mode 100644 erpnext/assets/doctype/asset/test_asset.js delete mode 100644 erpnext/assets/doctype/asset_category/test_asset_category.js delete mode 100644 erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.js delete mode 100644 erpnext/assets/doctype/asset_maintenance_log/test_asset_maintenance_log.js delete mode 100644 erpnext/assets/doctype/asset_maintenance_team/test_asset_maintenance_team.js delete mode 100644 erpnext/assets/doctype/asset_movement/test_asset_movement.js delete mode 100644 erpnext/assets/doctype/asset_repair/test_asset_repair.js delete mode 100644 erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.js delete mode 100644 erpnext/assets/doctype/location/test_location.js delete mode 100644 erpnext/assets/doctype/maintenance_team_member/test_maintenance_team_member.js delete mode 100644 erpnext/crm/doctype/contract/test_contract.js delete mode 100644 erpnext/crm/doctype/contract_fulfilment_checklist/test_contract_fulfilment_checklist.js delete mode 100644 erpnext/crm/doctype/contract_template/test_contract_template.js delete mode 100644 erpnext/crm/doctype/market_segment/test_market_segment.js delete mode 100644 erpnext/crm/doctype/opportunity_type/test_opportunity_type.js delete mode 100644 erpnext/crm/doctype/sales_stage/test_sales_stage.js delete mode 100644 erpnext/education/doctype/academic_year/test_academic_year.js delete mode 100644 erpnext/education/doctype/article/test_article.js delete mode 100644 erpnext/education/doctype/content_question/test_content_question.js delete mode 100644 erpnext/education/doctype/course_activity/test_course_activity.js delete mode 100644 erpnext/education/doctype/course_content/test_course_content.js delete mode 100644 erpnext/education/doctype/course_enrollment/test_course_enrollment.js delete mode 100644 erpnext/education/doctype/course_schedule/test_course_schedule.js delete mode 100644 erpnext/education/doctype/course_scheduling_tool/test_course_scheduling_tool.js delete mode 100644 erpnext/education/doctype/course_topic/test_course_topic.js delete mode 100644 erpnext/education/doctype/fee_category/test_fee_category.js delete mode 100644 erpnext/education/doctype/fee_schedule/test_fee_schedule.js delete mode 100644 erpnext/education/doctype/fee_structure/test_fee_structure.js delete mode 100644 erpnext/education/doctype/program_enrollment/test_program_enrollment.js delete mode 100644 erpnext/education/doctype/program_enrollment_tool/test_program_enrollment_tool.js delete mode 100644 erpnext/education/doctype/question/test_question.js delete mode 100644 erpnext/education/doctype/quiz/test_quiz.js delete mode 100644 erpnext/education/doctype/quiz_activity/test_quiz_activity.js delete mode 100644 erpnext/education/doctype/quiz_result/test_quiz_result.js delete mode 100644 erpnext/education/doctype/school_house/test_school_house.js delete mode 100644 erpnext/education/doctype/student/test_student.js delete mode 100644 erpnext/education/doctype/student_language/test_student_language.js delete mode 100644 erpnext/education/doctype/student_report_generation_tool/test_student_report_generation_tool.js delete mode 100644 erpnext/education/doctype/topic/test_topic.js delete mode 100644 erpnext/education/doctype/topic_content/test_topic_content.js delete mode 100644 erpnext/erpnext_integrations/doctype/amazon_mws_settings/test_amazon_mws_settings.js delete mode 100644 erpnext/erpnext_integrations/doctype/gocardless_mandate/test_gocardless_mandate.js delete mode 100644 erpnext/erpnext_integrations/doctype/gocardless_settings/test_gocardless_settings.js delete mode 100644 erpnext/erpnext_integrations/doctype/plaid_settings/test_plaid_settings.js delete mode 100644 erpnext/erpnext_integrations/doctype/quickbooks_migrator/test_quickbooks_migrator.js delete mode 100644 erpnext/erpnext_integrations/doctype/tally_migration/test_tally_migration.js delete mode 100644 erpnext/erpnext_integrations/doctype/woocommerce_settings/test_woocommerce_settings.js delete mode 100644 erpnext/healthcare/doctype/antibiotic/test_antibiotic.js delete mode 100644 erpnext/healthcare/doctype/appointment_type/test_appointment_type.js delete mode 100644 erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.js delete mode 100644 erpnext/healthcare/doctype/clinical_procedure_template/test_clinical_procedure_template.js delete mode 100644 erpnext/healthcare/doctype/complaint/test_complaint.js delete mode 100644 erpnext/healthcare/doctype/diagnosis/test_diagnosis.js delete mode 100644 erpnext/healthcare/doctype/dosage_form/test_dosage_form.js delete mode 100644 erpnext/healthcare/doctype/fee_validity/test_fee_validity.js delete mode 100644 erpnext/healthcare/doctype/healthcare_practitioner/test_healthcare_practitioner.js delete mode 100644 erpnext/healthcare/doctype/healthcare_service_unit/test_healthcare_service_unit.js delete mode 100644 erpnext/healthcare/doctype/healthcare_service_unit_type/test_healthcare_service_unit_type.js delete mode 100644 erpnext/healthcare/doctype/healthcare_settings/test_healthcare_settings.js delete mode 100644 erpnext/healthcare/doctype/inpatient_record/test_inpatient_record.js delete mode 100644 erpnext/healthcare/doctype/lab_test/test_lab_test.js delete mode 100644 erpnext/healthcare/doctype/lab_test_sample/test_lab_test_sample.js delete mode 100644 erpnext/healthcare/doctype/lab_test_template/test_lab_test_template.js delete mode 100644 erpnext/healthcare/doctype/lab_test_uom/test_lab_test_uom.js delete mode 100644 erpnext/healthcare/doctype/medical_code/test_medical_code.js delete mode 100644 erpnext/healthcare/doctype/medical_code_standard/test_medical_code_standard.js delete mode 100644 erpnext/healthcare/doctype/medical_department/test_medical_department.js delete mode 100644 erpnext/healthcare/doctype/organism/test_organism.js delete mode 100644 erpnext/healthcare/doctype/patient/test_patient.js delete mode 100644 erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.js delete mode 100644 erpnext/healthcare/doctype/patient_encounter/test_patient_encounter.js delete mode 100644 erpnext/healthcare/doctype/patient_medical_record/test_patient_medical_record.js delete mode 100644 erpnext/healthcare/doctype/practitioner_schedule/test_practitioner_schedule.js delete mode 100644 erpnext/healthcare/doctype/prescription_dosage/test_prescription_dosage.js delete mode 100644 erpnext/healthcare/doctype/prescription_duration/test_prescription_duration.js delete mode 100644 erpnext/healthcare/doctype/sample_collection/test_sample_collection.js delete mode 100644 erpnext/healthcare/doctype/sensitivity/test_sensitivity.js delete mode 100644 erpnext/healthcare/doctype/vital_signs/test_vital_signs.js delete mode 100644 erpnext/hotels/doctype/hotel_room/test_hotel_room.js delete mode 100644 erpnext/hotels/doctype/hotel_room_package/test_hotel_room_package.js delete mode 100644 erpnext/hotels/doctype/hotel_room_pricing/test_hotel_room_pricing.js delete mode 100644 erpnext/hotels/doctype/hotel_room_pricing_package/test_hotel_room_pricing_package.js delete mode 100644 erpnext/hotels/doctype/hotel_room_reservation/test_hotel_room_reservation.js delete mode 100644 erpnext/hotels/doctype/hotel_room_type/test_hotel_room_type.js delete mode 100644 erpnext/hotels/doctype/hotel_settings/test_hotel_settings.js delete mode 100644 erpnext/hr/doctype/attendance_request/test_attendance_request.js delete mode 100644 erpnext/hr/doctype/branch/test_branch.js delete mode 100644 erpnext/hr/doctype/compensatory_leave_request/test_compensatory_leave_request.js delete mode 100644 erpnext/hr/doctype/daily_work_summary/test_daily_work_summary.js delete mode 100644 erpnext/hr/doctype/department/test_department.js delete mode 100644 erpnext/hr/doctype/designation/test_designation.js delete mode 100644 erpnext/hr/doctype/driver/test_driver.js delete mode 100644 erpnext/hr/doctype/employee_advance/test_employee_advance.js delete mode 100644 erpnext/hr/doctype/employee_grade/test_employee_grade.js delete mode 100644 erpnext/hr/doctype/employee_health_insurance/test_employee_health_insurance.js delete mode 100644 erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.js delete mode 100644 erpnext/hr/doctype/employee_onboarding_template/test_employee_onboarding_template.js delete mode 100644 erpnext/hr/doctype/employee_promotion/test_employee_promotion.js delete mode 100644 erpnext/hr/doctype/employee_separation/test_employee_separation.js delete mode 100644 erpnext/hr/doctype/employee_separation_template/test_employee_separation_template.js delete mode 100644 erpnext/hr/doctype/employee_transfer/test_employee_transfer.js delete mode 100644 erpnext/hr/doctype/employee_transfer_property/test_employee_transfer_property.js delete mode 100644 erpnext/hr/doctype/hr_settings/test_hr_settings.js delete mode 100644 erpnext/hr/doctype/identification_document_type/test_identification_document_type.js delete mode 100644 erpnext/hr/doctype/job_applicant_source/test_job_applicant_source.js delete mode 100644 erpnext/hr/doctype/leave_encashment/test_leave_encashment.js delete mode 100644 erpnext/hr/doctype/leave_period/test_leave_period.js delete mode 100644 erpnext/hr/doctype/leave_policy/test_leave_policy.js delete mode 100644 erpnext/hr/doctype/leave_policy_detail/test_leave_policy_detail.js delete mode 100644 erpnext/hr/doctype/purpose_of_travel/test_purpose_of_travel.js delete mode 100644 erpnext/hr/doctype/shift_assignment/test_shift_assignment.js delete mode 100644 erpnext/hr/doctype/shift_request/test_shift_request.js delete mode 100644 erpnext/hr/doctype/shift_type/test_shift_type.js delete mode 100644 erpnext/hr/doctype/staffing_plan/test_staffing_plan.js delete mode 100644 erpnext/hr/doctype/training_program/test_training_program.js delete mode 100644 erpnext/hr/doctype/training_result/test_training_result.js delete mode 100644 erpnext/hr/doctype/travel_request/test_travel_request.js delete mode 100644 erpnext/hr/doctype/vehicle/test_vehicle.js delete mode 100644 erpnext/hub_node/doctype/marketplace_settings/test_marketplace_settings.js delete mode 100644 erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.js delete mode 100644 erpnext/manufacturing/doctype/blanket_order/test_blanket_order.js delete mode 100644 erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.js delete mode 100644 erpnext/manufacturing/doctype/job_card/test_job_card.js delete mode 100644 erpnext/manufacturing/doctype/manufacturing_settings/test_manufacturing_settings.js delete mode 100644 erpnext/manufacturing/doctype/material_request_plan_item/test_material_request_plan_item.js delete mode 100644 erpnext/manufacturing/doctype/production_plan/test_production_plan.js delete mode 100644 erpnext/manufacturing/doctype/routing/test_routing.js delete mode 100644 erpnext/non_profit/doctype/certification_application/test_certification_application.js delete mode 100644 erpnext/non_profit/doctype/certified_consultant/test_certified_consultant.js delete mode 100644 erpnext/non_profit/doctype/chapter/test_chapter.js delete mode 100644 erpnext/non_profit/doctype/donor_type/test_donor_type.js delete mode 100644 erpnext/non_profit/doctype/membership/test_membership.js delete mode 100644 erpnext/payroll/doctype/additional_salary/test_additional_salary.js delete mode 100644 erpnext/payroll/doctype/employee_benefit_application/test_employee_benefit_application.js delete mode 100644 erpnext/payroll/doctype/employee_benefit_claim/test_employee_benefit_claim.js delete mode 100644 erpnext/payroll/doctype/employee_incentive/test_employee_incentive.js delete mode 100644 erpnext/payroll/doctype/employee_tax_exemption_category/test_employee_tax_exemption_category.js delete mode 100644 erpnext/payroll/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.js delete mode 100644 erpnext/payroll/doctype/employee_tax_exemption_proof_submission/test_employee_tax_exemption_proof_submission.js delete mode 100644 erpnext/payroll/doctype/employee_tax_exemption_sub_category/test_employee_tax_exemption_sub_category.js delete mode 100644 erpnext/payroll/doctype/payroll_period/test_payroll_period.js delete mode 100644 erpnext/payroll/doctype/retention_bonus/test_retention_bonus.js delete mode 100644 erpnext/payroll/doctype/salary_component/test_salary_component.js delete mode 100644 erpnext/payroll/doctype/salary_structure_assignment/test_salary_structure_assignment.js delete mode 100644 erpnext/portal/doctype/products_settings/test_products_settings.js delete mode 100644 erpnext/projects/doctype/project/test_project.js delete mode 100644 erpnext/projects/doctype/project_type/test_project_type.js delete mode 100644 erpnext/projects/doctype/project_update/test_project_update.js delete mode 100644 erpnext/projects/doctype/projects_settings/test_projects_settings.js delete mode 100644 erpnext/projects/doctype/timesheet/test_timesheet.js delete mode 100644 erpnext/regional/doctype/gst_hsn_code/test_gst_hsn_code.js delete mode 100644 erpnext/regional/doctype/gst_settings/test_gst_settings.js delete mode 100644 erpnext/selling/doctype/customer/test_customer.js delete mode 100644 erpnext/selling/doctype/sales_order/test_sales_order.js delete mode 100644 erpnext/selling/doctype/sales_partner_type/test_sales_partner_type.js delete mode 100644 erpnext/setup/doctype/currency_exchange/test_currency_exchange.js delete mode 100644 erpnext/setup/doctype/global_defaults/test_global_defaults.js delete mode 100644 erpnext/setup/doctype/item_group/test_item_group.js delete mode 100644 erpnext/setup/doctype/naming_series/test_naming_series.js delete mode 100644 erpnext/setup/doctype/party_type/test_party_type.js delete mode 100644 erpnext/setup/doctype/supplier_group/test_supplier_group.js delete mode 100644 erpnext/setup/doctype/uom_conversion_factor/test_uom_conversion_factor.js delete mode 100644 erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.js delete mode 100644 erpnext/stock/doctype/customs_tariff_number/test_customs_tariff_number.js delete mode 100644 erpnext/stock/doctype/delivery_settings/test_delivery_settings.js delete mode 100644 erpnext/stock/doctype/delivery_trip/test_delivery_trip.js delete mode 100644 erpnext/stock/doctype/item/test_item.js delete mode 100644 erpnext/stock/doctype/item_alternative/test_item_alternative.js delete mode 100644 erpnext/stock/doctype/item_variant_settings/test_item_variant_settings.js delete mode 100644 erpnext/stock/doctype/manufacturer/test_manufacturer.js delete mode 100644 erpnext/stock/doctype/material_request/test_material_request.js delete mode 100644 erpnext/stock/doctype/price_list/test_price_list.js delete mode 100644 erpnext/stock/doctype/quality_inspection/test_quality_inspection.js delete mode 100644 erpnext/stock/doctype/quality_inspection_template/test_quality_inspection_template.js delete mode 100644 erpnext/stock/doctype/serial_no/test_serial_no.js delete mode 100644 erpnext/stock/doctype/stock_settings/test_stock_settings.js delete mode 100644 erpnext/stock/doctype/uom_category/test_uom_category.js delete mode 100644 erpnext/stock/doctype/variant_field/test_variant_field.js delete mode 100644 erpnext/support/doctype/support_settings/test_support_settings.js diff --git a/.github/workflows/ui-tests.yml b/.github/workflows/ui-tests.yml index 0be9bd8f87..0ece0d8ee6 100644 --- a/.github/workflows/ui-tests.yml +++ b/.github/workflows/ui-tests.yml @@ -95,7 +95,7 @@ jobs: run: cd ~/frappe-bench/ && bench --site test_site execute erpnext.setup.utils.before_tests - name: cypress pre-requisites - run: cd ~/frappe-bench/apps/frappe && yarn add cypress-file-upload@^5 --no-lockfile + run: cd ~/frappe-bench/apps/frappe && yarn add cypress-file-upload@^5 @testing-library/cypress@^8 --no-lockfile - name: Build Assets diff --git a/erpnext/accounts/doctype/accounting_period/test_accounting_period.js b/erpnext/accounts/doctype/accounting_period/test_accounting_period.js deleted file mode 100644 index 71ce5b8d04..0000000000 --- a/erpnext/accounts/doctype/accounting_period/test_accounting_period.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Accounting Period", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Accounting Period - () => frappe.tests.make('Accounting Period', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/bank/test_bank.js b/erpnext/accounts/doctype/bank/test_bank.js deleted file mode 100644 index 9ec264415a..0000000000 --- a/erpnext/accounts/doctype/bank/test_bank.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Bank", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Bank - () => frappe.tests.make('Bank', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/bank_account/test_bank_account.js b/erpnext/accounts/doctype/bank_account/test_bank_account.js deleted file mode 100644 index c20a7990e8..0000000000 --- a/erpnext/accounts/doctype/bank_account/test_bank_account.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Bank Account", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Bank Account - () => frappe.tests.make('Bank Account', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/bank_account_subtype/test_bank_account_subtype.js b/erpnext/accounts/doctype/bank_account_subtype/test_bank_account_subtype.js deleted file mode 100644 index f59999845a..0000000000 --- a/erpnext/accounts/doctype/bank_account_subtype/test_bank_account_subtype.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Bank Account Subtype", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Bank Account Subtype - () => frappe.tests.make('Bank Account Subtype', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/bank_guarantee/test_bank_guarantee.js b/erpnext/accounts/doctype/bank_guarantee/test_bank_guarantee.js deleted file mode 100644 index 0c60920cf9..0000000000 --- a/erpnext/accounts/doctype/bank_guarantee/test_bank_guarantee.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Bank Guarantee", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Bank Guarantee - () => frappe.tests.make('Bank Guarantee', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.js b/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.js deleted file mode 100644 index 305119e137..0000000000 --- a/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Bank Transaction", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Bank Transaction - () => frappe.tests.make('Bank Transaction', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/cash_flow_mapper/test_cash_flow_mapper.js b/erpnext/accounts/doctype/cash_flow_mapper/test_cash_flow_mapper.js deleted file mode 100644 index 12ca254c5a..0000000000 --- a/erpnext/accounts/doctype/cash_flow_mapper/test_cash_flow_mapper.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Cash Flow Mapper", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Cash Flow Mapper - () => frappe.tests.make('Cash Flow Mapper', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/cash_flow_mapping/test_cash_flow_mapping.js b/erpnext/accounts/doctype/cash_flow_mapping/test_cash_flow_mapping.js deleted file mode 100644 index 1970ca806d..0000000000 --- a/erpnext/accounts/doctype/cash_flow_mapping/test_cash_flow_mapping.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Cash Flow Mapping", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Cash Flow Mapping - () => frappe.tests.make('Cash Flow Mapping', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/cash_flow_mapping_template/test_cash_flow_mapping_template.js b/erpnext/accounts/doctype/cash_flow_mapping_template/test_cash_flow_mapping_template.js deleted file mode 100644 index 12546ce2e3..0000000000 --- a/erpnext/accounts/doctype/cash_flow_mapping_template/test_cash_flow_mapping_template.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Cash Flow Mapping Template", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Cash Flow Mapping Template - () => frappe.tests.make('Cash Flow Mapping Template', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/cash_flow_mapping_template_details/test_cash_flow_mapping_template_details.js b/erpnext/accounts/doctype/cash_flow_mapping_template_details/test_cash_flow_mapping_template_details.js deleted file mode 100644 index eecabda751..0000000000 --- a/erpnext/accounts/doctype/cash_flow_mapping_template_details/test_cash_flow_mapping_template_details.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Cash Flow Mapping Template Details", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Cash Flow Mapping Template Details - () => frappe.tests.make('Cash Flow Mapping Template Details', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/cashier_closing/test_cashier_closing.js b/erpnext/accounts/doctype/cashier_closing/test_cashier_closing.js deleted file mode 100644 index a7fcc8d842..0000000000 --- a/erpnext/accounts/doctype/cashier_closing/test_cashier_closing.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Cashier Closing", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Cashier Closing - () => frappe.tests.make('Cashier Closing', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/chart_of_accounts_importer/test_chart_of_accounts_importer.js b/erpnext/accounts/doctype/chart_of_accounts_importer/test_chart_of_accounts_importer.js deleted file mode 100644 index b075a015d6..0000000000 --- a/erpnext/accounts/doctype/chart_of_accounts_importer/test_chart_of_accounts_importer.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Chart of Accounts Importer", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Chart of Accounts Importer - () => frappe.tests.make('Chart of Accounts Importer', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/coupon_code/test_coupon_code.js b/erpnext/accounts/doctype/coupon_code/test_coupon_code.js deleted file mode 100644 index 460fedc97f..0000000000 --- a/erpnext/accounts/doctype/coupon_code/test_coupon_code.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Coupon Code", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Coupon Code - () => frappe.tests.make('Coupon Code', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/exchange_rate_revaluation/test_exchange_rate_revaluation.js b/erpnext/accounts/doctype/exchange_rate_revaluation/test_exchange_rate_revaluation.js deleted file mode 100644 index 57c6a7871d..0000000000 --- a/erpnext/accounts/doctype/exchange_rate_revaluation/test_exchange_rate_revaluation.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Exchange Rate Revaluation", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Exchange Rate Revaluation - () => frappe.tests.make('Exchange Rate Revaluation', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/finance_book/test_finance_book.js b/erpnext/accounts/doctype/finance_book/test_finance_book.js deleted file mode 100644 index 9fb7d4fcc8..0000000000 --- a/erpnext/accounts/doctype/finance_book/test_finance_book.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Finance Book", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Finance Book - () => frappe.tests.make('Finance Book', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/gl_entry/test_gl_entry.js b/erpnext/accounts/doctype/gl_entry/test_gl_entry.js deleted file mode 100644 index 2986e5e4e3..0000000000 --- a/erpnext/accounts/doctype/gl_entry/test_gl_entry.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: GL Entry", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially('GL Entry', [ - // insert a new GL Entry - () => frappe.tests.make([ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/item_tax_template/test_item_tax_template.js b/erpnext/accounts/doctype/item_tax_template/test_item_tax_template.js deleted file mode 100644 index 6893499391..0000000000 --- a/erpnext/accounts/doctype/item_tax_template/test_item_tax_template.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Item Tax Template", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Item Tax Template - () => frappe.tests.make('Item Tax Template', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/loyalty_point_entry/test_loyalty_point_entry.js b/erpnext/accounts/doctype/loyalty_point_entry/test_loyalty_point_entry.js deleted file mode 100644 index a916b67522..0000000000 --- a/erpnext/accounts/doctype/loyalty_point_entry/test_loyalty_point_entry.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Loyalty Point Entry", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Loyalty Point Entry - () => frappe.tests.make('Loyalty Point Entry', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/loyalty_program/test_loyalty_program.js b/erpnext/accounts/doctype/loyalty_program/test_loyalty_program.js deleted file mode 100644 index 9321c14e1f..0000000000 --- a/erpnext/accounts/doctype/loyalty_program/test_loyalty_program.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Loyalty Program", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Loyalty Program - () => frappe.tests.make('Loyalty Program', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.js b/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.js deleted file mode 100644 index f95d0d8213..0000000000 --- a/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Opening Invoice Creation Tool", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Opening Invoice Creation Tool - () => frappe.tests.make('Opening Invoice Creation Tool', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/payment_order/test_payment_order.js b/erpnext/accounts/doctype/payment_order/test_payment_order.js deleted file mode 100644 index f63fc54521..0000000000 --- a/erpnext/accounts/doctype/payment_order/test_payment_order.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Payment Order", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Payment Order - () => frappe.tests.make('Payment Order', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/payment_request/test_payment_request.js b/erpnext/accounts/doctype/payment_request/test_payment_request.js deleted file mode 100644 index 070b595fc6..0000000000 --- a/erpnext/accounts/doctype/payment_request/test_payment_request.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Payment Request", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Payment Request - () => frappe.tests.make('Payment Request', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/payment_term/test_payment_term.js b/erpnext/accounts/doctype/payment_term/test_payment_term.js deleted file mode 100644 index b26e42aa37..0000000000 --- a/erpnext/accounts/doctype/payment_term/test_payment_term.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Payment Term", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Payment Term - () => frappe.tests.make('Payment Term', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/payment_terms_template/test_payment_terms_template.js b/erpnext/accounts/doctype/payment_terms_template/test_payment_terms_template.js deleted file mode 100644 index 494a0ed21f..0000000000 --- a/erpnext/accounts/doctype/payment_terms_template/test_payment_terms_template.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Payment Terms Template", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Payment Terms Template - () => frappe.tests.make('Payment Terms Template', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.js b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.js deleted file mode 100644 index 48109b159c..0000000000 --- a/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: POS Closing Entry", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new POS Closing Entry - () => frappe.tests.make('POS Closing Entry', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/pos_profile/test_pos_profile.js b/erpnext/accounts/doctype/pos_profile/test_pos_profile.js deleted file mode 100644 index 42e5b7f92f..0000000000 --- a/erpnext/accounts/doctype/pos_profile/test_pos_profile.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: POS Profile", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially('POS Profile', [ - // insert a new POS Profile - () => frappe.tests.make([ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/pos_profile_user/test_pos_profile_user.js b/erpnext/accounts/doctype/pos_profile_user/test_pos_profile_user.js deleted file mode 100644 index 5449ab76a3..0000000000 --- a/erpnext/accounts/doctype/pos_profile_user/test_pos_profile_user.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: POS Profile User", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new POS Profile User - () => frappe.tests.make('POS Profile User', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/pos_settings/test_pos_settings.js b/erpnext/accounts/doctype/pos_settings/test_pos_settings.js deleted file mode 100644 index 639c94ed10..0000000000 --- a/erpnext/accounts/doctype/pos_settings/test_pos_settings.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: POS Settings", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new POS Settings - () => frappe.tests.make('POS Settings', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/share_transfer/test_share_transfer.js b/erpnext/accounts/doctype/share_transfer/test_share_transfer.js deleted file mode 100644 index e5530fa0aa..0000000000 --- a/erpnext/accounts/doctype/share_transfer/test_share_transfer.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Share Transfer", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Share Transfer - () => frappe.tests.make('Share Transfer', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/share_type/test_share_type.js b/erpnext/accounts/doctype/share_type/test_share_type.js deleted file mode 100644 index 620afa2ba8..0000000000 --- a/erpnext/accounts/doctype/share_type/test_share_type.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Share Type", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Share Type - () => frappe.tests.make('Share Type', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/shareholder/test_shareholder.js b/erpnext/accounts/doctype/shareholder/test_shareholder.js deleted file mode 100644 index 61c53120ea..0000000000 --- a/erpnext/accounts/doctype/shareholder/test_shareholder.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Shareholder", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Shareholder - () => frappe.tests.make('Shareholder', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/subscription_invoice/test_subscription_invoice.js b/erpnext/accounts/doctype/subscription_invoice/test_subscription_invoice.js deleted file mode 100644 index 15d3df2a63..0000000000 --- a/erpnext/accounts/doctype/subscription_invoice/test_subscription_invoice.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Subscription Invoice", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Subscription Invoice - () => frappe.tests.make('Subscription Invoice', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/subscription_plan/test_subscription_plan.js b/erpnext/accounts/doctype/subscription_plan/test_subscription_plan.js deleted file mode 100644 index 3ceb9a6050..0000000000 --- a/erpnext/accounts/doctype/subscription_plan/test_subscription_plan.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Subscription Plan", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Subscription Plan - () => frappe.tests.make('Subscription Plan', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/subscription_settings/test_subscription_settings.js b/erpnext/accounts/doctype/subscription_settings/test_subscription_settings.js deleted file mode 100644 index 5a751ea99c..0000000000 --- a/erpnext/accounts/doctype/subscription_settings/test_subscription_settings.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Subscription Settings", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Subscription Settings - () => frappe.tests.make('Subscription Settings', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/tax_category/test_tax_category.js b/erpnext/accounts/doctype/tax_category/test_tax_category.js deleted file mode 100644 index 5142456d76..0000000000 --- a/erpnext/accounts/doctype/tax_category/test_tax_category.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Tax Category", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Tax Category - () => frappe.tests.make('Tax Category', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/tax_rule/test_tax_rule.js b/erpnext/accounts/doctype/tax_rule/test_tax_rule.js deleted file mode 100644 index 72d177deff..0000000000 --- a/erpnext/accounts/doctype/tax_rule/test_tax_rule.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Tax Rule", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Tax Rule - () => frappe.tests.make('Tax Rule', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.js b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.js deleted file mode 100644 index eab98d4389..0000000000 --- a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Tax Withholding Category", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Tax Withholding Category - () => frappe.tests.make('Tax Withholding Category', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/agriculture/doctype/agriculture_analysis_criteria/test_agriculture_analysis_criteria.js b/erpnext/agriculture/doctype/agriculture_analysis_criteria/test_agriculture_analysis_criteria.js deleted file mode 100644 index f70dcd2f32..0000000000 --- a/erpnext/agriculture/doctype/agriculture_analysis_criteria/test_agriculture_analysis_criteria.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Agriculture Analysis Criteria", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Agriculture Analysis Criteria - () => frappe.tests.make('Agriculture Analysis Criteria', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/agriculture/doctype/agriculture_task/test_agriculture_task.js b/erpnext/agriculture/doctype/agriculture_task/test_agriculture_task.js deleted file mode 100644 index a012c4b1ad..0000000000 --- a/erpnext/agriculture/doctype/agriculture_task/test_agriculture_task.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Agriculture Task", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Agriculture Task - () => frappe.tests.make('Agriculture Task', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/agriculture/doctype/plant_analysis/test_plant_analysis.js b/erpnext/agriculture/doctype/plant_analysis/test_plant_analysis.js deleted file mode 100644 index 786c0471a4..0000000000 --- a/erpnext/agriculture/doctype/plant_analysis/test_plant_analysis.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Plant Analysis", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Plant Analysis - () => frappe.tests.make('Plant Analysis', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/agriculture/doctype/soil_analysis/test_soil_analysis.js b/erpnext/agriculture/doctype/soil_analysis/test_soil_analysis.js deleted file mode 100644 index 29128eba27..0000000000 --- a/erpnext/agriculture/doctype/soil_analysis/test_soil_analysis.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Soil Analysis", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Soil Analysis - () => frappe.tests.make('Soil Analysis', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/agriculture/doctype/weather/test_weather.js b/erpnext/agriculture/doctype/weather/test_weather.js deleted file mode 100644 index b5009a4ccd..0000000000 --- a/erpnext/agriculture/doctype/weather/test_weather.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Weather", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Weather - () => frappe.tests.make('Weather', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/assets/doctype/asset/test_asset.js b/erpnext/assets/doctype/asset/test_asset.js deleted file mode 100644 index 6119e38217..0000000000 --- a/erpnext/assets/doctype/asset/test_asset.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Asset", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Asset - () => frappe.tests.make('Asset', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/assets/doctype/asset_category/test_asset_category.js b/erpnext/assets/doctype/asset_category/test_asset_category.js deleted file mode 100644 index 7e343b7519..0000000000 --- a/erpnext/assets/doctype/asset_category/test_asset_category.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Asset Category", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Asset Category - () => frappe.tests.make('Asset Category', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.js b/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.js deleted file mode 100644 index f9b38a1020..0000000000 --- a/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Asset Maintenance", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Asset Maintenance - () => frappe.tests.make('Asset Maintenance', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/assets/doctype/asset_maintenance_log/test_asset_maintenance_log.js b/erpnext/assets/doctype/asset_maintenance_log/test_asset_maintenance_log.js deleted file mode 100644 index 4e80184ea7..0000000000 --- a/erpnext/assets/doctype/asset_maintenance_log/test_asset_maintenance_log.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Asset Maintenance Log", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Asset Maintenance Log - () => frappe.tests.make('Asset Maintenance Log', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/assets/doctype/asset_maintenance_team/test_asset_maintenance_team.js b/erpnext/assets/doctype/asset_maintenance_team/test_asset_maintenance_team.js deleted file mode 100644 index 41bf69623e..0000000000 --- a/erpnext/assets/doctype/asset_maintenance_team/test_asset_maintenance_team.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Asset Maintenance Team", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Asset Maintenance Team - () => frappe.tests.make('Asset Maintenance Team', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/assets/doctype/asset_movement/test_asset_movement.js b/erpnext/assets/doctype/asset_movement/test_asset_movement.js deleted file mode 100644 index b9515763c4..0000000000 --- a/erpnext/assets/doctype/asset_movement/test_asset_movement.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Asset Movement", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Asset Movement - () => frappe.tests.make('Asset Movement', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/assets/doctype/asset_repair/test_asset_repair.js b/erpnext/assets/doctype/asset_repair/test_asset_repair.js deleted file mode 100644 index 7424ffe2b8..0000000000 --- a/erpnext/assets/doctype/asset_repair/test_asset_repair.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Asset Repair", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Asset Repair - () => frappe.tests.make('Asset Repair', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.js b/erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.js deleted file mode 100644 index 32831c61d2..0000000000 --- a/erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Asset Value Adjustment", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Asset Value Adjustment - () => frappe.tests.make('Asset Value Adjustment', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/assets/doctype/location/test_location.js b/erpnext/assets/doctype/location/test_location.js deleted file mode 100644 index 3c06b63e82..0000000000 --- a/erpnext/assets/doctype/location/test_location.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Location", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Location - () => frappe.tests.make('Location', [ - // values to be set - { location_name: 'Basil Farm' } - ]), - () => { - assert.equal(cur_frm.doc.name, 'Basil Farm'); - }, - () => done() - ]); - -}); diff --git a/erpnext/assets/doctype/maintenance_team_member/test_maintenance_team_member.js b/erpnext/assets/doctype/maintenance_team_member/test_maintenance_team_member.js deleted file mode 100644 index d942e2a156..0000000000 --- a/erpnext/assets/doctype/maintenance_team_member/test_maintenance_team_member.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Maintenance Team Member", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Maintenance Team Member - () => frappe.tests.make('Maintenance Team Member', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/crm/doctype/contract/test_contract.js b/erpnext/crm/doctype/contract/test_contract.js deleted file mode 100644 index 4c77c3d649..0000000000 --- a/erpnext/crm/doctype/contract/test_contract.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Contract", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Contract - () => frappe.tests.make('Contract', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/crm/doctype/contract_fulfilment_checklist/test_contract_fulfilment_checklist.js b/erpnext/crm/doctype/contract_fulfilment_checklist/test_contract_fulfilment_checklist.js deleted file mode 100644 index 2a2d5e1bfc..0000000000 --- a/erpnext/crm/doctype/contract_fulfilment_checklist/test_contract_fulfilment_checklist.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Contract Fulfilment Checklist", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Contract Fulfilment Checklist - () => frappe.tests.make('Contract Fulfilment Checklist', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/crm/doctype/contract_template/test_contract_template.js b/erpnext/crm/doctype/contract_template/test_contract_template.js deleted file mode 100644 index 6aaddd7df4..0000000000 --- a/erpnext/crm/doctype/contract_template/test_contract_template.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Contract Template", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Contract Template - () => frappe.tests.make('Contract Template', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/crm/doctype/market_segment/test_market_segment.js b/erpnext/crm/doctype/market_segment/test_market_segment.js deleted file mode 100644 index aa4b868f93..0000000000 --- a/erpnext/crm/doctype/market_segment/test_market_segment.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Market Segment", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Market Segment - () => frappe.tests.make('Market Segment', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/crm/doctype/opportunity_type/test_opportunity_type.js b/erpnext/crm/doctype/opportunity_type/test_opportunity_type.js deleted file mode 100644 index 3a1ede94db..0000000000 --- a/erpnext/crm/doctype/opportunity_type/test_opportunity_type.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Opportunity Type", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Opportunity Type - () => frappe.tests.make('Opportunity Type', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/crm/doctype/sales_stage/test_sales_stage.js b/erpnext/crm/doctype/sales_stage/test_sales_stage.js deleted file mode 100644 index 807af1fd98..0000000000 --- a/erpnext/crm/doctype/sales_stage/test_sales_stage.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Sales Stage", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Sales Stage - () => frappe.tests.make('Sales Stage', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/education/doctype/academic_year/test_academic_year.js b/erpnext/education/doctype/academic_year/test_academic_year.js deleted file mode 100644 index 51e9cf307d..0000000000 --- a/erpnext/education/doctype/academic_year/test_academic_year.js +++ /dev/null @@ -1,23 +0,0 @@ -// Testing Setup Module in Education -QUnit.module('education'); - -QUnit.test('Test: Academic Year', function(assert){ - assert.expect(3); - let done = assert.async(); - frappe.run_serially([ - () => { - return frappe.tests.make('Academic Year', [ - {academic_year_name: '2016-17'}, - {year_start_date: '2016-07-20'}, - {year_end_date:'2017-06-20'}, - ]); - }, - - () => { - assert.ok(cur_frm.doc.academic_year_name=='2016-17'); - assert.ok(cur_frm.doc.year_start_date=='2016-07-20'); - assert.ok(cur_frm.doc.year_end_date=='2017-06-20'); - }, - () => done() - ]); -}); diff --git a/erpnext/education/doctype/article/test_article.js b/erpnext/education/doctype/article/test_article.js deleted file mode 100644 index 9dbf063e84..0000000000 --- a/erpnext/education/doctype/article/test_article.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Article", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Article - () => frappe.tests.make('Article', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/education/doctype/content_question/test_content_question.js b/erpnext/education/doctype/content_question/test_content_question.js deleted file mode 100644 index cc869a87fc..0000000000 --- a/erpnext/education/doctype/content_question/test_content_question.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Content Question", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Content Question - () => frappe.tests.make('Content Question', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/education/doctype/course_activity/test_course_activity.js b/erpnext/education/doctype/course_activity/test_course_activity.js deleted file mode 100644 index c89c89e5d3..0000000000 --- a/erpnext/education/doctype/course_activity/test_course_activity.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Course Activity", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Course Activity - () => frappe.tests.make('Course Activity', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/education/doctype/course_content/test_course_content.js b/erpnext/education/doctype/course_content/test_course_content.js deleted file mode 100644 index 786e67e9a3..0000000000 --- a/erpnext/education/doctype/course_content/test_course_content.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Course Content", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Course Content - () => frappe.tests.make('Course Content', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/education/doctype/course_enrollment/test_course_enrollment.js b/erpnext/education/doctype/course_enrollment/test_course_enrollment.js deleted file mode 100644 index 216cc30799..0000000000 --- a/erpnext/education/doctype/course_enrollment/test_course_enrollment.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Course Enrollment", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Course Enrollment - () => frappe.tests.make('Course Enrollment', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/education/doctype/course_schedule/test_course_schedule.js b/erpnext/education/doctype/course_schedule/test_course_schedule.js deleted file mode 100644 index 5cdb67be48..0000000000 --- a/erpnext/education/doctype/course_schedule/test_course_schedule.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Course Schedule", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Course Schedule - () => frappe.tests.make('Course Schedule', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/education/doctype/course_scheduling_tool/test_course_scheduling_tool.js b/erpnext/education/doctype/course_scheduling_tool/test_course_scheduling_tool.js deleted file mode 100644 index 4419d18116..0000000000 --- a/erpnext/education/doctype/course_scheduling_tool/test_course_scheduling_tool.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Course Scheduling Tool", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Course Scheduling Tool - () => frappe.tests.make('Course Scheduling Tool', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/education/doctype/course_topic/test_course_topic.js b/erpnext/education/doctype/course_topic/test_course_topic.js deleted file mode 100644 index d8d154fb9c..0000000000 --- a/erpnext/education/doctype/course_topic/test_course_topic.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Course Topic", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Course Topic - () => frappe.tests.make('Course Topic', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/education/doctype/fee_category/test_fee_category.js b/erpnext/education/doctype/fee_category/test_fee_category.js deleted file mode 100644 index a08ed33e8b..0000000000 --- a/erpnext/education/doctype/fee_category/test_fee_category.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Fee Category", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Fee Category - () => frappe.tests.make('Fee Category', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/education/doctype/fee_schedule/test_fee_schedule.js b/erpnext/education/doctype/fee_schedule/test_fee_schedule.js deleted file mode 100644 index d495b4ce7b..0000000000 --- a/erpnext/education/doctype/fee_schedule/test_fee_schedule.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Fee Schedule", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially('Fee Schedule', [ - // insert a new Fee Schedule - () => frappe.tests.make([ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/education/doctype/fee_structure/test_fee_structure.js b/erpnext/education/doctype/fee_structure/test_fee_structure.js deleted file mode 100644 index 61f41354c3..0000000000 --- a/erpnext/education/doctype/fee_structure/test_fee_structure.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Fee Structure", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Fee Structure - () => frappe.tests.make('Fee Structure', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/education/doctype/program_enrollment/test_program_enrollment.js b/erpnext/education/doctype/program_enrollment/test_program_enrollment.js deleted file mode 100644 index aea81a0714..0000000000 --- a/erpnext/education/doctype/program_enrollment/test_program_enrollment.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Program Enrollment", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Program Enrollment - () => frappe.tests.make('Program Enrollment', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/education/doctype/program_enrollment_tool/test_program_enrollment_tool.js b/erpnext/education/doctype/program_enrollment_tool/test_program_enrollment_tool.js deleted file mode 100644 index 8d55104a0f..0000000000 --- a/erpnext/education/doctype/program_enrollment_tool/test_program_enrollment_tool.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Program Enrollment Tool", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Program Enrollment Tool - () => frappe.tests.make('Program Enrollment Tool', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/education/doctype/question/test_question.js b/erpnext/education/doctype/question/test_question.js deleted file mode 100644 index 509939c6b5..0000000000 --- a/erpnext/education/doctype/question/test_question.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Question", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Question - () => frappe.tests.make('Question', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/education/doctype/quiz/test_quiz.js b/erpnext/education/doctype/quiz/test_quiz.js deleted file mode 100644 index 147d13952a..0000000000 --- a/erpnext/education/doctype/quiz/test_quiz.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Quiz", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Quiz - () => frappe.tests.make('Quiz', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/education/doctype/quiz_activity/test_quiz_activity.js b/erpnext/education/doctype/quiz_activity/test_quiz_activity.js deleted file mode 100644 index 94b5ab796a..0000000000 --- a/erpnext/education/doctype/quiz_activity/test_quiz_activity.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Quiz Activity", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Quiz Activity - () => frappe.tests.make('Quiz Activity', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/education/doctype/quiz_result/test_quiz_result.js b/erpnext/education/doctype/quiz_result/test_quiz_result.js deleted file mode 100644 index 43f53a1dc7..0000000000 --- a/erpnext/education/doctype/quiz_result/test_quiz_result.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Quiz Result", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Quiz Result - () => frappe.tests.make('Quiz Result', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/education/doctype/school_house/test_school_house.js b/erpnext/education/doctype/school_house/test_school_house.js deleted file mode 100644 index dde63ecc4c..0000000000 --- a/erpnext/education/doctype/school_house/test_school_house.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: School House", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new School House - () => frappe.tests.make('School House', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/education/doctype/student/test_student.js b/erpnext/education/doctype/student/test_student.js deleted file mode 100644 index e18d39aee0..0000000000 --- a/erpnext/education/doctype/student/test_student.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Student", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Student - () => frappe.tests.make('Student', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/education/doctype/student_language/test_student_language.js b/erpnext/education/doctype/student_language/test_student_language.js deleted file mode 100644 index 9b25569961..0000000000 --- a/erpnext/education/doctype/student_language/test_student_language.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Student Language", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Student Language - () => frappe.tests.make('Student Language', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/education/doctype/student_report_generation_tool/test_student_report_generation_tool.js b/erpnext/education/doctype/student_report_generation_tool/test_student_report_generation_tool.js deleted file mode 100644 index 10be092bb9..0000000000 --- a/erpnext/education/doctype/student_report_generation_tool/test_student_report_generation_tool.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Student Report Generation Tool", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Student Report Generation Tool - () => frappe.tests.make('Student Report Generation Tool', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/education/doctype/topic/test_topic.js b/erpnext/education/doctype/topic/test_topic.js deleted file mode 100644 index 4460b79478..0000000000 --- a/erpnext/education/doctype/topic/test_topic.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Topic", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Topic - () => frappe.tests.make('Topic', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/education/doctype/topic_content/test_topic_content.js b/erpnext/education/doctype/topic_content/test_topic_content.js deleted file mode 100644 index bf9a62d037..0000000000 --- a/erpnext/education/doctype/topic_content/test_topic_content.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Topic Content", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Topic Content - () => frappe.tests.make('Topic Content', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/test_amazon_mws_settings.js b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/test_amazon_mws_settings.js deleted file mode 100644 index 9c8990986e..0000000000 --- a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/test_amazon_mws_settings.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Amazon MWS Settings", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Amazon MWS Settings - () => frappe.tests.make('Amazon MWS Settings', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/erpnext_integrations/doctype/gocardless_mandate/test_gocardless_mandate.js b/erpnext/erpnext_integrations/doctype/gocardless_mandate/test_gocardless_mandate.js deleted file mode 100644 index caa9399eb6..0000000000 --- a/erpnext/erpnext_integrations/doctype/gocardless_mandate/test_gocardless_mandate.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: GoCardless Mandate", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new GoCardless Mandate - () => frappe.tests.make('GoCardless Mandate', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/erpnext_integrations/doctype/gocardless_settings/test_gocardless_settings.js b/erpnext/erpnext_integrations/doctype/gocardless_settings/test_gocardless_settings.js deleted file mode 100644 index b6daad8de4..0000000000 --- a/erpnext/erpnext_integrations/doctype/gocardless_settings/test_gocardless_settings.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: GoCardless Settings", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new GoCardless Settings - () => frappe.tests.make('GoCardless Settings', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/test_plaid_settings.js b/erpnext/erpnext_integrations/doctype/plaid_settings/test_plaid_settings.js deleted file mode 100644 index dc91347336..0000000000 --- a/erpnext/erpnext_integrations/doctype/plaid_settings/test_plaid_settings.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Plaid Settings", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Plaid Settings - () => frappe.tests.make('Plaid Settings', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/erpnext_integrations/doctype/quickbooks_migrator/test_quickbooks_migrator.js b/erpnext/erpnext_integrations/doctype/quickbooks_migrator/test_quickbooks_migrator.js deleted file mode 100644 index b71d704807..0000000000 --- a/erpnext/erpnext_integrations/doctype/quickbooks_migrator/test_quickbooks_migrator.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: QuickBooks Migrator", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new QuickBooks Migrator - () => frappe.tests.make('QuickBooks Migrator', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/erpnext_integrations/doctype/tally_migration/test_tally_migration.js b/erpnext/erpnext_integrations/doctype/tally_migration/test_tally_migration.js deleted file mode 100644 index 433c5e2cda..0000000000 --- a/erpnext/erpnext_integrations/doctype/tally_migration/test_tally_migration.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Tally Migration", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Tally Migration - () => frappe.tests.make('Tally Migration', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/erpnext_integrations/doctype/woocommerce_settings/test_woocommerce_settings.js b/erpnext/erpnext_integrations/doctype/woocommerce_settings/test_woocommerce_settings.js deleted file mode 100644 index ea06ab2dc4..0000000000 --- a/erpnext/erpnext_integrations/doctype/woocommerce_settings/test_woocommerce_settings.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Woocommerce Settings", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Woocommerce Settings - () => frappe.tests.make('Woocommerce Settings', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/antibiotic/test_antibiotic.js b/erpnext/healthcare/doctype/antibiotic/test_antibiotic.js deleted file mode 100644 index b92103d750..0000000000 --- a/erpnext/healthcare/doctype/antibiotic/test_antibiotic.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Antibiotic", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Antibiotic - () => frappe.tests.make('Antibiotic', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/appointment_type/test_appointment_type.js b/erpnext/healthcare/doctype/appointment_type/test_appointment_type.js deleted file mode 100644 index 93274e55c7..0000000000 --- a/erpnext/healthcare/doctype/appointment_type/test_appointment_type.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Appointment Type", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Appointment Type - () => frappe.tests.make('Appointment Type', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.js b/erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.js deleted file mode 100644 index 80ef3d55f2..0000000000 --- a/erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Clinical Procedure", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Clinical Procedure - () => frappe.tests.make('Clinical Procedure', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/clinical_procedure_template/test_clinical_procedure_template.js b/erpnext/healthcare/doctype/clinical_procedure_template/test_clinical_procedure_template.js deleted file mode 100644 index 1dde8b5d86..0000000000 --- a/erpnext/healthcare/doctype/clinical_procedure_template/test_clinical_procedure_template.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Clinical Procedure Template", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Clinical Procedure Template - () => frappe.tests.make('Clinical Procedure Template', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/complaint/test_complaint.js b/erpnext/healthcare/doctype/complaint/test_complaint.js deleted file mode 100644 index 9ff44d8da4..0000000000 --- a/erpnext/healthcare/doctype/complaint/test_complaint.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Complaint", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Complaint - () => frappe.tests.make('Complaint', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/diagnosis/test_diagnosis.js b/erpnext/healthcare/doctype/diagnosis/test_diagnosis.js deleted file mode 100644 index cacfef5b17..0000000000 --- a/erpnext/healthcare/doctype/diagnosis/test_diagnosis.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Diagnosis", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Diagnosis - () => frappe.tests.make('Diagnosis', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/dosage_form/test_dosage_form.js b/erpnext/healthcare/doctype/dosage_form/test_dosage_form.js deleted file mode 100644 index ba54ab16fa..0000000000 --- a/erpnext/healthcare/doctype/dosage_form/test_dosage_form.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Dosage Form", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Dosage Form - () => frappe.tests.make('Dosage Form', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/fee_validity/test_fee_validity.js b/erpnext/healthcare/doctype/fee_validity/test_fee_validity.js deleted file mode 100644 index 0ebb97438c..0000000000 --- a/erpnext/healthcare/doctype/fee_validity/test_fee_validity.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Fee Validity", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Fee Validity - () => frappe.tests.make('Fee Validity', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/healthcare_practitioner/test_healthcare_practitioner.js b/erpnext/healthcare/doctype/healthcare_practitioner/test_healthcare_practitioner.js deleted file mode 100644 index 75aa208ec1..0000000000 --- a/erpnext/healthcare/doctype/healthcare_practitioner/test_healthcare_practitioner.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Healthcare Practitioner", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Healthcare Practitioner - () => frappe.tests.make('Healthcare Practitioner', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/healthcare_service_unit/test_healthcare_service_unit.js b/erpnext/healthcare/doctype/healthcare_service_unit/test_healthcare_service_unit.js deleted file mode 100644 index a67a411707..0000000000 --- a/erpnext/healthcare/doctype/healthcare_service_unit/test_healthcare_service_unit.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Healthcare Service Unit", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Healthcare Service Unit - () => frappe.tests.make('Healthcare Service Unit', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/healthcare_service_unit_type/test_healthcare_service_unit_type.js b/erpnext/healthcare/doctype/healthcare_service_unit_type/test_healthcare_service_unit_type.js deleted file mode 100644 index 6db8f9e9c1..0000000000 --- a/erpnext/healthcare/doctype/healthcare_service_unit_type/test_healthcare_service_unit_type.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Healthcare Service Unit Type", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Healthcare Service Unit Type - () => frappe.tests.make('Healthcare Service Unit Type', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/healthcare_settings/test_healthcare_settings.js b/erpnext/healthcare/doctype/healthcare_settings/test_healthcare_settings.js deleted file mode 100644 index ca10925e59..0000000000 --- a/erpnext/healthcare/doctype/healthcare_settings/test_healthcare_settings.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Healthcare Settings", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Healthcare Settings - () => frappe.tests.make('Healthcare Settings', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/inpatient_record/test_inpatient_record.js b/erpnext/healthcare/doctype/inpatient_record/test_inpatient_record.js deleted file mode 100644 index 1ce9afa96d..0000000000 --- a/erpnext/healthcare/doctype/inpatient_record/test_inpatient_record.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Inpatient Record", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Inpatient Record - () => frappe.tests.make('Inpatient Record', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/lab_test/test_lab_test.js b/erpnext/healthcare/doctype/lab_test/test_lab_test.js deleted file mode 100644 index 57cb22b269..0000000000 --- a/erpnext/healthcare/doctype/lab_test/test_lab_test.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Lab Test", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Lab Test - () => frappe.tests.make('Lab Test', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/lab_test_sample/test_lab_test_sample.js b/erpnext/healthcare/doctype/lab_test_sample/test_lab_test_sample.js deleted file mode 100644 index ace60de752..0000000000 --- a/erpnext/healthcare/doctype/lab_test_sample/test_lab_test_sample.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Lab Test Sample", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Lab Test Sample - () => frappe.tests.make('Lab Test Sample', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/lab_test_template/test_lab_test_template.js b/erpnext/healthcare/doctype/lab_test_template/test_lab_test_template.js deleted file mode 100644 index 7c2ec8c348..0000000000 --- a/erpnext/healthcare/doctype/lab_test_template/test_lab_test_template.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Lab Test Template", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Lab Test Template - () => frappe.tests.make('Lab Test Template', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/lab_test_uom/test_lab_test_uom.js b/erpnext/healthcare/doctype/lab_test_uom/test_lab_test_uom.js deleted file mode 100644 index 1328dda282..0000000000 --- a/erpnext/healthcare/doctype/lab_test_uom/test_lab_test_uom.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Lab Test UOM", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Lab Test UOM - () => frappe.tests.make('Lab Test UOM', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/medical_code/test_medical_code.js b/erpnext/healthcare/doctype/medical_code/test_medical_code.js deleted file mode 100644 index 8cc7c40025..0000000000 --- a/erpnext/healthcare/doctype/medical_code/test_medical_code.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Medical Code", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Medical Code - () => frappe.tests.make('Medical Code', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/medical_code_standard/test_medical_code_standard.js b/erpnext/healthcare/doctype/medical_code_standard/test_medical_code_standard.js deleted file mode 100644 index 6ab6d531df..0000000000 --- a/erpnext/healthcare/doctype/medical_code_standard/test_medical_code_standard.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Medical Code Standard", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Medical Code Standard - () => frappe.tests.make('Medical Code Standard', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/medical_department/test_medical_department.js b/erpnext/healthcare/doctype/medical_department/test_medical_department.js deleted file mode 100644 index fdf49718dc..0000000000 --- a/erpnext/healthcare/doctype/medical_department/test_medical_department.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Medical Department", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Medical Department - () => frappe.tests.make('Medical Department', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/organism/test_organism.js b/erpnext/healthcare/doctype/organism/test_organism.js deleted file mode 100644 index d57e5536c6..0000000000 --- a/erpnext/healthcare/doctype/organism/test_organism.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Organism", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Organism - () => frappe.tests.make('Organism', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/patient/test_patient.js b/erpnext/healthcare/doctype/patient/test_patient.js deleted file mode 100644 index e1d9ecbd24..0000000000 --- a/erpnext/healthcare/doctype/patient/test_patient.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Patient", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially('Patient', [ - // insert a new Patient - () => frappe.tests.make([ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.js b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.js deleted file mode 100644 index 71fc177845..0000000000 --- a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Patient Appointment", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Patient Appointment - () => frappe.tests.make('Patient Appointment', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/patient_encounter/test_patient_encounter.js b/erpnext/healthcare/doctype/patient_encounter/test_patient_encounter.js deleted file mode 100644 index 1baabf7eef..0000000000 --- a/erpnext/healthcare/doctype/patient_encounter/test_patient_encounter.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Patient Encounter", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Patient Encounter - () => frappe.tests.make('Patient Encounter', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/patient_medical_record/test_patient_medical_record.js b/erpnext/healthcare/doctype/patient_medical_record/test_patient_medical_record.js deleted file mode 100644 index 66dda09e25..0000000000 --- a/erpnext/healthcare/doctype/patient_medical_record/test_patient_medical_record.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Patient Medical Record", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Patient Medical Record - () => frappe.tests.make('Patient Medical Record', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/practitioner_schedule/test_practitioner_schedule.js b/erpnext/healthcare/doctype/practitioner_schedule/test_practitioner_schedule.js deleted file mode 100644 index 32dac2c652..0000000000 --- a/erpnext/healthcare/doctype/practitioner_schedule/test_practitioner_schedule.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Practitioner Schedule", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Practitioner Schedule - () => frappe.tests.make('Practitioner Schedule', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/prescription_dosage/test_prescription_dosage.js b/erpnext/healthcare/doctype/prescription_dosage/test_prescription_dosage.js deleted file mode 100644 index 009614ff5d..0000000000 --- a/erpnext/healthcare/doctype/prescription_dosage/test_prescription_dosage.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Prescription Dosage", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Prescription Dosage - () => frappe.tests.make('Prescription Dosage', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/prescription_duration/test_prescription_duration.js b/erpnext/healthcare/doctype/prescription_duration/test_prescription_duration.js deleted file mode 100644 index 4971e79198..0000000000 --- a/erpnext/healthcare/doctype/prescription_duration/test_prescription_duration.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Prescription Duration", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Prescription Duration - () => frappe.tests.make('Prescription Duration', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/sample_collection/test_sample_collection.js b/erpnext/healthcare/doctype/sample_collection/test_sample_collection.js deleted file mode 100644 index 2b4aed756b..0000000000 --- a/erpnext/healthcare/doctype/sample_collection/test_sample_collection.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Sample Collection", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Sample Collection - () => frappe.tests.make('Sample Collection', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/sensitivity/test_sensitivity.js b/erpnext/healthcare/doctype/sensitivity/test_sensitivity.js deleted file mode 100644 index c2cf406f96..0000000000 --- a/erpnext/healthcare/doctype/sensitivity/test_sensitivity.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Sensitivity", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Sensitivity - () => frappe.tests.make('Sensitivity', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/healthcare/doctype/vital_signs/test_vital_signs.js b/erpnext/healthcare/doctype/vital_signs/test_vital_signs.js deleted file mode 100644 index f4ab4466be..0000000000 --- a/erpnext/healthcare/doctype/vital_signs/test_vital_signs.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Vital Signs", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Vital Signs - () => frappe.tests.make('Vital Signs', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hotels/doctype/hotel_room/test_hotel_room.js b/erpnext/hotels/doctype/hotel_room/test_hotel_room.js deleted file mode 100644 index 8b2b83330f..0000000000 --- a/erpnext/hotels/doctype/hotel_room/test_hotel_room.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Hotel Room", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Hotel Room - () => frappe.tests.make('Hotel Room', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hotels/doctype/hotel_room_package/test_hotel_room_package.js b/erpnext/hotels/doctype/hotel_room_package/test_hotel_room_package.js deleted file mode 100644 index f1ebad41d4..0000000000 --- a/erpnext/hotels/doctype/hotel_room_package/test_hotel_room_package.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Hotel Room Package", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Hotel Room Package - () => frappe.tests.make('Hotel Room Package', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hotels/doctype/hotel_room_pricing/test_hotel_room_pricing.js b/erpnext/hotels/doctype/hotel_room_pricing/test_hotel_room_pricing.js deleted file mode 100644 index ba0d1fd3e9..0000000000 --- a/erpnext/hotels/doctype/hotel_room_pricing/test_hotel_room_pricing.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Hotel Room Pricing", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Hotel Room Pricing - () => frappe.tests.make('Hotel Room Pricing', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hotels/doctype/hotel_room_pricing_package/test_hotel_room_pricing_package.js b/erpnext/hotels/doctype/hotel_room_pricing_package/test_hotel_room_pricing_package.js deleted file mode 100644 index 73a561c408..0000000000 --- a/erpnext/hotels/doctype/hotel_room_pricing_package/test_hotel_room_pricing_package.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Hotel Room Pricing Package", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Hotel Room Pricing Package - () => frappe.tests.make('Hotel Room Pricing Package', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hotels/doctype/hotel_room_reservation/test_hotel_room_reservation.js b/erpnext/hotels/doctype/hotel_room_reservation/test_hotel_room_reservation.js deleted file mode 100644 index 2897139359..0000000000 --- a/erpnext/hotels/doctype/hotel_room_reservation/test_hotel_room_reservation.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Hotel Room Reservation", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Hotel Room Reservation - () => frappe.tests.make('Hotel Room Reservation', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hotels/doctype/hotel_room_type/test_hotel_room_type.js b/erpnext/hotels/doctype/hotel_room_type/test_hotel_room_type.js deleted file mode 100644 index e2dd5780e3..0000000000 --- a/erpnext/hotels/doctype/hotel_room_type/test_hotel_room_type.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Hotel Room Type", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Hotel Room Type - () => frappe.tests.make('Hotel Room Type', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hotels/doctype/hotel_settings/test_hotel_settings.js b/erpnext/hotels/doctype/hotel_settings/test_hotel_settings.js deleted file mode 100644 index bc0b7f8341..0000000000 --- a/erpnext/hotels/doctype/hotel_settings/test_hotel_settings.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Hotel Settings", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Hotel Settings - () => frappe.tests.make('Hotel Settings', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/attendance_request/test_attendance_request.js b/erpnext/hr/doctype/attendance_request/test_attendance_request.js deleted file mode 100644 index d40ec61b08..0000000000 --- a/erpnext/hr/doctype/attendance_request/test_attendance_request.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Attendance Request", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Attendance Request - () => frappe.tests.make('Attendance Request', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/branch/test_branch.js b/erpnext/hr/doctype/branch/test_branch.js deleted file mode 100644 index 82a6ae103e..0000000000 --- a/erpnext/hr/doctype/branch/test_branch.js +++ /dev/null @@ -1,23 +0,0 @@ -QUnit.module('hr'); - -QUnit.test("Test: Branch [HR]", function (assert) { - assert.expect(1); - let done = assert.async(); - - frappe.run_serially([ - // test branch creation - () => frappe.set_route("List", "Branch", "List"), - () => frappe.new_doc("Branch"), - () => frappe.timeout(1), - () => frappe.quick_entry.dialog.$wrapper.find('.edit-full').click(), - () => frappe.timeout(1), - () => cur_frm.set_value("branch", "Test Branch"), - - // save form - () => cur_frm.save(), - () => frappe.timeout(1), - () => assert.equal("Test Branch", cur_frm.doc.branch, - 'name of branch correctly saved'), - () => done() - ]); -}); diff --git a/erpnext/hr/doctype/compensatory_leave_request/test_compensatory_leave_request.js b/erpnext/hr/doctype/compensatory_leave_request/test_compensatory_leave_request.js deleted file mode 100644 index bebcaac400..0000000000 --- a/erpnext/hr/doctype/compensatory_leave_request/test_compensatory_leave_request.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Compensatory Leave Request", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Compensatory Leave Request - () => frappe.tests.make('Compensatory Leave Request', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/daily_work_summary/test_daily_work_summary.js b/erpnext/hr/doctype/daily_work_summary/test_daily_work_summary.js deleted file mode 100644 index 1533517147..0000000000 --- a/erpnext/hr/doctype/daily_work_summary/test_daily_work_summary.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Daily Work Summary", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Daily Work Summary - () => frappe.tests.make('Daily Work Summary', [ - // values to be set - { key: 'value' } - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/department/test_department.js b/erpnext/hr/doctype/department/test_department.js deleted file mode 100644 index e73779c97c..0000000000 --- a/erpnext/hr/doctype/department/test_department.js +++ /dev/null @@ -1,23 +0,0 @@ -QUnit.module('hr'); - -QUnit.test("Test: Department [HR]", function (assert) { - assert.expect(1); - let done = assert.async(); - - frappe.run_serially([ - // test department creation - () => frappe.set_route("List", "Department", "List"), - () => frappe.new_doc("Department"), - () => frappe.timeout(1), - () => frappe.quick_entry.dialog.$wrapper.find('.edit-full').click(), - () => frappe.timeout(1), - () => cur_frm.set_value("department_name", "Test Department"), - () => cur_frm.set_value("leave_block_list", "Test Leave block list"), - // save form - () => cur_frm.save(), - () => frappe.timeout(1), - () => assert.equal("Test Department", cur_frm.doc.department_name, - 'name of department correctly saved'), - () => done() - ]); -}); diff --git a/erpnext/hr/doctype/designation/test_designation.js b/erpnext/hr/doctype/designation/test_designation.js deleted file mode 100644 index 00adf8293f..0000000000 --- a/erpnext/hr/doctype/designation/test_designation.js +++ /dev/null @@ -1,23 +0,0 @@ -QUnit.module('hr'); - -QUnit.test("Test: Designation [HR]", function (assert) { - assert.expect(1); - let done = assert.async(); - - frappe.run_serially([ - // test designation creation - () => frappe.set_route("List", "Designation", "List"), - () => frappe.new_doc("Designation"), - () => frappe.timeout(1), - () => frappe.quick_entry.dialog.$wrapper.find('.edit-full').click(), - () => frappe.timeout(1), - () => cur_frm.set_value("designation_name", "Test Designation"), - () => cur_frm.set_value("description", "This designation is just for testing."), - // save form - () => cur_frm.save(), - () => frappe.timeout(1), - () => assert.equal("Test Designation", cur_frm.doc.designation_name, - 'name of designation correctly saved'), - () => done() - ]); -}); diff --git a/erpnext/hr/doctype/driver/test_driver.js b/erpnext/hr/doctype/driver/test_driver.js deleted file mode 100644 index ff9f61e66a..0000000000 --- a/erpnext/hr/doctype/driver/test_driver.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Driver", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Driver - () => frappe.tests.make('Driver', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/employee_advance/test_employee_advance.js b/erpnext/hr/doctype/employee_advance/test_employee_advance.js deleted file mode 100644 index 1b9ec6f6d0..0000000000 --- a/erpnext/hr/doctype/employee_advance/test_employee_advance.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Employee Advance", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Employee Advance - () => frappe.tests.make('Employee Advance', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/employee_grade/test_employee_grade.js b/erpnext/hr/doctype/employee_grade/test_employee_grade.js deleted file mode 100644 index d684fb2ad1..0000000000 --- a/erpnext/hr/doctype/employee_grade/test_employee_grade.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Employee Grade", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Employee Grade - () => frappe.tests.make('Employee Grade', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/employee_health_insurance/test_employee_health_insurance.js b/erpnext/hr/doctype/employee_health_insurance/test_employee_health_insurance.js deleted file mode 100644 index 245cb32971..0000000000 --- a/erpnext/hr/doctype/employee_health_insurance/test_employee_health_insurance.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Employee Health Insurance", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Employee Health Insurance - () => frappe.tests.make('Employee Health Insurance', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.js b/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.js deleted file mode 100644 index d15cef77dc..0000000000 --- a/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Employee Onboarding", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Employee Onboarding - () => frappe.tests.make('Employee Onboarding', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/employee_onboarding_template/test_employee_onboarding_template.js b/erpnext/hr/doctype/employee_onboarding_template/test_employee_onboarding_template.js deleted file mode 100644 index 10912edb6a..0000000000 --- a/erpnext/hr/doctype/employee_onboarding_template/test_employee_onboarding_template.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Employee Onboarding Template", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Employee Onboarding Template - () => frappe.tests.make('Employee Onboarding Template', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/employee_promotion/test_employee_promotion.js b/erpnext/hr/doctype/employee_promotion/test_employee_promotion.js deleted file mode 100644 index 5f0a5baf81..0000000000 --- a/erpnext/hr/doctype/employee_promotion/test_employee_promotion.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Employee Promotion", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Employee Promotion - () => frappe.tests.make('Employee Promotion', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/employee_separation/test_employee_separation.js b/erpnext/hr/doctype/employee_separation/test_employee_separation.js deleted file mode 100644 index d6c635951f..0000000000 --- a/erpnext/hr/doctype/employee_separation/test_employee_separation.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Employee Separation", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Employee Separation - () => frappe.tests.make('Employee Separation', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/employee_separation_template/test_employee_separation_template.js b/erpnext/hr/doctype/employee_separation_template/test_employee_separation_template.js deleted file mode 100644 index 66fd450804..0000000000 --- a/erpnext/hr/doctype/employee_separation_template/test_employee_separation_template.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Employee Separation Template", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Employee Separation Template - () => frappe.tests.make('Employee Separation Template', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/employee_transfer/test_employee_transfer.js b/erpnext/hr/doctype/employee_transfer/test_employee_transfer.js deleted file mode 100644 index 05a3e1a573..0000000000 --- a/erpnext/hr/doctype/employee_transfer/test_employee_transfer.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Employee Transfer", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Employee Transfer - () => frappe.tests.make('Employee Transfer', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/employee_transfer_property/test_employee_transfer_property.js b/erpnext/hr/doctype/employee_transfer_property/test_employee_transfer_property.js deleted file mode 100644 index 00a334a63d..0000000000 --- a/erpnext/hr/doctype/employee_transfer_property/test_employee_transfer_property.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Employee Transfer Property", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Employee Transfer Property - () => frappe.tests.make('Employee Transfer Property', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/hr_settings/test_hr_settings.js b/erpnext/hr/doctype/hr_settings/test_hr_settings.js deleted file mode 100644 index f32640ba5c..0000000000 --- a/erpnext/hr/doctype/hr_settings/test_hr_settings.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: HR Settings", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new HR Settings - () => frappe.tests.make('HR Settings', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/identification_document_type/test_identification_document_type.js b/erpnext/hr/doctype/identification_document_type/test_identification_document_type.js deleted file mode 100644 index 65879098e8..0000000000 --- a/erpnext/hr/doctype/identification_document_type/test_identification_document_type.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Identification Document Type", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Identification Document Type - () => frappe.tests.make('Identification Document Type', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/job_applicant_source/test_job_applicant_source.js b/erpnext/hr/doctype/job_applicant_source/test_job_applicant_source.js deleted file mode 100644 index c093928f32..0000000000 --- a/erpnext/hr/doctype/job_applicant_source/test_job_applicant_source.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Job Applicant Source", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Job Applicant Source - () => frappe.tests.make('Job Applicant Source', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/leave_encashment/test_leave_encashment.js b/erpnext/hr/doctype/leave_encashment/test_leave_encashment.js deleted file mode 100644 index cafd9602cb..0000000000 --- a/erpnext/hr/doctype/leave_encashment/test_leave_encashment.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Leave Encashment", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Leave Encashment - () => frappe.tests.make('Leave Encashment', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/leave_period/test_leave_period.js b/erpnext/hr/doctype/leave_period/test_leave_period.js deleted file mode 100644 index ec0a809689..0000000000 --- a/erpnext/hr/doctype/leave_period/test_leave_period.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Leave Period", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Leave Period - () => frappe.tests.make('Leave Period', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/leave_policy/test_leave_policy.js b/erpnext/hr/doctype/leave_policy/test_leave_policy.js deleted file mode 100644 index 5404a63bed..0000000000 --- a/erpnext/hr/doctype/leave_policy/test_leave_policy.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Leave Policy", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Leave Policy - () => frappe.tests.make('Leave Policy', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/leave_policy_detail/test_leave_policy_detail.js b/erpnext/hr/doctype/leave_policy_detail/test_leave_policy_detail.js deleted file mode 100644 index 1c8995b796..0000000000 --- a/erpnext/hr/doctype/leave_policy_detail/test_leave_policy_detail.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Leave Policy Detail", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Leave Policy Detail - () => frappe.tests.make('Leave Policy Detail', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/purpose_of_travel/test_purpose_of_travel.js b/erpnext/hr/doctype/purpose_of_travel/test_purpose_of_travel.js deleted file mode 100644 index 936c21ccf0..0000000000 --- a/erpnext/hr/doctype/purpose_of_travel/test_purpose_of_travel.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Purpose of Travel", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Purpose of Travel - () => frappe.tests.make('Purpose of Travel', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/shift_assignment/test_shift_assignment.js b/erpnext/hr/doctype/shift_assignment/test_shift_assignment.js deleted file mode 100644 index 7727287742..0000000000 --- a/erpnext/hr/doctype/shift_assignment/test_shift_assignment.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Shift Assignment", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Shift Assignment - () => frappe.tests.make('Shift Assignment', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/shift_request/test_shift_request.js b/erpnext/hr/doctype/shift_request/test_shift_request.js deleted file mode 100644 index 9c8cd70020..0000000000 --- a/erpnext/hr/doctype/shift_request/test_shift_request.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Shift Request", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Shift Request - () => frappe.tests.make('Shift Request', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/shift_type/test_shift_type.js b/erpnext/hr/doctype/shift_type/test_shift_type.js deleted file mode 100644 index 846f9316f5..0000000000 --- a/erpnext/hr/doctype/shift_type/test_shift_type.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Shift Type", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Shift Type - () => frappe.tests.make('Shift Type', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/staffing_plan/test_staffing_plan.js b/erpnext/hr/doctype/staffing_plan/test_staffing_plan.js deleted file mode 100644 index 64320bcd92..0000000000 --- a/erpnext/hr/doctype/staffing_plan/test_staffing_plan.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Staffing Plan", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Staffing Plan - () => frappe.tests.make('Staffing Plan', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/training_program/test_training_program.js b/erpnext/hr/doctype/training_program/test_training_program.js deleted file mode 100644 index 3a62b2fa22..0000000000 --- a/erpnext/hr/doctype/training_program/test_training_program.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Training Program", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Training Program - () => frappe.tests.make('Training Program', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/training_result/test_training_result.js b/erpnext/hr/doctype/training_result/test_training_result.js deleted file mode 100644 index cb1d7fb27a..0000000000 --- a/erpnext/hr/doctype/training_result/test_training_result.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Training Result", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Training Result - () => frappe.tests.make('Training Result', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/travel_request/test_travel_request.js b/erpnext/hr/doctype/travel_request/test_travel_request.js deleted file mode 100644 index 7e64591823..0000000000 --- a/erpnext/hr/doctype/travel_request/test_travel_request.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Travel Request", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Travel Request - () => frappe.tests.make('Travel Request', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hr/doctype/vehicle/test_vehicle.js b/erpnext/hr/doctype/vehicle/test_vehicle.js deleted file mode 100644 index 4d40cce086..0000000000 --- a/erpnext/hr/doctype/vehicle/test_vehicle.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Vehicle", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Vehicle - () => frappe.tests.make('Vehicle', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/hub_node/doctype/marketplace_settings/test_marketplace_settings.js b/erpnext/hub_node/doctype/marketplace_settings/test_marketplace_settings.js deleted file mode 100644 index fba3e098d4..0000000000 --- a/erpnext/hub_node/doctype/marketplace_settings/test_marketplace_settings.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Marketplace Settings", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Marketplace Settings - () => frappe.tests.make('Marketplace Settings', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.js b/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.js deleted file mode 100644 index e0f05b1abb..0000000000 --- a/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Maintenance Schedule", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Maintenance Schedule - () => frappe.tests.make('Maintenance Schedule', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.js b/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.js deleted file mode 100644 index 51a0d94841..0000000000 --- a/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Blanket Order", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Blanket Order - () => frappe.tests.make('Blanket Order', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.js b/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.js deleted file mode 100644 index d220df2824..0000000000 --- a/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: BOM Update Tool", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially('BOM Update Tool', [ - // insert a new BOM Update Tool - () => frappe.tests.make([ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/manufacturing/doctype/job_card/test_job_card.js b/erpnext/manufacturing/doctype/job_card/test_job_card.js deleted file mode 100644 index 5dc7805d22..0000000000 --- a/erpnext/manufacturing/doctype/job_card/test_job_card.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Job Card", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Job Card - () => frappe.tests.make('Job Card', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/manufacturing/doctype/manufacturing_settings/test_manufacturing_settings.js b/erpnext/manufacturing/doctype/manufacturing_settings/test_manufacturing_settings.js deleted file mode 100644 index 2b2589eddd..0000000000 --- a/erpnext/manufacturing/doctype/manufacturing_settings/test_manufacturing_settings.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Manufacturing Settings", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially('Manufacturing Settings', [ - // insert a new Manufacturing Settings - () => frappe.tests.make([ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/manufacturing/doctype/material_request_plan_item/test_material_request_plan_item.js b/erpnext/manufacturing/doctype/material_request_plan_item/test_material_request_plan_item.js deleted file mode 100644 index 14c6e39384..0000000000 --- a/erpnext/manufacturing/doctype/material_request_plan_item/test_material_request_plan_item.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Material Request Plan Item", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Material Request Plan Item - () => frappe.tests.make('Material Request Plan Item', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.js b/erpnext/manufacturing/doctype/production_plan/test_production_plan.js deleted file mode 100644 index ef7d64c92d..0000000000 --- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Production Plan", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Production Plan - () => frappe.tests.make('Production Plan', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/manufacturing/doctype/routing/test_routing.js b/erpnext/manufacturing/doctype/routing/test_routing.js deleted file mode 100644 index 6cb65494af..0000000000 --- a/erpnext/manufacturing/doctype/routing/test_routing.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Routing", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Routing - () => frappe.tests.make('Routing', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/non_profit/doctype/certification_application/test_certification_application.js b/erpnext/non_profit/doctype/certification_application/test_certification_application.js deleted file mode 100644 index 40e94864d4..0000000000 --- a/erpnext/non_profit/doctype/certification_application/test_certification_application.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Certification Application", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Certification Application - () => frappe.tests.make('Certification Application', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/non_profit/doctype/certified_consultant/test_certified_consultant.js b/erpnext/non_profit/doctype/certified_consultant/test_certified_consultant.js deleted file mode 100644 index f6a72a4327..0000000000 --- a/erpnext/non_profit/doctype/certified_consultant/test_certified_consultant.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Certified Consultant", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Certified Consultant - () => frappe.tests.make('Certified Consultant', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/non_profit/doctype/chapter/test_chapter.js b/erpnext/non_profit/doctype/chapter/test_chapter.js deleted file mode 100644 index e30d6a5bf9..0000000000 --- a/erpnext/non_profit/doctype/chapter/test_chapter.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Chapter", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Chapter - () => frappe.tests.make('Chapter', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/non_profit/doctype/donor_type/test_donor_type.js b/erpnext/non_profit/doctype/donor_type/test_donor_type.js deleted file mode 100644 index 22dc18ed76..0000000000 --- a/erpnext/non_profit/doctype/donor_type/test_donor_type.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Donor Type", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Member - () => frappe.tests.make('Donor Type', [ - // values to be set - {donor_type: 'Test Organization'}, - ]), - () => { - assert.equal(cur_frm.doc.donor_type, 'Test Organization'); - }, - () => done() - ]); - -}); diff --git a/erpnext/non_profit/doctype/membership/test_membership.js b/erpnext/non_profit/doctype/membership/test_membership.js deleted file mode 100644 index 24c85c6157..0000000000 --- a/erpnext/non_profit/doctype/membership/test_membership.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Membership", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Membership - () => frappe.tests.make('Membership', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/payroll/doctype/additional_salary/test_additional_salary.js b/erpnext/payroll/doctype/additional_salary/test_additional_salary.js deleted file mode 100644 index c18e187585..0000000000 --- a/erpnext/payroll/doctype/additional_salary/test_additional_salary.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Additional Salary", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Additional Salary - () => frappe.tests.make('Additional Salary', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/payroll/doctype/employee_benefit_application/test_employee_benefit_application.js b/erpnext/payroll/doctype/employee_benefit_application/test_employee_benefit_application.js deleted file mode 100644 index b355e1c436..0000000000 --- a/erpnext/payroll/doctype/employee_benefit_application/test_employee_benefit_application.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Employee Benefit Application", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Employee Benefit Application - () => frappe.tests.make('Employee Benefit Application', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/payroll/doctype/employee_benefit_claim/test_employee_benefit_claim.js b/erpnext/payroll/doctype/employee_benefit_claim/test_employee_benefit_claim.js deleted file mode 100644 index 3c808c0a56..0000000000 --- a/erpnext/payroll/doctype/employee_benefit_claim/test_employee_benefit_claim.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Employee Benefit Claim", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Employee Benefit Claim - () => frappe.tests.make('Employee Benefit Claim', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/payroll/doctype/employee_incentive/test_employee_incentive.js b/erpnext/payroll/doctype/employee_incentive/test_employee_incentive.js deleted file mode 100644 index 10bc03701f..0000000000 --- a/erpnext/payroll/doctype/employee_incentive/test_employee_incentive.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Employee Incentive", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Employee Incentive - () => frappe.tests.make('Employee Incentive', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/payroll/doctype/employee_tax_exemption_category/test_employee_tax_exemption_category.js b/erpnext/payroll/doctype/employee_tax_exemption_category/test_employee_tax_exemption_category.js deleted file mode 100644 index e0e43c32e3..0000000000 --- a/erpnext/payroll/doctype/employee_tax_exemption_category/test_employee_tax_exemption_category.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Employee Tax Exemption Category", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Employee Tax Exemption Category - () => frappe.tests.make('Employee Tax Exemption Category', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/payroll/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.js b/erpnext/payroll/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.js deleted file mode 100644 index 274a3a3860..0000000000 --- a/erpnext/payroll/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Employee Tax Exemption Declaration", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Employee Tax Exemption Declaration - () => frappe.tests.make('Employee Tax Exemption Declaration', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/test_employee_tax_exemption_proof_submission.js b/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/test_employee_tax_exemption_proof_submission.js deleted file mode 100644 index cec7508728..0000000000 --- a/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/test_employee_tax_exemption_proof_submission.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Employee Tax Exemption Proof Submission", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Employee Tax Exemption Proof Submission - () => frappe.tests.make('Employee Tax Exemption Proof Submission', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/payroll/doctype/employee_tax_exemption_sub_category/test_employee_tax_exemption_sub_category.js b/erpnext/payroll/doctype/employee_tax_exemption_sub_category/test_employee_tax_exemption_sub_category.js deleted file mode 100644 index 8a1a6d151d..0000000000 --- a/erpnext/payroll/doctype/employee_tax_exemption_sub_category/test_employee_tax_exemption_sub_category.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Employee Tax Exemption Sub Category", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Employee Tax Exemption Sub Category - () => frappe.tests.make('Employee Tax Exemption Sub Category', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/payroll/doctype/payroll_period/test_payroll_period.js b/erpnext/payroll/doctype/payroll_period/test_payroll_period.js deleted file mode 100644 index 8c4ded96f3..0000000000 --- a/erpnext/payroll/doctype/payroll_period/test_payroll_period.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Payroll Period", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Payroll Period - () => frappe.tests.make('Payroll Period', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/payroll/doctype/retention_bonus/test_retention_bonus.js b/erpnext/payroll/doctype/retention_bonus/test_retention_bonus.js deleted file mode 100644 index a4b95d3cb1..0000000000 --- a/erpnext/payroll/doctype/retention_bonus/test_retention_bonus.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Retention Bonus", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Retention Bonus - () => frappe.tests.make('Retention Bonus', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/payroll/doctype/salary_component/test_salary_component.js b/erpnext/payroll/doctype/salary_component/test_salary_component.js deleted file mode 100644 index c47d32d996..0000000000 --- a/erpnext/payroll/doctype/salary_component/test_salary_component.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Salary Component", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Salary Component - () => frappe.tests.make('Salary Component', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/payroll/doctype/salary_structure_assignment/test_salary_structure_assignment.js b/erpnext/payroll/doctype/salary_structure_assignment/test_salary_structure_assignment.js deleted file mode 100644 index 2f52576c7a..0000000000 --- a/erpnext/payroll/doctype/salary_structure_assignment/test_salary_structure_assignment.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Salary Structure Assignment", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Salary Structure Assignment - () => frappe.tests.make('Salary Structure Assignment', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/portal/doctype/products_settings/test_products_settings.js b/erpnext/portal/doctype/products_settings/test_products_settings.js deleted file mode 100644 index b7049b37e1..0000000000 --- a/erpnext/portal/doctype/products_settings/test_products_settings.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Products Settings", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Products Settings - () => frappe.tests.make('Products Settings', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/projects/doctype/project/test_project.js b/erpnext/projects/doctype/project/test_project.js deleted file mode 100644 index 16494f62b6..0000000000 --- a/erpnext/projects/doctype/project/test_project.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Project", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Project - () => frappe.tests.make('Project', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/projects/doctype/project_type/test_project_type.js b/erpnext/projects/doctype/project_type/test_project_type.js deleted file mode 100644 index c2198c452c..0000000000 --- a/erpnext/projects/doctype/project_type/test_project_type.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Project Type", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially('Project Type', [ - // insert a new Project Type - () => frappe.tests.make([ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/projects/doctype/project_update/test_project_update.js b/erpnext/projects/doctype/project_update/test_project_update.js deleted file mode 100644 index bda510b921..0000000000 --- a/erpnext/projects/doctype/project_update/test_project_update.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Project Update", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Project Update - () => frappe.tests.make('Project Update', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/projects/doctype/projects_settings/test_projects_settings.js b/erpnext/projects/doctype/projects_settings/test_projects_settings.js deleted file mode 100644 index f6feaa4804..0000000000 --- a/erpnext/projects/doctype/projects_settings/test_projects_settings.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Projects Settings", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Projects Settings - () => frappe.tests.make('Projects Settings', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/projects/doctype/timesheet/test_timesheet.js b/erpnext/projects/doctype/timesheet/test_timesheet.js deleted file mode 100644 index c081d6f8ea..0000000000 --- a/erpnext/projects/doctype/timesheet/test_timesheet.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Timesheet", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Timesheet - () => frappe.tests.make('Timesheet', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/regional/doctype/gst_hsn_code/test_gst_hsn_code.js b/erpnext/regional/doctype/gst_hsn_code/test_gst_hsn_code.js deleted file mode 100644 index 24c5fd355f..0000000000 --- a/erpnext/regional/doctype/gst_hsn_code/test_gst_hsn_code.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: GST HSN Code", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new GST HSN Code - () => frappe.tests.make('GST HSN Code', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/regional/doctype/gst_settings/test_gst_settings.js b/erpnext/regional/doctype/gst_settings/test_gst_settings.js deleted file mode 100644 index 00fcca6f32..0000000000 --- a/erpnext/regional/doctype/gst_settings/test_gst_settings.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: GST Settings", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new GST Settings - () => frappe.tests.make('GST Settings', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/selling/doctype/customer/test_customer.js b/erpnext/selling/doctype/customer/test_customer.js deleted file mode 100644 index 65b81af32c..0000000000 --- a/erpnext/selling/doctype/customer/test_customer.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Customer", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Customer - () => frappe.tests.make('Customer', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.js b/erpnext/selling/doctype/sales_order/test_sales_order.js deleted file mode 100644 index 57ed19b696..0000000000 --- a/erpnext/selling/doctype/sales_order/test_sales_order.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Sales Order", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially('Sales Order', [ - // insert a new Sales Order - () => frappe.tests.make([ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/selling/doctype/sales_partner_type/test_sales_partner_type.js b/erpnext/selling/doctype/sales_partner_type/test_sales_partner_type.js deleted file mode 100644 index 3ed7b46e1d..0000000000 --- a/erpnext/selling/doctype/sales_partner_type/test_sales_partner_type.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Sales Partner Type", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Sales Partner Type - () => frappe.tests.make('Sales Partner Type', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/setup/doctype/currency_exchange/test_currency_exchange.js b/erpnext/setup/doctype/currency_exchange/test_currency_exchange.js deleted file mode 100644 index 19fde2e148..0000000000 --- a/erpnext/setup/doctype/currency_exchange/test_currency_exchange.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Currency Exchange", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Currency Exchange - () => frappe.tests.make('Currency Exchange', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/setup/doctype/global_defaults/test_global_defaults.js b/erpnext/setup/doctype/global_defaults/test_global_defaults.js deleted file mode 100644 index 33634eb0f8..0000000000 --- a/erpnext/setup/doctype/global_defaults/test_global_defaults.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Global Defaults", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Global Defaults - () => frappe.tests.make('Global Defaults', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/setup/doctype/item_group/test_item_group.js b/erpnext/setup/doctype/item_group/test_item_group.js deleted file mode 100644 index ea322e23d6..0000000000 --- a/erpnext/setup/doctype/item_group/test_item_group.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Item Group", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Item Group - () => frappe.tests.make('Item Group', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/setup/doctype/naming_series/test_naming_series.js b/erpnext/setup/doctype/naming_series/test_naming_series.js deleted file mode 100644 index 22b664b2e6..0000000000 --- a/erpnext/setup/doctype/naming_series/test_naming_series.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Naming Series", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Naming Series - () => frappe.tests.make('Naming Series', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/setup/doctype/party_type/test_party_type.js b/erpnext/setup/doctype/party_type/test_party_type.js deleted file mode 100644 index c97dbc58c8..0000000000 --- a/erpnext/setup/doctype/party_type/test_party_type.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Party Type", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Party Type - () => frappe.tests.make('Party Type', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/setup/doctype/supplier_group/test_supplier_group.js b/erpnext/setup/doctype/supplier_group/test_supplier_group.js deleted file mode 100644 index 976dd2cc4f..0000000000 --- a/erpnext/setup/doctype/supplier_group/test_supplier_group.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Supplier Group", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Supplier Group - () => frappe.tests.make('Supplier Group', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/setup/doctype/uom_conversion_factor/test_uom_conversion_factor.js b/erpnext/setup/doctype/uom_conversion_factor/test_uom_conversion_factor.js deleted file mode 100644 index afcf74ccb4..0000000000 --- a/erpnext/setup/doctype/uom_conversion_factor/test_uom_conversion_factor.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: UOM Conversion Factor", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new UOM Conversion Factor - () => frappe.tests.make('UOM Conversion Factor', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.js b/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.js deleted file mode 100644 index c8485e73fa..0000000000 --- a/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Shopping Cart Settings", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Shopping Cart Settings - () => frappe.tests.make('Shopping Cart Settings', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/stock/doctype/customs_tariff_number/test_customs_tariff_number.js b/erpnext/stock/doctype/customs_tariff_number/test_customs_tariff_number.js deleted file mode 100644 index 85812d6973..0000000000 --- a/erpnext/stock/doctype/customs_tariff_number/test_customs_tariff_number.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Customs Tariff Number", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Customs Tariff Number - () => frappe.tests.make('Customs Tariff Number', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/stock/doctype/delivery_settings/test_delivery_settings.js b/erpnext/stock/doctype/delivery_settings/test_delivery_settings.js deleted file mode 100644 index 22977c08f7..0000000000 --- a/erpnext/stock/doctype/delivery_settings/test_delivery_settings.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Delivery Settings", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Delivery Settings - () => frappe.tests.make('Delivery Settings', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/stock/doctype/delivery_trip/test_delivery_trip.js b/erpnext/stock/doctype/delivery_trip/test_delivery_trip.js deleted file mode 100644 index b6d6d1af64..0000000000 --- a/erpnext/stock/doctype/delivery_trip/test_delivery_trip.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Delivery Trip", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Delivery Trip - () => frappe.tests.make('Delivery Trip', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/stock/doctype/item/test_item.js b/erpnext/stock/doctype/item/test_item.js deleted file mode 100644 index af44278a59..0000000000 --- a/erpnext/stock/doctype/item/test_item.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Item", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Item - () => frappe.tests.make('Item', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/stock/doctype/item_alternative/test_item_alternative.js b/erpnext/stock/doctype/item_alternative/test_item_alternative.js deleted file mode 100644 index 87318499fe..0000000000 --- a/erpnext/stock/doctype/item_alternative/test_item_alternative.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Item Alternative", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Item Alternative - () => frappe.tests.make('Item Alternative', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/stock/doctype/item_variant_settings/test_item_variant_settings.js b/erpnext/stock/doctype/item_variant_settings/test_item_variant_settings.js deleted file mode 100644 index 3b3bf94f37..0000000000 --- a/erpnext/stock/doctype/item_variant_settings/test_item_variant_settings.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Item Variant Settings", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Item Variant Settings - () => frappe.tests.make('Item Variant Settings', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/stock/doctype/manufacturer/test_manufacturer.js b/erpnext/stock/doctype/manufacturer/test_manufacturer.js deleted file mode 100644 index 0254a367cc..0000000000 --- a/erpnext/stock/doctype/manufacturer/test_manufacturer.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Manufacturer", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially('Manufacturer', [ - // insert a new Manufacturer - () => frappe.tests.make([ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/stock/doctype/material_request/test_material_request.js b/erpnext/stock/doctype/material_request/test_material_request.js deleted file mode 100644 index 793cad0f3b..0000000000 --- a/erpnext/stock/doctype/material_request/test_material_request.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Material Request", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially('Material Request', [ - // insert a new Material Request - () => frappe.tests.make([ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/stock/doctype/price_list/test_price_list.js b/erpnext/stock/doctype/price_list/test_price_list.js deleted file mode 100644 index fe4e07b3bd..0000000000 --- a/erpnext/stock/doctype/price_list/test_price_list.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Price List", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Price List - () => frappe.tests.make('Price List', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/stock/doctype/quality_inspection/test_quality_inspection.js b/erpnext/stock/doctype/quality_inspection/test_quality_inspection.js deleted file mode 100644 index 327484e6cc..0000000000 --- a/erpnext/stock/doctype/quality_inspection/test_quality_inspection.js +++ /dev/null @@ -1,23 +0,0 @@ -/* 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/test_quality_inspection_template.js b/erpnext/stock/doctype/quality_inspection_template/test_quality_inspection_template.js deleted file mode 100644 index 879c262ed2..0000000000 --- a/erpnext/stock/doctype/quality_inspection_template/test_quality_inspection_template.js +++ /dev/null @@ -1,23 +0,0 @@ -/* 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/serial_no/test_serial_no.js b/erpnext/stock/doctype/serial_no/test_serial_no.js deleted file mode 100644 index bf8293257c..0000000000 --- a/erpnext/stock/doctype/serial_no/test_serial_no.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Serial No", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Serial No - () => frappe.tests.make('Serial No', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/stock/doctype/stock_settings/test_stock_settings.js b/erpnext/stock/doctype/stock_settings/test_stock_settings.js deleted file mode 100644 index 57d9fc61aa..0000000000 --- a/erpnext/stock/doctype/stock_settings/test_stock_settings.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Stock Settings", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Stock Settings - () => frappe.tests.make('Stock Settings', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/stock/doctype/uom_category/test_uom_category.js b/erpnext/stock/doctype/uom_category/test_uom_category.js deleted file mode 100644 index 4b5972ea71..0000000000 --- a/erpnext/stock/doctype/uom_category/test_uom_category.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: UOM Category", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new UOM Category - () => frappe.tests.make('UOM Category', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/stock/doctype/variant_field/test_variant_field.js b/erpnext/stock/doctype/variant_field/test_variant_field.js deleted file mode 100644 index 2600a10fe0..0000000000 --- a/erpnext/stock/doctype/variant_field/test_variant_field.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Variant Field", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Variant Field - () => frappe.tests.make('Variant Field', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/support/doctype/support_settings/test_support_settings.js b/erpnext/support/doctype/support_settings/test_support_settings.js deleted file mode 100644 index 0787306c3e..0000000000 --- a/erpnext/support/doctype/support_settings/test_support_settings.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Support Settings", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Support Settings - () => frappe.tests.make('Support Settings', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); From f91faac7cd6f2c885729681d947b7a8bb9e43f0e Mon Sep 17 00:00:00 2001 From: Lovin Maxwell Date: Thu, 26 Aug 2021 18:24:02 +0300 Subject: [PATCH 44/54] fix: Pricing Rule on Transaction Based on Coupon (#26949) --- erpnext/accounts/doctype/pricing_rule/utils.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py index 94abf3b3c0..5467cb0bc5 100644 --- a/erpnext/accounts/doctype/pricing_rule/utils.py +++ b/erpnext/accounts/doctype/pricing_rule/utils.py @@ -475,7 +475,20 @@ def apply_pricing_rule_on_transaction(doc): frappe.msgprint(_("User has not applied rule on the invoice {0}") .format(doc.name)) else: - doc.set(field, d.get(pr_field)) + if not d.coupon_code_based: + doc.set(field, d.get(pr_field)) + elif doc.get('coupon_code'): + # coupon code based pricing rule + coupon_code_pricing_rule = frappe.db.get_value('Coupon Code', doc.get('coupon_code'), 'pricing_rule') + if coupon_code_pricing_rule == d.name: + # if selected coupon code is linked with pricing rule + doc.set(field, d.get(pr_field)) + else: + # reset discount if not linked + doc.set(field, 0) + else: + # if coupon code based but no coupon code selected + doc.set(field, 0) doc.calculate_taxes_and_totals() elif d.price_or_product_discount == 'Product': From 422f67a4c9d5b7ce6de42c0ca6e68382d930dabb Mon Sep 17 00:00:00 2001 From: Noah Jacob Date: Thu, 26 Aug 2021 21:40:48 +0530 Subject: [PATCH 45/54] refactor: update manufacturing module onboarding (#26945) * refactor: updated manufacturing onboarding cards * refactor: added form tours * refactor: updated form tours and card descriptions * Fix: Case of description Co-authored-by: Nabin Hait --- erpnext/manufacturing/doctype/bom/bom.js | 25 +++++++- .../doctype/operation/operation.js | 18 ++++++ .../production_plan/production_plan.js | 33 ++++++++++ .../manufacturing/doctype/routing/routing.js | 14 +++++ .../doctype/work_order/work_order.js | 60 +++++++++++++++++++ .../doctype/workstation/workstation.js | 27 ++++++++- .../manufacturing/manufacturing.json | 14 ++--- .../create_bom/create_bom.json | 8 ++- .../create_product/create_product.json | 10 ++-- .../create_raw_materials.json | 2 +- .../explore_manufacturing_settings.json | 8 ++- .../onboarding_step/operation/operation.json | 10 ++-- .../production_planning.json | 21 +++++++ .../onboarding_step/routing/routing.json | 21 +++++++ .../work_order/work_order.json | 8 ++- .../workstation/workstation.json | 10 ++-- erpnext/stock/doctype/item/item.js | 45 ++++++++++++++ 17 files changed, 303 insertions(+), 31 deletions(-) create mode 100644 erpnext/manufacturing/onboarding_step/production_planning/production_planning.json create mode 100644 erpnext/manufacturing/onboarding_step/routing/routing.json diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js index 1481f1c54f..05123d5f85 100644 --- a/erpnext/manufacturing/doctype/bom/bom.js +++ b/erpnext/manufacturing/doctype/bom/bom.js @@ -661,6 +661,29 @@ frappe.ui.form.on("BOM", "with_operations", function(frm) { } }); +frappe.tour['BOM'] = [ + { + fieldname: "item", + title: "Item", + description: __("Select the Item to be manufactured. The Item name, UoM, Company, and Currency will be fetched automatically.") + }, + { + fieldname: "quantity", + title: "Quantity", + description: __("Enter the quantity of the Item that will be manufactured from this Bill of Materials.") + }, + { + fieldname: "with_operations", + title: "With Operations", + description: __("To add Operations tick the 'With Operations' checkbox.") + }, + { + fieldname: "items", + title: "Raw Materials", + description: __("Select the raw materials (Items) required to manufacture the Item") + } +]; + frappe.ui.form.on("BOM Scrap Item", { item_code(frm, cdt, cdn) { const { item_code } = locals[cdt][cdn]; @@ -691,4 +714,4 @@ function trigger_process_loss_qty_prompt(frm, cdt, cdn, item_code) { __("Set Process Loss Item Quantity"), __("Set Quantity") ); -} +} \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/operation/operation.js b/erpnext/manufacturing/doctype/operation/operation.js index 2936e33b11..95643bf49f 100644 --- a/erpnext/manufacturing/doctype/operation/operation.js +++ b/erpnext/manufacturing/doctype/operation/operation.js @@ -12,3 +12,21 @@ frappe.ui.form.on('Operation', { }); } }); + +frappe.tour['Operation'] = [ + { + fieldname: "__newname", + title: "Operation Name", + description: __("Enter a name for the Operation, for example, Cutting.") + }, + { + fieldname: "workstation", + title: "Default Workstation", + description: __("Select the Default Workstation where the Operation will be performed. This will be fetched in BOMs and Work Orders.") + }, + { + fieldname: "sub_operations", + title: "Sub Operations", + description: __("If an operation is divided into sub operations, they can be added here.") + } +]; \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.js b/erpnext/manufacturing/doctype/production_plan/production_plan.js index d198a6962a..847004fc47 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.js +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.js @@ -428,3 +428,36 @@ cur_frm.fields_dict['sales_orders'].grid.get_field("sales_order").get_query = fu ] } }; + +frappe.tour['Production Plan'] = [ + { + fieldname: "get_items_from", + title: "Get Items From", + description: __("Select whether to get items from a Sales Order or a Material Request. For now select Sales Order.\n A Production Plan can also be created manually where you can select the Items to manufacture.") + }, + { + fieldname: "get_sales_orders", + title: "Get Sales Orders", + description: __("Click on Get Sales Orders to fetch sales orders based on the above filters.") + }, + { + fieldname: "get_items", + title: "Get Finished Goods for Manufacture", + description: __("Click on 'Get Finished Goods for Manufacture' to fetch the items from the above Sales Orders. Items only for which a BOM is present will be fetched.") + }, + { + fieldname: "po_items", + title: "Finished Goods", + description: __("On expanding a row in the Items to Manufacture table, you'll see an option to 'Include Exploded Items'. Ticking this includes raw materials of the sub-assembly items in the production process.") + }, + { + fieldname: "include_non_stock_items", + title: "Include Non Stock Items", + description: __("To include non-stock items in the material request planning. i.e. Items for which 'Maintain Stock' checkbox is unticked.") + }, + { + fieldname: "include_subcontracted_items", + title: "Include Subcontracted Items", + description: __("To add subcontracted Item's raw materials if include exploded items is disabled.") + } +]; diff --git a/erpnext/manufacturing/doctype/routing/routing.js b/erpnext/manufacturing/doctype/routing/routing.js index 032c9cd9a2..c17a8e959d 100644 --- a/erpnext/manufacturing/doctype/routing/routing.js +++ b/erpnext/manufacturing/doctype/routing/routing.js @@ -69,3 +69,17 @@ frappe.ui.form.on('BOM Operation', { frm.events.calculate_operating_cost(frm, d); } }); + +frappe.tour['Routing'] = [ + { + fieldname: "routing_name", + title: "Routing Name", + description: __("Enter a name for Routing.") + }, + { + fieldname: "operations", + title: "BOM Operations", + description: __("Enter the Operation, the table will fetch the Operation details like Hourly Rate, Workstation automatically.\n\n After that, set the Operation Time in minutes and the table will calculate the Operation Costs based on the Hourly Rate and Operation Time.") + } +]; + diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js index 512048512e..51c46f63ab 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.js +++ b/erpnext/manufacturing/doctype/work_order/work_order.js @@ -731,3 +731,63 @@ erpnext.work_order = { }); } }; + +frappe.tour['Work Order'] = [ + { + fieldname: "production_item", + title: "Item to Manufacture", + description: __("Select the Item to be manufactured.") + }, + { + fieldname: "bom_no", + title: "BOM No", + description: __("The default BOM for that item will be fetched by the system. You can also change the BOM.") + }, + { + fieldname: "qty", + title: "Qty to Manufacture", + description: __("Enter the quantity to manufacture. Raw material Items will be fetched only when this is set.") + }, + { + fieldname: "use_multi_level_bom", + title: "Use Multi-Level BOM", + description: __("This is enabled by default. If you want to plan materials for sub-assemblies of the Item you're manufacturing leave this enabled. If you plan and manufacture the sub-assemblies separately, you can disable this checkbox.") + }, + { + fieldname: "source_warehouse", + title: "Source Warehouse", + description: __("The warehouse where you store your raw materials. Each required item can have a separate source warehouse. Group warehouse also can be selected as source warehouse. On submission of the Work Order, the raw materials will be reserved in these warehouses for production usage.") + }, + { + fieldname: "fg_warehouse", + title: "Target Warehouse", + description: __("The warehouse where you store finished Items before they are shipped.") + }, + { + fieldname: "wip_warehouse", + title: "Work-in-Progress Warehouse", + description: __("The warehouse where your Items will be transferred when you begin production. Group Warehouse can also be selected as a Work in Progress warehouse.") + }, + { + fieldname: "scrap_warehouse", + title: "Scrap Warehouse", + description: __("If the BOM results in Scrap material, the Scrap Warehouse needs to be selected.") + }, + { + fieldname: "required_items", + title: "Required Items", + description: __("All the required items (raw materials) will be fetched from BOM and populated in this table. Here you can also change the Source Warehouse for any item. And during the production, you can track transferred raw materials from this table.") + }, + { + fieldname: "planned_start_date", + title: "Planned Start Date", + description: __("Set the Planned Start Date (an Estimated Date at which you want the Production to begin)") + }, + { + fieldname: "operations", + title: "Operations", + description: __("If the selected BOM has Operations mentioned in it, the system will fetch all Operations from BOM, these values can be changed.") + }, + + +]; diff --git a/erpnext/manufacturing/doctype/workstation/workstation.js b/erpnext/manufacturing/doctype/workstation/workstation.js index d8d25fc6f8..4f5231e449 100644 --- a/erpnext/manufacturing/doctype/workstation/workstation.js +++ b/erpnext/manufacturing/doctype/workstation/workstation.js @@ -16,4 +16,29 @@ frappe.ui.form.on("Workstation", { }) } } -}) +}); + +frappe.tour['Workstation'] = [ + { + fieldname: "workstation_name", + title: "Workstation Name", + description: __("You can set it as a machine name or operation type. For example, stiching machine 12") + }, + { + fieldname: "production_capacity", + title: "Production Capacity", + description: __("No. of parallel job cards which can be allowed on this workstation. Example: 2 would mean this workstation can process production for two Work Orders at a time.") + }, + { + fieldname: "holiday_list", + title: "Holiday List", + description: __("A Holiday List can be added to exclude counting these days for the Workstation.") + }, + { + fieldname: "working_hours", + title: "Working Hours", + description: __("Under Working Hours table, you can add start and end times for a Workstation. For example, a Workstation may be active from 9 am to 1 pm, then 2 pm to 5 pm. You can also specify the working hours based on shifts. While scheduling a Work Order, the system will check for the availability of the Workstation based on the working hours specified.") + }, + + +]; \ No newline at end of file diff --git a/erpnext/manufacturing/module_onboarding/manufacturing/manufacturing.json b/erpnext/manufacturing/module_onboarding/manufacturing/manufacturing.json index 7317152565..032091f67e 100644 --- a/erpnext/manufacturing/module_onboarding/manufacturing/manufacturing.json +++ b/erpnext/manufacturing/module_onboarding/manufacturing/manufacturing.json @@ -19,14 +19,14 @@ "documentation_url": "https://docs.erpnext.com/docs/user/manual/en/manufacturing", "idx": 0, "is_complete": 0, - "modified": "2020-06-29 20:25:36.899106", + "modified": "2021-08-13 16:04:34.333812", "modified_by": "Administrator", "module": "Manufacturing", "name": "Manufacturing", "owner": "Administrator", "steps": [ { - "step": "Warehouse" + "step": "Explore Manufacturing Settings" }, { "step": "Workstation" @@ -35,22 +35,22 @@ "step": "Operation" }, { - "step": "Create Product" + "step": "Routing" }, { - "step": "Create Raw Materials" + "step": "Create Product" }, { "step": "Create BOM" }, { - "step": "Work Order" + "step": "Production Planning" }, { - "step": "Explore Manufacturing Settings" + "step": "Work Order" } ], "subtitle": "Products, Raw Materials, BOM, Work Order, and more.", "success_message": "Manufacturing module is all set up!", "title": "Let's Set Up the Manufacturing Module." -} +} \ No newline at end of file diff --git a/erpnext/manufacturing/onboarding_step/create_bom/create_bom.json b/erpnext/manufacturing/onboarding_step/create_bom/create_bom.json index 84b4088f23..9d7a58c121 100644 --- a/erpnext/manufacturing/onboarding_step/create_bom/create_bom.json +++ b/erpnext/manufacturing/onboarding_step/create_bom/create_bom.json @@ -1,19 +1,21 @@ { "action": "Create Entry", + "action_label": "Create your first Bill of Materials", "creation": "2020-05-05 16:41:20.239696", + "description": "# Create a Bill of Materials\n\nA Bill of Materials (BOM) is a list of items and sub-assemblies with quantities required to manufacture an Item.\n\nBOM also provides cost estimation for the production of the item. It takes raw-materials cost based on valuation and operations to cost based on routing, which gives total costing for a BOM.", "docstatus": 0, "doctype": "Onboarding Step", "idx": 0, "is_complete": 0, - "is_mandatory": 1, "is_single": 0, "is_skipped": 0, - "modified": "2020-05-19 12:51:31.315686", + "modified": "2021-08-13 16:00:51.092671", "modified_by": "Administrator", "name": "Create BOM", "owner": "Administrator", "reference_document": "BOM", + "show_form_tour": 1, "show_full_form": 1, - "title": "Create a BOM (Bill of Material)", + "title": "Bill of Materials", "validate_action": 1 } \ No newline at end of file diff --git a/erpnext/manufacturing/onboarding_step/create_product/create_product.json b/erpnext/manufacturing/onboarding_step/create_product/create_product.json index 0ffa30158b..ad7345234d 100644 --- a/erpnext/manufacturing/onboarding_step/create_product/create_product.json +++ b/erpnext/manufacturing/onboarding_step/create_product/create_product.json @@ -1,19 +1,21 @@ { "action": "Create Entry", + "action_label": "Create an Item", "creation": "2020-05-05 16:42:31.476275", + "description": "# Create Items for Bill of Materials\n\nOne of the prerequisites of a BOM is the creation of raw materials, sub-assembly, and finished items. Once these items are created, you will be able to proceed to the Bill of Materials master, which is composed of items and routing.\n", "docstatus": 0, "doctype": "Onboarding Step", "idx": 0, "is_complete": 0, - "is_mandatory": 1, "is_single": 0, "is_skipped": 0, - "modified": "2020-05-19 12:50:59.010439", + "modified": "2021-08-13 16:00:22.407811", "modified_by": "Administrator", "name": "Create Product", "owner": "Administrator", "reference_document": "Item", - "show_full_form": 0, - "title": "Create a Finished Good", + "show_form_tour": 1, + "show_full_form": 1, + "title": "Finished Items", "validate_action": 1 } \ No newline at end of file diff --git a/erpnext/manufacturing/onboarding_step/create_raw_materials/create_raw_materials.json b/erpnext/manufacturing/onboarding_step/create_raw_materials/create_raw_materials.json index 0764f2e44a..3f94764f08 100644 --- a/erpnext/manufacturing/onboarding_step/create_raw_materials/create_raw_materials.json +++ b/erpnext/manufacturing/onboarding_step/create_raw_materials/create_raw_materials.json @@ -5,7 +5,6 @@ "doctype": "Onboarding Step", "idx": 0, "is_complete": 0, - "is_mandatory": 0, "is_single": 0, "is_skipped": 0, "modified": "2020-05-19 11:53:25.147837", @@ -13,6 +12,7 @@ "name": "Create Raw Materials", "owner": "Administrator", "reference_document": "Item", + "show_form_tour": 0, "show_full_form": 0, "title": "Create Raw Materials", "validate_action": 1 diff --git a/erpnext/manufacturing/onboarding_step/explore_manufacturing_settings/explore_manufacturing_settings.json b/erpnext/manufacturing/onboarding_step/explore_manufacturing_settings/explore_manufacturing_settings.json index 7ef202ee4e..1d2c27e379 100644 --- a/erpnext/manufacturing/onboarding_step/explore_manufacturing_settings/explore_manufacturing_settings.json +++ b/erpnext/manufacturing/onboarding_step/explore_manufacturing_settings/explore_manufacturing_settings.json @@ -1,20 +1,22 @@ { "action": "Show Form Tour", + "action_label": "Take a walk-through of Manufacturing Settings", "creation": "2020-05-19 11:55:11.378374", + "description": "# Review Manufacturing Settings\n\nIn ERPNext, the Manufacturing module\u2019s features are configurable as per your business needs. Manufacturing Settings is the place where you can set your preferences for:\n\n- Capacity planning for allocating jobs to workstations\n- Raw-material consumption based on BOM or actual\n- Default values and over-production allowance\n", "docstatus": 0, "doctype": "Onboarding Step", "idx": 0, "is_complete": 0, - "is_mandatory": 0, "is_single": 1, "is_skipped": 0, - "modified": "2020-05-26 20:28:03.558199", + "modified": "2021-08-13 15:59:32.145655", "modified_by": "Administrator", "name": "Explore Manufacturing Settings", "owner": "Administrator", "reference_document": "Manufacturing Settings", + "show_form_tour": 0, "show_full_form": 0, - "title": "Explore Manufacturing Settings", + "title": "Manufacturing Settings", "validate_action": 0, "video_url": "https://www.youtube.com/watch?v=UVGfzwOOZC4" } \ No newline at end of file diff --git a/erpnext/manufacturing/onboarding_step/operation/operation.json b/erpnext/manufacturing/onboarding_step/operation/operation.json index b532e6778c..2e9592185e 100644 --- a/erpnext/manufacturing/onboarding_step/operation/operation.json +++ b/erpnext/manufacturing/onboarding_step/operation/operation.json @@ -1,19 +1,21 @@ { "action": "Create Entry", + "action_label": "Let\u2019s create an Operation", "creation": "2020-05-12 16:15:31.706756", + "description": "# Create Operations\n\nAn Operation refers to any manufacturing operation performed on the raw materials to process it further in the manufacturing path. As an example, if you are into garments manufacturing, you will create Operations like fabric cutting, stitching, and washing as some of the operations.", "docstatus": 0, "doctype": "Onboarding Step", "idx": 0, "is_complete": 0, - "is_mandatory": 0, "is_single": 0, "is_skipped": 0, - "modified": "2020-05-19 12:50:41.642754", + "modified": "2021-08-13 15:59:53.313532", "modified_by": "Administrator", "name": "Operation", "owner": "Administrator", "reference_document": "Operation", - "show_full_form": 0, - "title": "Create a Operation", + "show_form_tour": 1, + "show_full_form": 1, + "title": "Operation", "validate_action": 1 } \ No newline at end of file diff --git a/erpnext/manufacturing/onboarding_step/production_planning/production_planning.json b/erpnext/manufacturing/onboarding_step/production_planning/production_planning.json new file mode 100644 index 0000000000..ff9fdb9fd0 --- /dev/null +++ b/erpnext/manufacturing/onboarding_step/production_planning/production_planning.json @@ -0,0 +1,21 @@ +{ + "action": "Create Entry", + "action_label": "Learn more about Production Planning", + "creation": "2021-08-04 17:33:06.551077", + "description": "# How Production Planning Works\n\nProduction Plan helps in production and material planning for the Items planned for manufacturing. These production items can be committed via Sales Order (to Customers) or Material Requests (internally).\n", + "docstatus": 0, + "doctype": "Onboarding Step", + "idx": 0, + "is_complete": 0, + "is_single": 0, + "is_skipped": 0, + "modified": "2021-08-13 16:04:15.491414", + "modified_by": "Administrator", + "name": "Production Planning", + "owner": "Administrator", + "reference_document": "Production Plan", + "show_form_tour": 0, + "show_full_form": 1, + "title": "Production Planning", + "validate_action": 1 +} \ No newline at end of file diff --git a/erpnext/manufacturing/onboarding_step/routing/routing.json b/erpnext/manufacturing/onboarding_step/routing/routing.json new file mode 100644 index 0000000000..be4fbff171 --- /dev/null +++ b/erpnext/manufacturing/onboarding_step/routing/routing.json @@ -0,0 +1,21 @@ +{ + "action": "Create Entry", + "action_label": "Check help to setup Routing", + "creation": "2021-08-04 11:56:42.455758", + "description": "# Setup Routing\n\nA Routing stores all Operations along with the description, hourly rate, operation time, batch size, etc. Click below to learn how the Routing template can be created, for quick selection in the BOM.", + "docstatus": 0, + "doctype": "Onboarding Step", + "idx": 0, + "is_complete": 0, + "is_single": 0, + "is_skipped": 0, + "modified": "2021-08-13 16:00:07.391563", + "modified_by": "Administrator", + "name": "Routing", + "owner": "Administrator", + "reference_document": "Routing", + "show_form_tour": 1, + "show_full_form": 1, + "title": "Routing", + "validate_action": 1 +} \ No newline at end of file diff --git a/erpnext/manufacturing/onboarding_step/work_order/work_order.json b/erpnext/manufacturing/onboarding_step/work_order/work_order.json index c63363e7cb..d2756c9275 100644 --- a/erpnext/manufacturing/onboarding_step/work_order/work_order.json +++ b/erpnext/manufacturing/onboarding_step/work_order/work_order.json @@ -1,19 +1,21 @@ { "action": "Create Entry", + "action_label": "Create your first Work Order", "creation": "2020-05-12 16:15:56.084682", + "description": "# Create a Work Order\n\nA Work Order or a Job order is given to the manufacturing shop floor by the Production Manager to initiate the manufacturing of a certain quantity of an item. Work Order carriers details of production Item, its BOM, quantities to be manufactured, and operations.\n\nThrough Work Order, you can track various production status like:\n\n- Issue of raw-material to shop material\n- Progress on each Workstation via Job Card\n- Manufactured Quantity against Work Order\n", "docstatus": 0, "doctype": "Onboarding Step", "idx": 0, "is_complete": 0, - "is_mandatory": 0, "is_single": 0, "is_skipped": 0, - "modified": "2020-05-19 12:51:38.133150", + "modified": "2021-08-13 16:02:04.223536", "modified_by": "Administrator", "name": "Work Order", "owner": "Administrator", "reference_document": "Work Order", + "show_form_tour": 1, "show_full_form": 1, - "title": "Create a Work Order", + "title": "Work Order", "validate_action": 1 } \ No newline at end of file diff --git a/erpnext/manufacturing/onboarding_step/workstation/workstation.json b/erpnext/manufacturing/onboarding_step/workstation/workstation.json index df244bb494..67dd52eba2 100644 --- a/erpnext/manufacturing/onboarding_step/workstation/workstation.json +++ b/erpnext/manufacturing/onboarding_step/workstation/workstation.json @@ -1,19 +1,21 @@ { "action": "Create Entry", + "action_label": "Let\u2019s create a Workstation", "creation": "2020-05-12 16:14:14.930214", + "description": "# Create Workstations\n\nA Workstation stores information regarding the place where the workstation operations are performed. As an example, if you have ten sewing machines doing stitching jobs, each machine will be added as a workstation.", "docstatus": 0, "doctype": "Onboarding Step", "idx": 0, "is_complete": 0, - "is_mandatory": 0, "is_single": 0, "is_skipped": 0, - "modified": "2020-05-19 12:50:33.938176", + "modified": "2021-08-13 15:59:59.634802", "modified_by": "Administrator", "name": "Workstation", "owner": "Administrator", "reference_document": "Workstation", - "show_full_form": 0, - "title": "Create a Workstation / Machine", + "show_form_tour": 1, + "show_full_form": 1, + "title": "Workstation", "validate_action": 1 } \ No newline at end of file diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js index 3de35e6062..752a1fe732 100644 --- a/erpnext/stock/doctype/item/item.js +++ b/erpnext/stock/doctype/item/item.js @@ -792,3 +792,48 @@ frappe.ui.form.on("UOM Conversion Detail", { } } }); + +frappe.tour['Item'] = [ + { + fieldname: "item_code", + title: "Item Code", + description: __("Enter an Item Code, the name will be auto-filled the same as Item Code on clicking inside the Item Name field.") + }, + { + fieldname: "item_group", + title: "Item Group", + description: __("Select an Item Group.") + }, + { + fieldname: "is_stock_item", + title: "Maintain Stock", + description: __("If you are maintaining stock of this Item in your Inventory, ERPNext will make a stock ledger entry for each transaction of this item.") + }, + { + fieldname: "include_item_in_manufacturing", + title: "Include Item in Manufacturing", + description: __("This is for raw material Items that'll be used to create finished goods. If the Item is an additional service like 'washing' that'll be used in the BOM, keep this unchecked.") + }, + { + fieldname: "opening_stock", + title: "Opening Stock", + description: __("Enter the opening stock units.") + }, + { + fieldname: "valuation_rate", + title: "Valuation Rate", + description: __("There are two options to maintain valuation of stock. FIFO (first in - first out) and Moving Average. To understand this topic in detail please visit Item Valuation, FIFO and Moving Average.") + }, + { + fieldname: "standard_rate", + title: "Standard Selling Rate", + description: __("When creating an Item, entering a value for this field will automatically create an Item Price at the backend.") + }, + { + fieldname: "item_defaults", + title: "Item Defaults", + description: __("In this section, you can define Company-wide transaction-related defaults for this Item. Eg. Default Warehouse, Default Price List, Supplier, etc.") + } + + +]; From 16eed07a0fb34b8d0ad042ed18d79a1123cc6076 Mon Sep 17 00:00:00 2001 From: Rohan Date: Thu, 26 Aug 2021 21:47:00 +0530 Subject: [PATCH 46/54] fix: use Stripe's Price API for plan-price information (#26107) * fix: use Stripe's new Plan API for price information * patch: use inbuilt function to rename field * fix: patch call Co-authored-by: Ankush Menat Co-authored-by: Nabin Hait --- .../subscription_plan/subscription_plan.json | 14 +++--- .../stripe_integration.py | 46 +++++++++++-------- erpnext/patches.txt | 1 + erpnext/patches/v13_0/migrate_stripe_api.py | 7 +++ 4 files changed, 42 insertions(+), 26 deletions(-) create mode 100644 erpnext/patches/v13_0/migrate_stripe_api.py diff --git a/erpnext/accounts/doctype/subscription_plan/subscription_plan.json b/erpnext/accounts/doctype/subscription_plan/subscription_plan.json index 771611a786..878ae09889 100644 --- a/erpnext/accounts/doctype/subscription_plan/subscription_plan.json +++ b/erpnext/accounts/doctype/subscription_plan/subscription_plan.json @@ -21,7 +21,7 @@ "column_break_13", "billing_interval_count", "payment_plan_section", - "payment_plan_id", + "product_price_id", "column_break_16", "payment_gateway", "accounting_dimensions_section", @@ -114,11 +114,6 @@ "fieldtype": "Section Break", "label": "Payment Plan" }, - { - "fieldname": "payment_plan_id", - "fieldtype": "Data", - "label": "Payment Plan" - }, { "fieldname": "column_break_16", "fieldtype": "Column Break" @@ -144,10 +139,15 @@ "fieldtype": "Link", "label": "Cost Center", "options": "Cost Center" + }, + { + "fieldname": "product_price_id", + "fieldtype": "Data", + "label": "Product Price ID" } ], "links": [], - "modified": "2021-08-09 10:53:44.205774", + "modified": "2021-08-13 10:53:44.205774", "modified_by": "Administrator", "module": "Accounts", "name": "Subscription Plan", diff --git a/erpnext/erpnext_integrations/stripe_integration.py b/erpnext/erpnext_integrations/stripe_integration.py index 108b4c0dd8..820c740532 100644 --- a/erpnext/erpnext_integrations/stripe_integration.py +++ b/erpnext/erpnext_integrations/stripe_integration.py @@ -2,11 +2,12 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -from __future__ import unicode_literals +import stripe + import frappe from frappe import _ from frappe.integrations.utils import create_request_log -import stripe + def create_stripe_subscription(gateway_controller, data): stripe_settings = frappe.get_doc("Stripe Settings", gateway_controller) @@ -23,31 +24,38 @@ def create_stripe_subscription(gateway_controller, data): except Exception: frappe.log_error(frappe.get_traceback()) return{ - "redirect_to": frappe.redirect_to_message(_('Server Error'), _("It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.")), + "redirect_to": frappe.redirect_to_message( + _('Server Error'), + _("It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.") + ), "status": 401 } def create_subscription_on_stripe(stripe_settings): - items = [] - for payment_plan in stripe_settings.payment_plans: - plan = frappe.db.get_value("Subscription Plan", payment_plan.plan, "payment_plan_id") - items.append({"plan": plan, "quantity": payment_plan.qty}) + items = [] + for payment_plan in stripe_settings.payment_plans: + plan = frappe.db.get_value("Subscription Plan", payment_plan.plan, "product_price_id") + items.append({"price": plan, "quantity": payment_plan.qty}) - try: - customer = stripe.Customer.create(description=stripe_settings.data.payer_name, email=stripe_settings.data.payer_email, source=stripe_settings.data.stripe_token_id) - subscription = stripe.Subscription.create(customer=customer, items=items) + try: + customer = stripe.Customer.create( + source=stripe_settings.data.stripe_token_id, + description=stripe_settings.data.payer_name, + email=stripe_settings.data.payer_email + ) - if subscription.status == "active": - stripe_settings.integration_request.db_set('status', 'Completed', update_modified=False) - stripe_settings.flags.status_changed_to = "Completed" + subscription = stripe.Subscription.create(customer=customer, items=items) - else: - stripe_settings.integration_request.db_set('status', 'Failed', update_modified=False) - frappe.log_error('Subscription N°: ' + subscription.id, 'Stripe Payment not completed') + if subscription.status == "active": + stripe_settings.integration_request.db_set('status', 'Completed', update_modified=False) + stripe_settings.flags.status_changed_to = "Completed" - except Exception: + else: stripe_settings.integration_request.db_set('status', 'Failed', update_modified=False) - frappe.log_error(frappe.get_traceback()) + frappe.log_error('Subscription N°: ' + subscription.id, 'Stripe Payment not completed') + except Exception: + stripe_settings.integration_request.db_set('status', 'Failed', update_modified=False) + frappe.log_error(frappe.get_traceback()) - return stripe_settings.finalize_request() + return stripe_settings.finalize_request() diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 0a6a8bdbdc..311e785f8c 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -295,6 +295,7 @@ erpnext.patches.v13_0.update_tds_check_field #3 erpnext.patches.v13_0.add_custom_field_for_south_africa #2 erpnext.patches.v13_0.update_recipient_email_digest erpnext.patches.v13_0.shopify_deprecation_warning +erpnext.patches.v13_0.migrate_stripe_api erpnext.patches.v13_0.reset_clearance_date_for_intracompany_payment_entries erpnext.patches.v13_0.einvoicing_deprecation_warning erpnext.patches.v14_0.delete_einvoicing_doctypes diff --git a/erpnext/patches/v13_0/migrate_stripe_api.py b/erpnext/patches/v13_0/migrate_stripe_api.py new file mode 100644 index 0000000000..355421a1f4 --- /dev/null +++ b/erpnext/patches/v13_0/migrate_stripe_api.py @@ -0,0 +1,7 @@ +import frappe +from frappe.model.utils.rename_field import rename_field + + +def execute(): + frappe.reload_doc("accounts", "doctype", "subscription_plan") + rename_field("Subscription Plan", "payment_plan_id", "product_price_id") From f1b77360ee3b5cc418f074aefa83a1871964da99 Mon Sep 17 00:00:00 2001 From: Chillar Anand Date: Thu, 26 Aug 2021 22:15:30 +0530 Subject: [PATCH 47/54] feat(healthcare): Added Treatment Plan Template feature (#26557) * feat: Added doctypes for treatment plan template * feat: Added child doctype * feat: Added validations for patient age * chore: Clean up treatment plan template * fix: Limit plan items to templates * Added multiselectdialogbox for treatment plan template * Add template name as autoname * Clean up code * Cleanup lint issues * Clean up code * Added tests for tpt filters * Added test records * Fix order of fields * Added tests for care plan template * Added age property for patient * Clean up code * Clean up list view * Clean up code * Fix lint issues * Clean up test records * Code cleanup no-docs * chore: Code cleanup * chore: Use ORM instead of raw sql * fix: Make treatment plan item fields mandatory * fix: Added healthcare roles in permissions rules * fix: Added filters for symptoms, diagnosis * fix: Show applicable treatment plans button only if patient is present * fix: Fix key error issues * fix: Fix issues with filters in plan templates * chore: Fix age filters * refactor: appending treatment plan items * fix: treatment plan test Co-authored-by: Jannat Patel <31363128+pateljannat@users.noreply.github.com> Co-authored-by: Rucha Mahabal --- .../drug_prescription/drug_prescription.json | 3 +- erpnext/healthcare/doctype/patient/patient.py | 17 +- .../patient_encounter/patient_encounter.js | 37 +++- .../patient_encounter/patient_encounter.json | 11 +- .../patient_encounter/patient_encounter.py | 80 ++++++++ .../test_patient_encounter.py | 79 +++++++- .../treatment_plan_template/__init__.py | 0 .../treatment_plan_template/test_records.json | 7 + .../test_treatment_plan_template.py | 8 + .../treatment_plan_template.js | 14 ++ .../treatment_plan_template.json | 189 ++++++++++++++++++ .../treatment_plan_template.py | 19 ++ .../treatment_plan_template_list.js | 10 + .../treatment_plan_template_item/__init__.py | 0 .../treatment_plan_template_item.json | 55 +++++ .../treatment_plan_template_item.py | 8 + .../__init__.py | 0 .../treatment_plan_template_practitioner.json | 32 +++ .../treatment_plan_template_practitioner.py | 8 + 19 files changed, 567 insertions(+), 10 deletions(-) create mode 100644 erpnext/healthcare/doctype/treatment_plan_template/__init__.py create mode 100644 erpnext/healthcare/doctype/treatment_plan_template/test_records.json create mode 100644 erpnext/healthcare/doctype/treatment_plan_template/test_treatment_plan_template.py create mode 100644 erpnext/healthcare/doctype/treatment_plan_template/treatment_plan_template.js create mode 100644 erpnext/healthcare/doctype/treatment_plan_template/treatment_plan_template.json create mode 100644 erpnext/healthcare/doctype/treatment_plan_template/treatment_plan_template.py create mode 100644 erpnext/healthcare/doctype/treatment_plan_template/treatment_plan_template_list.js create mode 100644 erpnext/healthcare/doctype/treatment_plan_template_item/__init__.py create mode 100644 erpnext/healthcare/doctype/treatment_plan_template_item/treatment_plan_template_item.json create mode 100644 erpnext/healthcare/doctype/treatment_plan_template_item/treatment_plan_template_item.py create mode 100644 erpnext/healthcare/doctype/treatment_plan_template_practitioner/__init__.py create mode 100644 erpnext/healthcare/doctype/treatment_plan_template_practitioner/treatment_plan_template_practitioner.json create mode 100644 erpnext/healthcare/doctype/treatment_plan_template_practitioner/treatment_plan_template_practitioner.py diff --git a/erpnext/healthcare/doctype/drug_prescription/drug_prescription.json b/erpnext/healthcare/doctype/drug_prescription/drug_prescription.json index d91e6bf9dc..a65c56694e 100644 --- a/erpnext/healthcare/doctype/drug_prescription/drug_prescription.json +++ b/erpnext/healthcare/doctype/drug_prescription/drug_prescription.json @@ -56,6 +56,7 @@ "reqd": 1 }, { + "allow_in_quick_entry": 1, "fieldname": "dosage_form", "fieldtype": "Link", "ignore_user_permissions": 1, @@ -109,7 +110,7 @@ ], "istable": 1, "links": [], - "modified": "2020-09-30 23:32:09.495288", + "modified": "2021-06-11 11:53:06.343704", "modified_by": "Administrator", "module": "Healthcare", "name": "Drug Prescription", diff --git a/erpnext/healthcare/doctype/patient/patient.py b/erpnext/healthcare/doctype/patient/patient.py index 56a34007ff..f77ad70633 100644 --- a/erpnext/healthcare/doctype/patient/patient.py +++ b/erpnext/healthcare/doctype/patient/patient.py @@ -102,12 +102,19 @@ class Patient(Document): return name + @property + def age(self): + if not self.dob: + return + dob = getdate(self.dob) + age = dateutil.relativedelta.relativedelta(getdate(), dob) + return age + def get_age(self): - age_str = '' - if self.dob: - dob = getdate(self.dob) - age = dateutil.relativedelta.relativedelta(getdate(), dob) - age_str = str(age.years) + ' ' + _("Years(s)") + ' ' + str(age.months) + ' ' + _("Month(s)") + ' ' + str(age.days) + ' ' + _("Day(s)") + age = self.age + if not age: + return + age_str = str(age.years) + ' ' + _("Years(s)") + ' ' + str(age.months) + ' ' + _("Month(s)") + ' ' + str(age.days) + ' ' + _("Day(s)") return age_str @frappe.whitelist() diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js index aaeaa692e6..c3466260d2 100644 --- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js +++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js @@ -185,7 +185,42 @@ frappe.ui.form.on('Patient Encounter', { }; frm.set_value(values); } - } + }, + + get_applicable_treatment_plans: function(frm) { + frappe.call({ + method: 'get_applicable_treatment_plans', + doc: frm.doc, + args: {'encounter': frm.doc}, + freeze: true, + freeze_message: __('Fetching Treatment Plans'), + callback: function() { + new frappe.ui.form.MultiSelectDialog({ + doctype: "Treatment Plan Template", + target: this.cur_frm, + setters: { + medical_department: "", + }, + action(selections) { + frappe.call({ + method: 'set_treatment_plans', + doc: frm.doc, + args: selections, + }).then(() => { + frm.refresh_field('drug_prescription'); + frm.refresh_field('procedure_prescription'); + frm.refresh_field('lab_test_prescription'); + frm.refresh_field('therapies'); + }); + cur_dialog.hide(); + } + }); + + + } + }); + }, + }); var schedule_inpatient = function(frm) { diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json index b646ff9ebe..994597dca7 100644 --- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json +++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.json @@ -31,6 +31,7 @@ "sb_symptoms", "symptoms", "symptoms_in_print", + "get_applicable_treatment_plans", "physical_examination", "diagnosis", "diagnosis_in_print", @@ -324,11 +325,17 @@ "no_copy": 1, "print_hide": 1, "read_only": 1 + }, + { + "depends_on": "eval:doc.patient", + "fieldname": "get_applicable_treatment_plans", + "fieldtype": "Button", + "label": "Get Applicable Treatment Plans" } ], "is_submittable": 1, "links": [], - "modified": "2020-11-30 10:39:00.783119", + "modified": "2021-07-27 11:39:12.347704", "modified_by": "Administrator", "module": "Healthcare", "name": "Patient Encounter", @@ -358,4 +365,4 @@ "title_field": "title", "track_changes": 1, "track_seen": 1 -} \ No newline at end of file +} diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py index 2b3029efde..7a745ae468 100644 --- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py +++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py @@ -10,6 +10,7 @@ from frappe.utils import cstr, getdate, add_days from frappe import _ from frappe.model.mapper import get_mapped_doc + class PatientEncounter(Document): def validate(self): self.set_title() @@ -33,6 +34,85 @@ class PatientEncounter(Document): self.title = _('{0} with {1}').format(self.patient_name or self.patient, self.practitioner_name or self.practitioner)[:100] + @frappe.whitelist() + @staticmethod + def get_applicable_treatment_plans(encounter): + patient = frappe.get_doc('Patient', encounter['patient']) + + plan_filters = {} + plan_filters['name'] = ['in', []] + + age = patient.age + if age: + plan_filters['patient_age_from'] = ['<=', age.years] + plan_filters['patient_age_to'] = ['>=', age.years] + + gender = patient.sex + if gender: + plan_filters['gender'] = ['in', [gender, None]] + + diagnosis = encounter.get('diagnosis') + if diagnosis: + diagnosis = [_diagnosis['diagnosis'] for _diagnosis in encounter['diagnosis']] + filters = [ + ['diagnosis', 'in', diagnosis], + ['parenttype', '=', 'Treatment Plan Template'], + ] + diagnosis = frappe.get_list('Patient Encounter Diagnosis', filters=filters, fields='*') + plan_names = [_diagnosis['parent'] for _diagnosis in diagnosis] + plan_filters['name'][1].extend(plan_names) + + symptoms = encounter.get('symptoms') + if symptoms: + symptoms = [symptom['complaint'] for symptom in encounter['symptoms']] + filters = [ + ['complaint', 'in', symptoms], + ['parenttype', '=', 'Treatment Plan Template'], + ] + symptoms = frappe.get_list('Patient Encounter Symptom', filters=filters, fields='*') + plan_names = [symptom['parent'] for symptom in symptoms] + plan_filters['name'][1].extend(plan_names) + + if not plan_filters['name'][1]: + plan_filters.pop('name') + + plans = frappe.get_list('Treatment Plan Template', fields='*', filters=plan_filters) + + return plans + + @frappe.whitelist() + def set_treatment_plans(self, treatment_plans=None): + for treatment_plan in treatment_plans: + self.set_treatment_plan(treatment_plan) + + def set_treatment_plan(self, plan): + plan_items = frappe.get_list('Treatment Plan Template Item', filters={'parent': plan}, fields='*') + for plan_item in plan_items: + self.set_treatment_plan_item(plan_item) + + drugs = frappe.get_list('Drug Prescription', filters={'parent': plan}, fields='*') + for drug in drugs: + self.append('drug_prescription', drug) + + self.save() + + def set_treatment_plan_item(self, plan_item): + if plan_item.type == 'Clinical Procedure Template': + self.append('procedure_prescription', { + 'procedure': plan_item.template + }) + + if plan_item.type == 'Lab Test Template': + self.append('lab_test_prescription', { + 'lab_test_code': plan_item.template + }) + + if plan_item.type == 'Therapy Type': + self.append('therapies', { + 'therapy_type': plan_item.template + }) + + @frappe.whitelist() def make_ip_medication_order(source_name, target_doc=None): def set_missing_values(source, target): diff --git a/erpnext/healthcare/doctype/patient_encounter/test_patient_encounter.py b/erpnext/healthcare/doctype/patient_encounter/test_patient_encounter.py index f5df152050..96976821a7 100644 --- a/erpnext/healthcare/doctype/patient_encounter/test_patient_encounter.py +++ b/erpnext/healthcare/doctype/patient_encounter/test_patient_encounter.py @@ -4,5 +4,82 @@ from __future__ import unicode_literals import unittest +import frappe +from erpnext.healthcare.doctype.patient_encounter.patient_encounter import PatientEncounter + + class TestPatientEncounter(unittest.TestCase): - pass + def setUp(self): + try: + gender_m = frappe.get_doc({ + 'doctype': 'Gender', + 'gender': 'MALE' + }).insert() + gender_f = frappe.get_doc({ + 'doctype': 'Gender', + 'gender': 'FEMALE' + }).insert() + except frappe.exceptions.DuplicateEntryError: + gender_m = frappe.get_doc({ + 'doctype': 'Gender', + 'gender': 'MALE' + }) + gender_f = frappe.get_doc({ + 'doctype': 'Gender', + 'gender': 'FEMALE' + }) + + self.patient_male = frappe.get_doc({ + 'doctype': 'Patient', + 'first_name': 'John', + 'sex': gender_m.gender, + }).insert() + self.patient_female = frappe.get_doc({ + 'doctype': 'Patient', + 'first_name': 'Curie', + 'sex': gender_f.gender, + }).insert() + self.practitioner = frappe.get_doc({ + 'doctype': 'Healthcare Practitioner', + 'first_name': 'Doc', + 'sex': 'MALE', + }).insert() + try: + self.care_plan_male = frappe.get_doc({ + 'doctype': 'Treatment Plan Template', + 'template_name': 'test plan - m', + 'gender': gender_m.gender, + }).insert() + self.care_plan_female = frappe.get_doc({ + 'doctype': 'Treatment Plan Template', + 'template_name': 'test plan - f', + 'gender': gender_f.gender, + }).insert() + except frappe.exceptions.DuplicateEntryError: + self.care_plan_male = frappe.get_doc({ + 'doctype': 'Treatment Plan Template', + 'template_name': 'test plan - m', + 'gender': gender_m.gender, + }) + self.care_plan_female = frappe.get_doc({ + 'doctype': 'Treatment Plan Template', + 'template_name': 'test plan - f', + 'gender': gender_f.gender, + }) + + def test_treatment_plan_template_filter(self): + encounter = frappe.get_doc({ + 'doctype': 'Patient Encounter', + 'patient': self.patient_male.name, + 'practitioner': self.practitioner.name, + }).insert() + plans = PatientEncounter.get_applicable_treatment_plans(encounter.as_dict()) + self.assertEqual(plans[0]['name'], self.care_plan_male.template_name) + + encounter = frappe.get_doc({ + 'doctype': 'Patient Encounter', + 'patient': self.patient_female.name, + 'practitioner': self.practitioner.name, + }).insert() + plans = PatientEncounter.get_applicable_treatment_plans(encounter.as_dict()) + self.assertEqual(plans[0]['name'], self.care_plan_female.template_name) diff --git a/erpnext/healthcare/doctype/treatment_plan_template/__init__.py b/erpnext/healthcare/doctype/treatment_plan_template/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/healthcare/doctype/treatment_plan_template/test_records.json b/erpnext/healthcare/doctype/treatment_plan_template/test_records.json new file mode 100644 index 0000000000..d661b4304f --- /dev/null +++ b/erpnext/healthcare/doctype/treatment_plan_template/test_records.json @@ -0,0 +1,7 @@ +[ + { + "doctype": "Treatment Plan Template", + "template_name": "Chemo", + "patient_age_from": 21 + } +] diff --git a/erpnext/healthcare/doctype/treatment_plan_template/test_treatment_plan_template.py b/erpnext/healthcare/doctype/treatment_plan_template/test_treatment_plan_template.py new file mode 100644 index 0000000000..21ede7129f --- /dev/null +++ b/erpnext/healthcare/doctype/treatment_plan_template/test_treatment_plan_template.py @@ -0,0 +1,8 @@ +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt + +# import frappe +import unittest + +class TestTreatmentPlanTemplate(unittest.TestCase): + pass diff --git a/erpnext/healthcare/doctype/treatment_plan_template/treatment_plan_template.js b/erpnext/healthcare/doctype/treatment_plan_template/treatment_plan_template.js new file mode 100644 index 0000000000..986c3cb6e4 --- /dev/null +++ b/erpnext/healthcare/doctype/treatment_plan_template/treatment_plan_template.js @@ -0,0 +1,14 @@ +// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Treatment Plan Template', { + refresh: function (frm) { + frm.set_query('type', 'items', function () { + return { + filters: { + 'name': ['in', ['Lab Test Template', 'Clinical Procedure Template', 'Therapy Type']], + } + }; + }); + }, +}); diff --git a/erpnext/healthcare/doctype/treatment_plan_template/treatment_plan_template.json b/erpnext/healthcare/doctype/treatment_plan_template/treatment_plan_template.json new file mode 100644 index 0000000000..85a312fb17 --- /dev/null +++ b/erpnext/healthcare/doctype/treatment_plan_template/treatment_plan_template.json @@ -0,0 +1,189 @@ +{ + "actions": [], + "autoname": "field:template_name", + "creation": "2021-06-10 10:14:17.901273", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "section_break_1", + "template_name", + "description", + "practitioners", + "disabled", + "column_break_1", + "medical_department", + "goal", + "order_group", + "section_break_8", + "patient_age_from", + "complaints", + "gender", + "column_break_12", + "patient_age_to", + "diagnosis", + "plan_items_section", + "items", + "drugs" + ], + "fields": [ + { + "fieldname": "section_break_1", + "fieldtype": "Section Break", + "label": "Plan Details" + }, + { + "fieldname": "medical_department", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Medical Department", + "options": "Medical Department" + }, + { + "fieldname": "description", + "fieldtype": "Small Text", + "label": "Description" + }, + { + "fieldname": "goal", + "fieldtype": "Small Text", + "label": "Goal" + }, + { + "fieldname": "practitioners", + "fieldtype": "Table MultiSelect", + "label": "Practitioners", + "options": "Treatment Plan Template Practitioner" + }, + { + "fieldname": "order_group", + "fieldtype": "Link", + "label": "Order Group", + "options": "Patient Encounter", + "read_only": 1 + }, + { + "fieldname": "section_break_8", + "fieldtype": "Section Break", + "label": "Plan Conditions" + }, + { + "fieldname": "template_name", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Template Name", + "reqd": 1, + "unique": 1 + }, + { + "fieldname": "patient_age_from", + "fieldtype": "Int", + "label": "Patient Age From", + "non_negative": 1 + }, + { + "fieldname": "column_break_12", + "fieldtype": "Column Break" + }, + { + "fieldname": "patient_age_to", + "fieldtype": "Int", + "label": "Patient Age To", + "non_negative": 1 + }, + { + "fieldname": "gender", + "fieldtype": "Link", + "label": "Gender", + "options": "Gender" + }, + { + "fieldname": "complaints", + "fieldtype": "Table MultiSelect", + "label": "Complaints", + "options": "Patient Encounter Symptom" + }, + { + "fieldname": "diagnosis", + "fieldtype": "Table MultiSelect", + "label": "Diagnosis", + "options": "Patient Encounter Diagnosis" + }, + { + "fieldname": "plan_items_section", + "fieldtype": "Section Break", + "label": "Plan Items" + }, + { + "fieldname": "items", + "fieldtype": "Table", + "label": "Items", + "options": "Treatment Plan Template Item" + }, + { + "fieldname": "drugs", + "fieldtype": "Table", + "label": "Drugs", + "options": "Drug Prescription" + }, + { + "default": "0", + "fieldname": "disabled", + "fieldtype": "Check", + "label": "Disabled" + }, + { + "fieldname": "column_break_1", + "fieldtype": "Column Break" + } + ], + "index_web_pages_for_search": 1, + "links": [], + "modified": "2021-08-18 02:41:58.354296", + "modified_by": "Administrator", + "module": "Healthcare", + "name": "Treatment Plan Template", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Physician", + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Healthcare Administrator", + "share": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "title_field": "template_name", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/healthcare/doctype/treatment_plan_template/treatment_plan_template.py b/erpnext/healthcare/doctype/treatment_plan_template/treatment_plan_template.py new file mode 100644 index 0000000000..a92e2668fe --- /dev/null +++ b/erpnext/healthcare/doctype/treatment_plan_template/treatment_plan_template.py @@ -0,0 +1,19 @@ +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +import frappe +from frappe import _ +from frappe.model.document import Document + +class TreatmentPlanTemplate(Document): + def validate(self): + self.validate_age() + + def validate_age(self): + if self.patient_age_from and self.patient_age_from < 0: + frappe.throw(_('Patient Age From cannot be less than 0')) + if self.patient_age_to and self.patient_age_to < 0: + frappe.throw(_('Patient Age To cannot be less than 0')) + if self.patient_age_to and self.patient_age_from and \ + self.patient_age_to < self.patient_age_from: + frappe.throw(_('Patient Age To cannot be less than Patient Age From')) diff --git a/erpnext/healthcare/doctype/treatment_plan_template/treatment_plan_template_list.js b/erpnext/healthcare/doctype/treatment_plan_template/treatment_plan_template_list.js new file mode 100644 index 0000000000..7ab31dff79 --- /dev/null +++ b/erpnext/healthcare/doctype/treatment_plan_template/treatment_plan_template_list.js @@ -0,0 +1,10 @@ +frappe.listview_settings['Treatment Plan Template'] = { + get_indicator: function(doc) { + var colors = { + 1: 'gray', + 0: 'blue', + }; + let label = doc.disabled == 1 ? 'Disabled' : 'Enabled'; + return [__(label), colors[doc.disabled], 'disable,=,' + doc.disabled]; + } +}; diff --git a/erpnext/healthcare/doctype/treatment_plan_template_item/__init__.py b/erpnext/healthcare/doctype/treatment_plan_template_item/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/healthcare/doctype/treatment_plan_template_item/treatment_plan_template_item.json b/erpnext/healthcare/doctype/treatment_plan_template_item/treatment_plan_template_item.json new file mode 100644 index 0000000000..20a9d6793a --- /dev/null +++ b/erpnext/healthcare/doctype/treatment_plan_template_item/treatment_plan_template_item.json @@ -0,0 +1,55 @@ +{ + "actions": [], + "creation": "2021-06-10 11:47:29.194795", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "type", + "template", + "qty", + "instructions" + ], + "fields": [ + { + "fieldname": "type", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Type", + "options": "DocType", + "reqd": 1 + }, + { + "fieldname": "template", + "fieldtype": "Dynamic Link", + "in_list_view": 1, + "label": "Template", + "options": "type", + "reqd": 1 + }, + { + "default": "1", + "fieldname": "qty", + "fieldtype": "Int", + "label": "Qty" + }, + { + "fieldname": "instructions", + "fieldtype": "Small Text", + "in_list_view": 1, + "label": "Instructions" + } + ], + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2021-08-17 11:19:03.515441", + "modified_by": "Administrator", + "module": "Healthcare", + "name": "Treatment Plan Template Item", + "owner": "Administrator", + "permissions": [], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/healthcare/doctype/treatment_plan_template_item/treatment_plan_template_item.py b/erpnext/healthcare/doctype/treatment_plan_template_item/treatment_plan_template_item.py new file mode 100644 index 0000000000..5f58b06af6 --- /dev/null +++ b/erpnext/healthcare/doctype/treatment_plan_template_item/treatment_plan_template_item.py @@ -0,0 +1,8 @@ +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + +class TreatmentPlanTemplateItem(Document): + pass diff --git a/erpnext/healthcare/doctype/treatment_plan_template_practitioner/__init__.py b/erpnext/healthcare/doctype/treatment_plan_template_practitioner/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/healthcare/doctype/treatment_plan_template_practitioner/treatment_plan_template_practitioner.json b/erpnext/healthcare/doctype/treatment_plan_template_practitioner/treatment_plan_template_practitioner.json new file mode 100644 index 0000000000..04da387f7b --- /dev/null +++ b/erpnext/healthcare/doctype/treatment_plan_template_practitioner/treatment_plan_template_practitioner.json @@ -0,0 +1,32 @@ +{ + "actions": [], + "creation": "2021-06-10 10:37:56.669416", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "practitioner" + ], + "fields": [ + { + "fieldname": "practitioner", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Practitioner", + "options": "Healthcare Practitioner", + "reqd": 1 + } + ], + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2021-06-11 16:05:06.733299", + "modified_by": "Administrator", + "module": "Healthcare", + "name": "Treatment Plan Template Practitioner", + "owner": "Administrator", + "permissions": [], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/healthcare/doctype/treatment_plan_template_practitioner/treatment_plan_template_practitioner.py b/erpnext/healthcare/doctype/treatment_plan_template_practitioner/treatment_plan_template_practitioner.py new file mode 100644 index 0000000000..6d34568e15 --- /dev/null +++ b/erpnext/healthcare/doctype/treatment_plan_template_practitioner/treatment_plan_template_practitioner.py @@ -0,0 +1,8 @@ +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + +class TreatmentPlanTemplatePractitioner(Document): + pass From db69d1dc002dceac9029895d5037452a573c8cb6 Mon Sep 17 00:00:00 2001 From: Pawan Mehta Date: Thu, 26 Aug 2021 22:54:24 +0530 Subject: [PATCH 48/54] fix: fetch from more than one sales order in Maintenance Visit (#26924) * [fix] #26336 * fix(ux): make customer field reqd for fetching SO Co-authored-by: Ankush Menat --- .../doctype/maintenance_visit/maintenance_visit.js | 12 ++++++++++-- erpnext/selling/doctype/sales_order/sales_order.py | 6 ++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js index 53ecdf5a61..6b3f18484a 100644 --- a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js +++ b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js @@ -73,12 +73,16 @@ erpnext.maintenance.MaintenanceVisit = class MaintenanceVisit extends frappe.ui. if (this.frm.doc.docstatus === 0) { this.frm.add_custom_button(__('Maintenance Schedule'), function () { + if (!me.frm.doc.customer) { + frappe.msgprint(__('Please select Customer first')); + return; + } erpnext.utils.map_current_doc({ method: "erpnext.maintenance.doctype.maintenance_schedule.maintenance_schedule.make_maintenance_visit", source_doctype: "Maintenance Schedule", target: me.frm, setters: { - customer: me.frm.doc.customer || undefined, + customer: me.frm.doc.customer, }, get_query_filters: { docstatus: 1, @@ -104,12 +108,16 @@ erpnext.maintenance.MaintenanceVisit = class MaintenanceVisit extends frappe.ui. }, __("Get Items From")); this.frm.add_custom_button(__('Sales Order'), function () { + if (!me.frm.doc.customer) { + frappe.msgprint(__('Please select Customer first')); + return; + } erpnext.utils.map_current_doc({ method: "erpnext.selling.doctype.sales_order.sales_order.make_maintenance_visit", source_doctype: "Sales Order", target: me.frm, setters: { - customer: me.frm.doc.customer || undefined, + customer: me.frm.doc.customer, }, get_query_filters: { docstatus: 1, diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index bba54018ae..5d44582aab 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -718,8 +718,7 @@ def make_maintenance_schedule(source_name, target_doc=None): "doctype": "Maintenance Schedule Item", "field_map": { "parent": "sales_order" - }, - "add_if_empty": True + } } }, target_doc) @@ -745,8 +744,7 @@ def make_maintenance_visit(source_name, target_doc=None): "field_map": { "parent": "prevdoc_docname", "parenttype": "prevdoc_doctype" - }, - "add_if_empty": True + } } }, target_doc) From a1737c9a0c892aaaa2f22b863aa0dc2566b4a35b Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Thu, 26 Aug 2021 23:04:54 +0530 Subject: [PATCH 49/54] fix: Production Plan: load document defaults for plan items & remove name column from listview (#26584) (#27184) (cherry picked from commit 69d88a921273c9e0ea29d7131232686a0be7bb78) Co-authored-by: Richard Case <64409021+casesolved-co-uk@users.noreply.github.com> --- .../manufacturing/doctype/production_plan/production_plan.py | 2 +- .../doctype/production_plan/production_plan_list.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index b4c663507c..6b61c6d330 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -213,7 +213,6 @@ class ProductionPlan(Document): }) pi = self.append('po_items', { - 'include_exploded_items': 1, 'warehouse': data.warehouse, 'item_code': data.item_code, 'description': data.description or item_details.description, @@ -224,6 +223,7 @@ class ProductionPlan(Document): 'planned_start_date': now_datetime(), 'product_bundle_item': data.parent_item }) + pi._set_defaults() if self.get_items_from == "Sales Order": pi.sales_order = data.parent diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan_list.js b/erpnext/manufacturing/doctype/production_plan/production_plan_list.js index c2e3e6d712..8f94686624 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan_list.js +++ b/erpnext/manufacturing/doctype/production_plan/production_plan_list.js @@ -1,4 +1,5 @@ frappe.listview_settings['Production Plan'] = { + hide_name_column: true, add_fields: ["status"], filters: [["status", "!=", "Closed"]], get_indicator: function (doc) { From ae7ec8e44d3059a31e9e0b9a60821ac0e8adb74f Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Thu, 26 Aug 2021 23:51:09 +0530 Subject: [PATCH 50/54] fix: Base amount in tax gl entry --- erpnext/accounts/doctype/payment_entry/payment_entry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 5a183e2e51..b259b11c63 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -787,7 +787,7 @@ class PaymentEntry(AccountsController): "account": payment_or_advance_account, "against": against, rev_dr_or_cr: tax_amount, - rev_dr_or_cr + "_in_account_currency": -1 * base_tax_amount + rev_dr_or_cr + "_in_account_currency": base_tax_amount if account_currency==self.company_currency else d.tax_amount, "cost_center": self.cost_center, From e6799d78efb031538dd69bb27f9f41494f81cf90 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Fri, 27 Aug 2021 10:46:45 +0530 Subject: [PATCH 51/54] fix: operation time auto set to zero (#27188) --- erpnext/manufacturing/doctype/bom/bom.py | 12 ++++++++---- erpnext/patches.txt | 1 + .../set_operation_time_based_on_operating_cost.py | 15 +++++++++++++++ 3 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 erpnext/patches/v13_0/set_operation_time_based_on_operating_cost.py diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 1d7d451cc8..6e1c7dd81b 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -517,17 +517,21 @@ class BOM(WebsiteGenerator): def update_rate_and_time(self, row, update_hour_rate = False): if not row.hour_rate or update_hour_rate: hour_rate = flt(frappe.get_cached_value("Workstation", row.workstation, "hour_rate")) - row.hour_rate = (hour_rate / flt(self.conversion_rate) - if self.conversion_rate and hour_rate else hour_rate) + + if hour_rate: + row.hour_rate = (hour_rate / flt(self.conversion_rate) + if self.conversion_rate and hour_rate else hour_rate) if self.routing: - row.time_in_mins = flt(frappe.db.get_value("BOM Operation", { + time_in_mins = flt(frappe.db.get_value("BOM Operation", { "workstation": row.workstation, "operation": row.operation, - "sequence_id": row.sequence_id, "parent": self.routing }, ["time_in_mins"])) + if time_in_mins: + row.time_in_mins = time_in_mins + if row.hour_rate and row.time_in_mins: row.base_hour_rate = flt(row.hour_rate) * flt(self.conversion_rate) row.operating_cost = flt(row.hour_rate) * flt(row.time_in_mins) / 60.0 diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 311e785f8c..0f6a606cb1 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -299,3 +299,4 @@ erpnext.patches.v13_0.migrate_stripe_api erpnext.patches.v13_0.reset_clearance_date_for_intracompany_payment_entries erpnext.patches.v13_0.einvoicing_deprecation_warning erpnext.patches.v14_0.delete_einvoicing_doctypes +erpnext.patches.v13_0.set_operation_time_based_on_operating_cost \ No newline at end of file diff --git a/erpnext/patches/v13_0/set_operation_time_based_on_operating_cost.py b/erpnext/patches/v13_0/set_operation_time_based_on_operating_cost.py new file mode 100644 index 0000000000..4acbdd63a0 --- /dev/null +++ b/erpnext/patches/v13_0/set_operation_time_based_on_operating_cost.py @@ -0,0 +1,15 @@ +import frappe + +def execute(): + frappe.reload_doc('manufacturing', 'doctype', 'bom') + frappe.reload_doc('manufacturing', 'doctype', 'bom_operation') + + frappe.db.sql(''' + UPDATE + `tabBOM Operation` + SET + time_in_mins = (operating_cost * 60) / hour_rate + WHERE + time_in_mins = 0 AND operating_cost > 0 + AND hour_rate > 0 AND docstatus = 1 AND parenttype = "BOM" + ''') \ No newline at end of file From 71b7c63ec052d5ca182e2eba33ca8693fe517256 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Fri, 27 Aug 2021 11:12:24 +0530 Subject: [PATCH 52/54] feat: Ability to schedule onboarding and separation activities (#26738) * refactor: employee onboarding form clean-up * feat: ability to schedule onboarding / separation tasks * feat: skip holidays while setting boarding activity dates * chore: remove unused child table - Employee Onboarding Activity * fix: tests * fix: employee separation test --- .../employee_boarding_controller.py | 45 ++- .../employee_boarding_activity.json | 29 +- .../employee_onboarding.json | 50 ++- .../test_employee_onboarding.py | 8 +- .../employee_onboarding_activity/__init__.py | 0 .../employee_onboarding_activity.json | 290 ------------------ .../employee_onboarding_activity.py | 10 - .../employee_separation.json | 9 +- .../test_employee_separation.py | 4 +- .../doctype/salary_slip/test_salary_slip.py | 6 +- 10 files changed, 129 insertions(+), 322 deletions(-) delete mode 100644 erpnext/hr/doctype/employee_onboarding_activity/__init__.py delete mode 100644 erpnext/hr/doctype/employee_onboarding_activity/employee_onboarding_activity.json delete mode 100644 erpnext/hr/doctype/employee_onboarding_activity/employee_onboarding_activity.py diff --git a/erpnext/controllers/employee_boarding_controller.py b/erpnext/controllers/employee_boarding_controller.py index 1898222916..f43c80416f 100644 --- a/erpnext/controllers/employee_boarding_controller.py +++ b/erpnext/controllers/employee_boarding_controller.py @@ -5,7 +5,9 @@ import frappe from frappe import _ from frappe.desk.form import assign_to from frappe.model.document import Document -from frappe.utils import flt, unique +from frappe.utils import flt, unique, add_days +from erpnext.hr.doctype.holiday_list.holiday_list import is_holiday +from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee class EmployeeBoardingController(Document): ''' @@ -41,10 +43,14 @@ class EmployeeBoardingController(Document): def create_task_and_notify_user(self): # create the task for the given project and assign to the concerned person + holiday_list = self.get_holiday_list() + for activity in self.activities: if activity.task: continue + dates = self.get_task_dates(activity, holiday_list) + task = frappe.get_doc({ 'doctype': 'Task', 'project': self.project, @@ -52,7 +58,9 @@ class EmployeeBoardingController(Document): 'description': activity.description, 'department': self.department, 'company': self.company, - 'task_weight': activity.task_weight + 'task_weight': activity.task_weight, + 'exp_start_date': dates[0], + 'exp_end_date': dates[1] }).insert(ignore_permissions=True) activity.db_set('task', task.name) @@ -79,6 +87,36 @@ class EmployeeBoardingController(Document): if users: self.assign_task_to_users(task, users) + def get_holiday_list(self): + if self.doctype == 'Employee Separation': + return get_holiday_list_for_employee(self.employee) + else: + if self.employee: + return get_holiday_list_for_employee(self.employee) + else: + if not self.holiday_list: + frappe.throw(_('Please set the Holiday List.'), frappe.MandatoryError) + else: + return self.holiday_list + + def get_task_dates(self, activity, holiday_list): + start_date = end_date = None + + if activity.begin_on: + start_date = add_days(self.boarding_begins_on, activity.begin_on) + start_date = self.update_if_holiday(start_date, holiday_list) + + if activity.duration: + end_date = add_days(self.boarding_begins_on, activity.begin_on + activity.duration) + end_date = self.update_if_holiday(end_date, holiday_list) + + return [start_date, end_date] + + def update_if_holiday(self, date, holiday_list): + while is_holiday(holiday_list, date): + date = add_days(date, 1) + return date + def assign_task_to_users(self, task, users): for user in users: args = { @@ -103,7 +141,8 @@ class EmployeeBoardingController(Document): @frappe.whitelist() def get_onboarding_details(parent, parenttype): return frappe.get_all('Employee Boarding Activity', - fields=['activity_name', 'role', 'user', 'required_for_employee_creation', 'description', 'task_weight'], + fields=['activity_name', 'role', 'user', 'required_for_employee_creation', + 'description', 'task_weight', 'begin_on', 'duration'], filters={'parent': parent, 'parenttype': parenttype}, order_by= 'idx') diff --git a/erpnext/hr/doctype/employee_boarding_activity/employee_boarding_activity.json b/erpnext/hr/doctype/employee_boarding_activity/employee_boarding_activity.json index 65792b42fb..044a5a9886 100644 --- a/erpnext/hr/doctype/employee_boarding_activity/employee_boarding_activity.json +++ b/erpnext/hr/doctype/employee_boarding_activity/employee_boarding_activity.json @@ -1,4 +1,5 @@ { + "actions": [], "creation": "2018-05-09 05:37:18.439763", "doctype": "DocType", "editable_grid": 1, @@ -7,6 +8,8 @@ "activity_name", "user", "role", + "begin_on", + "duration", "column_break_3", "task", "task_weight", @@ -16,12 +19,16 @@ ], "fields": [ { + "columns": 3, "fieldname": "activity_name", "fieldtype": "Data", "in_list_view": 1, - "label": "Activity Name" + "label": "Activity Name", + "reqd": 1 }, { + "columns": 2, + "depends_on": "eval:!doc.role", "fieldname": "user", "fieldtype": "Link", "in_list_view": 1, @@ -29,9 +36,10 @@ "options": "User" }, { + "columns": 1, + "depends_on": "eval:!doc.user", "fieldname": "role", "fieldtype": "Link", - "in_list_view": 1, "label": "Role", "options": "Role" }, @@ -67,10 +75,25 @@ "fieldname": "description", "fieldtype": "Text Editor", "label": "Description" + }, + { + "columns": 2, + "fieldname": "duration", + "fieldtype": "Int", + "in_list_view": 1, + "label": "Duration (Days)" + }, + { + "columns": 2, + "fieldname": "begin_on", + "fieldtype": "Int", + "in_list_view": 1, + "label": "Begin On (Days)" } ], "istable": 1, - "modified": "2019-06-03 19:22:42.965762", + "links": [], + "modified": "2021-07-30 15:55:22.470102", "modified_by": "Administrator", "module": "HR", "name": "Employee Boarding Activity", diff --git a/erpnext/hr/doctype/employee_onboarding/employee_onboarding.json b/erpnext/hr/doctype/employee_onboarding/employee_onboarding.json index 673e228395..fd877a68d8 100644 --- a/erpnext/hr/doctype/employee_onboarding/employee_onboarding.json +++ b/erpnext/hr/doctype/employee_onboarding/employee_onboarding.json @@ -8,20 +8,24 @@ "field_order": [ "job_applicant", "job_offer", - "employee_name", - "employee", - "date_of_joining", - "boarding_status", - "notify_users_by_email", - "column_break_7", "employee_onboarding_template", + "column_break_7", "company", + "boarding_status", + "project", + "details_section", + "employee", + "employee_name", "department", "designation", "employee_grade", - "project", + "holiday_list", + "column_break_13", + "date_of_joining", + "boarding_begins_on", "table_for_activity", "activities", + "notify_users_by_email", "amended_from" ], "fields": [ @@ -58,7 +62,8 @@ "fieldname": "date_of_joining", "fieldtype": "Date", "in_list_view": 1, - "label": "Date of Joining" + "label": "Date of Joining", + "reqd": 1 }, { "allow_on_submit": 1, @@ -90,7 +95,8 @@ "fieldname": "company", "fieldtype": "Link", "label": "Company", - "options": "Company" + "options": "Company", + "reqd": 1 }, { "fieldname": "department", @@ -121,7 +127,8 @@ }, { "fieldname": "table_for_activity", - "fieldtype": "Section Break" + "fieldtype": "Section Break", + "label": "Onboarding Activities" }, { "allow_on_submit": 1, @@ -138,11 +145,32 @@ "options": "Employee Onboarding", "print_hide": 1, "read_only": 1 + }, + { + "fieldname": "details_section", + "fieldtype": "Section Break", + "label": "Employee Details" + }, + { + "fieldname": "column_break_13", + "fieldtype": "Column Break" + }, + { + "fieldname": "boarding_begins_on", + "fieldtype": "Date", + "label": "Onboarding Begins On", + "reqd": 1 + }, + { + "fieldname": "holiday_list", + "fieldtype": "Link", + "label": "Holiday List", + "options": "Holiday List" } ], "is_submittable": 1, "links": [], - "modified": "2021-06-03 18:01:51.097927", + "modified": "2021-07-30 14:55:04.560683", "modified_by": "Administrator", "module": "HR", "name": "Employee Onboarding", diff --git a/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py b/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py index 0445270b9f..ea46aa24a6 100644 --- a/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py +++ b/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py @@ -5,8 +5,9 @@ from __future__ import unicode_literals import frappe import unittest -from frappe.utils import nowdate +from frappe.utils import getdate from erpnext.hr.doctype.employee_onboarding.employee_onboarding import make_employee +from erpnext.payroll.doctype.salary_slip.test_salary_slip import make_holiday_list from erpnext.hr.doctype.employee_onboarding.employee_onboarding import IncompleteTaskError from erpnext.hr.doctype.job_offer.test_job_offer import create_job_offer @@ -46,7 +47,7 @@ class TestEmployeeOnboarding(unittest.TestCase): onboarding.reload() employee = make_employee(onboarding.name) employee.first_name = employee.employee_name - employee.date_of_joining = nowdate() + employee.date_of_joining = getdate() employee.date_of_birth = '1990-05-08' employee.gender = 'Female' employee.insert() @@ -82,11 +83,14 @@ def get_job_offer(applicant_name): def create_employee_onboarding(): applicant = get_job_applicant() job_offer = get_job_offer(applicant.name) + holiday_list = make_holiday_list() onboarding = frappe.new_doc('Employee Onboarding') onboarding.job_applicant = applicant.name onboarding.job_offer = job_offer.name + onboarding.date_of_joining = onboarding.boarding_begins_on = getdate() onboarding.company = '_Test Company' + onboarding.holiday_list = holiday_list onboarding.designation = 'Researcher' onboarding.append('activities', { 'activity_name': 'Assign ID Card', diff --git a/erpnext/hr/doctype/employee_onboarding_activity/__init__.py b/erpnext/hr/doctype/employee_onboarding_activity/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/hr/doctype/employee_onboarding_activity/employee_onboarding_activity.json b/erpnext/hr/doctype/employee_onboarding_activity/employee_onboarding_activity.json deleted file mode 100644 index 4e91b72384..0000000000 --- a/erpnext/hr/doctype/employee_onboarding_activity/employee_onboarding_activity.json +++ /dev/null @@ -1,290 +0,0 @@ -{ - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2018-05-09 05:37:18.439763", - "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": "activity_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": "Activity 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": 0, - "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": "user", - "fieldtype": "Link", - "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": "User", - "length": 0, - "no_copy": 0, - "options": "User", - "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, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "role", - "fieldtype": "Link", - "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": "Role", - "length": 0, - "no_copy": 0, - "options": "Role", - "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, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_3", - "fieldtype": "Column Break", - "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, - "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, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval: doc.parenttype == \"Employee Onboarding\"", - "fieldname": "completed", - "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": "Completed", - "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, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "required_for_employee_creation", - "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": "Required for Employee Creation", - "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, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_6", - "fieldtype": "Section Break", - "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, - "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, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "description", - "fieldtype": "Text Editor", - "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": "Description", - "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, - "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": 1, - "max_attachments": 0, - "modified": "2018-05-09 06:15:41.768236", - "modified_by": "Administrator", - "module": "HR", - "name": "Employee Onboarding Activity", - "name_case": "", - "owner": "Administrator", - "permissions": [], - "quick_entry": 1, - "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/hr/doctype/employee_onboarding_activity/employee_onboarding_activity.py b/erpnext/hr/doctype/employee_onboarding_activity/employee_onboarding_activity.py deleted file mode 100644 index d170631819..0000000000 --- a/erpnext/hr/doctype/employee_onboarding_activity/employee_onboarding_activity.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- 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 EmployeeOnboardingActivity(Document): - pass diff --git a/erpnext/hr/doctype/employee_separation/employee_separation.json b/erpnext/hr/doctype/employee_separation/employee_separation.json index c10da5c35e..c240493e82 100644 --- a/erpnext/hr/doctype/employee_separation/employee_separation.json +++ b/erpnext/hr/doctype/employee_separation/employee_separation.json @@ -15,6 +15,7 @@ "company", "boarding_status", "resignation_letter_date", + "boarding_begins_on", "project", "table_for_activity", "employee_separation_template", @@ -144,11 +145,17 @@ "options": "Employee Separation", "print_hide": 1, "read_only": 1 + }, + { + "fieldname": "boarding_begins_on", + "fieldtype": "Date", + "label": "Separation Begins On", + "reqd": 1 } ], "is_submittable": 1, "links": [], - "modified": "2021-06-03 18:02:54.007313", + "modified": "2021-07-30 14:03:51.218791", "modified_by": "Administrator", "module": "HR", "name": "Employee Separation", diff --git a/erpnext/hr/doctype/employee_separation/test_employee_separation.py b/erpnext/hr/doctype/employee_separation/test_employee_separation.py index d63501a931..2c11cbbe2c 100644 --- a/erpnext/hr/doctype/employee_separation/test_employee_separation.py +++ b/erpnext/hr/doctype/employee_separation/test_employee_separation.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import frappe +from frappe.utils import getdate import unittest test_dependencies = ['Employee Onboarding'] @@ -34,9 +35,10 @@ class TestEmployeeSeparation(unittest.TestCase): doc.delete() def create_employee_separation(): - employee = frappe.db.get_value('Employee', {'status': 'Active'}) + employee = frappe.db.get_value('Employee', {'status': 'Active', 'company': '_Test Company'}) separation = frappe.new_doc('Employee Separation') separation.employee = employee + separation.boarding_begins_on = getdate() separation.company = '_Test Company' separation.append('activities', { 'activity_name': 'Deactivate Employee', diff --git a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py index d730fcf1fa..636ec0b5a6 100644 --- a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py +++ b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py @@ -828,7 +828,8 @@ def setup_test(): def make_holiday_list(): fiscal_year = get_fiscal_year(nowdate(), company=erpnext.get_default_company()) - if not frappe.db.get_value("Holiday List", "Salary Slip Test Holiday List"): + holiday_list = frappe.db.exists("Holiday List", "Salary Slip Test Holiday List") + if not holiday_list: holiday_list = frappe.get_doc({ "doctype": "Holiday List", "holiday_list_name": "Salary Slip Test Holiday List", @@ -838,3 +839,6 @@ def make_holiday_list(): }).insert() holiday_list.get_weekly_off_dates() holiday_list.save() + holiday_list = holiday_list.name + + return holiday_list From 987746592c73b7c163df11e8f97e4a94c984ec6c Mon Sep 17 00:00:00 2001 From: Saqib Date: Fri, 27 Aug 2021 15:41:26 +0530 Subject: [PATCH 53/54] fix: period closing voucher tests (#27198) --- .../test_period_closing_voucher.py | 138 ++++++++---------- 1 file changed, 58 insertions(+), 80 deletions(-) diff --git a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py index 2d1939131c..2a636bb338 100644 --- a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py +++ b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py @@ -13,59 +13,49 @@ from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sal class TestPeriodClosingVoucher(unittest.TestCase): def test_closing_entry(self): - year_start_date = get_fiscal_year(today(), company="_Test Company")[1] + frappe.db.sql("delete from `tabGL Entry` where company='Test PCV Company'") - make_journal_entry("_Test Bank - _TC", "Sales - _TC", 400, - "_Test Cost Center - _TC", posting_date=now(), submit=True) + company = create_company() + cost_center = create_cost_center('Test Cost Center 1') - make_journal_entry("_Test Account Cost for Goods Sold - _TC", - "_Test Bank - _TC", 600, "_Test Cost Center - _TC", posting_date=now(), submit=True) + jv1 = make_journal_entry( + amount=400, + account1="Cash - TPC", + account2="Sales - TPC", + cost_center=cost_center, + posting_date=now(), + save=False + ) + jv1.company = company + jv1.save() + jv1.submit() - random_expense_account = frappe.db.sql(""" - select t1.account, - sum(t1.debit) - sum(t1.credit) as balance, - sum(t1.debit_in_account_currency) - sum(t1.credit_in_account_currency) \ - as balance_in_account_currency - from `tabGL Entry` t1, `tabAccount` t2 - where t1.account = t2.name and t2.root_type = 'Expense' - and t2.docstatus < 2 and t2.company = '_Test Company' - and t1.posting_date between %s and %s - group by t1.account - having sum(t1.debit) > sum(t1.credit) - limit 1""", (year_start_date, today()), as_dict=True) - - profit_or_loss = frappe.db.sql("""select sum(t1.debit) - sum(t1.credit) as balance - from `tabGL Entry` t1, `tabAccount` t2 - where t1.account = t2.name and t2.report_type = 'Profit and Loss' - and t2.docstatus < 2 and t2.company = '_Test Company' - and t1.posting_date between %s and %s""", (year_start_date, today())) - - profit_or_loss = flt(profit_or_loss[0][0]) if profit_or_loss else 0 + jv2 = make_journal_entry( + amount=600, + account1="Cost of Goods Sold - TPC", + account2="Cash - TPC", + cost_center=cost_center, + posting_date=now(), + save=False + ) + jv2.company = company + jv2.save() + jv2.submit() pcv = self.make_period_closing_voucher() + surplus_account = pcv.closing_account_head - # Check value for closing account - gle_amount_for_closing_account = frappe.db.sql("""select debit - credit - from `tabGL Entry` where voucher_type='Period Closing Voucher' and voucher_no=%s - and account = '_Test Account Reserves and Surplus - _TC'""", pcv.name) + expected_gle = ( + ('Cost of Goods Sold - TPC', 0.0, 600.0), + (surplus_account, 600.0, 400.0), + ('Sales - TPC', 400.0, 0.0) + ) - gle_amount_for_closing_account = flt(gle_amount_for_closing_account[0][0]) \ - if gle_amount_for_closing_account else 0 + pcv_gle = frappe.db.sql(""" + select account, debit, credit from `tabGL Entry` where voucher_no=%s order by account + """, (pcv.name)) - self.assertEqual(gle_amount_for_closing_account, profit_or_loss) - - if random_expense_account: - # Check posted value for teh above random_expense_account - gle_for_random_expense_account = frappe.db.sql(""" - select sum(debit - credit) as amount, - sum(debit_in_account_currency - credit_in_account_currency) as amount_in_account_currency - from `tabGL Entry` - where voucher_type='Period Closing Voucher' and voucher_no=%s and account =%s""", - (pcv.name, random_expense_account[0].account), as_dict=True) - - self.assertEqual(gle_for_random_expense_account[0].amount, -1*random_expense_account[0].balance) - self.assertEqual(gle_for_random_expense_account[0].amount_in_account_currency, - -1*random_expense_account[0].balance_in_account_currency) + self.assertEqual(pcv_gle, expected_gle) def test_cost_center_wise_posting(self): frappe.db.sql("delete from `tabGL Entry` where company='Test PCV Company'") @@ -93,31 +83,23 @@ class TestPeriodClosingVoucher(unittest.TestCase): debit_to="Debtors - TPC" ) - pcv = frappe.get_doc({ - "transaction_date": today(), - "posting_date": today(), - "fiscal_year": get_fiscal_year(today())[0], - "company": "Test PCV Company", - "cost_center_wise_pnl": 1, - "closing_account_head": surplus_account, - "remarks": "Test", - "doctype": "Period Closing Voucher" - }) - pcv.insert() - pcv.submit() + pcv = self.make_period_closing_voucher() + surplus_account = pcv.closing_account_head expected_gle = ( - ('Sales - TPC', 200.0, 0.0, cost_center2), + (surplus_account, 0.0, 400.0, cost_center1), (surplus_account, 0.0, 200.0, cost_center2), ('Sales - TPC', 400.0, 0.0, cost_center1), - (surplus_account, 0.0, 400.0, cost_center1) + ('Sales - TPC', 200.0, 0.0, cost_center2), ) pcv_gle = frappe.db.sql(""" - select account, debit, credit, cost_center from `tabGL Entry` where voucher_no=%s + select account, debit, credit, cost_center + from `tabGL Entry` where voucher_no=%s + order by account, cost_center """, (pcv.name)) - self.assertTrue(pcv_gle, expected_gle) + self.assertEqual(pcv_gle, expected_gle) def test_period_closing_with_finance_book_entries(self): frappe.db.sql("delete from `tabGL Entry` where company='Test PCV Company'") @@ -146,39 +128,35 @@ class TestPeriodClosingVoucher(unittest.TestCase): jv.save() jv.submit() - pcv = frappe.get_doc({ - "transaction_date": today(), - "posting_date": today(), - "fiscal_year": get_fiscal_year(today())[0], - "company": company, - "closing_account_head": surplus_account, - "remarks": "Test", - "doctype": "Period Closing Voucher" - }) - pcv.insert() - pcv.submit() + pcv = self.make_period_closing_voucher() + surplus_account = pcv.closing_account_head expected_gle = ( - (surplus_account, 0.0, 400.0, ''), + (surplus_account, 0.0, 400.0, None), (surplus_account, 0.0, 400.0, jv.finance_book), - ('Sales - TPC', 400.0, 0.0, ''), + ('Sales - TPC', 400.0, 0.0, None), ('Sales - TPC', 400.0, 0.0, jv.finance_book) ) pcv_gle = frappe.db.sql(""" - select account, debit, credit, finance_book from `tabGL Entry` where voucher_no=%s + select account, debit, credit, finance_book + from `tabGL Entry` where voucher_no=%s + order by account, finance_book """, (pcv.name)) - self.assertTrue(pcv_gle, expected_gle) + self.assertEqual(pcv_gle, expected_gle) def make_period_closing_voucher(self): + surplus_account = create_account() + cost_center = create_cost_center("Test Cost Center 1") pcv = frappe.get_doc({ "doctype": "Period Closing Voucher", - "closing_account_head": "_Test Account Reserves and Surplus - _TC", - "company": "_Test Company", - "fiscal_year": get_fiscal_year(today(), company="_Test Company")[0], + "transaction_date": today(), "posting_date": today(), - "cost_center": "_Test Cost Center - _TC", + "company": "Test PCV Company", + "fiscal_year": get_fiscal_year(today(), company="Test PCV Company")[0], + "cost_center": cost_center, + "closing_account_head": surplus_account, "remarks": "test" }) pcv.insert() From a285b5b78b8080cda0a917cd45cc06e7de4e6ff9 Mon Sep 17 00:00:00 2001 From: Kamal Johnson Date: Fri, 27 Aug 2021 15:47:11 +0530 Subject: [PATCH 54/54] feat: Accounts, Selling & Assets Onboarding cleanup (#27112) * refactor: company form fields arrangement * refactor: accounts onboarding steps * refactor: re-arrange fields & modify labels in company form * feat: onbording steps for accounts module * fix: updated onboarding steps for selling module * fix: remove unwanted steps from accounts * feat: add more onboarding steps * feat: Refactor onboarding-module for accounting workspace * feat: Add basic asset onboarding steps * feat: Add basic asset item form tour * feat: Add basic selling onboarding-steps * feat: Add basic form tour for purchase recipt * feat: Add basic form tour for existing asset * feat: Adding asset category form tour * feat: Add form tour for asset category * feat: Refactor sales taxes and charges template form tour with new method * refactor: Remove old form tour for accounts settings * refactor: Change asset category form tour with new tour method * refactor: Change asset item form tour with new tour method * refactor: Change purchase receipt form tour with new tour method * refactor: Change asset form tour with new tour method * refactor: Remove old form tour for selling settings * refactor: general fix/typo in onboarding steps * Apply suggestions from code review Co-authored-by: Nabin Hait * refactor: Remove old form tour method for sales order. * fix: removed duplicate section break * fix: Removed duplicate fields Co-authored-by: Saqib Ansari Co-authored-by: Anuja Co-authored-by: Afshan <33727827+AfshanKhan@users.noreply.github.com> Co-authored-by: Nabin Hait --- .../accounts_settings/accounts_settings.js | 43 ------ .../sales_taxes_and_charges_template.js | 22 --- .../accounts_settings/accounts_settings.json | 113 ++++++++++++++++ .../purchase_invoice/purchase_invoice.json | 96 ++++++++++++++ .../sales_taxes_and_charges_template.json | 65 +++++++++ .../module_onboarding/accounts/accounts.json | 16 +-- .../accounts_settings/accounts_settings.json | 21 +++ .../chart_of_accounts/chart_of_accounts.json | 11 +- .../onboarding_step/company/company.json | 22 +++ ...cost_centers_for_report_and_budgeting.json | 21 +++ .../create_your_first_purchase_invoice.json | 7 +- .../financial_statements.json | 23 ++++ .../setup_taxes/setup_taxes.json | 8 +- .../updating_opening_balances.json | 22 +++ erpnext/assets/form_tour/asset/asset.json | 125 ++++++++++++++++++ .../asset_category/asset_category.json | 65 +++++++++ .../module_onboarding/assets/assets.json | 12 +- .../asset_category/asset_category.json | 21 +++ .../asset_item/asset_item.json | 21 +++ .../asset_purchase/asset_purchase.json | 21 +++ .../existing_asset/existing_asset.json | 21 +++ .../fixed_asset_accounts.json | 21 +++ .../selling_settings/selling_settings.js | 23 ---- .../form_tour/sales_order/sales_order.json | 97 ++++++++++++++ .../selling_settings/selling_settings.json | 65 +++++++++ .../module_onboarding/selling/selling.json | 23 +--- .../create_a_customer/create_a_customer.json | 2 +- .../create_a_product/create_a_product.json | 4 +- .../create_a_quotation.json | 2 +- .../create_a_sales_order.json | 21 +++ .../introduction_to_selling.json | 2 +- .../sales_order/sales_order.json | 21 +++ .../selling_settings/selling_settings.json | 8 +- .../setup_your_warehouse.json | 4 +- erpnext/setup/doctype/company/company.json | 20 +-- erpnext/stock/form_tour/item/item.json | 89 +++++++++++++ .../purchase_receipt/purchase_receipt.json | 41 ++++++ 37 files changed, 1066 insertions(+), 153 deletions(-) create mode 100644 erpnext/accounts/form_tour/accounts_settings/accounts_settings.json create mode 100644 erpnext/accounts/form_tour/purchase_invoice/purchase_invoice.json create mode 100644 erpnext/accounts/form_tour/sales_taxes_and_charges_template/sales_taxes_and_charges_template.json create mode 100644 erpnext/accounts/onboarding_step/accounts_settings/accounts_settings.json create mode 100644 erpnext/accounts/onboarding_step/company/company.json create mode 100644 erpnext/accounts/onboarding_step/cost_centers_for_report_and_budgeting/cost_centers_for_report_and_budgeting.json create mode 100644 erpnext/accounts/onboarding_step/financial_statements/financial_statements.json create mode 100644 erpnext/accounts/onboarding_step/updating_opening_balances/updating_opening_balances.json create mode 100644 erpnext/assets/form_tour/asset/asset.json create mode 100644 erpnext/assets/form_tour/asset_category/asset_category.json create mode 100644 erpnext/assets/onboarding_step/asset_category/asset_category.json create mode 100644 erpnext/assets/onboarding_step/asset_item/asset_item.json create mode 100644 erpnext/assets/onboarding_step/asset_purchase/asset_purchase.json create mode 100644 erpnext/assets/onboarding_step/existing_asset/existing_asset.json create mode 100644 erpnext/assets/onboarding_step/fixed_asset_accounts/fixed_asset_accounts.json create mode 100644 erpnext/selling/form_tour/sales_order/sales_order.json create mode 100644 erpnext/selling/form_tour/selling_settings/selling_settings.json create mode 100644 erpnext/selling/onboarding_step/create_a_sales_order/create_a_sales_order.json create mode 100644 erpnext/selling/onboarding_step/sales_order/sales_order.json create mode 100644 erpnext/stock/form_tour/item/item.json create mode 100644 erpnext/stock/form_tour/purchase_receipt/purchase_receipt.json diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.js b/erpnext/accounts/doctype/accounts_settings/accounts_settings.js index e44af3a916..0627675de7 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.js +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.js @@ -6,46 +6,3 @@ frappe.ui.form.on('Accounts Settings', { } }); - -frappe.tour['Accounts Settings'] = [ - { - fieldname: "acc_frozen_upto", - title: "Accounts Frozen Upto", - description: __("Freeze accounting transactions up to specified date, nobody can make/modify entry except the specified Role."), - }, - { - fieldname: "frozen_accounts_modifier", - title: "Role Allowed to Set Frozen Accounts & Edit Frozen Entries", - description: __("Users with this Role are allowed to set frozen accounts and create/modify accounting entries against frozen accounts.") - }, - { - fieldname: "determine_address_tax_category_from", - title: "Determine Address Tax Category From", - description: __("Tax category can be set on Addresses. An address can be Shipping or Billing address. Set which addres to select when applying Tax Category.") - }, - { - fieldname: "over_billing_allowance", - title: "Over Billing Allowance Percentage", - description: __("The percentage by which you can overbill transactions. For example, if the order value is $100 for an Item and percentage here is set as 10% then you are allowed to bill for $110.") - }, - { - fieldname: "credit_controller", - title: "Credit Controller", - description: __("Select the role that is allowed to submit transactions that exceed credit limits set. The credit limit can be set in the Customer form.") - }, - { - fieldname: "make_payment_via_journal_entry", - title: "Make Payment via Journal Entry", - description: __("When checked, if user proceeds to make payment from an invoice, the system will open a Journal Entry instead of a Payment Entry.") - }, - { - fieldname: "unlink_payment_on_cancellation_of_invoice", - title: "Unlink Payment on Cancellation of Invoice", - description: __("If checked, system will unlink the payment against the respective invoice.") - }, - { - fieldname: "unlink_advance_payment_on_cancelation_of_order", - title: "Unlink Advance Payment on Cancellation of Order", - description: __("Similar to the previous option, this unlinks any advance payments made against Purchase/Sales Orders.") - } -]; diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.js b/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.js index 0e011883b1..97a6fdd336 100644 --- a/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.js +++ b/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.js @@ -5,25 +5,3 @@ cur_frm.cscript.tax_table = "Sales Taxes and Charges"; {% include "erpnext/public/js/controllers/accounts.js" %} -frappe.tour['Sales Taxes and Charges Template'] = [ - { - fieldname: "title", - title: __("Title"), - description: __("A name by which you will identify this template. You can change this later."), - }, - { - fieldname: "company", - title: __("Company"), - description: __("Company for which this tax template will be applicable"), - }, - { - fieldname: "is_default", - title: __("Is this Default?"), - description: __("Set this template as the default for all sales transactions"), - }, - { - fieldname: "taxes", - title: __("Taxes Table"), - description: __("You can add a row for a tax rule here. These rules can be applied on the net total, or can be a flat amount."), - } -]; diff --git a/erpnext/accounts/form_tour/accounts_settings/accounts_settings.json b/erpnext/accounts/form_tour/accounts_settings/accounts_settings.json new file mode 100644 index 0000000000..e2bf50d20a --- /dev/null +++ b/erpnext/accounts/form_tour/accounts_settings/accounts_settings.json @@ -0,0 +1,113 @@ +{ + "creation": "2021-06-29 17:00:18.273054", + "docstatus": 0, + "doctype": "Form Tour", + "idx": 0, + "is_standard": 1, + "modified": "2021-06-29 17:00:26.145996", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Accounts Settings", + "owner": "Administrator", + "reference_doctype": "Accounts Settings", + "save_on_complete": 0, + "steps": [ + { + "description": "The percentage by which you can overbill transactions. For example, if the order value is $100 for an Item and percentage here is set as 10% then you are allowed to bill for $110.", + "field": "", + "fieldname": "over_billing_allowance", + "fieldtype": "Currency", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Over Billing Allowance (%)", + "parent_field": "", + "position": "Right", + "title": "Over Billing Allowance Percentage" + }, + { + "description": "Select the role that is allowed to overbill a transactions.", + "field": "", + "fieldname": "role_allowed_to_over_bill", + "fieldtype": "Link", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Role Allowed to Over Bill ", + "parent_field": "", + "position": "Right", + "title": "Role Allowed to Over Bill" + }, + { + "description": "If checked, system will unlink the payment against the respective invoice.", + "field": "", + "fieldname": "unlink_payment_on_cancellation_of_invoice", + "fieldtype": "Check", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Unlink Payment on Cancellation of Invoice", + "parent_field": "", + "position": "Bottom", + "title": "Unlink Payment on Cancellation of Invoice" + }, + { + "description": "Similar to the previous option, this unlinks any advance payments made against Purchase/Sales Orders.", + "field": "", + "fieldname": "unlink_advance_payment_on_cancelation_of_order", + "fieldtype": "Check", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Unlink Advance Payment on Cancellation of Order", + "parent_field": "", + "position": "Bottom", + "title": "Unlink Advance Payment on Cancellation of Order" + }, + { + "description": "Tax category can be set on Addresses. An address can be Shipping or Billing address. Set which addres to select when applying Tax Category.", + "field": "", + "fieldname": "determine_address_tax_category_from", + "fieldtype": "Select", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Determine Address Tax Category From", + "parent_field": "", + "position": "Right", + "title": "Determine Address Tax Category From" + }, + { + "description": "Freeze accounting transactions up to specified date, nobody can make/modify entry except the specified Role.", + "field": "", + "fieldname": "acc_frozen_upto", + "fieldtype": "Date", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Accounts Frozen Till Date", + "parent_field": "", + "position": "Right", + "title": "Accounts Frozen Upto" + }, + { + "description": "Users with this Role are allowed to set frozen accounts and create/modify accounting entries against frozen accounts.", + "field": "", + "fieldname": "frozen_accounts_modifier", + "fieldtype": "Link", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Role Allowed to Set Frozen Accounts and Edit Frozen Entries", + "parent_field": "", + "position": "Right", + "title": "Role Allowed to Set Frozen Accounts & Edit Frozen Entries" + }, + { + "description": "Select the role that is allowed to submit transactions that exceed credit limits set. The credit limit can be set in the Customer form.", + "field": "", + "fieldname": "credit_controller", + "fieldtype": "Link", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Credit Controller", + "parent_field": "", + "position": "Left", + "title": "Credit Controller" + } + ], + "title": "Accounts Settings" +} \ No newline at end of file diff --git a/erpnext/accounts/form_tour/purchase_invoice/purchase_invoice.json b/erpnext/accounts/form_tour/purchase_invoice/purchase_invoice.json new file mode 100644 index 0000000000..2dffcd1c0e --- /dev/null +++ b/erpnext/accounts/form_tour/purchase_invoice/purchase_invoice.json @@ -0,0 +1,96 @@ +{ + "creation": "2021-06-29 16:31:48.558826", + "docstatus": 0, + "doctype": "Form Tour", + "idx": 0, + "is_standard": 1, + "modified": "2021-06-29 16:31:48.558826", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Purchase Invoice", + "owner": "Administrator", + "reference_doctype": "Purchase Invoice", + "save_on_complete": 1, + "steps": [ + { + "description": "Select Supplier", + "field": "", + "fieldname": "supplier", + "fieldtype": "Link", + "has_next_condition": 1, + "is_table_field": 0, + "label": "Supplier", + "next_step_condition": "supplier", + "parent_field": "", + "position": "Right", + "title": "Select Supplier" + }, + { + "description": "Add items in the table", + "field": "", + "fieldname": "items", + "fieldtype": "Table", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Items", + "parent_field": "", + "position": "Bottom", + "title": "List of Items" + }, + { + "child_doctype": "Purchase Invoice Item", + "description": "Select an item", + "field": "", + "fieldname": "item_code", + "fieldtype": "Link", + "has_next_condition": 0, + "is_table_field": 1, + "label": "Item", + "parent_field": "", + "parent_fieldname": "items", + "position": "Right", + "title": "Select Item" + }, + { + "child_doctype": "Purchase Invoice Item", + "description": "Enter the quantity", + "field": "", + "fieldname": "qty", + "fieldtype": "Float", + "has_next_condition": 0, + "is_table_field": 1, + "label": "Accepted Qty", + "parent_field": "", + "parent_fieldname": "items", + "position": "Right", + "title": "Enter Quantity" + }, + { + "child_doctype": "Purchase Invoice Item", + "description": "Enter rate of the item", + "field": "", + "fieldname": "rate", + "fieldtype": "Currency", + "has_next_condition": 0, + "is_table_field": 1, + "label": "Rate", + "parent_field": "", + "parent_fieldname": "items", + "position": "Right", + "title": "Enter Rate" + }, + { + "description": "You can add taxes here", + "field": "", + "fieldname": "taxes", + "fieldtype": "Table", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Purchase Taxes and Charges", + "parent_field": "", + "position": "Bottom", + "title": "Select taxes" + } + ], + "title": "Purchase Invoice" +} \ No newline at end of file diff --git a/erpnext/accounts/form_tour/sales_taxes_and_charges_template/sales_taxes_and_charges_template.json b/erpnext/accounts/form_tour/sales_taxes_and_charges_template/sales_taxes_and_charges_template.json new file mode 100644 index 0000000000..7de9ae1539 --- /dev/null +++ b/erpnext/accounts/form_tour/sales_taxes_and_charges_template/sales_taxes_and_charges_template.json @@ -0,0 +1,65 @@ +{ + "creation": "2021-08-24 12:28:18.044902", + "docstatus": 0, + "doctype": "Form Tour", + "idx": 0, + "is_standard": 1, + "modified": "2021-08-24 12:28:18.044902", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Sales Taxes and Charges Template", + "owner": "Administrator", + "reference_doctype": "Sales Taxes and Charges Template", + "save_on_complete": 0, + "steps": [ + { + "description": "A name by which you will identify this template. You can change this later.", + "field": "", + "fieldname": "title", + "fieldtype": "Data", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Title", + "parent_field": "", + "position": "Bottom", + "title": "Title" + }, + { + "description": "Company for which this tax template will be applicable", + "field": "", + "fieldname": "company", + "fieldtype": "Link", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Company", + "parent_field": "", + "position": "Bottom", + "title": "Company" + }, + { + "description": "Set this template as the default for all sales transactions", + "field": "", + "fieldname": "is_default", + "fieldtype": "Check", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Default", + "parent_field": "", + "position": "Bottom", + "title": "Is this Default Tax Template?" + }, + { + "description": "You can add a row for a tax rule here. These rules can be applied on the net total, or can be a flat amount.", + "field": "", + "fieldname": "taxes", + "fieldtype": "Table", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Sales Taxes and Charges", + "parent_field": "", + "position": "Bottom", + "title": "Taxes Table" + } + ], + "title": "Sales Taxes and Charges Template" +} \ No newline at end of file diff --git a/erpnext/accounts/module_onboarding/accounts/accounts.json b/erpnext/accounts/module_onboarding/accounts/accounts.json index 6b5c5a1db8..2e0ab4305d 100644 --- a/erpnext/accounts/module_onboarding/accounts/accounts.json +++ b/erpnext/accounts/module_onboarding/accounts/accounts.json @@ -13,12 +13,15 @@ "documentation_url": "https://docs.erpnext.com/docs/user/manual/en/accounts", "idx": 0, "is_complete": 0, - "modified": "2020-10-30 15:41:15.547225", + "modified": "2021-08-13 11:59:35.690443", "modified_by": "Administrator", "module": "Accounts", "name": "Accounts", "owner": "Administrator", "steps": [ + { + "step": "Company" + }, { "step": "Chart of Accounts" }, @@ -26,22 +29,19 @@ "step": "Setup Taxes" }, { - "step": "Create a Product" + "step": "Accounts Settings" }, { - "step": "Create a Supplier" + "step": "Cost Centers for Report and Budgeting" }, { "step": "Create Your First Purchase Invoice" }, { - "step": "Create a Customer" + "step": "Updating Opening Balances" }, { - "step": "Create Your First Sales Invoice" - }, - { - "step": "Configure Account Settings" + "step": "Financial Statements" } ], "subtitle": "Accounts, Invoices, Taxation, and more.", diff --git a/erpnext/accounts/onboarding_step/accounts_settings/accounts_settings.json b/erpnext/accounts/onboarding_step/accounts_settings/accounts_settings.json new file mode 100644 index 0000000000..3f44a73685 --- /dev/null +++ b/erpnext/accounts/onboarding_step/accounts_settings/accounts_settings.json @@ -0,0 +1,21 @@ +{ + "action": "Show Form Tour", + "action_label": "Take a quick walk-through of Accounts Settings", + "creation": "2021-06-29 16:42:03.400731", + "description": "# Account Settings\n\nIn ERPNext, Accounting features are configurable as per your business needs. Accounts Settings is the place to define some of your accounting preferences like:\n\n - Credit Limit and over billing settings\n - Taxation preferences\n - Deferred accounting preferences\n", + "docstatus": 0, + "doctype": "Onboarding Step", + "idx": 0, + "is_complete": 0, + "is_single": 1, + "is_skipped": 0, + "modified": "2021-08-13 11:50:06.227835", + "modified_by": "Administrator", + "name": "Accounts Settings", + "owner": "Administrator", + "reference_document": "Accounts Settings", + "show_form_tour": 0, + "show_full_form": 0, + "title": "Accounts Settings", + "validate_action": 1 +} \ No newline at end of file diff --git a/erpnext/accounts/onboarding_step/chart_of_accounts/chart_of_accounts.json b/erpnext/accounts/onboarding_step/chart_of_accounts/chart_of_accounts.json index fc49bd652b..67553baec7 100644 --- a/erpnext/accounts/onboarding_step/chart_of_accounts/chart_of_accounts.json +++ b/erpnext/accounts/onboarding_step/chart_of_accounts/chart_of_accounts.json @@ -1,10 +1,10 @@ { - "action": "Go to Page", - "action_label": "View Chart of Accounts", + "action": "Watch Video", + "action_label": "Learn more about Chart of Accounts", "callback_message": "You can continue with the onboarding after exploring this page", "callback_title": "Awesome Work", "creation": "2020-05-13 19:58:20.928127", - "description": "# Chart Of Accounts\n\nThe Chart of Accounts is the blueprint of the accounts in your organization.\nIt is a tree view of the names of the Accounts (Ledgers and Groups) that a Company requires to manage its books of accounts. ERPNext sets up a simple chart of accounts for each Company you create, but you can modify it according to your needs and legal requirements.\n\nFor each company, Chart of Accounts signifies the way to classify the accounting entries, mostly\nbased on statutory (tax, compliance to government regulations) requirements.\n\nThere's a brief video tutorial about chart of accounts in the next step.", + "description": "# Chart Of Accounts\n\nERPNext sets up a simple chart of accounts for each Company you create, but you can modify it according to business and legal requirements.", "docstatus": 0, "doctype": "Onboarding Step", "idx": 0, @@ -12,7 +12,7 @@ "is_complete": 0, "is_single": 0, "is_skipped": 0, - "modified": "2020-10-30 14:35:59.474920", + "modified": "2021-08-13 11:46:25.878506", "modified_by": "Administrator", "name": "Chart of Accounts", "owner": "Administrator", @@ -21,5 +21,6 @@ "show_form_tour": 0, "show_full_form": 0, "title": "Review Chart of Accounts", - "validate_action": 0 + "validate_action": 0, + "video_url": "https://www.youtube.com/embed/AcfMCT7wLLo" } \ No newline at end of file diff --git a/erpnext/accounts/onboarding_step/company/company.json b/erpnext/accounts/onboarding_step/company/company.json new file mode 100644 index 0000000000..4992e4d018 --- /dev/null +++ b/erpnext/accounts/onboarding_step/company/company.json @@ -0,0 +1,22 @@ +{ + "action": "Go to Page", + "action_label": "Let's Review your Company", + "creation": "2021-06-29 14:47:42.497318", + "description": "# Company\n\nIn ERPNext, you can also create multiple companies, and establish relationships (group/subsidiary) among them.\n\nWithin the company master, you can capture various default accounts for that Company and set crucial settings related to the accounting methodology followed for a company. \n", + "docstatus": 0, + "doctype": "Onboarding Step", + "idx": 0, + "is_complete": 0, + "is_single": 0, + "is_skipped": 0, + "modified": "2021-08-13 11:43:35.767341", + "modified_by": "Administrator", + "name": "Company", + "owner": "Administrator", + "path": "app/company", + "reference_document": "Company", + "show_form_tour": 0, + "show_full_form": 0, + "title": "Review Company", + "validate_action": 1 +} \ No newline at end of file diff --git a/erpnext/accounts/onboarding_step/cost_centers_for_report_and_budgeting/cost_centers_for_report_and_budgeting.json b/erpnext/accounts/onboarding_step/cost_centers_for_report_and_budgeting/cost_centers_for_report_and_budgeting.json new file mode 100644 index 0000000000..252b075697 --- /dev/null +++ b/erpnext/accounts/onboarding_step/cost_centers_for_report_and_budgeting/cost_centers_for_report_and_budgeting.json @@ -0,0 +1,21 @@ +{ + "action": "Go to Page", + "action_label": "View Cost Center Tree", + "creation": "2021-07-12 12:02:05.726608", + "description": "# Cost Centers for Budgeting and Analysis\n\nWhile your Books of Accounts are framed to fulfill statutory requirements, you can set up Cost Center and Accounting Dimensions to address your companies reporting and budgeting requirements.\n\nClick here to learn more about how [Cost Center](https://docs.erpnext.com/docs/v13/user/manual/en/accounts/cost-center) and [Dimensions](https://docs.erpnext.com/docs/v13/user/manual/en/accounts/accounting-dimensions) allow you to get advanced financial analytics reports from ERPNext.", + "docstatus": 0, + "doctype": "Onboarding Step", + "idx": 0, + "is_complete": 0, + "is_single": 0, + "is_skipped": 0, + "modified": "2021-08-13 11:55:08.510366", + "modified_by": "Administrator", + "name": "Cost Centers for Report and Budgeting", + "owner": "Administrator", + "path": "cost-center/view/tree", + "show_form_tour": 0, + "show_full_form": 0, + "title": "Cost Centers for Budgeting and Analysis", + "validate_action": 1 +} \ No newline at end of file diff --git a/erpnext/accounts/onboarding_step/create_your_first_purchase_invoice/create_your_first_purchase_invoice.json b/erpnext/accounts/onboarding_step/create_your_first_purchase_invoice/create_your_first_purchase_invoice.json index ddbc89ec0a..f4e298e701 100644 --- a/erpnext/accounts/onboarding_step/create_your_first_purchase_invoice/create_your_first_purchase_invoice.json +++ b/erpnext/accounts/onboarding_step/create_your_first_purchase_invoice/create_your_first_purchase_invoice.json @@ -1,14 +1,15 @@ { - "action": "Create Entry", + "action": "Show Form Tour", + "action_label": "Let\u2019s create your first Purchase Invoice", "creation": "2020-05-14 22:10:07.049704", - "description": "# What's a Purchase Invoice?\n\nA Purchase Invoice is a bill you receive from your Suppliers against which you need to make the payment.\nPurchase Invoice is the exact opposite of your Sales Invoice. Here you accrue expenses to your Supplier. \n\nThe following is what a typical purchase cycle looks like, however you can create a purchase invoice directly as well.\n\n![Purchase Flow](https://docs.erpnext.com/docs/assets/img/accounts/pi-flow.png)\n\n", + "description": "# Create your first Purchase Invoice\n\nA Purchase Invoice is a bill received from a Supplier for a product(s) or service(s) delivery to your company. You can track payables through Purchase Invoice and process Payment Entries against it.\n\nPurchase Invoices can also be created against a Purchase Order or Purchase Receipt.", "docstatus": 0, "doctype": "Onboarding Step", "idx": 0, "is_complete": 0, "is_single": 0, "is_skipped": 0, - "modified": "2020-10-30 15:30:26.337773", + "modified": "2021-08-13 11:56:11.677253", "modified_by": "Administrator", "name": "Create Your First Purchase Invoice", "owner": "Administrator", diff --git a/erpnext/accounts/onboarding_step/financial_statements/financial_statements.json b/erpnext/accounts/onboarding_step/financial_statements/financial_statements.json new file mode 100644 index 0000000000..85cf9cdd7c --- /dev/null +++ b/erpnext/accounts/onboarding_step/financial_statements/financial_statements.json @@ -0,0 +1,23 @@ +{ + "action": "View Report", + "creation": "2021-07-12 12:08:47.026115", + "description": "# Financial Statements\n\nIn ERPNext, you can get crucial financial reports like [Balance Sheet] and [Profit and Loss] statements with a click of a button. You can run in the report for a different period and plot analytics charts premised on statement data. For more reports, check sections like Financial Statements, General Ledger, and Profitability reports.\n\n[Check Accounting reports](https://docs.erpnext.com/docs/v13/user/manual/en/accounts/accounting-reports)", + "docstatus": 0, + "doctype": "Onboarding Step", + "idx": 0, + "is_complete": 0, + "is_single": 0, + "is_skipped": 0, + "modified": "2021-08-13 11:59:18.767407", + "modified_by": "Administrator", + "name": "Financial Statements", + "owner": "Administrator", + "reference_report": "General Ledger", + "report_description": "General Ledger", + "report_reference_doctype": "GL Entry", + "report_type": "Script Report", + "show_form_tour": 0, + "show_full_form": 0, + "title": "Financial Statements", + "validate_action": 1 +} \ No newline at end of file diff --git a/erpnext/accounts/onboarding_step/setup_taxes/setup_taxes.json b/erpnext/accounts/onboarding_step/setup_taxes/setup_taxes.json index a4922013da..9f4c873e34 100644 --- a/erpnext/accounts/onboarding_step/setup_taxes/setup_taxes.json +++ b/erpnext/accounts/onboarding_step/setup_taxes/setup_taxes.json @@ -1,21 +1,21 @@ { "action": "Create Entry", - "action_label": "Make a Sales Tax Template", + "action_label": "Manage Sales Tax Templates", "creation": "2020-05-13 19:29:43.844463", - "description": "# Setting up Taxes\n\nAny sophisticated accounting system, including ERPNext will have automatic tax calculations for your transactions. These calculations are based on user defined rules in compliance to local rules and regulations.\n\nERPNext allows this via *Tax Templates*. These templates can be used in Sales Orders and Sales Invoices. Other types of charges that may apply to your invoices (like shipping, insurance etc.) can also be configured as taxes.\n\nFor Tax Accounts that you want to use in the tax templates, go to:\n\n`> Accounting > Taxes > Sales Taxes and Charges Template`\n\nYou can read more about these templates in our documentation [here](https://docs.erpnext.com/docs/user/manual/en/selling/sales-taxes-and-charges-template)\n", + "description": "# Setting up Taxes\n\nERPNext lets you configure your taxes so that they are automatically applied in your buying and selling transactions. You can configure them globally or even on Items. ERPNext taxes are pre-configured for most regions.\n", "docstatus": 0, "doctype": "Onboarding Step", "idx": 0, "is_complete": 0, "is_single": 0, "is_skipped": 0, - "modified": "2020-10-30 14:54:18.087383", + "modified": "2021-08-13 11:48:37.238610", "modified_by": "Administrator", "name": "Setup Taxes", "owner": "Administrator", "reference_document": "Sales Taxes and Charges Template", "show_form_tour": 1, "show_full_form": 1, - "title": "Lets create a Tax Template for Sales ", + "title": "Setting up Taxes", "validate_action": 0 } \ No newline at end of file diff --git a/erpnext/accounts/onboarding_step/updating_opening_balances/updating_opening_balances.json b/erpnext/accounts/onboarding_step/updating_opening_balances/updating_opening_balances.json new file mode 100644 index 0000000000..c0849a4ef5 --- /dev/null +++ b/erpnext/accounts/onboarding_step/updating_opening_balances/updating_opening_balances.json @@ -0,0 +1,22 @@ +{ + "action": "Watch Video", + "action_label": "Learn how to update opening balances", + "creation": "2021-07-12 11:53:50.525030", + "description": "# Updating Opening Balances\n\nOnce you close the financial statement in previous accounting software, you can update the same as opening in your ERPNext's Balance Sheet accounts. This will allow you to get complete financial statements from ERPNext in the coming years, and discontinue the parallel accounting system right away.", + "docstatus": 0, + "doctype": "Onboarding Step", + "idx": 0, + "intro_video_url": "https://www.youtube.com/embed/U5wPIvEn-0c", + "is_complete": 0, + "is_single": 0, + "is_skipped": 0, + "modified": "2021-08-13 11:56:45.483418", + "modified_by": "Administrator", + "name": "Updating Opening Balances", + "owner": "Administrator", + "show_form_tour": 0, + "show_full_form": 0, + "title": "Updating Opening Balances", + "validate_action": 1, + "video_url": "https://www.youtube.com/embed/U5wPIvEn-0c" +} \ No newline at end of file diff --git a/erpnext/assets/form_tour/asset/asset.json b/erpnext/assets/form_tour/asset/asset.json new file mode 100644 index 0000000000..7c47a38bd1 --- /dev/null +++ b/erpnext/assets/form_tour/asset/asset.json @@ -0,0 +1,125 @@ +{ + "creation": "2021-08-24 16:55:10.923434", + "docstatus": 0, + "doctype": "Form Tour", + "idx": 0, + "is_standard": 1, + "modified": "2021-08-24 16:55:10.923434", + "modified_by": "Administrator", + "module": "Assets", + "name": "Asset", + "owner": "Administrator", + "reference_doctype": "Asset", + "save_on_complete": 0, + "steps": [ + { + "description": "Select Naming Series based on which Asset ID will be generated", + "field": "", + "fieldname": "naming_series", + "fieldtype": "Select", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Naming Series", + "parent_field": "", + "position": "Bottom", + "title": "Naming Series" + }, + { + "description": "Select an Asset Item", + "field": "", + "fieldname": "item_code", + "fieldtype": "Link", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Item Code", + "parent_field": "", + "position": "Bottom", + "title": "Item Code" + }, + { + "description": "Select a Location", + "field": "", + "fieldname": "location", + "fieldtype": "Link", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Location", + "parent_field": "", + "position": "Bottom", + "title": "Location" + }, + { + "description": "Check Is Existing Asset", + "field": "", + "fieldname": "is_existing_asset", + "fieldtype": "Check", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Is Existing Asset", + "parent_field": "", + "position": "Bottom", + "title": "Is Existing Asset?" + }, + { + "description": "Set Available for use date", + "field": "", + "fieldname": "available_for_use_date", + "fieldtype": "Date", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Available-for-use Date", + "parent_field": "", + "position": "Bottom", + "title": "Available For Use Date" + }, + { + "description": "Set Gross purchase amount", + "field": "", + "fieldname": "gross_purchase_amount", + "fieldtype": "Currency", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Gross Purchase Amount", + "parent_field": "", + "position": "Bottom", + "title": "Gross Purchase Amount" + }, + { + "description": "Set Purchase Date", + "field": "", + "fieldname": "purchase_date", + "fieldtype": "Date", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Purchase Date", + "parent_field": "", + "position": "Bottom", + "title": "Purchase Date" + }, + { + "description": "Check Calculate Depreciation", + "field": "", + "fieldname": "calculate_depreciation", + "fieldtype": "Check", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Calculate Depreciation", + "parent_field": "", + "position": "Bottom", + "title": "Calculate Depreciation" + }, + { + "description": "Enter depreciation which has already been booked for this asset", + "field": "", + "fieldname": "opening_accumulated_depreciation", + "fieldtype": "Currency", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Opening Accumulated Depreciation", + "parent_field": "", + "position": "Bottom", + "title": "Accumulated Depreciation" + } + ], + "title": "Asset" +} \ No newline at end of file diff --git a/erpnext/assets/form_tour/asset_category/asset_category.json b/erpnext/assets/form_tour/asset_category/asset_category.json new file mode 100644 index 0000000000..02834447a5 --- /dev/null +++ b/erpnext/assets/form_tour/asset_category/asset_category.json @@ -0,0 +1,65 @@ +{ + "creation": "2021-08-24 12:48:20.763173", + "docstatus": 0, + "doctype": "Form Tour", + "idx": 0, + "is_standard": 1, + "modified": "2021-08-24 12:48:20.763173", + "modified_by": "Administrator", + "module": "Assets", + "name": "Asset Category", + "owner": "Administrator", + "reference_doctype": "Asset Category", + "save_on_complete": 0, + "steps": [ + { + "description": "Name Asset category. You can create categories based on Asset Types like Furniture, Property, Electronics etc.", + "field": "", + "fieldname": "asset_category_name", + "fieldtype": "Data", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Asset Category Name", + "parent_field": "", + "position": "Bottom", + "title": "Asset Category Name" + }, + { + "description": "Check to enable Capital Work in Progress accounting", + "field": "", + "fieldname": "enable_cwip_accounting", + "fieldtype": "Check", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Enable Capital Work in Progress Accounting", + "parent_field": "", + "position": "Bottom", + "title": "Enable CWIP Accounting" + }, + { + "description": "Add a row to define Depreciation Method and other details. Note that you can leave Finance Book blank to have it's accounting done in the primary books of accounts.", + "field": "", + "fieldname": "finance_books", + "fieldtype": "Table", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Finance Books", + "parent_field": "", + "position": "Bottom", + "title": "Finance Book Detail" + }, + { + "description": "Select the Fixed Asset and Depreciation accounts applicable for this Asset Category type", + "field": "", + "fieldname": "accounts", + "fieldtype": "Table", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Accounts", + "parent_field": "", + "position": "Bottom", + "title": "Accounts" + } + ], + "title": "Asset Category" +} \ No newline at end of file diff --git a/erpnext/assets/module_onboarding/assets/assets.json b/erpnext/assets/module_onboarding/assets/assets.json index 1086ab4bcd..e6df88b000 100644 --- a/erpnext/assets/module_onboarding/assets/assets.json +++ b/erpnext/assets/module_onboarding/assets/assets.json @@ -13,26 +13,26 @@ "documentation_url": "https://docs.erpnext.com/docs/user/manual/en/asset", "idx": 0, "is_complete": 0, - "modified": "2020-07-08 14:05:51.828497", + "modified": "2021-08-24 17:50:41.573281", "modified_by": "Administrator", "module": "Assets", "name": "Assets", "owner": "Administrator", "steps": [ { - "step": "Introduction to Assets" + "step": "Fixed Asset Accounts" }, { - "step": "Create a Fixed Asset Item" + "step": "Asset Category" }, { - "step": "Create an Asset Category" + "step": "Asset Item" }, { - "step": "Purchase an Asset Item" + "step": "Asset Purchase" }, { - "step": "Create an Asset" + "step": "Existing Asset" } ], "subtitle": "Assets, Depreciations, Repairs, and more.", diff --git a/erpnext/assets/onboarding_step/asset_category/asset_category.json b/erpnext/assets/onboarding_step/asset_category/asset_category.json new file mode 100644 index 0000000000..033e86669c --- /dev/null +++ b/erpnext/assets/onboarding_step/asset_category/asset_category.json @@ -0,0 +1,21 @@ +{ + "action": "Show Form Tour", + "action_label": "Let's review existing Asset Category", + "creation": "2021-08-13 14:26:18.656303", + "description": "# Asset Category\n\nAn Asset Category classifies different assets of a Company.\n\nYou can create an Asset Category based on the type of assets. For example, all your desktops and laptops can be part of an Asset Category named \"Electronic Equipments\". Create a separate category for furniture. Also, you can update default properties for each category, like:\n - Depreciation type and duration\n - Fixed asset account\n - Depreciation account\n", + "docstatus": 0, + "doctype": "Onboarding Step", + "idx": 0, + "is_complete": 0, + "is_single": 0, + "is_skipped": 0, + "modified": "2021-08-24 12:49:37.665239", + "modified_by": "Administrator", + "name": "Asset Category", + "owner": "Administrator", + "reference_document": "Asset Category", + "show_form_tour": 0, + "show_full_form": 0, + "title": "Define Asset Category", + "validate_action": 1 +} \ No newline at end of file diff --git a/erpnext/assets/onboarding_step/asset_item/asset_item.json b/erpnext/assets/onboarding_step/asset_item/asset_item.json new file mode 100644 index 0000000000..8a174c5b77 --- /dev/null +++ b/erpnext/assets/onboarding_step/asset_item/asset_item.json @@ -0,0 +1,21 @@ +{ + "action": "Show Form Tour", + "action_label": "Let's create a new Asset item", + "creation": "2021-08-13 14:27:07.277167", + "description": "# Asset Item\n\nAsset items are created based on Asset Category. You can create one or multiple items against once Asset Category. The sales and purchase transaction for Asset is done via Asset Item. ", + "docstatus": 0, + "doctype": "Onboarding Step", + "idx": 0, + "is_complete": 0, + "is_single": 0, + "is_skipped": 0, + "modified": "2021-08-16 13:59:18.362233", + "modified_by": "Administrator", + "name": "Asset Item", + "owner": "Administrator", + "reference_document": "Item", + "show_form_tour": 0, + "show_full_form": 0, + "title": "Create an Asset Item", + "validate_action": 1 +} \ No newline at end of file diff --git a/erpnext/assets/onboarding_step/asset_purchase/asset_purchase.json b/erpnext/assets/onboarding_step/asset_purchase/asset_purchase.json new file mode 100644 index 0000000000..54611edc29 --- /dev/null +++ b/erpnext/assets/onboarding_step/asset_purchase/asset_purchase.json @@ -0,0 +1,21 @@ +{ + "action": "Show Form Tour", + "action_label": "Let's create a Purchase Receipt", + "creation": "2021-08-13 14:27:53.678621", + "description": "# Purchase an Asset\n\nAssets purchases process if done following the standard Purchase cycle. If capital work in progress is enabled in Asset Category, Asset will be created as soon as Purchase Receipt is created for it. You can quickly create a Purchase Receipt for Asset and see its impact on books of accounts.", + "docstatus": 0, + "doctype": "Onboarding Step", + "idx": 0, + "is_complete": 0, + "is_single": 0, + "is_skipped": 0, + "modified": "2021-08-24 17:26:57.180637", + "modified_by": "Administrator", + "name": "Asset Purchase", + "owner": "Administrator", + "reference_document": "Purchase Receipt", + "show_form_tour": 0, + "show_full_form": 0, + "title": "Purchase an Asset", + "validate_action": 1 +} \ No newline at end of file diff --git a/erpnext/assets/onboarding_step/existing_asset/existing_asset.json b/erpnext/assets/onboarding_step/existing_asset/existing_asset.json new file mode 100644 index 0000000000..052d5e8d77 --- /dev/null +++ b/erpnext/assets/onboarding_step/existing_asset/existing_asset.json @@ -0,0 +1,21 @@ +{ + "action": "Show Form Tour", + "action_label": "Add an existing Asset", + "creation": "2021-08-13 14:28:30.650459", + "description": "# Add an Existing Asset\n\nIf you are just starting with ERPNext, you will need to enter Assets you already possess. You can add them as existing fixed assets in ERPNext. Please note that you will have to make a Journal Entry separately updating the opening balance in the fixed asset account.", + "docstatus": 0, + "doctype": "Onboarding Step", + "idx": 0, + "is_complete": 0, + "is_single": 0, + "is_skipped": 0, + "modified": "2021-08-16 14:03:48.850471", + "modified_by": "Administrator", + "name": "Existing Asset", + "owner": "Administrator", + "reference_document": "Asset", + "show_form_tour": 0, + "show_full_form": 0, + "title": "Add an Existing Asset", + "validate_action": 1 +} \ No newline at end of file diff --git a/erpnext/assets/onboarding_step/fixed_asset_accounts/fixed_asset_accounts.json b/erpnext/assets/onboarding_step/fixed_asset_accounts/fixed_asset_accounts.json new file mode 100644 index 0000000000..cebee7a7ea --- /dev/null +++ b/erpnext/assets/onboarding_step/fixed_asset_accounts/fixed_asset_accounts.json @@ -0,0 +1,21 @@ +{ + "action": "Go to Page", + "action_label": "Let's walk-through Chart of Accounts to review setup", + "creation": "2021-08-13 14:23:09.297765", + "description": "# Fixed Asset Accounts\n\nWith the company, a host of fixed asset accounts are pre-configured. To ensure your asset transactions are leading to correct accounting entries, you can review and set up following asset accounts as per your business requirements.\n - Fixed asset accounts (Asset account)\n - Accumulated depreciation\n - Capital Work in progress (CWIP) account\n - Asset Depreciation account (Expense account)", + "docstatus": 0, + "doctype": "Onboarding Step", + "idx": 0, + "is_complete": 0, + "is_single": 0, + "is_skipped": 0, + "modified": "2021-08-24 17:46:37.646174", + "modified_by": "Administrator", + "name": "Fixed Asset Accounts", + "owner": "Administrator", + "path": "app/account/view/tree", + "show_form_tour": 0, + "show_full_form": 0, + "title": "Review Fixed Asset Accounts", + "validate_action": 1 +} \ No newline at end of file diff --git a/erpnext/selling/doctype/selling_settings/selling_settings.js b/erpnext/selling/doctype/selling_settings/selling_settings.js index d8d30515f8..cf6fb2806e 100644 --- a/erpnext/selling/doctype/selling_settings/selling_settings.js +++ b/erpnext/selling/doctype/selling_settings/selling_settings.js @@ -6,26 +6,3 @@ frappe.ui.form.on('Selling Settings', { } }); - -frappe.tour['Selling Settings'] = [ - { - fieldname: "cust_master_name", - title: "Customer Naming By", - description: __("By default, the Customer Name is set as per the Full Name entered. If you want Customers to be named by a ") + "Naming Series" + __(" choose the 'Naming Series' option."), - }, - { - fieldname: "selling_price_list", - title: "Default Selling Price List", - description: __("Configure the default Price List when creating a new Sales transaction. Item prices will be fetched from this Price List.") - }, - { - fieldname: "so_required", - title: "Sales Order Required for Sales Invoice & Delivery Note Creation", - description: __("If this option is configured 'Yes', ERPNext will prevent you from creating a Sales Invoice or Delivery Note without creating a Sales Order first. This configuration can be overridden for a particular Customer by enabling the 'Allow Sales Invoice Creation Without Sales Order' checkbox in the Customer master.") - }, - { - fieldname: "dn_required", - title: "Delivery Note Required for Sales Invoice Creation", - description: __("If this option is configured 'Yes', ERPNext will prevent you from creating a Sales Invoice without creating a Delivery Note first. This configuration can be overridden for a particular Customer by enabling the 'Allow Sales Invoice Creation Without Delivery Note' checkbox in the Customer master.") - } -]; diff --git a/erpnext/selling/form_tour/sales_order/sales_order.json b/erpnext/selling/form_tour/sales_order/sales_order.json new file mode 100644 index 0000000000..a81eb4a043 --- /dev/null +++ b/erpnext/selling/form_tour/sales_order/sales_order.json @@ -0,0 +1,97 @@ +{ + "creation": "2021-06-29 21:13:36.089054", + "docstatus": 0, + "doctype": "Form Tour", + "idx": 0, + "is_standard": 1, + "modified": "2021-06-29 21:13:36.089054", + "modified_by": "Administrator", + "module": "Selling", + "name": "Sales Order", + "owner": "Administrator", + "reference_doctype": "Sales Order", + "save_on_complete": 1, + "steps": [ + { + "description": "Select a customer.", + "field": "", + "fieldname": "customer", + "fieldtype": "Link", + "has_next_condition": 1, + "is_table_field": 0, + "label": "Customer", + "next_step_condition": "customer", + "parent_field": "", + "position": "Right", + "title": "Select Customer" + }, + { + "description": "You can add items here.", + "field": "", + "fieldname": "items", + "fieldtype": "Table", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Items", + "parent_field": "", + "position": "Bottom", + "title": "List of items" + }, + { + "child_doctype": "Sales Order Item", + "description": "Select an item.", + "field": "", + "fieldname": "item_code", + "fieldtype": "Link", + "has_next_condition": 1, + "is_table_field": 1, + "label": "Item Code", + "next_step_condition": "eval: doc.item_code", + "parent_field": "", + "parent_fieldname": "items", + "position": "Right", + "title": "Select Item" + }, + { + "child_doctype": "Sales Order Item", + "description": "Enter quantity.", + "field": "", + "fieldname": "qty", + "fieldtype": "Float", + "has_next_condition": 0, + "is_table_field": 1, + "label": "Quantity", + "parent_field": "", + "parent_fieldname": "items", + "position": "Right", + "title": "Enter Quantity" + }, + { + "child_doctype": "Sales Order Item", + "description": "Enter rate of the item.", + "field": "", + "fieldname": "rate", + "fieldtype": "Currency", + "has_next_condition": 0, + "is_table_field": 1, + "label": "Rate", + "parent_field": "", + "parent_fieldname": "items", + "position": "Right", + "title": "Enter Rate" + }, + { + "description": "You can add sales taxes and charges here.", + "field": "", + "fieldname": "taxes", + "fieldtype": "Table", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Sales Taxes and Charges", + "parent_field": "", + "position": "Bottom", + "title": "Add Sales Taxes and Charges" + } + ], + "title": "Sales Order" +} \ No newline at end of file diff --git a/erpnext/selling/form_tour/selling_settings/selling_settings.json b/erpnext/selling/form_tour/selling_settings/selling_settings.json new file mode 100644 index 0000000000..20c718f8c0 --- /dev/null +++ b/erpnext/selling/form_tour/selling_settings/selling_settings.json @@ -0,0 +1,65 @@ +{ + "creation": "2021-06-29 20:39:19.408763", + "docstatus": 0, + "doctype": "Form Tour", + "idx": 0, + "is_standard": 1, + "modified": "2021-06-29 20:49:01.359489", + "modified_by": "Administrator", + "module": "Selling", + "name": "Selling Settings", + "owner": "Administrator", + "reference_doctype": "Selling Settings", + "save_on_complete": 0, + "steps": [ + { + "description": "By default, the Customer Name is set as per the Full Name entered. If you want Customers to be named by a Naming Series. Choose the 'Naming Series' option.", + "field": "", + "fieldname": "cust_master_name", + "fieldtype": "Select", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Customer Naming By", + "parent_field": "", + "position": "Right", + "title": "Customer Naming By" + }, + { + "description": "If this option is configured 'Yes', ERPNext will prevent you from creating a Sales Invoice or Delivery Note without creating a Sales Order first. This configuration can be overridden for a particular Customer by enabling the 'Allow Sales Invoice Creation Without Sales Order' checkbox in the Customer master.", + "field": "", + "fieldname": "so_required", + "fieldtype": "Select", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Is Sales Order Required for Sales Invoice & Delivery Note Creation?", + "parent_field": "", + "position": "Left", + "title": "Sales Order Required for Sales Invoice & Delivery Note Creation" + }, + { + "description": "If this option is configured 'Yes', ERPNext will prevent you from creating a Sales Invoice without creating a Delivery Note first. This configuration can be overridden for a particular Customer by enabling the 'Allow Sales Invoice Creation Without Delivery Note' checkbox in the Customer master.", + "field": "", + "fieldname": "dn_required", + "fieldtype": "Select", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Is Delivery Note Required for Sales Invoice Creation?", + "parent_field": "", + "position": "Left", + "title": "Delivery Note Required for Sales Invoice Creation" + }, + { + "description": "Configure the default Price List when creating a new Sales transaction. Item prices will be fetched from this Price List.", + "field": "", + "fieldname": "selling_price_list", + "fieldtype": "Link", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Default Price List", + "parent_field": "", + "position": "Right", + "title": "Default Selling Price List" + } + ], + "title": "Selling Settings" +} \ No newline at end of file diff --git a/erpnext/selling/module_onboarding/selling/selling.json b/erpnext/selling/module_onboarding/selling/selling.json index 160208ff68..c02f444b05 100644 --- a/erpnext/selling/module_onboarding/selling/selling.json +++ b/erpnext/selling/module_onboarding/selling/selling.json @@ -19,32 +19,17 @@ "documentation_url": "https://docs.erpnext.com/docs/user/manual/en/selling", "idx": 0, "is_complete": 0, - "modified": "2020-07-08 14:05:37.669753", + "modified": "2021-08-24 18:12:38.052434", "modified_by": "Administrator", "module": "Selling", "name": "Selling", "owner": "Administrator", "steps": [ - { - "step": "Introduction to Selling" - }, - { - "step": "Create a Customer" - }, - { - "step": "Setup your Warehouse" - }, - { - "step": "Create a Product" - }, - { - "step": "Create a Quotation" - }, - { - "step": "Create your first Sales Order" - }, { "step": "Selling Settings" + }, + { + "step": "Sales Order" } ], "subtitle": "Products, Sales, Analysis, and more.", diff --git a/erpnext/selling/onboarding_step/create_a_customer/create_a_customer.json b/erpnext/selling/onboarding_step/create_a_customer/create_a_customer.json index 5a403b06cf..64defbfe3d 100644 --- a/erpnext/selling/onboarding_step/create_a_customer/create_a_customer.json +++ b/erpnext/selling/onboarding_step/create_a_customer/create_a_customer.json @@ -5,7 +5,6 @@ "doctype": "Onboarding Step", "idx": 0, "is_complete": 0, - "is_mandatory": 0, "is_single": 0, "is_skipped": 0, "modified": "2020-06-01 13:16:19.731719", @@ -13,6 +12,7 @@ "name": "Create a Customer", "owner": "Administrator", "reference_document": "Customer", + "show_form_tour": 0, "show_full_form": 0, "title": "Create a Customer", "validate_action": 1 diff --git a/erpnext/selling/onboarding_step/create_a_product/create_a_product.json b/erpnext/selling/onboarding_step/create_a_product/create_a_product.json index d2068e167b..52a5861551 100644 --- a/erpnext/selling/onboarding_step/create_a_product/create_a_product.json +++ b/erpnext/selling/onboarding_step/create_a_product/create_a_product.json @@ -5,14 +5,14 @@ "doctype": "Onboarding Step", "idx": 0, "is_complete": 0, - "is_mandatory": 0, "is_single": 0, "is_skipped": 0, - "modified": "2020-05-12 18:30:02.489949", + "modified": "2020-10-14 14:53:00.133574", "modified_by": "Administrator", "name": "Create a Product", "owner": "Administrator", "reference_document": "Item", + "show_form_tour": 0, "show_full_form": 0, "title": "Create a Product", "validate_action": 1 diff --git a/erpnext/selling/onboarding_step/create_a_quotation/create_a_quotation.json b/erpnext/selling/onboarding_step/create_a_quotation/create_a_quotation.json index 27253d15b6..6f1837e24c 100644 --- a/erpnext/selling/onboarding_step/create_a_quotation/create_a_quotation.json +++ b/erpnext/selling/onboarding_step/create_a_quotation/create_a_quotation.json @@ -5,7 +5,6 @@ "doctype": "Onboarding Step", "idx": 0, "is_complete": 0, - "is_mandatory": 0, "is_single": 0, "is_skipped": 0, "modified": "2020-06-01 13:34:58.958641", @@ -13,6 +12,7 @@ "name": "Create a Quotation", "owner": "Administrator", "reference_document": "Quotation", + "show_form_tour": 0, "show_full_form": 1, "title": "Create a Quotation", "validate_action": 1 diff --git a/erpnext/selling/onboarding_step/create_a_sales_order/create_a_sales_order.json b/erpnext/selling/onboarding_step/create_a_sales_order/create_a_sales_order.json new file mode 100644 index 0000000000..378f295f0c --- /dev/null +++ b/erpnext/selling/onboarding_step/create_a_sales_order/create_a_sales_order.json @@ -0,0 +1,21 @@ +{ + "action": "Create Entry", + "action_label": "Create Sales Order", + "creation": "2021-06-29 21:22:54.204880", + "description": "A Sales Order is a confirmation of an order from your customer. It is also referred to as Proforma Invoice.\n\nSales Order at the heart of your sales and purchase transactions. Sales Orders are linked in Delivery Note, Sales Invoices, Material Request, and Maintenance transactions. Through Sales Order, you can track fulfillment of the overall deal towards the customer.", + "docstatus": 0, + "doctype": "Onboarding Step", + "idx": 0, + "is_complete": 0, + "is_single": 0, + "is_skipped": 0, + "modified": "2021-06-29 21:22:54.204880", + "modified_by": "Administrator", + "name": "Create a Sales Order", + "owner": "Administrator", + "reference_document": "Sales Order", + "show_form_tour": 1, + "show_full_form": 1, + "title": "Create a Sales Order", + "validate_action": 1 +} \ No newline at end of file diff --git a/erpnext/selling/onboarding_step/introduction_to_selling/introduction_to_selling.json b/erpnext/selling/onboarding_step/introduction_to_selling/introduction_to_selling.json index d21c1f4954..636453363b 100644 --- a/erpnext/selling/onboarding_step/introduction_to_selling/introduction_to_selling.json +++ b/erpnext/selling/onboarding_step/introduction_to_selling/introduction_to_selling.json @@ -5,13 +5,13 @@ "doctype": "Onboarding Step", "idx": 0, "is_complete": 0, - "is_mandatory": 0, "is_single": 0, "is_skipped": 0, "modified": "2020-06-01 13:29:13.703177", "modified_by": "Administrator", "name": "Introduction to Selling", "owner": "Administrator", + "show_form_tour": 0, "show_full_form": 0, "title": "Introduction to Selling", "validate_action": 1, diff --git a/erpnext/selling/onboarding_step/sales_order/sales_order.json b/erpnext/selling/onboarding_step/sales_order/sales_order.json new file mode 100644 index 0000000000..d616fae066 --- /dev/null +++ b/erpnext/selling/onboarding_step/sales_order/sales_order.json @@ -0,0 +1,21 @@ +{ + "action": "Show Form Tour", + "action_label": "Let\u2019s convert your first Sales Order against a Quotation", + "creation": "2021-08-13 14:03:49.217866", + "description": "# Sales Order\n\nA Sales Order is a confirmation of an order from your customer. It is also referred to as Proforma Invoice.\n\nSales Order at the heart of your sales and purchase transactions. Sales Orders are linked in Delivery Note, Sales Invoices, Material Request, and Maintenance transactions. Through Sales Order, you can track fulfillment of the overall deal towards the customer.", + "docstatus": 0, + "doctype": "Onboarding Step", + "idx": 0, + "is_complete": 0, + "is_single": 0, + "is_skipped": 0, + "modified": "2021-08-24 18:12:32.394992", + "modified_by": "Administrator", + "name": "Sales Order", + "owner": "Administrator", + "reference_document": "Sales Order", + "show_form_tour": 0, + "show_full_form": 0, + "title": "Sales Order", + "validate_action": 1 +} \ No newline at end of file diff --git a/erpnext/selling/onboarding_step/selling_settings/selling_settings.json b/erpnext/selling/onboarding_step/selling_settings/selling_settings.json index 7996d7b159..ec30fd3033 100644 --- a/erpnext/selling/onboarding_step/selling_settings/selling_settings.json +++ b/erpnext/selling/onboarding_step/selling_settings/selling_settings.json @@ -1,19 +1,21 @@ { "action": "Show Form Tour", + "action_label": "Let\u2019s walk-through Selling Settings", "creation": "2020-06-01 13:01:45.615189", + "description": "# Selling Settings\n\nCRM and Selling module\u2019s features are configurable as per your business needs. Selling Settings is the place where you can set your preferences for:\n - Customer naming and default values\n - Billing and shipping preference in sales transactions\n", "docstatus": 0, "doctype": "Onboarding Step", "idx": 0, "is_complete": 0, - "is_mandatory": 0, "is_single": 1, "is_skipped": 0, - "modified": "2020-06-01 13:04:14.980743", + "modified": "2021-08-24 18:11:21.264335", "modified_by": "Administrator", "name": "Selling Settings", "owner": "Administrator", "reference_document": "Selling Settings", + "show_form_tour": 0, "show_full_form": 0, - "title": "Configure Selling Settings.", + "title": "Selling Settings", "validate_action": 0 } \ No newline at end of file diff --git a/erpnext/selling/onboarding_step/setup_your_warehouse/setup_your_warehouse.json b/erpnext/selling/onboarding_step/setup_your_warehouse/setup_your_warehouse.json index 9457deee26..1e20eb0eba 100644 --- a/erpnext/selling/onboarding_step/setup_your_warehouse/setup_your_warehouse.json +++ b/erpnext/selling/onboarding_step/setup_your_warehouse/setup_your_warehouse.json @@ -5,15 +5,15 @@ "doctype": "Onboarding Step", "idx": 0, "is_complete": 0, - "is_mandatory": 0, "is_single": 0, "is_skipped": 0, - "modified": "2020-07-04 12:33:16.970031", + "modified": "2020-10-14 14:53:25.538900", "modified_by": "Administrator", "name": "Setup your Warehouse", "owner": "Administrator", "path": "Tree/Warehouse", "reference_document": "Warehouse", + "show_form_tour": 0, "show_full_form": 0, "title": "Set up your Warehouse", "validate_action": 1 diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json index e4ee3ecea7..58cb52c04d 100644 --- a/erpnext/setup/doctype/company/company.json +++ b/erpnext/setup/doctype/company/company.json @@ -715,6 +715,15 @@ "label": "Default Payment Discount Account", "options": "Account" }, + { + "fieldname": "hr_settings_section", + "fieldtype": "Section Break", + "label": "HR & Payroll Settings" + }, + { + "fieldname": "column_break_26", + "fieldtype": "Column Break" + }, { "collapsible": 1, "fieldname": "fixed_asset_defaults", @@ -731,15 +740,6 @@ "fieldname": "section_break_28", "fieldtype": "Section Break", "label": "Chart of Accounts" - }, - { - "fieldname": "hr_settings_section", - "fieldtype": "Section Break", - "label": "HR & Payroll Settings" - }, - { - "fieldname": "column_break_26", - "fieldtype": "Column Break" } ], "icon": "fa fa-building", @@ -808,4 +808,4 @@ "sort_field": "modified", "sort_order": "ASC", "track_changes": 1 -} \ No newline at end of file +} diff --git a/erpnext/stock/form_tour/item/item.json b/erpnext/stock/form_tour/item/item.json new file mode 100644 index 0000000000..821e91b28d --- /dev/null +++ b/erpnext/stock/form_tour/item/item.json @@ -0,0 +1,89 @@ +{ + "creation": "2021-08-24 17:56:40.754909", + "docstatus": 0, + "doctype": "Form Tour", + "idx": 0, + "is_standard": 1, + "modified": "2021-08-24 18:04:50.928431", + "modified_by": "Administrator", + "module": "Stock", + "name": "Item", + "owner": "Administrator", + "reference_doctype": "Item", + "save_on_complete": 0, + "steps": [ + { + "description": "Enter code for Asset Item", + "field": "", + "fieldname": "item_code", + "fieldtype": "Data", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Item Code", + "parent_field": "", + "position": "Bottom", + "title": "Asset Item Code" + }, + { + "description": "Enter name for Asset Item", + "field": "", + "fieldname": "item_name", + "fieldtype": "Data", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Item Name", + "parent_field": "", + "position": "Bottom", + "title": "Asset Item Name" + }, + { + "description": "Check this field to make this an Asset Item", + "field": "", + "fieldname": "is_fixed_asset", + "fieldtype": "Check", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Is Fixed Asset", + "parent_field": "", + "position": "Bottom", + "title": "Is this a Fixed Asset?" + }, + { + "description": "On checking it, the system will create an Asset automatically on purchase", + "field": "", + "fieldname": "auto_create_assets", + "fieldtype": "Check", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Auto Create Assets on Purchase", + "parent_field": "", + "position": "Bottom", + "title": "Auto Create Asset on Purchase" + }, + { + "description": "Select an Asset Category for this Asset Item", + "field": "", + "fieldname": "asset_category", + "fieldtype": "Link", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Asset Category", + "parent_field": "", + "position": "Bottom", + "title": "Asset Category" + }, + { + "description": "Select a naming series which will be used to create an Asset automatically", + "field": "", + "fieldname": "asset_naming_series", + "fieldtype": "Select", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Asset Naming Series", + "parent_field": "", + "position": "Bottom", + "title": "Asset Naming Series" + } + ], + "title": "Item" +} diff --git a/erpnext/stock/form_tour/purchase_receipt/purchase_receipt.json b/erpnext/stock/form_tour/purchase_receipt/purchase_receipt.json new file mode 100644 index 0000000000..6fba3f4d68 --- /dev/null +++ b/erpnext/stock/form_tour/purchase_receipt/purchase_receipt.json @@ -0,0 +1,41 @@ +{ + "creation": "2021-08-24 13:03:21.333088", + "docstatus": 0, + "doctype": "Form Tour", + "idx": 0, + "is_standard": 1, + "modified": "2021-08-24 13:03:21.333088", + "modified_by": "Administrator", + "module": "Stock", + "name": "Purchase Receipt", + "owner": "Administrator", + "reference_doctype": "Purchase Receipt", + "save_on_complete": 0, + "steps": [ + { + "description": "Select Asset Supplier", + "field": "", + "fieldname": "supplier", + "fieldtype": "Link", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Supplier", + "parent_field": "", + "position": "Bottom", + "title": "Supplier" + }, + { + "description": "Select an Asset Item, Enter rate and quantity", + "field": "", + "fieldname": "items", + "fieldtype": "Table", + "has_next_condition": 0, + "is_table_field": 0, + "label": "Items", + "parent_field": "", + "position": "Bottom", + "title": "Items" + } + ], + "title": "Purchase Receipt" +} \ No newline at end of file