From 23e1d2b536b6da805eb305c70c6878374d07aaa6 Mon Sep 17 00:00:00 2001
From: 18alantom <2.alan.tom@gmail.com>
Date: Tue, 18 May 2021 17:11:47 +0530
Subject: [PATCH 01/80] refactor: update stock onboarding
---
.../stock/module_onboarding/stock/stock.json | 16 +++++++++----
.../create_a_delivery_note.json | 20 ++++++++++++++++
.../create_a_purchase_receipt.json | 5 ++--
.../create_a_stock_entry.json | 5 ++--
.../create_a_supplier/create_a_supplier.json | 7 +++---
.../create_a_warehouse.json | 20 ++++++++++++++++
.../create_an_item/create_an_item.json | 22 ++++++++++++++++++
.../introduction_to_stock_entry.json | 5 ++--
.../setup_your_warehouse.json | 4 ++--
.../stock_settings/stock_settings.json | 5 ++--
.../view_stock_ledger/view_stock_ledger.json | 23 +++++++++++++++++++
.../view_warehouses/view_warehouses.json | 20 ++++++++++++++++
12 files changed, 134 insertions(+), 18 deletions(-)
create mode 100644 erpnext/stock/onboarding_step/create_a_delivery_note/create_a_delivery_note.json
create mode 100644 erpnext/stock/onboarding_step/create_a_warehouse/create_a_warehouse.json
create mode 100644 erpnext/stock/onboarding_step/create_an_item/create_an_item.json
create mode 100644 erpnext/stock/onboarding_step/view_stock_ledger/view_stock_ledger.json
create mode 100644 erpnext/stock/onboarding_step/view_warehouses/view_warehouses.json
diff --git a/erpnext/stock/module_onboarding/stock/stock.json b/erpnext/stock/module_onboarding/stock/stock.json
index 847464822b4..6cc8ec6b052 100644
--- a/erpnext/stock/module_onboarding/stock/stock.json
+++ b/erpnext/stock/module_onboarding/stock/stock.json
@@ -19,20 +19,23 @@
"documentation_url": "https://docs.erpnext.com/docs/user/manual/en/stock",
"idx": 0,
"is_complete": 0,
- "modified": "2020-10-14 14:54:42.741971",
+ "modified": "2021-05-18 17:01:36.137180",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock",
"owner": "Administrator",
"steps": [
{
- "step": "Setup your Warehouse"
+ "step": "Create an Item"
},
{
- "step": "Create a Product"
+ "step": "View Warehouses"
},
{
- "step": "Create a Supplier"
+ "step": "Create a Warehouse"
+ },
+ {
+ "step": "Stock Settings"
},
{
"step": "Introduction to Stock Entry"
@@ -40,11 +43,14 @@
{
"step": "Create a Stock Entry"
},
+ {
+ "step": "View Stock Ledger"
+ },
{
"step": "Create a Purchase Receipt"
},
{
- "step": "Stock Settings"
+ "step": "Create a Delivery Note"
}
],
"subtitle": "Inventory, Warehouses, Analysis, and more.",
diff --git a/erpnext/stock/onboarding_step/create_a_delivery_note/create_a_delivery_note.json b/erpnext/stock/onboarding_step/create_a_delivery_note/create_a_delivery_note.json
new file mode 100644
index 00000000000..7b702f013b6
--- /dev/null
+++ b/erpnext/stock/onboarding_step/create_a_delivery_note/create_a_delivery_note.json
@@ -0,0 +1,20 @@
+{
+ "action": "Create Entry",
+ "creation": "2021-05-17 16:15:11.745214",
+ "description": "# Create a Delivery Note\nA [**Delivery Note**](https://docs.erpnext.com/docs/user/manual/en/stock/delivery-note) is made when a shipment is shipped from the company\u2019s *Warehouse* to the *Customer*. \n\nIn this step we will create a *Delivery Note*.",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2021-05-18 15:33:47.452298",
+ "modified_by": "Administrator",
+ "name": "Create a Delivery Note",
+ "owner": "Administrator",
+ "reference_document": "Delivery Note",
+ "show_form_tour": 1,
+ "show_full_form": 1,
+ "title": "Create a Delivery Note",
+ "validate_action": 1
+}
\ No newline at end of file
diff --git a/erpnext/stock/onboarding_step/create_a_purchase_receipt/create_a_purchase_receipt.json b/erpnext/stock/onboarding_step/create_a_purchase_receipt/create_a_purchase_receipt.json
index 9012493f57e..549fe26c253 100644
--- a/erpnext/stock/onboarding_step/create_a_purchase_receipt/create_a_purchase_receipt.json
+++ b/erpnext/stock/onboarding_step/create_a_purchase_receipt/create_a_purchase_receipt.json
@@ -1,18 +1,19 @@
{
"action": "Create Entry",
"creation": "2020-05-19 18:59:13.266713",
+ "description": "# Create a Purchase Entry\nA [**Purchase Receipt**](https://docs.erpnext.com/docs/user/manual/en/stock/purchase-receipt) is made when an *Item* is received from a *Supplier*. \n\nIn this step we will create a *Purchase Receipt*.",
"docstatus": 0,
"doctype": "Onboarding Step",
"idx": 0,
"is_complete": 0,
- "is_mandatory": 0,
"is_single": 0,
"is_skipped": 0,
- "modified": "2020-10-14 14:53:25.618434",
+ "modified": "2021-05-18 15:17:44.204445",
"modified_by": "Administrator",
"name": "Create a Purchase Receipt",
"owner": "Administrator",
"reference_document": "Purchase Receipt",
+ "show_form_tour": 1,
"show_full_form": 1,
"title": "Create a Purchase Receipt",
"validate_action": 1
diff --git a/erpnext/stock/onboarding_step/create_a_stock_entry/create_a_stock_entry.json b/erpnext/stock/onboarding_step/create_a_stock_entry/create_a_stock_entry.json
index 09902b8844e..2244c13d5de 100644
--- a/erpnext/stock/onboarding_step/create_a_stock_entry/create_a_stock_entry.json
+++ b/erpnext/stock/onboarding_step/create_a_stock_entry/create_a_stock_entry.json
@@ -1,18 +1,19 @@
{
"action": "Create Entry",
"creation": "2020-05-15 03:20:16.277043",
+ "description": "# Create a Stock Entry\nA [**Stock Entry**](https://docs.erpnext.com/docs/user/manual/en/stock/stock-entry) allows you to record the movement of *Items* between *Warehouses*. \n\nIn this step we will create *Stock Entry*.",
"docstatus": 0,
"doctype": "Onboarding Step",
"idx": 0,
"is_complete": 0,
- "is_mandatory": 0,
"is_single": 0,
"is_skipped": 0,
- "modified": "2020-10-14 14:53:00.105905",
+ "modified": "2021-05-18 15:15:26.355884",
"modified_by": "Administrator",
"name": "Create a Stock Entry",
"owner": "Administrator",
"reference_document": "Stock Entry",
+ "show_form_tour": 1,
"show_full_form": 1,
"title": "Create a Stock Entry",
"validate_action": 1
diff --git a/erpnext/stock/onboarding_step/create_a_supplier/create_a_supplier.json b/erpnext/stock/onboarding_step/create_a_supplier/create_a_supplier.json
index ef61fa3b2e2..49efe578a29 100644
--- a/erpnext/stock/onboarding_step/create_a_supplier/create_a_supplier.json
+++ b/erpnext/stock/onboarding_step/create_a_supplier/create_a_supplier.json
@@ -1,18 +1,19 @@
{
- "action": "Create Entry",
+ "action": "Show Form Tour",
"creation": "2020-05-14 22:09:10.043554",
+ "description": "# Create a Supplier\nIn this step we will create a **Supplier**. If you have already created a **Supplier** you can skip this step.",
"docstatus": 0,
"doctype": "Onboarding Step",
"idx": 0,
"is_complete": 0,
- "is_mandatory": 0,
"is_single": 0,
"is_skipped": 0,
- "modified": "2020-10-14 14:53:00.120455",
+ "modified": "2021-05-17 16:37:37.697077",
"modified_by": "Administrator",
"name": "Create a Supplier",
"owner": "Administrator",
"reference_document": "Supplier",
+ "show_form_tour": 0,
"show_full_form": 0,
"title": "Create a Supplier",
"validate_action": 1
diff --git a/erpnext/stock/onboarding_step/create_a_warehouse/create_a_warehouse.json b/erpnext/stock/onboarding_step/create_a_warehouse/create_a_warehouse.json
new file mode 100644
index 00000000000..b31b0d03d7b
--- /dev/null
+++ b/erpnext/stock/onboarding_step/create_a_warehouse/create_a_warehouse.json
@@ -0,0 +1,20 @@
+{
+ "action": "Create Entry",
+ "creation": "2021-05-17 16:13:19.297789",
+ "description": "# Create a Warehouse\nIn this step we will create a [**Warehouse**](https://docs.erpnext.com/docs/user/manual/en/stock/warehouse).",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2021-05-18 15:00:36.896793",
+ "modified_by": "Administrator",
+ "name": "Create a Warehouse",
+ "owner": "Administrator",
+ "reference_document": "Warehouse",
+ "show_form_tour": 1,
+ "show_full_form": 1,
+ "title": "Create a Warehouse",
+ "validate_action": 1
+}
\ No newline at end of file
diff --git a/erpnext/stock/onboarding_step/create_an_item/create_an_item.json b/erpnext/stock/onboarding_step/create_an_item/create_an_item.json
new file mode 100644
index 00000000000..016cbd566d5
--- /dev/null
+++ b/erpnext/stock/onboarding_step/create_an_item/create_an_item.json
@@ -0,0 +1,22 @@
+{
+ "action": "Create Entry",
+ "action_label": "",
+ "creation": "2021-05-17 13:47:18.515052",
+ "description": "# Create an Item\nThe Stock module deals with the movement of items.\n\nIn this step we will create an [**Item**](https://docs.erpnext.com/docs/user/manual/en/stock/item).",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "intro_video_url": "",
+ "is_complete": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2021-05-18 16:15:20.695028",
+ "modified_by": "Administrator",
+ "name": "Create an Item",
+ "owner": "Administrator",
+ "reference_document": "Item",
+ "show_form_tour": 1,
+ "show_full_form": 1,
+ "title": "Create an Item",
+ "validate_action": 1
+}
\ No newline at end of file
diff --git a/erpnext/stock/onboarding_step/introduction_to_stock_entry/introduction_to_stock_entry.json b/erpnext/stock/onboarding_step/introduction_to_stock_entry/introduction_to_stock_entry.json
index 212e5055eda..384950e8b99 100644
--- a/erpnext/stock/onboarding_step/introduction_to_stock_entry/introduction_to_stock_entry.json
+++ b/erpnext/stock/onboarding_step/introduction_to_stock_entry/introduction_to_stock_entry.json
@@ -1,17 +1,18 @@
{
"action": "Watch Video",
"creation": "2020-05-15 02:47:17.958806",
+ "description": "# Introduction to Stock Entry\nThis video will give a quick introduction to [**Stock Entry**](https://docs.erpnext.com/docs/user/manual/en/stock/stock-entry).",
"docstatus": 0,
"doctype": "Onboarding Step",
"idx": 0,
"is_complete": 0,
- "is_mandatory": 0,
"is_single": 0,
"is_skipped": 0,
- "modified": "2020-10-14 14:53:00.075177",
+ "modified": "2021-05-18 15:13:43.306064",
"modified_by": "Administrator",
"name": "Introduction to Stock Entry",
"owner": "Administrator",
+ "show_form_tour": 0,
"show_full_form": 0,
"title": "Introduction to Stock Entry",
"validate_action": 1,
diff --git a/erpnext/stock/onboarding_step/setup_your_warehouse/setup_your_warehouse.json b/erpnext/stock/onboarding_step/setup_your_warehouse/setup_your_warehouse.json
index 75940ed2a6c..5d33a649100 100644
--- a/erpnext/stock/onboarding_step/setup_your_warehouse/setup_your_warehouse.json
+++ b/erpnext/stock/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-10-14 14:53:25.538900",
+ "modified": "2021-05-17 13:53:06.936579",
"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/stock/onboarding_step/stock_settings/stock_settings.json b/erpnext/stock/onboarding_step/stock_settings/stock_settings.json
index ae34afa695f..096a3d2b471 100644
--- a/erpnext/stock/onboarding_step/stock_settings/stock_settings.json
+++ b/erpnext/stock/onboarding_step/stock_settings/stock_settings.json
@@ -1,18 +1,19 @@
{
"action": "Show Form Tour",
"creation": "2020-05-15 02:53:57.209967",
+ "description": "# Stock Settings\nIn this step we will view the [**Stock Settings**](https://docs.erpnext.com/docs/user/manual/en/stock/stock-settings) page, here you can set the default settings for your stock related transactions.",
"docstatus": 0,
"doctype": "Onboarding Step",
"idx": 0,
"is_complete": 0,
- "is_mandatory": 0,
"is_single": 1,
"is_skipped": 0,
- "modified": "2020-10-14 14:53:00.092504",
+ "modified": "2021-05-18 16:44:58.084849",
"modified_by": "Administrator",
"name": "Stock Settings",
"owner": "Administrator",
"reference_document": "Stock Settings",
+ "show_form_tour": 0,
"show_full_form": 0,
"title": "Explore Stock Settings",
"validate_action": 1
diff --git a/erpnext/stock/onboarding_step/view_stock_ledger/view_stock_ledger.json b/erpnext/stock/onboarding_step/view_stock_ledger/view_stock_ledger.json
new file mode 100644
index 00000000000..13661bc9fbd
--- /dev/null
+++ b/erpnext/stock/onboarding_step/view_stock_ledger/view_stock_ledger.json
@@ -0,0 +1,23 @@
+{
+ "action": "View Report",
+ "creation": "2021-05-17 16:16:10.727959",
+ "description": "# View Stock Ledger\nThe [**Stock Ledger**](https://docs.erpnext.com/docs/user/manual/en/stock/stock-ledger) is a detailed record that keeps track of stock movements for a company. \n\nIn this step we will view the *Stock Ledger*.",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2021-05-18 16:16:38.150079",
+ "modified_by": "Administrator",
+ "name": "View Stock Ledger",
+ "owner": "Administrator",
+ "reference_report": "Stock Ledger",
+ "report_description": "You can set the filters to see entries specific to the previous steps.",
+ "report_reference_doctype": "Stock Ledger Entry",
+ "report_type": "Script Report",
+ "show_form_tour": 0,
+ "show_full_form": 0,
+ "title": "View Stock Ledger",
+ "validate_action": 1
+}
\ No newline at end of file
diff --git a/erpnext/stock/onboarding_step/view_warehouses/view_warehouses.json b/erpnext/stock/onboarding_step/view_warehouses/view_warehouses.json
new file mode 100644
index 00000000000..c46c4bdab86
--- /dev/null
+++ b/erpnext/stock/onboarding_step/view_warehouses/view_warehouses.json
@@ -0,0 +1,20 @@
+{
+ "action": "Go to Page",
+ "creation": "2021-05-17 16:12:43.427579",
+ "description": "# View Warehouse\nIn ERPNext the term 'warehouse' can be thought of as a storage location.\n\nWarehouses are arranged in ERPNext in a tree like structure, where multiple sub-warehouses can be grouped under a single warehouse.\n\nIn this step we will view the [**Warehouse Tree**](https://docs.erpnext.com/docs/user/manual/en/stock/warehouse#21-tree-view) to view the [**Warehouses**](https://docs.erpnext.com/docs/user/manual/en/stock/warehouse) that are set by default.",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2021-05-18 15:04:41.198413",
+ "modified_by": "Administrator",
+ "name": "View Warehouses",
+ "owner": "Administrator",
+ "path": "Tree/Warehouse",
+ "show_form_tour": 0,
+ "show_full_form": 0,
+ "title": "View Warehouses",
+ "validate_action": 1
+}
\ No newline at end of file
From 0b669b3d7e0e079a4029ec5898d8de0e38333648 Mon Sep 17 00:00:00 2001
From: 18alantom <2.alan.tom@gmail.com>
Date: Tue, 18 May 2021 17:18:04 +0530
Subject: [PATCH 02/80] refactor: add form tour for stock module onboarding
---
.../doctype/delivery_note/delivery_note.js | 20 ++++++++++
erpnext/stock/doctype/item/item.js | 39 +++++++++++++++++++
.../purchase_receipt/purchase_receipt.js | 20 ++++++++++
.../stock/doctype/stock_entry/stock_entry.js | 20 ++++++++++
erpnext/stock/doctype/warehouse/warehouse.js | 25 +++++++++++-
5 files changed, 123 insertions(+), 1 deletion(-)
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js
index 36dfa6d7951..b73ebd6c3bd 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.js
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.js
@@ -356,3 +356,23 @@ erpnext.stock.delivery_note.set_print_hide = function(doc, cdt, cdn){
dn_fields['taxes'].print_hide = 0;
}
}
+
+
+frappe.tour['Delivery Note'] = [
+ {
+ fieldname: "customer",
+ title: __("Customer"),
+ description: __("This field is used to set the 'Customer'.")
+ },
+ {
+ fieldname: "items",
+ title: __("Items"),
+ description: __("This table is used to set details about the 'Item', 'Qty', 'Basic Rate', etc. ") +
+ __("Different 'Source Warehouse' and 'Target Warehouse' can be set for each row.")
+ },
+ {
+ fieldname: "set_posting_time",
+ title: __("Edit Posting Date and Time"),
+ description: __("This option can be checked to edit the 'Posting Date' and 'Posting Time' fields.")
+ }
+]
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index c5bc9f14fb1..6af14c95a45 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -793,3 +793,42 @@ frappe.ui.form.on("UOM Conversion Detail", {
}
}
})
+
+
+frappe.tour['Item'] = [
+ {
+ fieldname: "item_name",
+ title: __("Item Name"),
+ description: __("This is the actual name of the product or service.")
+ },
+ {
+ fieldname: "item_code",
+ title: __("Item Code"),
+ description: __("The Item Code can be thought of as a short-form that refers to the item. ") +
+ __("For more information click here: ") +
+ "Item Codification" +
+ __("."),
+ },
+ {
+ fieldname: "item_group",
+ title: __("Item Group"),
+ description: __("This is used for categorizing items under a common criteria. ") +
+ __("For more information click here: ") +
+ "Item Group" +
+ __("."),
+ },
+ {
+ fieldname: "stock_uom",
+ title: __("Default Unit of Measure"),
+ description: __("The Item Code can be thought of as a short-form that refers to the item. ") +
+ __("For more information click here: ") +
+ "Unit of Measure" +
+ __("."),
+ },
+ {
+ fieldname: "is_stock_item",
+ title: __("Maintain Stock"),
+ description: __("Selecting this creates a stock item and 'Stock Ledger' entries are created for all transcations. ") +
+ __("Unselect this for a non-stock item such as a service.")
+ },
+]
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
index 0182ed55a18..fd4be86ae98 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
@@ -347,3 +347,23 @@ var validate_sample_quantity = function(frm, cdt, cdn) {
});
}
};
+
+
+frappe.tour['Purchase Receipt'] = [
+ {
+ fieldname: "supplier",
+ title: __("Supplier"),
+ description: __("This field is used to set the 'Supplier'.")
+ },
+ {
+ fieldname: "items",
+ title: __("Items"),
+ description: __("This table is used to set details about the 'Item', 'Qty', 'Basic Rate', etc. ") +
+ __("Different 'Source Warehouse' and 'Target Warehouse' can be set for each row.")
+ },
+ {
+ fieldname: "set_posting_time",
+ title: __("Edit Posting Date and Time"),
+ description: __("This option can be checked to edit the 'Posting Date' and 'Posting Time' fields.")
+ }
+]
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 908020d02ba..8616a4cd3fe 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -1101,3 +1101,23 @@ function check_should_not_attach_bom_items(bom_no) {
}
$.extend(cur_frm.cscript, new erpnext.stock.StockEntry({frm: cur_frm}));
+
+frappe.tour['Stock Entry'] = [
+ {
+ fieldname: "stock_entry_type",
+ title: __("Stock Entry Type"),
+ description: __("There are multiple 'Stock Entry Type's you can even create your own. ") +
+ __("For moving material between warehouses you can select 'Material Transfer'")
+ },
+ {
+ fieldname: "items",
+ title: __("Items"),
+ description: __("This table is used to set details about the 'Item', 'Qty', 'Basic Rate', etc. ") +
+ __("Different 'Source Warehouse' and 'Target Warehouse' can be set for each row.")
+ },
+ {
+ fieldname: "set_posting_time",
+ title: __("Edit Posting Date and Time"),
+ description: __("This option can be checked to edit the 'Posting Date' and 'Posting Time' fields.")
+ }
+]
diff --git a/erpnext/stock/doctype/warehouse/warehouse.js b/erpnext/stock/doctype/warehouse/warehouse.js
index 1f172504a7f..9b5f2bc0b1d 100644
--- a/erpnext/stock/doctype/warehouse/warehouse.js
+++ b/erpnext/stock/doctype/warehouse/warehouse.js
@@ -85,4 +85,27 @@ function convert_to_group_or_ledger(frm){
}
})
-}
\ No newline at end of file
+}
+
+frappe.tour['Warehouse'] = [
+ {
+ fieldname: "warehouse_name",
+ title: __("Warehouse Name"),
+ description: __("A 'Warehouse Name' can be assigned to the warehouse. This should reflect the type of goods it contains.")
+ },
+ {
+ fieldname: "warehouse_type",
+ title: __("Warehouse Type"),
+ description: __("A 'Warehouse Type' can be set to classify warehouses.")
+ },
+ {
+ fieldname: "is_group",
+ title: __("Is Group"),
+ description: __("If you check 'Is Group', you can group warehouses under this warehouse.")
+ },
+ {
+ fieldname: "account",
+ title: __("Account"),
+ description: __("This field can be used to set a default account for all transactions with this warehouse.")
+ },
+]
From 1851232e3cc13676c131de99cc2df0b6fc5526ee Mon Sep 17 00:00:00 2001
From: 18alantom <2.alan.tom@gmail.com>
Date: Tue, 18 May 2021 17:30:23 +0530
Subject: [PATCH 03/80] refactor: move trailing whitespace out of translate
func
---
erpnext/stock/doctype/delivery_note/delivery_note.js | 2 +-
erpnext/stock/doctype/item/item.js | 12 ++++++------
.../doctype/purchase_receipt/purchase_receipt.js | 2 +-
erpnext/stock/doctype/stock_entry/stock_entry.js | 4 ++--
4 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js
index b73ebd6c3bd..706ca365988 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.js
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.js
@@ -367,7 +367,7 @@ frappe.tour['Delivery Note'] = [
{
fieldname: "items",
title: __("Items"),
- description: __("This table is used to set details about the 'Item', 'Qty', 'Basic Rate', etc. ") +
+ description: __("This table is used to set details about the 'Item', 'Qty', 'Basic Rate', etc.") + " " +
__("Different 'Source Warehouse' and 'Target Warehouse' can be set for each row.")
},
{
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index 6af14c95a45..e664e9c1cd7 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -804,7 +804,7 @@ frappe.tour['Item'] = [
{
fieldname: "item_code",
title: __("Item Code"),
- description: __("The Item Code can be thought of as a short-form that refers to the item. ") +
+ description: __("The Item Code can be thought of as a short-form that refers to the item.") + " " +
__("For more information click here: ") +
"Item Codification" +
__("."),
@@ -812,23 +812,23 @@ frappe.tour['Item'] = [
{
fieldname: "item_group",
title: __("Item Group"),
- description: __("This is used for categorizing items under a common criteria. ") +
- __("For more information click here: ") +
+ description: __("This is used for categorizing items under a common criteria.") + " " +
+ __("For more information click here:") + " " +
"Item Group" +
__("."),
},
{
fieldname: "stock_uom",
title: __("Default Unit of Measure"),
- description: __("The Item Code can be thought of as a short-form that refers to the item. ") +
- __("For more information click here: ") +
+ description: __("The Item Code can be thought of as a short-form that refers to the item.") + " " +
+ __("For more information click here:") + " " +
"Unit of Measure" +
__("."),
},
{
fieldname: "is_stock_item",
title: __("Maintain Stock"),
- description: __("Selecting this creates a stock item and 'Stock Ledger' entries are created for all transcations. ") +
+ description: __("Selecting this creates a stock item and 'Stock Ledger' entries are created for all transcations.") + " " +
__("Unselect this for a non-stock item such as a service.")
},
]
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
index fd4be86ae98..9f002f459fb 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
@@ -358,7 +358,7 @@ frappe.tour['Purchase Receipt'] = [
{
fieldname: "items",
title: __("Items"),
- description: __("This table is used to set details about the 'Item', 'Qty', 'Basic Rate', etc. ") +
+ description: __("This table is used to set details about the 'Item', 'Qty', 'Basic Rate', etc.") + " " +
__("Different 'Source Warehouse' and 'Target Warehouse' can be set for each row.")
},
{
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 8616a4cd3fe..30d0750959e 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -1106,13 +1106,13 @@ frappe.tour['Stock Entry'] = [
{
fieldname: "stock_entry_type",
title: __("Stock Entry Type"),
- description: __("There are multiple 'Stock Entry Type's you can even create your own. ") +
+ description: __("There are multiple 'Stock Entry Type's you can even create your own.") + " " +
__("For moving material between warehouses you can select 'Material Transfer'")
},
{
fieldname: "items",
title: __("Items"),
- description: __("This table is used to set details about the 'Item', 'Qty', 'Basic Rate', etc. ") +
+ description: __("This table is used to set details about the 'Item', 'Qty', 'Basic Rate', etc.") + " " +
__("Different 'Source Warehouse' and 'Target Warehouse' can be set for each row.")
},
{
From 51d2317bb5339022040d2e177156c30157a6c20e Mon Sep 17 00:00:00 2001
From: 18alantom <2.alan.tom@gmail.com>
Date: Tue, 18 May 2021 17:50:59 +0530
Subject: [PATCH 04/80] refactor: sider/semgrep
---
erpnext/stock/doctype/item/item.js | 6 +++---
erpnext/stock/doctype/warehouse/warehouse.js | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index e664e9c1cd7..3144f1c12a6 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -792,7 +792,7 @@ frappe.ui.form.on("UOM Conversion Detail", {
});
}
}
-})
+});
frappe.tour['Item'] = [
@@ -805,7 +805,7 @@ frappe.tour['Item'] = [
fieldname: "item_code",
title: __("Item Code"),
description: __("The Item Code can be thought of as a short-form that refers to the item.") + " " +
- __("For more information click here: ") +
+ __("For more information click here:") + " " +
"Item Codification" +
__("."),
},
@@ -831,4 +831,4 @@ frappe.tour['Item'] = [
description: __("Selecting this creates a stock item and 'Stock Ledger' entries are created for all transcations.") + " " +
__("Unselect this for a non-stock item such as a service.")
},
-]
+];
diff --git a/erpnext/stock/doctype/warehouse/warehouse.js b/erpnext/stock/doctype/warehouse/warehouse.js
index 9b5f2bc0b1d..af9a5152470 100644
--- a/erpnext/stock/doctype/warehouse/warehouse.js
+++ b/erpnext/stock/doctype/warehouse/warehouse.js
@@ -108,4 +108,4 @@ frappe.tour['Warehouse'] = [
title: __("Account"),
description: __("This field can be used to set a default account for all transactions with this warehouse.")
},
-]
+];
From 1d67d20185e48e537a1841d5bc73ceb56ad41cfd Mon Sep 17 00:00:00 2001
From: 18alantom <2.alan.tom@gmail.com>
Date: Thu, 20 May 2021 13:04:59 +0530
Subject: [PATCH 05/80] refactor: remove DN, PR; change wording, add/remove
steps in tour
---
erpnext/stock/doctype/item/item.js | 20 +++++++++---------
.../stock/doctype/stock_entry/stock_entry.js | 21 ++++++++++++-------
erpnext/stock/doctype/warehouse/warehouse.js | 8 +++----
.../create_a_delivery_note.json | 20 ------------------
.../create_a_purchase_receipt.json | 20 ------------------
5 files changed, 27 insertions(+), 62 deletions(-)
delete mode 100644 erpnext/stock/onboarding_step/create_a_delivery_note/create_a_delivery_note.json
delete mode 100644 erpnext/stock/onboarding_step/create_a_purchase_receipt/create_a_purchase_receipt.json
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index 3144f1c12a6..5c632fc7d54 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -796,23 +796,23 @@ frappe.ui.form.on("UOM Conversion Detail", {
frappe.tour['Item'] = [
- {
- fieldname: "item_name",
- title: __("Item Name"),
- description: __("This is the actual name of the product or service.")
- },
{
fieldname: "item_code",
title: __("Item Code"),
- description: __("The Item Code can be thought of as a short-form that refers to the item.") + " " +
+ description: __("Select an item code, this can be an SKU or a product code.") + " " +
__("For more information click here:") + " " +
"Item Codification" +
__("."),
},
+ {
+ fieldname: "item_name",
+ title: __("Item Name"),
+ description: __("Select an item name, this is the actual name of the item. You will be able to search and select an item with its name as well.")
+ },
{
fieldname: "item_group",
title: __("Item Group"),
- description: __("This is used for categorizing items under a common criteria.") + " " +
+ description: __("Select an item group to categorizing items under a common criteria. You can even create custom Item Groups.") + " " +
__("For more information click here:") + " " +
"Item Group" +
__("."),
@@ -820,7 +820,7 @@ frappe.tour['Item'] = [
{
fieldname: "stock_uom",
title: __("Default Unit of Measure"),
- description: __("The Item Code can be thought of as a short-form that refers to the item.") + " " +
+ description: __("This decides the unit of measure in which stock balance will be maintained for this item.") + " " +
__("For more information click here:") + " " +
"Unit of Measure" +
__("."),
@@ -828,7 +828,7 @@ frappe.tour['Item'] = [
{
fieldname: "is_stock_item",
title: __("Maintain Stock"),
- description: __("Selecting this creates a stock item and 'Stock Ledger' entries are created for all transcations.") + " " +
- __("Unselect this for a non-stock item such as a service.")
+ description: __("Check this field to maintain stock for this item.") + " " +
+ __("Uncheck this field for non-stock items such as a service.")
},
];
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 30d0750959e..e7bf0f3bf9b 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -1106,18 +1106,23 @@ frappe.tour['Stock Entry'] = [
{
fieldname: "stock_entry_type",
title: __("Stock Entry Type"),
- description: __("There are multiple 'Stock Entry Type's you can even create your own.") + " " +
- __("For moving material between warehouses you can select 'Material Transfer'")
+ description: __("Select the type of Stock Entry to be made.") + " " +
+ __("For now, to move stock between warehouses select Material Transfer.")
+ },
+ {
+ fieldname: "from_warehouse",
+ title: __("Default Source Warehouse"),
+ description: __("Select a source warehouse, where you have stock available.")
+ },
+ {
+ fieldname: "to_warehouse",
+ title: __("Default Target Warehouse"),
+ description: __("Select a target warehouse, where stock needs to be transferred.")
},
{
fieldname: "items",
title: __("Items"),
- description: __("This table is used to set details about the 'Item', 'Qty', 'Basic Rate', etc.") + " " +
+ description: __("Select an item and entry quantity to be delivered.") + " " +
__("Different 'Source Warehouse' and 'Target Warehouse' can be set for each row.")
},
- {
- fieldname: "set_posting_time",
- title: __("Edit Posting Date and Time"),
- description: __("This option can be checked to edit the 'Posting Date' and 'Posting Time' fields.")
- }
]
diff --git a/erpnext/stock/doctype/warehouse/warehouse.js b/erpnext/stock/doctype/warehouse/warehouse.js
index af9a5152470..b29c6fdde3c 100644
--- a/erpnext/stock/doctype/warehouse/warehouse.js
+++ b/erpnext/stock/doctype/warehouse/warehouse.js
@@ -91,21 +91,21 @@ frappe.tour['Warehouse'] = [
{
fieldname: "warehouse_name",
title: __("Warehouse Name"),
- description: __("A 'Warehouse Name' can be assigned to the warehouse. This should reflect the type of goods it contains.")
+ description: __("Select a name for the warehouse. This should reflect it's location or purpose.")
},
{
fieldname: "warehouse_type",
title: __("Warehouse Type"),
- description: __("A 'Warehouse Type' can be set to classify warehouses.")
+ description: __("Select a warehouse type to categorize the warehouse into a sub-group.")
},
{
fieldname: "is_group",
title: __("Is Group"),
- description: __("If you check 'Is Group', you can group warehouses under this warehouse.")
+ description: __("Check this field to group warehouses under this warehouse.")
},
{
fieldname: "account",
title: __("Account"),
- description: __("This field can be used to set a default account for all transactions with this warehouse.")
+ description: __("Select an account to set a default account for all transactions with this warehouse.")
},
];
diff --git a/erpnext/stock/onboarding_step/create_a_delivery_note/create_a_delivery_note.json b/erpnext/stock/onboarding_step/create_a_delivery_note/create_a_delivery_note.json
deleted file mode 100644
index 7b702f013b6..00000000000
--- a/erpnext/stock/onboarding_step/create_a_delivery_note/create_a_delivery_note.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "action": "Create Entry",
- "creation": "2021-05-17 16:15:11.745214",
- "description": "# Create a Delivery Note\nA [**Delivery Note**](https://docs.erpnext.com/docs/user/manual/en/stock/delivery-note) is made when a shipment is shipped from the company\u2019s *Warehouse* to the *Customer*. \n\nIn this step we will create a *Delivery Note*.",
- "docstatus": 0,
- "doctype": "Onboarding Step",
- "idx": 0,
- "is_complete": 0,
- "is_single": 0,
- "is_skipped": 0,
- "modified": "2021-05-18 15:33:47.452298",
- "modified_by": "Administrator",
- "name": "Create a Delivery Note",
- "owner": "Administrator",
- "reference_document": "Delivery Note",
- "show_form_tour": 1,
- "show_full_form": 1,
- "title": "Create a Delivery Note",
- "validate_action": 1
-}
\ No newline at end of file
diff --git a/erpnext/stock/onboarding_step/create_a_purchase_receipt/create_a_purchase_receipt.json b/erpnext/stock/onboarding_step/create_a_purchase_receipt/create_a_purchase_receipt.json
deleted file mode 100644
index 549fe26c253..00000000000
--- a/erpnext/stock/onboarding_step/create_a_purchase_receipt/create_a_purchase_receipt.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "action": "Create Entry",
- "creation": "2020-05-19 18:59:13.266713",
- "description": "# Create a Purchase Entry\nA [**Purchase Receipt**](https://docs.erpnext.com/docs/user/manual/en/stock/purchase-receipt) is made when an *Item* is received from a *Supplier*. \n\nIn this step we will create a *Purchase Receipt*.",
- "docstatus": 0,
- "doctype": "Onboarding Step",
- "idx": 0,
- "is_complete": 0,
- "is_single": 0,
- "is_skipped": 0,
- "modified": "2021-05-18 15:17:44.204445",
- "modified_by": "Administrator",
- "name": "Create a Purchase Receipt",
- "owner": "Administrator",
- "reference_document": "Purchase Receipt",
- "show_form_tour": 1,
- "show_full_form": 1,
- "title": "Create a Purchase Receipt",
- "validate_action": 1
-}
\ No newline at end of file
From 9581836885bd37e577e5c70fadf72738ecb0a7a3 Mon Sep 17 00:00:00 2001
From: 18alantom <2.alan.tom@gmail.com>
Date: Thu, 20 May 2021 15:23:17 +0530
Subject: [PATCH 06/80] refactor: add watch video step for stock opening
balance
---
.../stock/module_onboarding/stock/stock.json | 7 ++-----
.../stock_opening_balance.json | 21 +++++++++++++++++++
2 files changed, 23 insertions(+), 5 deletions(-)
create mode 100644 erpnext/stock/onboarding_step/stock_opening_balance/stock_opening_balance.json
diff --git a/erpnext/stock/module_onboarding/stock/stock.json b/erpnext/stock/module_onboarding/stock/stock.json
index 6cc8ec6b052..9e91090d5b2 100644
--- a/erpnext/stock/module_onboarding/stock/stock.json
+++ b/erpnext/stock/module_onboarding/stock/stock.json
@@ -19,7 +19,7 @@
"documentation_url": "https://docs.erpnext.com/docs/user/manual/en/stock",
"idx": 0,
"is_complete": 0,
- "modified": "2021-05-18 17:01:36.137180",
+ "modified": "2021-05-20 15:08:11.987145",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock",
@@ -47,10 +47,7 @@
"step": "View Stock Ledger"
},
{
- "step": "Create a Purchase Receipt"
- },
- {
- "step": "Create a Delivery Note"
+ "step": "Stock Opening Balance"
}
],
"subtitle": "Inventory, Warehouses, Analysis, and more.",
diff --git a/erpnext/stock/onboarding_step/stock_opening_balance/stock_opening_balance.json b/erpnext/stock/onboarding_step/stock_opening_balance/stock_opening_balance.json
new file mode 100644
index 00000000000..19d6a37ba4d
--- /dev/null
+++ b/erpnext/stock/onboarding_step/stock_opening_balance/stock_opening_balance.json
@@ -0,0 +1,21 @@
+{
+ "action": "Watch Video",
+ "creation": "2021-05-17 16:13:47.511883",
+ "description": "# Stock Opening Balance\nTo set the Stock Opening Balance, you can create a [**Stock Reconciliation**](https://docs.erpnext.com/docs/user/manual/en/stock/stock-reconciliation) entry with _Purpose_ set to _Opening Balance_.\n\nFor more information you can watch the video.",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2021-05-20 15:07:19.545934",
+ "modified_by": "Administrator",
+ "name": "Stock Opening Balance",
+ "owner": "Administrator",
+ "reference_document": "Stock Reconciliation",
+ "show_form_tour": 1,
+ "show_full_form": 1,
+ "title": "Stock Opening Balance",
+ "validate_action": 1,
+ "video_url": "https://www.youtube.com/watch?v=nlHX0ZZ84Lw"
+}
\ No newline at end of file
From 37466631f20b16e94253ac2115717aed2ceeb9b8 Mon Sep 17 00:00:00 2001
From: 18alantom <2.alan.tom@gmail.com>
Date: Thu, 20 May 2021 15:28:08 +0530
Subject: [PATCH 07/80] refactor: reorder steps according to stock settings
refactor
---
erpnext/stock/doctype/stock_settings/stock_settings.js | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.js b/erpnext/stock/doctype/stock_settings/stock_settings.js
index 48624e0f25e..e2f1f951ec3 100644
--- a/erpnext/stock/doctype/stock_settings/stock_settings.js
+++ b/erpnext/stock/doctype/stock_settings/stock_settings.js
@@ -27,17 +27,17 @@ frappe.tour['Stock Settings'] = [
title: __("Default Warehouse"),
description: __("Set a Default Warehouse for Inventory Transactions. This will be fetched into the Default Warehouse in the Item master.")
},
+ {
+ fieldname: "valuation_method",
+ title: __("Valuation Method"),
+ description: __("Choose between FIFO and Moving Average Valuation Methods. Click ") + "here" + __(" to know more about them.")
+ },
{
fieldname: "allow_negative_stock",
title: __("Allow Negative Stock"),
description: __("This will allow stock items to be displayed in negative values. Using this option depends on your use case. With this option unchecked, the system warns before obstructing a transaction that is causing negative stock.")
},
- {
- fieldname: "valuation_method",
- title: __("Valuation Method"),
- description: __("Choose between FIFO and Moving Average Valuation Methods. Click ") + "here" + __(" to know more about them.")
- },
{
fieldname: "show_barcode_field",
title: __("Show Barcode Field"),
From 95992a7ea54de397c200c3be4925e7c0a5fa6482 Mon Sep 17 00:00:00 2001
From: 18alantom <2.alan.tom@gmail.com>
Date: Thu, 20 May 2021 15:29:24 +0530
Subject: [PATCH 08/80] refactor: fix typo, remove target warehouse cause SE
Type dependency
---
erpnext/stock/doctype/stock_entry/stock_entry.js | 5 -----
erpnext/stock/doctype/warehouse/warehouse.js | 2 +-
2 files changed, 1 insertion(+), 6 deletions(-)
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index e7bf0f3bf9b..ecd3fee8286 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -1114,11 +1114,6 @@ frappe.tour['Stock Entry'] = [
title: __("Default Source Warehouse"),
description: __("Select a source warehouse, where you have stock available.")
},
- {
- fieldname: "to_warehouse",
- title: __("Default Target Warehouse"),
- description: __("Select a target warehouse, where stock needs to be transferred.")
- },
{
fieldname: "items",
title: __("Items"),
diff --git a/erpnext/stock/doctype/warehouse/warehouse.js b/erpnext/stock/doctype/warehouse/warehouse.js
index b29c6fdde3c..30575a7c933 100644
--- a/erpnext/stock/doctype/warehouse/warehouse.js
+++ b/erpnext/stock/doctype/warehouse/warehouse.js
@@ -91,7 +91,7 @@ frappe.tour['Warehouse'] = [
{
fieldname: "warehouse_name",
title: __("Warehouse Name"),
- description: __("Select a name for the warehouse. This should reflect it's location or purpose.")
+ description: __("Select a name for the warehouse. This should reflect its location or purpose.")
},
{
fieldname: "warehouse_type",
From 599c1024a221624f83f50a7295768292aebce48a Mon Sep 17 00:00:00 2001
From: 18alantom <2.alan.tom@gmail.com>
Date: Thu, 20 May 2021 15:49:26 +0530
Subject: [PATCH 09/80] fix: semgrep, remove trailing and leading whitespaces
---
erpnext/stock/doctype/stock_settings/stock_settings.js | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.js b/erpnext/stock/doctype/stock_settings/stock_settings.js
index e2f1f951ec3..6a919309f54 100644
--- a/erpnext/stock/doctype/stock_settings/stock_settings.js
+++ b/erpnext/stock/doctype/stock_settings/stock_settings.js
@@ -20,7 +20,9 @@ frappe.tour['Stock Settings'] = [
{
fieldname: "item_naming_by",
title: __("Item Naming By"),
- description: __("By default, the Item Name is set as per the Item Code entered. If you want Items to be named by a ") + "Naming Series" + __(" choose the 'Naming Series' option."),
+ description: __("By default, the Item Name is set as per the Item Code entered. If you want Items to be named by a") + " " +
+ "Naming Series" + " " +
+ __("choose the 'Naming Series' option."),
},
{
fieldname: "default_warehouse",
@@ -30,7 +32,9 @@ frappe.tour['Stock Settings'] = [
{
fieldname: "valuation_method",
title: __("Valuation Method"),
- description: __("Choose between FIFO and Moving Average Valuation Methods. Click ") + "here" + __(" to know more about them.")
+ description: __("Choose between FIFO and Moving Average Valuation Methods. Click") + " " +
+ "here" + " " +
+ __("to know more about them.")
},
{
fieldname: "allow_negative_stock",
From f7b747e19c322df60f7cc31ac3cf0c75bc9e29aa Mon Sep 17 00:00:00 2001
From: 18alantom <2.alan.tom@gmail.com>
Date: Fri, 18 Jun 2021 14:43:56 +0530
Subject: [PATCH 10/80] refactor: reduce steps, reword cards
---
erpnext/stock/doctype/item/item.js | 39 -------------------
.../purchase_receipt/purchase_receipt.js | 20 ----------
.../stock_reconciliation.js | 13 +++++++
.../stock/module_onboarding/stock/stock.json | 17 ++------
.../create_a_stock_entry.json | 7 ++--
.../create_a_warehouse.json | 7 ++--
.../stock_opening_balance.json | 9 +++--
.../stock_settings/stock_settings.json | 7 ++--
.../view_stock_balance.json | 24 ++++++++++++
.../view_stock_ledger/view_stock_ledger.json | 7 ++--
10 files changed, 62 insertions(+), 88 deletions(-)
create mode 100644 erpnext/stock/onboarding_step/view_stock_balance/view_stock_balance.json
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index 5c632fc7d54..c587dd5c7ec 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -793,42 +793,3 @@ frappe.ui.form.on("UOM Conversion Detail", {
}
}
});
-
-
-frappe.tour['Item'] = [
- {
- fieldname: "item_code",
- title: __("Item Code"),
- description: __("Select an item code, this can be an SKU or a product code.") + " " +
- __("For more information click here:") + " " +
- "Item Codification" +
- __("."),
- },
- {
- fieldname: "item_name",
- title: __("Item Name"),
- description: __("Select an item name, this is the actual name of the item. You will be able to search and select an item with its name as well.")
- },
- {
- fieldname: "item_group",
- title: __("Item Group"),
- description: __("Select an item group to categorizing items under a common criteria. You can even create custom Item Groups.") + " " +
- __("For more information click here:") + " " +
- "Item Group" +
- __("."),
- },
- {
- fieldname: "stock_uom",
- title: __("Default Unit of Measure"),
- description: __("This decides the unit of measure in which stock balance will be maintained for this item.") + " " +
- __("For more information click here:") + " " +
- "Unit of Measure" +
- __("."),
- },
- {
- fieldname: "is_stock_item",
- title: __("Maintain Stock"),
- description: __("Check this field to maintain stock for this item.") + " " +
- __("Uncheck this field for non-stock items such as a service.")
- },
-];
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
index 9f002f459fb..0182ed55a18 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
@@ -347,23 +347,3 @@ var validate_sample_quantity = function(frm, cdt, cdn) {
});
}
};
-
-
-frappe.tour['Purchase Receipt'] = [
- {
- fieldname: "supplier",
- title: __("Supplier"),
- description: __("This field is used to set the 'Supplier'.")
- },
- {
- fieldname: "items",
- title: __("Items"),
- description: __("This table is used to set details about the 'Item', 'Qty', 'Basic Rate', etc.") + " " +
- __("Different 'Source Warehouse' and 'Target Warehouse' can be set for each row.")
- },
- {
- fieldname: "set_posting_time",
- title: __("Edit Posting Date and Time"),
- description: __("This option can be checked to edit the 'Posting Date' and 'Posting Time' fields.")
- }
-]
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
index 84f65a077e0..49c85401ace 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
@@ -302,3 +302,16 @@ erpnext.stock.StockReconciliation = class StockReconciliation extends erpnext.st
};
cur_frm.cscript = new erpnext.stock.StockReconciliation({frm: cur_frm});
+
+frappe.tour['Stock Reconciliation'] = [
+ {
+ fieldname: "purpose",
+ title: __("Purpose"),
+ description: __("Set Purpose to Opening Stock to set the stock opening balance.")
+ },
+ {
+ fieldname: "items",
+ title: __("Items"),
+ description: __("Select the items for which the opening stock has to be set.")
+ },
+];
diff --git a/erpnext/stock/module_onboarding/stock/stock.json b/erpnext/stock/module_onboarding/stock/stock.json
index 9e91090d5b2..4503f534c7c 100644
--- a/erpnext/stock/module_onboarding/stock/stock.json
+++ b/erpnext/stock/module_onboarding/stock/stock.json
@@ -19,35 +19,26 @@
"documentation_url": "https://docs.erpnext.com/docs/user/manual/en/stock",
"idx": 0,
"is_complete": 0,
- "modified": "2021-05-20 15:08:11.987145",
+ "modified": "2021-06-18 14:41:24.286683",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock",
"owner": "Administrator",
"steps": [
{
- "step": "Create an Item"
- },
- {
- "step": "View Warehouses"
+ "step": "Stock Settings"
},
{
"step": "Create a Warehouse"
},
- {
- "step": "Stock Settings"
- },
- {
- "step": "Introduction to Stock Entry"
- },
{
"step": "Create a Stock Entry"
},
{
- "step": "View Stock Ledger"
+ "step": "Stock Opening Balance"
},
{
- "step": "Stock Opening Balance"
+ "step": "View Stock Balance"
}
],
"subtitle": "Inventory, Warehouses, Analysis, and more.",
diff --git a/erpnext/stock/onboarding_step/create_a_stock_entry/create_a_stock_entry.json b/erpnext/stock/onboarding_step/create_a_stock_entry/create_a_stock_entry.json
index 2244c13d5de..3cb522c893d 100644
--- a/erpnext/stock/onboarding_step/create_a_stock_entry/create_a_stock_entry.json
+++ b/erpnext/stock/onboarding_step/create_a_stock_entry/create_a_stock_entry.json
@@ -1,20 +1,21 @@
{
"action": "Create Entry",
+ "action_label": "Create a Material Transfer Entry",
"creation": "2020-05-15 03:20:16.277043",
- "description": "# Create a Stock Entry\nA [**Stock Entry**](https://docs.erpnext.com/docs/user/manual/en/stock/stock-entry) allows you to record the movement of *Items* between *Warehouses*. \n\nIn this step we will create *Stock Entry*.",
+ "description": "# Manage Stock Movements\nStock entry allows you to register the movement of stock for various purposes like transfer, received, issues, repacked, etc. To address issues related to theft and pilferages, you can always ensure that the movement of goods happens against a document reference Stock Entry in ERPNext.\n\nLet\u2019s get a quick walk-through on the various scenarios covered in Stock Entry by watching [*this video*](https://www.youtube.com/watch?v=Njt107hlY3I).",
"docstatus": 0,
"doctype": "Onboarding Step",
"idx": 0,
"is_complete": 0,
"is_single": 0,
"is_skipped": 0,
- "modified": "2021-05-18 15:15:26.355884",
+ "modified": "2021-06-18 13:57:11.434063",
"modified_by": "Administrator",
"name": "Create a Stock Entry",
"owner": "Administrator",
"reference_document": "Stock Entry",
"show_form_tour": 1,
"show_full_form": 1,
- "title": "Create a Stock Entry",
+ "title": "Manage Stock Movements",
"validate_action": 1
}
\ No newline at end of file
diff --git a/erpnext/stock/onboarding_step/create_a_warehouse/create_a_warehouse.json b/erpnext/stock/onboarding_step/create_a_warehouse/create_a_warehouse.json
index b31b0d03d7b..0ef6c3615c4 100644
--- a/erpnext/stock/onboarding_step/create_a_warehouse/create_a_warehouse.json
+++ b/erpnext/stock/onboarding_step/create_a_warehouse/create_a_warehouse.json
@@ -1,20 +1,21 @@
{
"action": "Create Entry",
+ "action_label": "Let\u2019s create your first warehouse ",
"creation": "2021-05-17 16:13:19.297789",
- "description": "# Create a Warehouse\nIn this step we will create a [**Warehouse**](https://docs.erpnext.com/docs/user/manual/en/stock/warehouse).",
+ "description": "# Setup a Warehouse\nThe warehouse can be your location/godown/store where you maintain the item's inventory, and receive/deliver them to various parties.\n\nIn ERPNext, you can maintain a Warehouse in the tree structure, so that location and sub-location of an item can be tracked. Also, you can link a Warehouse to a specific Accounting ledger, where the real-time stock value of that warehouse\u2019s item will be reflected.",
"docstatus": 0,
"doctype": "Onboarding Step",
"idx": 0,
"is_complete": 0,
"is_single": 0,
"is_skipped": 0,
- "modified": "2021-05-18 15:00:36.896793",
+ "modified": "2021-06-18 13:52:51.126984",
"modified_by": "Administrator",
"name": "Create a Warehouse",
"owner": "Administrator",
"reference_document": "Warehouse",
"show_form_tour": 1,
"show_full_form": 1,
- "title": "Create a Warehouse",
+ "title": "Setup a Warehouse",
"validate_action": 1
}
\ No newline at end of file
diff --git a/erpnext/stock/onboarding_step/stock_opening_balance/stock_opening_balance.json b/erpnext/stock/onboarding_step/stock_opening_balance/stock_opening_balance.json
index 19d6a37ba4d..48fd1fddee0 100644
--- a/erpnext/stock/onboarding_step/stock_opening_balance/stock_opening_balance.json
+++ b/erpnext/stock/onboarding_step/stock_opening_balance/stock_opening_balance.json
@@ -1,21 +1,22 @@
{
- "action": "Watch Video",
+ "action": "Create Entry",
+ "action_label": "Let\u2019s create a stock opening entry",
"creation": "2021-05-17 16:13:47.511883",
- "description": "# Stock Opening Balance\nTo set the Stock Opening Balance, you can create a [**Stock Reconciliation**](https://docs.erpnext.com/docs/user/manual/en/stock/stock-reconciliation) entry with _Purpose_ set to _Opening Balance_.\n\nFor more information you can watch the video.",
+ "description": "# Update Stock Opening Balance\nIt\u2019s an entry to update the stock balance of an item, in a warehouse, on a date and time you are going live on ERPNext.\n\nOnce opening stocks are updated, you can create transactions like manufacturing and stock deliveries, where this opening stock will be consumed.",
"docstatus": 0,
"doctype": "Onboarding Step",
"idx": 0,
"is_complete": 0,
"is_single": 0,
"is_skipped": 0,
- "modified": "2021-05-20 15:07:19.545934",
+ "modified": "2021-06-18 13:59:36.021097",
"modified_by": "Administrator",
"name": "Stock Opening Balance",
"owner": "Administrator",
"reference_document": "Stock Reconciliation",
"show_form_tour": 1,
"show_full_form": 1,
- "title": "Stock Opening Balance",
+ "title": "Update Stock Opening Balance",
"validate_action": 1,
"video_url": "https://www.youtube.com/watch?v=nlHX0ZZ84Lw"
}
\ No newline at end of file
diff --git a/erpnext/stock/onboarding_step/stock_settings/stock_settings.json b/erpnext/stock/onboarding_step/stock_settings/stock_settings.json
index 096a3d2b471..f7238da3348 100644
--- a/erpnext/stock/onboarding_step/stock_settings/stock_settings.json
+++ b/erpnext/stock/onboarding_step/stock_settings/stock_settings.json
@@ -1,20 +1,21 @@
{
"action": "Show Form Tour",
+ "action_label": "Take a walk through Stock Settings",
"creation": "2020-05-15 02:53:57.209967",
- "description": "# Stock Settings\nIn this step we will view the [**Stock Settings**](https://docs.erpnext.com/docs/user/manual/en/stock/stock-settings) page, here you can set the default settings for your stock related transactions.",
+ "description": "# Review Stock Settings\n\nIn ERPNext, the Stock module\u2019s features are configurable as per your business needs. Stock Settings is the place where you can set your preferences for:\n- Default values for Item and Pricing\n- Default valuation method for inventory valuation\n- Set preference for serialization and batching of item\n- Set tolerance for over-receipt and delivery of items",
"docstatus": 0,
"doctype": "Onboarding Step",
"idx": 0,
"is_complete": 0,
"is_single": 1,
"is_skipped": 0,
- "modified": "2021-05-18 16:44:58.084849",
+ "modified": "2021-06-18 14:13:12.678178",
"modified_by": "Administrator",
"name": "Stock Settings",
"owner": "Administrator",
"reference_document": "Stock Settings",
"show_form_tour": 0,
"show_full_form": 0,
- "title": "Explore Stock Settings",
+ "title": "Review Stock Settings",
"validate_action": 1
}
\ No newline at end of file
diff --git a/erpnext/stock/onboarding_step/view_stock_balance/view_stock_balance.json b/erpnext/stock/onboarding_step/view_stock_balance/view_stock_balance.json
new file mode 100644
index 00000000000..ed5fe369459
--- /dev/null
+++ b/erpnext/stock/onboarding_step/view_stock_balance/view_stock_balance.json
@@ -0,0 +1,24 @@
+{
+ "action": "View Report",
+ "action_label": "Check Stock Balance",
+ "creation": "2021-05-17 16:15:54.617572",
+ "description": "# Check Stock Reports\nBased on the various stock transactions, you can get a host of one-click Stock Reports in ERPNext like Stock Ledger, Stock Balance, Projected Quantity, and Ageing analysis.",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2021-06-18 14:41:18.499215",
+ "modified_by": "Administrator",
+ "name": "View Stock Balance",
+ "owner": "Administrator",
+ "reference_report": "Stock Balance",
+ "report_description": "You can set the filters to narrow the results, then click on Generate New Report to see the updated report.",
+ "report_reference_doctype": "Stock Ledger Entry",
+ "report_type": "Script Report",
+ "show_form_tour": 0,
+ "show_full_form": 0,
+ "title": "Check Stock Reports",
+ "validate_action": 1
+}
\ No newline at end of file
diff --git a/erpnext/stock/onboarding_step/view_stock_ledger/view_stock_ledger.json b/erpnext/stock/onboarding_step/view_stock_ledger/view_stock_ledger.json
index 13661bc9fbd..7a5f164e016 100644
--- a/erpnext/stock/onboarding_step/view_stock_ledger/view_stock_ledger.json
+++ b/erpnext/stock/onboarding_step/view_stock_ledger/view_stock_ledger.json
@@ -1,14 +1,15 @@
{
"action": "View Report",
+ "action_label": "Check Stock Ledger",
"creation": "2021-05-17 16:16:10.727959",
- "description": "# View Stock Ledger\nThe [**Stock Ledger**](https://docs.erpnext.com/docs/user/manual/en/stock/stock-ledger) is a detailed record that keeps track of stock movements for a company. \n\nIn this step we will view the *Stock Ledger*.",
+ "description": "# Check Stock Reports\nBased on the various stock transactions, you can get a host of one-click Stock Reports in ERPNext like Stock Ledger, Stock Balance, Projected Quantity, and Ageing analysis.",
"docstatus": 0,
"doctype": "Onboarding Step",
"idx": 0,
"is_complete": 0,
"is_single": 0,
"is_skipped": 0,
- "modified": "2021-05-18 16:16:38.150079",
+ "modified": "2021-06-18 14:09:39.399311",
"modified_by": "Administrator",
"name": "View Stock Ledger",
"owner": "Administrator",
@@ -18,6 +19,6 @@
"report_type": "Script Report",
"show_form_tour": 0,
"show_full_form": 0,
- "title": "View Stock Ledger",
+ "title": "Check Stock Reports",
"validate_action": 1
}
\ No newline at end of file
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 11/80] 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 0ba85078ead..6bd2a985e23 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 9f7091dd8d7..7018082e402 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 7b31d2fdf2d..478d5b2e0f1 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 22f412a2989..df65706c39d 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 12/80] 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 3f50b41be1b..a5ce8c61956 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 6bd2a985e23..de0c521cf50 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 13/80] 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 478d5b2e0f1..4f724ec637b 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 14/80] 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 a5ce8c61956..dd437dd5554 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 de0c521cf50..b90d54dea5f 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 15/80] 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 c89f7d66fdf..e61bb525927 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 00000000000..d74f31672d1
--- /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 16/80] 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 b90d54dea5f..8f01edd0e29 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 4f724ec637b..21c0e753930 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 17/80] 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 e61bb525927..fe7a8f151b2 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 d74f31672d1..285ae4f59e8 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 18/80] 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 dd437dd5554..7e755d424c4 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 19/80] 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 7e755d424c4..7de7e17abc2 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 20/80] 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 8f01edd0e29..8d9b10ddc13 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 21/80] 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 fe7a8f151b2..6e17f2a8314 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 bf1ccb71594..7f943d9cbb6 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 22/80] 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 7f943d9cbb6..d6a20df0c89 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 21c0e753930..8ea12752834 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 23/80] 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 00000000000..e69de29bb2d
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 00000000000..966a5f5d30b
--- /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 00000000000..2053dc0f00a
--- /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 00000000000..80f86e75a02
--- /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 00000000000..a3ea3959ba4
--- /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 24/80] 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 a246ae51a46..7d0ecfbafd9 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 25/80] 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 a16795e6287..e2f02f37ee7 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 5fa622856bc..f29f7bef22e 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 4c243d0cc46..1b232890620 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 26/80] 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 4d1e0c3e062..8bb25dc6633 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 27/80] 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 966a5f5d30b..6da9291d64d 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 6ef16ee4fb3d07526dcb81e6277bc9f5d5e9911e Mon Sep 17 00:00:00 2001
From: 18alantom <2.alan.tom@gmail.com>
Date: Fri, 20 Aug 2021 12:24:13 +0530
Subject: [PATCH 28/80] fix: update scrap table item details; typo
---
erpnext/manufacturing/doctype/bom/bom.py | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 0ba85078ead..eb1dfc8cae8 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -148,6 +148,7 @@ class BOM(WebsiteGenerator):
self.set_plc_conversion_rate()
self.validate_uom_is_interger()
self.set_bom_material_details()
+ self.set_bom_scrap_items_detail()
self.validate_materials()
self.set_routing_operations()
self.validate_operations()
@@ -200,7 +201,7 @@ class BOM(WebsiteGenerator):
def set_bom_material_details(self):
for item in self.get("items"):
- self.validate_bom_currecny(item)
+ self.validate_bom_currency(item)
ret = self.get_bom_material_detail({
"company": self.company,
@@ -219,6 +220,19 @@ class BOM(WebsiteGenerator):
if not item.get(r):
item.set(r, ret[r])
+ def set_bom_scrap_items_detail(self):
+ for item in self.get("scrap_items"):
+ args = {
+ "item_code": item.item_code,
+ "company": self.company,
+ "scrap_items": True,
+ "bom_no": '',
+ }
+ ret = self.get_bom_material_detail(args)
+ for key, value in ret.items():
+ if not item.get(key):
+ item.set(key, value)
+
@frappe.whitelist()
def get_bom_material_detail(self, args=None):
""" Get raw material details like uom, desc and rate"""
@@ -255,7 +269,7 @@ class BOM(WebsiteGenerator):
return ret_item
- def validate_bom_currecny(self, item):
+ def validate_bom_currency(self, item):
if item.get('bom_no') and frappe.db.get_value('BOM', item.get('bom_no'), 'currency') != self.currency:
frappe.throw(_("Row {0}: Currency of the BOM #{1} should be equal to the selected currency {2}")
.format(item.idx, item.bom_no, self.currency))
From 77ebbdd172c355f8598dcdc92cd1340cb8ad1f29 Mon Sep 17 00:00:00 2001
From: 18alantom <2.alan.tom@gmail.com>
Date: Fri, 20 Aug 2021 16:21:33 +0530
Subject: [PATCH 29/80] fix: minor changes
- remove Is Group from warehouse
- change stock entry type
- link to stock entry type
- add posting date to stock reco
- change report to Stock Projected Qty
- highlight quality inspection action
- remove allow neg highlight
---
.../stock/doctype/stock_entry/stock_entry.js | 12 ++++------
.../stock_reconciliation.js | 5 ++++
.../doctype/stock_settings/stock_settings.js | 12 +++++-----
erpnext/stock/doctype/warehouse/warehouse.js | 8 ++-----
.../stock/module_onboarding/stock/stock.json | 4 ++--
.../create_a_warehouse.json | 2 +-
.../stock_settings/stock_settings.json | 2 +-
.../view_stock_ledger/view_stock_ledger.json | 24 -------------------
.../view_stock_projected_qty.json} | 14 +++++------
9 files changed, 29 insertions(+), 54 deletions(-)
delete mode 100644 erpnext/stock/onboarding_step/view_stock_ledger/view_stock_ledger.json
rename erpnext/stock/onboarding_step/{view_stock_balance/view_stock_balance.json => view_stock_projected_qty/view_stock_projected_qty.json} (69%)
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index ecd3fee8286..5ea733c66d3 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -1106,18 +1106,16 @@ frappe.tour['Stock Entry'] = [
{
fieldname: "stock_entry_type",
title: __("Stock Entry Type"),
- description: __("Select the type of Stock Entry to be made.") + " " +
- __("For now, to move stock between warehouses select Material Transfer.")
+ description: __("Select the type of Stock Entry to be made. For now, to receive stock into a warehouses select") + ' ' + __("Material Receipt.") + ""
},
{
- fieldname: "from_warehouse",
- title: __("Default Source Warehouse"),
- description: __("Select a source warehouse, where you have stock available.")
+ fieldname: "to_warehouse",
+ title: __("Default Target Warehouse"),
+ description: __("Select a target warehouse where the stock will be received.")
},
{
fieldname: "items",
title: __("Items"),
- description: __("Select an item and entry quantity to be delivered.") + " " +
- __("Different 'Source Warehouse' and 'Target Warehouse' can be set for each row.")
+ description: __("Select an item and entry quantity to be delivered.")
},
]
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
index 49c85401ace..f91d0a740d8 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
@@ -309,6 +309,11 @@ frappe.tour['Stock Reconciliation'] = [
title: __("Purpose"),
description: __("Set Purpose to Opening Stock to set the stock opening balance.")
},
+ {
+ fieldname: "posting_date",
+ title: __("Posting Date"),
+ description: __("Edit the Posting Date by clicking on the Edit Posting Date and Time checkbox below.")
+ },
{
fieldname: "items",
title: __("Items"),
diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.js b/erpnext/stock/doctype/stock_settings/stock_settings.js
index 6a919309f54..08606fdcaa6 100644
--- a/erpnext/stock/doctype/stock_settings/stock_settings.js
+++ b/erpnext/stock/doctype/stock_settings/stock_settings.js
@@ -36,17 +36,17 @@ frappe.tour['Stock Settings'] = [
"here" + " " +
__("to know more about them.")
},
- {
- fieldname: "allow_negative_stock",
- title: __("Allow Negative Stock"),
- description: __("This will allow stock items to be displayed in negative values. Using this option depends on your use case. With this option unchecked, the system warns before obstructing a transaction that is causing negative stock.")
-
- },
{
fieldname: "show_barcode_field",
title: __("Show Barcode Field"),
description: __("Show 'Scan Barcode' field above every child table to insert Items with ease.")
},
+ {
+ fieldname: "action_if_quality_inspection_is_not_submitted",
+ title: __("Action if Quality Inspection Is Not Submitted"),
+ description: __("Quality inspection is performed on the inward and outward movement of goods. Receipt and delivery transactions will be stopped or the user will be warned if the quality inspection is not performed.")
+
+ },
{
fieldname: "automatically_set_serial_nos_based_on_fifo",
title: __("Automatically Set Serial Nos based on FIFO"),
diff --git a/erpnext/stock/doctype/warehouse/warehouse.js b/erpnext/stock/doctype/warehouse/warehouse.js
index 30575a7c933..8b925bebf9e 100644
--- a/erpnext/stock/doctype/warehouse/warehouse.js
+++ b/erpnext/stock/doctype/warehouse/warehouse.js
@@ -91,21 +91,17 @@ frappe.tour['Warehouse'] = [
{
fieldname: "warehouse_name",
title: __("Warehouse Name"),
- description: __("Select a name for the warehouse. This should reflect its location or purpose.")
+ description: __("Select name for the warehouse. This should reflect its location or purpose.")
},
{
fieldname: "warehouse_type",
title: __("Warehouse Type"),
description: __("Select a warehouse type to categorize the warehouse into a sub-group.")
},
- {
- fieldname: "is_group",
- title: __("Is Group"),
- description: __("Check this field to group warehouses under this warehouse.")
- },
{
fieldname: "account",
title: __("Account"),
description: __("Select an account to set a default account for all transactions with this warehouse.")
},
];
+
diff --git a/erpnext/stock/module_onboarding/stock/stock.json b/erpnext/stock/module_onboarding/stock/stock.json
index 4503f534c7c..c246747a5b3 100644
--- a/erpnext/stock/module_onboarding/stock/stock.json
+++ b/erpnext/stock/module_onboarding/stock/stock.json
@@ -19,7 +19,7 @@
"documentation_url": "https://docs.erpnext.com/docs/user/manual/en/stock",
"idx": 0,
"is_complete": 0,
- "modified": "2021-06-18 14:41:24.286683",
+ "modified": "2021-08-20 14:38:55.570067",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock",
@@ -38,7 +38,7 @@
"step": "Stock Opening Balance"
},
{
- "step": "View Stock Balance"
+ "step": "View Stock Projected Qty"
}
],
"subtitle": "Inventory, Warehouses, Analysis, and more.",
diff --git a/erpnext/stock/onboarding_step/create_a_warehouse/create_a_warehouse.json b/erpnext/stock/onboarding_step/create_a_warehouse/create_a_warehouse.json
index 0ef6c3615c4..22c88bf10ea 100644
--- a/erpnext/stock/onboarding_step/create_a_warehouse/create_a_warehouse.json
+++ b/erpnext/stock/onboarding_step/create_a_warehouse/create_a_warehouse.json
@@ -9,7 +9,7 @@
"is_complete": 0,
"is_single": 0,
"is_skipped": 0,
- "modified": "2021-06-18 13:52:51.126984",
+ "modified": "2021-08-18 12:23:36.675572",
"modified_by": "Administrator",
"name": "Create a Warehouse",
"owner": "Administrator",
diff --git a/erpnext/stock/onboarding_step/stock_settings/stock_settings.json b/erpnext/stock/onboarding_step/stock_settings/stock_settings.json
index f7238da3348..2cf90e806cd 100644
--- a/erpnext/stock/onboarding_step/stock_settings/stock_settings.json
+++ b/erpnext/stock/onboarding_step/stock_settings/stock_settings.json
@@ -9,7 +9,7 @@
"is_complete": 0,
"is_single": 1,
"is_skipped": 0,
- "modified": "2021-06-18 14:13:12.678178",
+ "modified": "2021-08-18 12:06:51.139387",
"modified_by": "Administrator",
"name": "Stock Settings",
"owner": "Administrator",
diff --git a/erpnext/stock/onboarding_step/view_stock_ledger/view_stock_ledger.json b/erpnext/stock/onboarding_step/view_stock_ledger/view_stock_ledger.json
deleted file mode 100644
index 7a5f164e016..00000000000
--- a/erpnext/stock/onboarding_step/view_stock_ledger/view_stock_ledger.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "action": "View Report",
- "action_label": "Check Stock Ledger",
- "creation": "2021-05-17 16:16:10.727959",
- "description": "# Check Stock Reports\nBased on the various stock transactions, you can get a host of one-click Stock Reports in ERPNext like Stock Ledger, Stock Balance, Projected Quantity, and Ageing analysis.",
- "docstatus": 0,
- "doctype": "Onboarding Step",
- "idx": 0,
- "is_complete": 0,
- "is_single": 0,
- "is_skipped": 0,
- "modified": "2021-06-18 14:09:39.399311",
- "modified_by": "Administrator",
- "name": "View Stock Ledger",
- "owner": "Administrator",
- "reference_report": "Stock Ledger",
- "report_description": "You can set the filters to see entries specific to the previous steps.",
- "report_reference_doctype": "Stock Ledger Entry",
- "report_type": "Script Report",
- "show_form_tour": 0,
- "show_full_form": 0,
- "title": "Check Stock Reports",
- "validate_action": 1
-}
\ No newline at end of file
diff --git a/erpnext/stock/onboarding_step/view_stock_balance/view_stock_balance.json b/erpnext/stock/onboarding_step/view_stock_projected_qty/view_stock_projected_qty.json
similarity index 69%
rename from erpnext/stock/onboarding_step/view_stock_balance/view_stock_balance.json
rename to erpnext/stock/onboarding_step/view_stock_projected_qty/view_stock_projected_qty.json
index ed5fe369459..e684780751f 100644
--- a/erpnext/stock/onboarding_step/view_stock_balance/view_stock_balance.json
+++ b/erpnext/stock/onboarding_step/view_stock_projected_qty/view_stock_projected_qty.json
@@ -1,7 +1,7 @@
{
"action": "View Report",
- "action_label": "Check Stock Balance",
- "creation": "2021-05-17 16:15:54.617572",
+ "action_label": "Check Stock Projected Qty",
+ "creation": "2021-08-20 14:38:41.649103",
"description": "# Check Stock Reports\nBased on the various stock transactions, you can get a host of one-click Stock Reports in ERPNext like Stock Ledger, Stock Balance, Projected Quantity, and Ageing analysis.",
"docstatus": 0,
"doctype": "Onboarding Step",
@@ -9,16 +9,16 @@
"is_complete": 0,
"is_single": 0,
"is_skipped": 0,
- "modified": "2021-06-18 14:41:18.499215",
+ "modified": "2021-08-20 14:38:41.649103",
"modified_by": "Administrator",
- "name": "View Stock Balance",
+ "name": "View Stock Projected Qty",
"owner": "Administrator",
- "reference_report": "Stock Balance",
+ "reference_report": "Stock Projected Qty",
"report_description": "You can set the filters to narrow the results, then click on Generate New Report to see the updated report.",
- "report_reference_doctype": "Stock Ledger Entry",
+ "report_reference_doctype": "Item",
"report_type": "Script Report",
"show_form_tour": 0,
"show_full_form": 0,
- "title": "Check Stock Reports",
+ "title": "Check Stock Projected Qty",
"validate_action": 1
}
\ No newline at end of file
From f4487c3ae540c7afa790a0a906e63ca95e736fde Mon Sep 17 00:00:00 2001
From: 18alantom <2.alan.tom@gmail.com>
Date: Fri, 20 Aug 2021 16:25:20 +0530
Subject: [PATCH 30/80] refactor: use Form Tour doc instead of controller form
tour
note - keeping controller form tours as a fallback, new form tours
seem to work only for Stock Settings
---
.../create_a_stock_entry.json | 56 ++++++++++++
.../create_a_warehouse.json | 54 +++++++++++
.../create_warehouse/create_warehouse.json | 54 +++++++++++
.../stock_opening_balance.json | 55 ++++++++++++
.../stock_settings/stock_settings.json | 89 +++++++++++++++++++
5 files changed, 308 insertions(+)
create mode 100644 erpnext/stock/form_tour/create_a_stock_entry/create_a_stock_entry.json
create mode 100644 erpnext/stock/form_tour/create_a_warehouse/create_a_warehouse.json
create mode 100644 erpnext/stock/form_tour/create_warehouse/create_warehouse.json
create mode 100644 erpnext/stock/form_tour/stock_opening_balance/stock_opening_balance.json
create mode 100644 erpnext/stock/form_tour/stock_settings/stock_settings.json
diff --git a/erpnext/stock/form_tour/create_a_stock_entry/create_a_stock_entry.json b/erpnext/stock/form_tour/create_a_stock_entry/create_a_stock_entry.json
new file mode 100644
index 00000000000..fbc4b558bc1
--- /dev/null
+++ b/erpnext/stock/form_tour/create_a_stock_entry/create_a_stock_entry.json
@@ -0,0 +1,56 @@
+{
+ "creation": "2021-08-20 16:02:59.314742",
+ "docstatus": 0,
+ "doctype": "Form Tour",
+ "idx": 0,
+ "is_standard": 1,
+ "modified": "2021-08-20 16:05:40.593997",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Create a Stock Entry",
+ "owner": "Administrator",
+ "reference_doctype": "Stock Entry",
+ "save_on_complete": 1,
+ "steps": [
+ {
+ "description": "Select the type of Stock Entry to be made. For now, to receive stock into a warehouses select Material Receipt.",
+ "field": "",
+ "fieldname": "stock_entry_type",
+ "fieldtype": "Link",
+ "has_next_condition": 1,
+ "is_table_field": 0,
+ "label": "Stock Entry Type",
+ "next_step_condition": "eval: doc.stock_entry_type === \"Material Receipt\"",
+ "parent_field": "",
+ "position": "Top",
+ "title": "Stock Entry Type"
+ },
+ {
+ "description": "Select a target warehouse where the stock will be received.",
+ "field": "",
+ "fieldname": "to_warehouse",
+ "fieldtype": "Link",
+ "has_next_condition": 1,
+ "is_table_field": 0,
+ "label": "Default Target Warehouse",
+ "next_step_condition": "eval: doc.to_warehouse",
+ "parent_field": "",
+ "position": "Top",
+ "title": "Default Target Warehouse"
+ },
+ {
+ "description": "Select an item and entry quantity to be delivered.",
+ "field": "",
+ "fieldname": "items",
+ "fieldtype": "Table",
+ "has_next_condition": 1,
+ "is_table_field": 0,
+ "label": "Items",
+ "next_step_condition": "eval: doc.items[0]?.item_code",
+ "parent_field": "",
+ "position": "Bottom",
+ "title": "Items"
+ }
+ ],
+ "title": "Create a Stock Entry"
+}
\ No newline at end of file
diff --git a/erpnext/stock/form_tour/create_a_warehouse/create_a_warehouse.json b/erpnext/stock/form_tour/create_a_warehouse/create_a_warehouse.json
new file mode 100644
index 00000000000..e9a598b4b1a
--- /dev/null
+++ b/erpnext/stock/form_tour/create_a_warehouse/create_a_warehouse.json
@@ -0,0 +1,54 @@
+{
+ "creation": "2021-08-20 15:56:10.157109",
+ "docstatus": 0,
+ "doctype": "Form Tour",
+ "idx": 0,
+ "is_standard": 1,
+ "modified": "2021-08-20 15:56:10.157109",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Create a Warehouse",
+ "owner": "Administrator",
+ "reference_doctype": "Warehouse",
+ "save_on_complete": 1,
+ "steps": [
+ {
+ "description": "Select a name for the warehouse. This should reflect its location or purpose.",
+ "field": "",
+ "fieldname": "warehouse_name",
+ "fieldtype": "Data",
+ "has_next_condition": 1,
+ "is_table_field": 0,
+ "label": "Warehouse Name",
+ "next_step_condition": "eval: doc.warehouse_name",
+ "parent_field": "",
+ "position": "Bottom",
+ "title": "Warehouse Name"
+ },
+ {
+ "description": "Select a warehouse type to categorize the warehouse into a sub-group.",
+ "field": "",
+ "fieldname": "warehouse_type",
+ "fieldtype": "Link",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Warehouse Type",
+ "parent_field": "",
+ "position": "Top",
+ "title": "Warehouse Type"
+ },
+ {
+ "description": "Select an account to set a default account for all transactions with this warehouse.",
+ "field": "",
+ "fieldname": "account",
+ "fieldtype": "Link",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Account",
+ "parent_field": "",
+ "position": "Top",
+ "title": "Account"
+ }
+ ],
+ "title": "Create a Warehouse"
+}
\ No newline at end of file
diff --git a/erpnext/stock/form_tour/create_warehouse/create_warehouse.json b/erpnext/stock/form_tour/create_warehouse/create_warehouse.json
new file mode 100644
index 00000000000..f25e3a1cf3a
--- /dev/null
+++ b/erpnext/stock/form_tour/create_warehouse/create_warehouse.json
@@ -0,0 +1,54 @@
+{
+ "creation": "2021-08-20 15:42:47.059290",
+ "docstatus": 0,
+ "doctype": "Form Tour",
+ "idx": 0,
+ "is_standard": 1,
+ "modified": "2021-08-20 15:54:58.440497",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Create Warehouse",
+ "owner": "Administrator",
+ "reference_doctype": "Warehouse",
+ "save_on_complete": 1,
+ "steps": [
+ {
+ "description": "Select a name for the warehouse. This should reflect its location or purpose.",
+ "field": "",
+ "fieldname": "warehouse_name",
+ "fieldtype": "Data",
+ "has_next_condition": 1,
+ "is_table_field": 0,
+ "label": "Warehouse Name",
+ "next_step_condition": "eval: doc.warehouse_name",
+ "parent_field": "",
+ "position": "Bottom",
+ "title": "Warehouse Name"
+ },
+ {
+ "description": "Select a warehouse type to categorize the warehouse into a sub-group.",
+ "field": "",
+ "fieldname": "warehouse_type",
+ "fieldtype": "Link",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Warehouse Type",
+ "parent_field": "",
+ "position": "Top",
+ "title": "Warehouse Type"
+ },
+ {
+ "description": "Select an account to set a default account for all transactions with this warehouse.",
+ "field": "",
+ "fieldname": "account",
+ "fieldtype": "Link",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Account",
+ "parent_field": "",
+ "position": "Top",
+ "title": "Account"
+ }
+ ],
+ "title": "Create Warehouse"
+}
\ No newline at end of file
diff --git a/erpnext/stock/form_tour/stock_opening_balance/stock_opening_balance.json b/erpnext/stock/form_tour/stock_opening_balance/stock_opening_balance.json
new file mode 100644
index 00000000000..94bdbbc442c
--- /dev/null
+++ b/erpnext/stock/form_tour/stock_opening_balance/stock_opening_balance.json
@@ -0,0 +1,55 @@
+{
+ "creation": "2021-08-20 16:08:39.298267",
+ "docstatus": 0,
+ "doctype": "Form Tour",
+ "idx": 0,
+ "is_standard": 1,
+ "modified": "2021-08-20 16:08:39.298267",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Stock Opening Balance",
+ "owner": "Administrator",
+ "reference_doctype": "Stock Reconciliation",
+ "save_on_complete": 1,
+ "steps": [
+ {
+ "description": "Set Purpose to Opening Stock to set the stock opening balance.",
+ "field": "",
+ "fieldname": "purpose",
+ "fieldtype": "Select",
+ "has_next_condition": 1,
+ "is_table_field": 0,
+ "label": "Purpose",
+ "next_step_condition": "eval: doc.purpose === \"Opening Stock\"",
+ "parent_field": "",
+ "position": "Top",
+ "title": "Purpose"
+ },
+ {
+ "description": "Edit the Posting Date by clicking on the Edit Posting Date and Time checkbox below.",
+ "field": "",
+ "fieldname": "posting_date",
+ "fieldtype": "Date",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Posting Date",
+ "parent_field": "",
+ "position": "Bottom",
+ "title": "Posting Date"
+ },
+ {
+ "description": "Select the items for which the opening stock has to be set.",
+ "field": "",
+ "fieldname": "items",
+ "fieldtype": "Table",
+ "has_next_condition": 1,
+ "is_table_field": 0,
+ "label": "Items",
+ "next_step_condition": "eval: doc.items[0]?.item_code",
+ "parent_field": "",
+ "position": "Bottom",
+ "title": "Items"
+ }
+ ],
+ "title": "Stock Opening Balance"
+}
\ No newline at end of file
diff --git a/erpnext/stock/form_tour/stock_settings/stock_settings.json b/erpnext/stock/form_tour/stock_settings/stock_settings.json
new file mode 100644
index 00000000000..282b87c21fc
--- /dev/null
+++ b/erpnext/stock/form_tour/stock_settings/stock_settings.json
@@ -0,0 +1,89 @@
+{
+ "creation": "2021-08-20 15:20:59.336585",
+ "docstatus": 0,
+ "doctype": "Form Tour",
+ "idx": 0,
+ "is_standard": 1,
+ "modified": "2021-08-20 15:37:36.151783",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Stock Settings",
+ "owner": "Administrator",
+ "reference_doctype": "Stock Settings",
+ "save_on_complete": 1,
+ "steps": [
+ {
+ "description": "By default, the Item Name is set as per the Item Code entered. If you want Items to be named by a Naming Series choose the 'Naming Series' option.",
+ "field": "",
+ "fieldname": "item_naming_by",
+ "fieldtype": "Select",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Item Naming By",
+ "parent_field": "",
+ "position": "Bottom",
+ "title": "Item Naming By"
+ },
+ {
+ "description": "Set a Default Warehouse for Inventory Transactions. This will be fetched into the Default Warehouse in the Item master.",
+ "field": "",
+ "fieldname": "default_warehouse",
+ "fieldtype": "Link",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Default Warehouse",
+ "parent_field": "",
+ "position": "Bottom",
+ "title": "Default Warehouse"
+ },
+ {
+ "description": "Choose between FIFO and Moving Average Valuation Methods. Click here to know more about them.",
+ "field": "",
+ "fieldname": "valuation_method",
+ "fieldtype": "Select",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Default Valuation Method",
+ "parent_field": "",
+ "position": "Bottom",
+ "title": "Default Valuation Method"
+ },
+ {
+ "description": "Show 'Scan Barcode' field above every child table to insert Items with ease.",
+ "field": "",
+ "fieldname": "show_barcode_field",
+ "fieldtype": "Check",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Show Barcode Field in Stock Transactions",
+ "parent_field": "",
+ "position": "Bottom",
+ "title": "Show Barcode Field"
+ },
+ {
+ "description": "Quality inspection is performed on the inward and outward movement of goods. Receipt and delivery transactions will be stopped or the user will be warned if the quality inspection is not performed.",
+ "field": "",
+ "fieldname": "action_if_quality_inspection_is_not_submitted",
+ "fieldtype": "Select",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Action If Quality Inspection Is Not Submitted",
+ "parent_field": "",
+ "position": "Bottom",
+ "title": "Action if Quality Inspection Is Not Submitted"
+ },
+ {
+ "description": "Serial numbers for stock will be set automatically based on the Items entered based on first in first out in transactions like Purchase/Sales Invoices, Delivery Notes, etc.",
+ "field": "",
+ "fieldname": "automatically_set_serial_nos_based_on_fifo",
+ "fieldtype": "Check",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Automatically Set Serial Nos Based on FIFO",
+ "parent_field": "",
+ "position": "Bottom",
+ "title": "Automatically Set Serial Nos based on FIFO"
+ }
+ ],
+ "title": "Stock Settings"
+}
\ No newline at end of file
From ad735522cb777431c9e85a900a24d38b6633a377 Mon Sep 17 00:00:00 2001
From: 18alantom <2.alan.tom@gmail.com>
Date: Tue, 24 Aug 2021 14:54:38 +0530
Subject: [PATCH 31/80] fix: rename form tours to doctype names, remove tours
from js controllers
---
.../stock/doctype/stock_entry/stock_entry.js | 17 ------
.../stock_reconciliation.js | 17 ------
.../doctype/stock_settings/stock_settings.js | 37 -------------
erpnext/stock/doctype/warehouse/warehouse.js | 18 -------
.../create_a_warehouse.json | 54 -------------------
.../stock_entry.json} | 8 +--
.../stock_reconciliation.json} | 8 +--
.../warehouse.json} | 8 +--
8 files changed, 12 insertions(+), 155 deletions(-)
delete mode 100644 erpnext/stock/form_tour/create_a_warehouse/create_a_warehouse.json
rename erpnext/stock/form_tour/{create_a_stock_entry/create_a_stock_entry.json => stock_entry/stock_entry.json} (91%)
rename erpnext/stock/form_tour/{stock_opening_balance/stock_opening_balance.json => stock_reconciliation/stock_reconciliation.json} (89%)
rename erpnext/stock/form_tour/{create_warehouse/create_warehouse.json => warehouse/warehouse.json} (89%)
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 5ea733c66d3..8f34794db9a 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -1102,20 +1102,3 @@ function check_should_not_attach_bom_items(bom_no) {
$.extend(cur_frm.cscript, new erpnext.stock.StockEntry({frm: cur_frm}));
-frappe.tour['Stock Entry'] = [
- {
- fieldname: "stock_entry_type",
- title: __("Stock Entry Type"),
- description: __("Select the type of Stock Entry to be made. For now, to receive stock into a warehouses select") + ' ' + __("Material Receipt.") + ""
- },
- {
- fieldname: "to_warehouse",
- title: __("Default Target Warehouse"),
- description: __("Select a target warehouse where the stock will be received.")
- },
- {
- fieldname: "items",
- title: __("Items"),
- description: __("Select an item and entry quantity to be delivered.")
- },
-]
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
index f91d0a740d8..aa502a432df 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
@@ -303,20 +303,3 @@ erpnext.stock.StockReconciliation = class StockReconciliation extends erpnext.st
cur_frm.cscript = new erpnext.stock.StockReconciliation({frm: cur_frm});
-frappe.tour['Stock Reconciliation'] = [
- {
- fieldname: "purpose",
- title: __("Purpose"),
- description: __("Set Purpose to Opening Stock to set the stock opening balance.")
- },
- {
- fieldname: "posting_date",
- title: __("Posting Date"),
- description: __("Edit the Posting Date by clicking on the Edit Posting Date and Time checkbox below.")
- },
- {
- fieldname: "items",
- title: __("Items"),
- description: __("Select the items for which the opening stock has to be set.")
- },
-];
diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.js b/erpnext/stock/doctype/stock_settings/stock_settings.js
index 08606fdcaa6..6167becdaac 100644
--- a/erpnext/stock/doctype/stock_settings/stock_settings.js
+++ b/erpnext/stock/doctype/stock_settings/stock_settings.js
@@ -16,40 +16,3 @@ frappe.ui.form.on('Stock Settings', {
}
});
-frappe.tour['Stock Settings'] = [
- {
- fieldname: "item_naming_by",
- title: __("Item Naming By"),
- description: __("By default, the Item Name is set as per the Item Code entered. If you want Items to be named by a") + " " +
- "Naming Series" + " " +
- __("choose the 'Naming Series' option."),
- },
- {
- fieldname: "default_warehouse",
- title: __("Default Warehouse"),
- description: __("Set a Default Warehouse for Inventory Transactions. This will be fetched into the Default Warehouse in the Item master.")
- },
- {
- fieldname: "valuation_method",
- title: __("Valuation Method"),
- description: __("Choose between FIFO and Moving Average Valuation Methods. Click") + " " +
- "here" + " " +
- __("to know more about them.")
- },
- {
- fieldname: "show_barcode_field",
- title: __("Show Barcode Field"),
- description: __("Show 'Scan Barcode' field above every child table to insert Items with ease.")
- },
- {
- fieldname: "action_if_quality_inspection_is_not_submitted",
- title: __("Action if Quality Inspection Is Not Submitted"),
- description: __("Quality inspection is performed on the inward and outward movement of goods. Receipt and delivery transactions will be stopped or the user will be warned if the quality inspection is not performed.")
-
- },
- {
- fieldname: "automatically_set_serial_nos_based_on_fifo",
- title: __("Automatically Set Serial Nos based on FIFO"),
- description: __("Serial numbers for stock will be set automatically based on the Items entered based on first in first out in transactions like Purchase/Sales Invoices, Delivery Notes, etc.")
- }
-];
diff --git a/erpnext/stock/doctype/warehouse/warehouse.js b/erpnext/stock/doctype/warehouse/warehouse.js
index b0c1c033a3b..4e1679c4116 100644
--- a/erpnext/stock/doctype/warehouse/warehouse.js
+++ b/erpnext/stock/doctype/warehouse/warehouse.js
@@ -87,21 +87,3 @@ function convert_to_group_or_ledger(frm){
})
}
-frappe.tour['Warehouse'] = [
- {
- fieldname: "warehouse_name",
- title: __("Warehouse Name"),
- description: __("Select name for the warehouse. This should reflect its location or purpose.")
- },
- {
- fieldname: "warehouse_type",
- title: __("Warehouse Type"),
- description: __("Select a warehouse type to categorize the warehouse into a sub-group.")
- },
- {
- fieldname: "account",
- title: __("Account"),
- description: __("Select an account to set a default account for all transactions with this warehouse.")
- },
-];
-
diff --git a/erpnext/stock/form_tour/create_a_warehouse/create_a_warehouse.json b/erpnext/stock/form_tour/create_a_warehouse/create_a_warehouse.json
deleted file mode 100644
index e9a598b4b1a..00000000000
--- a/erpnext/stock/form_tour/create_a_warehouse/create_a_warehouse.json
+++ /dev/null
@@ -1,54 +0,0 @@
-{
- "creation": "2021-08-20 15:56:10.157109",
- "docstatus": 0,
- "doctype": "Form Tour",
- "idx": 0,
- "is_standard": 1,
- "modified": "2021-08-20 15:56:10.157109",
- "modified_by": "Administrator",
- "module": "Stock",
- "name": "Create a Warehouse",
- "owner": "Administrator",
- "reference_doctype": "Warehouse",
- "save_on_complete": 1,
- "steps": [
- {
- "description": "Select a name for the warehouse. This should reflect its location or purpose.",
- "field": "",
- "fieldname": "warehouse_name",
- "fieldtype": "Data",
- "has_next_condition": 1,
- "is_table_field": 0,
- "label": "Warehouse Name",
- "next_step_condition": "eval: doc.warehouse_name",
- "parent_field": "",
- "position": "Bottom",
- "title": "Warehouse Name"
- },
- {
- "description": "Select a warehouse type to categorize the warehouse into a sub-group.",
- "field": "",
- "fieldname": "warehouse_type",
- "fieldtype": "Link",
- "has_next_condition": 0,
- "is_table_field": 0,
- "label": "Warehouse Type",
- "parent_field": "",
- "position": "Top",
- "title": "Warehouse Type"
- },
- {
- "description": "Select an account to set a default account for all transactions with this warehouse.",
- "field": "",
- "fieldname": "account",
- "fieldtype": "Link",
- "has_next_condition": 0,
- "is_table_field": 0,
- "label": "Account",
- "parent_field": "",
- "position": "Top",
- "title": "Account"
- }
- ],
- "title": "Create a Warehouse"
-}
\ No newline at end of file
diff --git a/erpnext/stock/form_tour/create_a_stock_entry/create_a_stock_entry.json b/erpnext/stock/form_tour/stock_entry/stock_entry.json
similarity index 91%
rename from erpnext/stock/form_tour/create_a_stock_entry/create_a_stock_entry.json
rename to erpnext/stock/form_tour/stock_entry/stock_entry.json
index fbc4b558bc1..98c5d62f10a 100644
--- a/erpnext/stock/form_tour/create_a_stock_entry/create_a_stock_entry.json
+++ b/erpnext/stock/form_tour/stock_entry/stock_entry.json
@@ -1,13 +1,13 @@
{
- "creation": "2021-08-20 16:02:59.314742",
+ "creation": "2021-08-24 14:44:22.292652",
"docstatus": 0,
"doctype": "Form Tour",
"idx": 0,
"is_standard": 1,
- "modified": "2021-08-20 16:05:40.593997",
+ "modified": "2021-08-24 14:50:48.017420",
"modified_by": "Administrator",
"module": "Stock",
- "name": "Create a Stock Entry",
+ "name": "Stock Entry",
"owner": "Administrator",
"reference_doctype": "Stock Entry",
"save_on_complete": 1,
@@ -52,5 +52,5 @@
"title": "Items"
}
],
- "title": "Create a Stock Entry"
+ "title": "Stock Entry"
}
\ No newline at end of file
diff --git a/erpnext/stock/form_tour/stock_opening_balance/stock_opening_balance.json b/erpnext/stock/form_tour/stock_reconciliation/stock_reconciliation.json
similarity index 89%
rename from erpnext/stock/form_tour/stock_opening_balance/stock_opening_balance.json
rename to erpnext/stock/form_tour/stock_reconciliation/stock_reconciliation.json
index 94bdbbc442c..83083b639a1 100644
--- a/erpnext/stock/form_tour/stock_opening_balance/stock_opening_balance.json
+++ b/erpnext/stock/form_tour/stock_reconciliation/stock_reconciliation.json
@@ -1,13 +1,13 @@
{
- "creation": "2021-08-20 16:08:39.298267",
+ "creation": "2021-08-24 14:44:46.770952",
"docstatus": 0,
"doctype": "Form Tour",
"idx": 0,
"is_standard": 1,
- "modified": "2021-08-20 16:08:39.298267",
+ "modified": "2021-08-24 14:50:41.512219",
"modified_by": "Administrator",
"module": "Stock",
- "name": "Stock Opening Balance",
+ "name": "Stock Reconciliation",
"owner": "Administrator",
"reference_doctype": "Stock Reconciliation",
"save_on_complete": 1,
@@ -51,5 +51,5 @@
"title": "Items"
}
],
- "title": "Stock Opening Balance"
+ "title": "Stock Reconciliation"
}
\ No newline at end of file
diff --git a/erpnext/stock/form_tour/create_warehouse/create_warehouse.json b/erpnext/stock/form_tour/warehouse/warehouse.json
similarity index 89%
rename from erpnext/stock/form_tour/create_warehouse/create_warehouse.json
rename to erpnext/stock/form_tour/warehouse/warehouse.json
index f25e3a1cf3a..23ff2aebbaa 100644
--- a/erpnext/stock/form_tour/create_warehouse/create_warehouse.json
+++ b/erpnext/stock/form_tour/warehouse/warehouse.json
@@ -1,13 +1,13 @@
{
- "creation": "2021-08-20 15:42:47.059290",
+ "creation": "2021-08-24 14:43:44.465237",
"docstatus": 0,
"doctype": "Form Tour",
"idx": 0,
"is_standard": 1,
- "modified": "2021-08-20 15:54:58.440497",
+ "modified": "2021-08-24 14:50:31.988256",
"modified_by": "Administrator",
"module": "Stock",
- "name": "Create Warehouse",
+ "name": "Warehouse",
"owner": "Administrator",
"reference_doctype": "Warehouse",
"save_on_complete": 1,
@@ -50,5 +50,5 @@
"title": "Account"
}
],
- "title": "Create Warehouse"
+ "title": "Warehouse"
}
\ No newline at end of file
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 32/80] 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 8d9b10ddc13..8d105789d0d 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 d6a20df0c89..0569092f883 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 33/80] 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 0569092f883..a00520f6a1b 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 3b56854aaf3..913fc85af61 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 282b5d0afe4..c37a1c9e5af 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 34/80] 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 c37a1c9e5af..1cdbc5f0e1c 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 00000000000..e69de29bb2d
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 00000000000..078b9e11ce9
--- /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 00000000000..afe4aff7f1c
--- /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 00000000000..be0f0151d40
--- /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 35/80] 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 7de7e17abc2..5afda7028a7 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 36/80] 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 a00520f6a1b..3a334a530cd 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 1dadea38a55346c1569a46029be39d662d7be139 Mon Sep 17 00:00:00 2001
From: Saqib
Date: Wed, 25 Aug 2021 11:05:51 +0530
Subject: [PATCH 37/80] fix: remove unexpected comma (#27132)
---
erpnext/accounts/doctype/sales_invoice/sales_invoice.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 1e37e4b2070..2dd3d690e93 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -443,7 +443,7 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends e
this.frm.refresh_field("outstanding_amount");
this.frm.refresh_field("paid_amount");
this.frm.refresh_field("base_paid_amount");
- },
+ }
currency() {
this._super();
From 8366b6322e5fe9aae5a7c2d20f4061fd07f197fc Mon Sep 17 00:00:00 2001
From: Afshan <33727827+AfshanKhan@users.noreply.github.com>
Date: Wed, 25 Aug 2021 11:57:24 +0530
Subject: [PATCH 38/80] fix: validate party and party type only if both
available (#27002)
* fix: validate party and party type only if both available
* fix: indentation
---
.../accounts/report/general_ledger/general_ledger.py | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py
index 5d8d49d6a65..3723c8e0d23 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.py
+++ b/erpnext/accounts/report/general_ledger/general_ledger.py
@@ -78,13 +78,10 @@ def validate_filters(filters, account_details):
def validate_party(filters):
party_type, party = filters.get("party_type"), filters.get("party")
- if party:
- if not party_type:
- frappe.throw(_("To filter based on Party, select Party Type first"))
- else:
- for d in party:
- if not frappe.db.exists(party_type, d):
- frappe.throw(_("Invalid {0}: {1}").format(party_type, d))
+ if party and party_type:
+ for d in party:
+ if not frappe.db.exists(party_type, d):
+ frappe.throw(_("Invalid {0}: {1}").format(party_type, d))
def set_account_currency(filters):
if filters.get("account") or (filters.get('party') and len(filters.party) == 1):
From a65498dc610287640e76dc8a646e9ada0c29a44a Mon Sep 17 00:00:00 2001
From: Chillar Anand
Date: Wed, 25 Aug 2021 14:40:22 +0530
Subject: [PATCH 39/80] fix(healthcare): Made payment fields mandatory for new
appointments (#26608)
* fix(healthcare): Made payment fields mandatory for new appointments
* fix: sider issues
* fix: Fix failing test
* fix: Patient appointment invoicing
Co-authored-by: Rucha Mahabal
Co-authored-by: Syed Mujeer Hashmi
---
.../doctype/fee_validity/test_fee_validity.py | 4 +--
.../patient_appointment.js | 7 ++++++
.../patient_appointment.json | 5 ++--
.../patient_appointment.py | 8 +-----
.../test_patient_appointment.py | 25 ++++++++++++++++++-
5 files changed, 37 insertions(+), 12 deletions(-)
diff --git a/erpnext/healthcare/doctype/fee_validity/test_fee_validity.py b/erpnext/healthcare/doctype/fee_validity/test_fee_validity.py
index 6ae3e12d50e..82e7136d6b9 100644
--- a/erpnext/healthcare/doctype/fee_validity/test_fee_validity.py
+++ b/erpnext/healthcare/doctype/fee_validity/test_fee_validity.py
@@ -29,10 +29,10 @@ class TestFeeValidity(unittest.TestCase):
healthcare_settings.save(ignore_permissions=True)
patient, medical_department, practitioner = create_healthcare_docs()
- # appointment should not be invoiced. Check Fee Validity created for new patient
+ # For first appointment, invoice is generated
appointment = create_appointment(patient, practitioner, nowdate())
invoiced = frappe.db.get_value("Patient Appointment", appointment.name, "invoiced")
- self.assertEqual(invoiced, 0)
+ self.assertEqual(invoiced, 1)
# appointment should not be invoiced as it is within fee validity
appointment = create_appointment(patient, practitioner, add_days(nowdate(), 4))
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js
index 2976ef13a1d..c6e489ec17c 100644
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js
@@ -241,6 +241,13 @@ frappe.ui.form.on('Patient Appointment', {
frm.toggle_reqd('mode_of_payment', 0);
frm.toggle_reqd('paid_amount', 0);
frm.toggle_reqd('billing_item', 0);
+ } else if (data.message) {
+ frm.toggle_display('mode_of_payment', 1);
+ frm.toggle_display('paid_amount', 1);
+ frm.toggle_display('billing_item', 1);
+ frm.toggle_reqd('mode_of_payment', 1);
+ frm.toggle_reqd('paid_amount', 1);
+ frm.toggle_reqd('billing_item', 1);
} else {
// if automated appointment invoicing is disabled, hide fields
frm.toggle_display('mode_of_payment', data.message ? 1 : 0);
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json
index 83c92af36ac..6e996bd128b 100644
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json
@@ -134,6 +134,7 @@
"set_only_once": 1
},
{
+ "depends_on": "eval:doc.practitioner;",
"fieldname": "section_break_12",
"fieldtype": "Section Break",
"label": "Appointment Details"
@@ -349,7 +350,7 @@
}
],
"links": [],
- "modified": "2021-02-08 13:13:15.116833",
+ "modified": "2021-06-16 00:40:26.841794",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Patient Appointment",
@@ -400,4 +401,4 @@
"title_field": "title",
"track_changes": 1,
"track_seen": 1
-}
\ No newline at end of file
+}
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
index cdd4ad39c88..05e2cd30df5 100755
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
@@ -135,8 +135,6 @@ def check_payment_fields_reqd(patient):
fee_validity = frappe.db.exists('Fee Validity', {'patient': patient, 'status': 'Pending'})
if fee_validity:
return {'fee_validity': fee_validity}
- if check_is_new_patient(patient):
- return False
return True
return False
@@ -151,8 +149,6 @@ def invoice_appointment(appointment_doc):
elif not fee_validity:
if frappe.db.exists('Fee Validity Reference', {'appointment': appointment_doc.name}):
return
- if check_is_new_patient(appointment_doc.patient, appointment_doc.name):
- return
else:
fee_validity = None
@@ -196,9 +192,7 @@ def check_is_new_patient(patient, name=None):
filters['name'] = ('!=', name)
has_previous_appointment = frappe.db.exists('Patient Appointment', filters)
- if has_previous_appointment:
- return False
- return True
+ return not has_previous_appointment
def get_appointment_item(appointment_doc, item):
diff --git a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
index 9dd4a2c73c0..2df6921b14f 100644
--- a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
@@ -4,11 +4,12 @@
from __future__ import unicode_literals
import unittest
import frappe
-from erpnext.healthcare.doctype.patient_appointment.patient_appointment import update_status, make_encounter
+from erpnext.healthcare.doctype.patient_appointment.patient_appointment import update_status, make_encounter, check_payment_fields_reqd, check_is_new_patient
from frappe.utils import nowdate, add_days, now_datetime
from frappe.utils.make_random import get_random
from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
+
class TestPatientAppointment(unittest.TestCase):
def setUp(self):
frappe.db.sql("""delete from `tabPatient Appointment`""")
@@ -176,6 +177,28 @@ class TestPatientAppointment(unittest.TestCase):
mark_invoiced_inpatient_occupancy(ip_record1)
discharge_patient(ip_record1)
+ def test_payment_should_be_mandatory_for_new_patient_appointment(self):
+ frappe.db.set_value('Healthcare Settings', None, 'enable_free_follow_ups', 1)
+ frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 1)
+ frappe.db.set_value('Healthcare Settings', None, 'max_visits', 3)
+ frappe.db.set_value('Healthcare Settings', None, 'valid_days', 30)
+
+ patient = create_patient()
+ assert check_is_new_patient(patient)
+ payment_required = check_payment_fields_reqd(patient)
+ assert payment_required is True
+
+ def test_sales_invoice_should_be_generated_for_new_patient_appointment(self):
+ patient, medical_department, practitioner = create_healthcare_docs()
+ frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 1)
+ invoice_count = frappe.db.count('Sales Invoice')
+
+ assert check_is_new_patient(patient)
+ create_appointment(patient, practitioner, nowdate())
+ new_invoice_count = frappe.db.count('Sales Invoice')
+
+ assert new_invoice_count == invoice_count + 1
+
def create_healthcare_docs():
patient = create_patient()
From 62114b226f30a5f4c634c2f17fd47a94149c6df8 Mon Sep 17 00:00:00 2001
From: Saqib
Date: Wed, 25 Aug 2021 16:25:51 +0530
Subject: [PATCH 40/80] feat: unreconcile on cancellation of bank transaction
(#27109)
---
.../bank_transaction/bank_transaction.py | 31 +++++++++++++------
.../bank_transaction/bank_transaction_list.js | 6 ++--
.../bank_transaction/test_bank_transaction.py | 9 +++++-
erpnext/controllers/status_updater.py | 3 +-
4 files changed, 36 insertions(+), 13 deletions(-)
diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
index 31cfb2da1da..0544a469d60 100644
--- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
+++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
@@ -21,6 +21,10 @@ class BankTransaction(StatusUpdater):
self.update_allocations()
self.clear_linked_payment_entries()
self.set_status(update=True)
+
+ def on_cancel(self):
+ self.clear_linked_payment_entries(for_cancel=True)
+ self.set_status(update=True)
def update_allocations(self):
if self.payment_entries:
@@ -41,21 +45,30 @@ class BankTransaction(StatusUpdater):
frappe.db.set_value(self.doctype, self.name, "status", "Reconciled")
self.reload()
-
- def clear_linked_payment_entries(self):
+
+ def clear_linked_payment_entries(self, for_cancel=False):
for payment_entry in self.payment_entries:
if payment_entry.payment_document in ["Payment Entry", "Journal Entry", "Purchase Invoice", "Expense Claim"]:
- self.clear_simple_entry(payment_entry)
+ self.clear_simple_entry(payment_entry, for_cancel=for_cancel)
elif payment_entry.payment_document == "Sales Invoice":
- self.clear_sales_invoice(payment_entry)
+ self.clear_sales_invoice(payment_entry, for_cancel=for_cancel)
- def clear_simple_entry(self, payment_entry):
- frappe.db.set_value(payment_entry.payment_document, payment_entry.payment_entry, "clearance_date", self.date)
+ def clear_simple_entry(self, payment_entry, for_cancel=False):
+ clearance_date = self.date if not for_cancel else None
+ frappe.db.set_value(
+ payment_entry.payment_document, payment_entry.payment_entry,
+ "clearance_date", clearance_date)
- def clear_sales_invoice(self, payment_entry):
- frappe.db.set_value("Sales Invoice Payment", dict(parenttype=payment_entry.payment_document,
- parent=payment_entry.payment_entry), "clearance_date", self.date)
+ def clear_sales_invoice(self, payment_entry, for_cancel=False):
+ clearance_date = self.date if not for_cancel else None
+ frappe.db.set_value(
+ "Sales Invoice Payment",
+ dict(
+ parenttype=payment_entry.payment_document,
+ parent=payment_entry.payment_entry
+ ),
+ "clearance_date", clearance_date)
def get_total_allocated_amount(payment_entry):
return frappe.db.sql("""
diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction_list.js b/erpnext/accounts/doctype/bank_transaction/bank_transaction_list.js
index bff41d5539b..2585ee9c923 100644
--- a/erpnext/accounts/doctype/bank_transaction/bank_transaction_list.js
+++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction_list.js
@@ -4,10 +4,12 @@
frappe.listview_settings['Bank Transaction'] = {
add_fields: ["unallocated_amount"],
get_indicator: function(doc) {
- if(flt(doc.unallocated_amount)>0) {
- return [__("Unreconciled"), "orange", "unallocated_amount,>,0"];
+ if(doc.docstatus == 2) {
+ return [__("Cancelled"), "red", "docstatus,=,2"];
} else if(flt(doc.unallocated_amount)<=0) {
return [__("Reconciled"), "green", "unallocated_amount,=,0"];
+ } else if(flt(doc.unallocated_amount)>0) {
+ return [__("Unreconciled"), "orange", "unallocated_amount,>,0"];
}
}
};
diff --git a/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py
index ce149f96e6f..439d4891194 100644
--- a/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py
+++ b/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py
@@ -25,7 +25,8 @@ class TestBankTransaction(unittest.TestCase):
def tearDownClass(cls):
for bt in frappe.get_all("Bank Transaction"):
doc = frappe.get_doc("Bank Transaction", bt.name)
- doc.cancel()
+ if doc.docstatus == 1:
+ doc.cancel()
doc.delete()
# Delete directly in DB to avoid validation errors for countries not allowing deletion
@@ -57,6 +58,12 @@ class TestBankTransaction(unittest.TestCase):
clearance_date = frappe.db.get_value("Payment Entry", payment.name, "clearance_date")
self.assertTrue(clearance_date is not None)
+ bank_transaction.reload()
+ bank_transaction.cancel()
+
+ clearance_date = frappe.db.get_value("Payment Entry", payment.name, "clearance_date")
+ self.assertFalse(clearance_date)
+
# Check if ERPNext can correctly filter a linked payments based on the debit/credit amount
def test_debit_credit_output(self):
bank_transaction = frappe.get_doc("Bank Transaction", dict(description="Auszahlung Karte MC/000002916 AUTOMAT 698769 K002 27.10. 14:07"))
diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py
index b1f89b08d79..7b24e50b143 100644
--- a/erpnext/controllers/status_updater.py
+++ b/erpnext/controllers/status_updater.py
@@ -86,7 +86,8 @@ status_map = {
],
"Bank Transaction": [
["Unreconciled", "eval:self.docstatus == 1 and self.unallocated_amount>0"],
- ["Reconciled", "eval:self.docstatus == 1 and self.unallocated_amount<=0"]
+ ["Reconciled", "eval:self.docstatus == 1 and self.unallocated_amount<=0"],
+ ["Cancelled", "eval:self.docstatus == 2"]
],
"POS Opening Entry": [
["Draft", None],
From dbea840ecfc82cb94fb2fb90f6125b97bb2e9150 Mon Sep 17 00:00:00 2001
From: 18alantom <2.alan.tom@gmail.com>
Date: Wed, 25 Aug 2021 16:34:31 +0530
Subject: [PATCH 41/80] fix: re-order tour to circumvent glitchy save highlight
---
.../form_tour/stock_entry/stock_entry.json | 4 +-
.../stock_reconciliation.json | 28 +++++------
.../stock_settings/stock_settings.json | 50 +++++++++----------
3 files changed, 41 insertions(+), 41 deletions(-)
diff --git a/erpnext/stock/form_tour/stock_entry/stock_entry.json b/erpnext/stock/form_tour/stock_entry/stock_entry.json
index 98c5d62f10a..6363c6ad4dd 100644
--- a/erpnext/stock/form_tour/stock_entry/stock_entry.json
+++ b/erpnext/stock/form_tour/stock_entry/stock_entry.json
@@ -4,7 +4,7 @@
"doctype": "Form Tour",
"idx": 0,
"is_standard": 1,
- "modified": "2021-08-24 14:50:48.017420",
+ "modified": "2021-08-25 16:31:31.441194",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Entry",
@@ -48,7 +48,7 @@
"label": "Items",
"next_step_condition": "eval: doc.items[0]?.item_code",
"parent_field": "",
- "position": "Bottom",
+ "position": "Top",
"title": "Items"
}
],
diff --git a/erpnext/stock/form_tour/stock_reconciliation/stock_reconciliation.json b/erpnext/stock/form_tour/stock_reconciliation/stock_reconciliation.json
index 83083b639a1..5b7fd72c082 100644
--- a/erpnext/stock/form_tour/stock_reconciliation/stock_reconciliation.json
+++ b/erpnext/stock/form_tour/stock_reconciliation/stock_reconciliation.json
@@ -4,7 +4,7 @@
"doctype": "Form Tour",
"idx": 0,
"is_standard": 1,
- "modified": "2021-08-24 14:50:41.512219",
+ "modified": "2021-08-25 16:26:11.718664",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Reconciliation",
@@ -25,6 +25,19 @@
"position": "Top",
"title": "Purpose"
},
+ {
+ "description": "Select the items for which the opening stock has to be set.",
+ "field": "",
+ "fieldname": "items",
+ "fieldtype": "Table",
+ "has_next_condition": 1,
+ "is_table_field": 0,
+ "label": "Items",
+ "next_step_condition": "eval: doc.items[0]?.item_code",
+ "parent_field": "",
+ "position": "Top",
+ "title": "Items"
+ },
{
"description": "Edit the Posting Date by clicking on the Edit Posting Date and Time checkbox below.",
"field": "",
@@ -36,19 +49,6 @@
"parent_field": "",
"position": "Bottom",
"title": "Posting Date"
- },
- {
- "description": "Select the items for which the opening stock has to be set.",
- "field": "",
- "fieldname": "items",
- "fieldtype": "Table",
- "has_next_condition": 1,
- "is_table_field": 0,
- "label": "Items",
- "next_step_condition": "eval: doc.items[0]?.item_code",
- "parent_field": "",
- "position": "Bottom",
- "title": "Items"
}
],
"title": "Stock Reconciliation"
diff --git a/erpnext/stock/form_tour/stock_settings/stock_settings.json b/erpnext/stock/form_tour/stock_settings/stock_settings.json
index 282b87c21fc..3d164e33b3b 100644
--- a/erpnext/stock/form_tour/stock_settings/stock_settings.json
+++ b/erpnext/stock/form_tour/stock_settings/stock_settings.json
@@ -4,7 +4,7 @@
"doctype": "Form Tour",
"idx": 0,
"is_standard": 1,
- "modified": "2021-08-20 15:37:36.151783",
+ "modified": "2021-08-25 16:19:37.699528",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Settings",
@@ -36,30 +36,6 @@
"position": "Bottom",
"title": "Default Warehouse"
},
- {
- "description": "Choose between FIFO and Moving Average Valuation Methods. Click here to know more about them.",
- "field": "",
- "fieldname": "valuation_method",
- "fieldtype": "Select",
- "has_next_condition": 0,
- "is_table_field": 0,
- "label": "Default Valuation Method",
- "parent_field": "",
- "position": "Bottom",
- "title": "Default Valuation Method"
- },
- {
- "description": "Show 'Scan Barcode' field above every child table to insert Items with ease.",
- "field": "",
- "fieldname": "show_barcode_field",
- "fieldtype": "Check",
- "has_next_condition": 0,
- "is_table_field": 0,
- "label": "Show Barcode Field in Stock Transactions",
- "parent_field": "",
- "position": "Bottom",
- "title": "Show Barcode Field"
- },
{
"description": "Quality inspection is performed on the inward and outward movement of goods. Receipt and delivery transactions will be stopped or the user will be warned if the quality inspection is not performed.",
"field": "",
@@ -83,6 +59,30 @@
"parent_field": "",
"position": "Bottom",
"title": "Automatically Set Serial Nos based on FIFO"
+ },
+ {
+ "description": "Show 'Scan Barcode' field above every child table to insert Items with ease.",
+ "field": "",
+ "fieldname": "show_barcode_field",
+ "fieldtype": "Check",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Show Barcode Field in Stock Transactions",
+ "parent_field": "",
+ "position": "Bottom",
+ "title": "Show Barcode Field"
+ },
+ {
+ "description": "Choose between FIFO and Moving Average Valuation Methods. Click here to know more about them.",
+ "field": "",
+ "fieldname": "valuation_method",
+ "fieldtype": "Select",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Default Valuation Method",
+ "parent_field": "",
+ "position": "Bottom",
+ "title": "Default Valuation Method"
}
],
"title": "Stock Settings"
From 8d116fb9ff45b193d4dad75db700439bc6fa5799 Mon Sep 17 00:00:00 2001
From: Ankush Menat
Date: Wed, 25 Aug 2021 16:45:41 +0530
Subject: [PATCH 42/80] fix: remove VARCHARs from Sales Invoice (#27136)
Sales Invoice doctype is starting to hit row length limit as many
integrations add custom fields on this doctype. This is just a small
change to remove VARCHAR(140) fields and reduce row size wherever
possible.
---
.../doctype/sales_invoice/sales_invoice.json | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index 5023c9c61a3..d8aa32e224b 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -247,7 +247,7 @@
"depends_on": "customer",
"fetch_from": "customer.customer_name",
"fieldname": "customer_name",
- "fieldtype": "Data",
+ "fieldtype": "Small Text",
"hide_days": 1,
"hide_seconds": 1,
"in_global_search": 1,
@@ -692,10 +692,11 @@
{
"fieldname": "scan_barcode",
"fieldtype": "Data",
- "options": "Barcode",
"hide_days": 1,
"hide_seconds": 1,
- "label": "Scan Barcode"
+ "label": "Scan Barcode",
+ "length": 1,
+ "options": "Barcode"
},
{
"allow_bulk_edit": 1,
@@ -1059,6 +1060,7 @@
"hide_days": 1,
"hide_seconds": 1,
"label": "Apply Additional Discount On",
+ "length": 15,
"options": "\nGrand Total\nNet Total",
"print_hide": 1
},
@@ -1145,7 +1147,7 @@
{
"description": "In Words will be visible once you save the Sales Invoice.",
"fieldname": "base_in_words",
- "fieldtype": "Data",
+ "fieldtype": "Small Text",
"hide_days": 1,
"hide_seconds": 1,
"label": "In Words (Company Currency)",
@@ -1205,7 +1207,7 @@
},
{
"fieldname": "in_words",
- "fieldtype": "Data",
+ "fieldtype": "Small Text",
"hide_days": 1,
"hide_seconds": 1,
"label": "In Words",
@@ -1558,6 +1560,7 @@
"hide_days": 1,
"hide_seconds": 1,
"label": "Print Language",
+ "length": 6,
"print_hide": 1,
"read_only": 1
},
@@ -1645,6 +1648,7 @@
"hide_seconds": 1,
"in_standard_filter": 1,
"label": "Status",
+ "length": 30,
"no_copy": 1,
"options": "\nDraft\nReturn\nCredit Note Issued\nSubmitted\nPaid\nUnpaid\nUnpaid and Discounted\nOverdue and Discounted\nOverdue\nCancelled\nInternal Transfer",
"print_hide": 1,
@@ -1704,6 +1708,7 @@
"hide_days": 1,
"hide_seconds": 1,
"label": "Is Opening Entry",
+ "length": 4,
"oldfieldname": "is_opening",
"oldfieldtype": "Select",
"options": "No\nYes",
@@ -1715,6 +1720,7 @@
"hide_days": 1,
"hide_seconds": 1,
"label": "C-Form Applicable",
+ "length": 4,
"no_copy": 1,
"options": "No\nYes",
"print_hide": 1
@@ -2015,7 +2021,7 @@
"link_fieldname": "consolidated_invoice"
}
],
- "modified": "2021-08-18 16:07:45.122570",
+ "modified": "2021-08-25 14:46:05.279588",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",
From 81b459047944c79443369658f4d6fabcb4e3cb20 Mon Sep 17 00:00:00 2001
From: Frappe PR Bot
Date: Wed, 25 Aug 2021 18:18:16 +0530
Subject: [PATCH 43/80] fix: TDS calculation on net total (#27058) (#27140)
(cherry picked from commit 4eb7c2a011f3abbe547c2a32978e7af6e1fd6d33)
Co-authored-by: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com>
---
.../tax_withholding_category.py | 9 +++---
.../test_tax_withholding_category.py | 32 ++++++++++++++++++-
2 files changed, 36 insertions(+), 5 deletions(-)
diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
index 1536a237dec..0cb872c4b81 100644
--- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
+++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
@@ -240,14 +240,15 @@ def get_deducted_tax(taxable_vouchers, fiscal_year, tax_details):
def get_tds_amount(ldc, parties, inv, tax_details, fiscal_year_details, tax_deducted, vouchers):
tds_amount = 0
invoice_filters = {
- 'name': ('in', vouchers),
- 'docstatus': 1
+ 'name': ('in', vouchers),
+ 'docstatus': 1,
+ 'apply_tds': 1
}
field = 'sum(net_total)'
- if not cint(tax_details.consider_party_ledger_amount):
- invoice_filters.update({'apply_tds': 1})
+ if cint(tax_details.consider_party_ledger_amount):
+ invoice_filters.pop('apply_tds', None)
field = 'sum(grand_total)'
supp_credit_amt = frappe.db.get_value('Purchase Invoice', invoice_filters, field) or 0.0
diff --git a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py
index 1c687e5cb15..0f921db678d 100644
--- a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py
+++ b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py
@@ -145,6 +145,36 @@ class TestTaxWithholdingCategory(unittest.TestCase):
for d in invoices:
d.cancel()
+ def test_tds_calculation_on_net_total(self):
+ frappe.db.set_value("Supplier", "Test TDS Supplier4", "tax_withholding_category", "Cumulative Threshold TDS")
+ invoices = []
+
+ pi = create_purchase_invoice(supplier = "Test TDS Supplier4", rate = 20000, do_not_save=True)
+ pi.append('taxes', {
+ "category": "Total",
+ "charge_type": "Actual",
+ "account_head": '_Test Account VAT - _TC',
+ "cost_center": 'Main - _TC',
+ "tax_amount": 1000,
+ "description": "Test",
+ "add_deduct_tax": "Add"
+
+ })
+ pi.save()
+ pi.submit()
+ invoices.append(pi)
+
+ # Second Invoice will apply TDS checked
+ pi1 = create_purchase_invoice(supplier = "Test TDS Supplier4", rate = 20000)
+ pi1.submit()
+ invoices.append(pi1)
+
+ self.assertEqual(pi1.taxes[0].tax_amount, 4000)
+
+ #delete invoices to avoid clashing
+ for d in invoices:
+ d.cancel()
+
def cancel_invoices():
purchase_invoices = frappe.get_all("Purchase Invoice", {
'supplier': ['in', ['Test TDS Supplier', 'Test TDS Supplier1', 'Test TDS Supplier2']],
@@ -220,7 +250,7 @@ def create_sales_invoice(**args):
def create_records():
# create a new suppliers
- for name in ['Test TDS Supplier', 'Test TDS Supplier1', 'Test TDS Supplier2', 'Test TDS Supplier3']:
+ for name in ['Test TDS Supplier', 'Test TDS Supplier1', 'Test TDS Supplier2', 'Test TDS Supplier3', 'Test TDS Supplier4']:
if frappe.db.exists('Supplier', name):
continue
From 60675379c2c5cb311bef4cf2374908511c6569a3 Mon Sep 17 00:00:00 2001
From: Saqib
Date: Wed, 25 Aug 2021 18:26:00 +0530
Subject: [PATCH 44/80] fix: partial rename while replacing abbreviation
(#27065)
---
erpnext/setup/doctype/company/company.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py
index 45d5ce0c1c7..6dee2ad92a0 100644
--- a/erpnext/setup/doctype/company/company.py
+++ b/erpnext/setup/doctype/company/company.py
@@ -423,11 +423,11 @@ def replace_abbr(company, old, new):
_rename_record(d)
try:
frappe.db.auto_commit_on_many_writes = 1
- frappe.db.set_value("Company", company, "abbr", new)
for dt in ["Warehouse", "Account", "Cost Center", "Department",
"Sales Taxes and Charges Template", "Purchase Taxes and Charges Template"]:
_rename_records(dt)
frappe.db.commit()
+ frappe.db.set_value("Company", company, "abbr", new)
except Exception:
frappe.log_error(title=_('Abbreviation Rename Error'))
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 45/80] 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 078b9e11ce9..b0c2b94a254 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 be0f0151d40..7494328ab43 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 4d98be2126572a32d13ab76db5954d674d6845b2 Mon Sep 17 00:00:00 2001
From: Anupam Kumar
Date: Wed, 25 Aug 2021 19:18:17 +0530
Subject: [PATCH 46/80] feat: provision to create customer from opportunity
(#27141)
* feat: provision to create customer from opportunity
* fead: linking of address and contact
* revert: create_opportunity_address_contact
* enabming print hide and no copy
---
.../crm/doctype/opportunity/opportunity.js | 19 +++++++++++++++++--
.../crm/doctype/opportunity/opportunity.py | 18 ++++++++++++++++++
.../selling/doctype/customer/customer.json | 11 ++++++++++-
3 files changed, 45 insertions(+), 3 deletions(-)
diff --git a/erpnext/crm/doctype/opportunity/opportunity.js b/erpnext/crm/doctype/opportunity/opportunity.js
index 632012b31d3..cb95881cb4c 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.js
+++ b/erpnext/crm/doctype/opportunity/opportunity.js
@@ -95,9 +95,17 @@ frappe.ui.form.on("Opportunity", {
}, __('Create'));
}
- frm.add_custom_button(__('Quotation'),
- cur_frm.cscript.create_quotation, __('Create'));
+ if (frm.doc.opportunity_from != "Customer") {
+ frm.add_custom_button(__('Customer'),
+ function() {
+ frm.trigger("make_customer")
+ }, __('Create'));
+ }
+ frm.add_custom_button(__('Quotation'),
+ function() {
+ frm.trigger("create_quotation")
+ }, __('Create'));
}
if(!frm.doc.__islocal && frm.perm[0].write && frm.doc.docstatus==0) {
@@ -195,6 +203,13 @@ erpnext.crm.Opportunity = class Opportunity extends frappe.ui.form.Controller {
frm: cur_frm
})
}
+
+ make_customer() {
+ frappe.model.open_mapped_doc({
+ method: "erpnext.crm.doctype.opportunity.opportunity.make_customer",
+ frm: cur_frm
+ })
+ }
};
extend_cscript(cur_frm.cscript, new erpnext.crm.Opportunity({frm: cur_frm}));
diff --git a/erpnext/crm/doctype/opportunity/opportunity.py b/erpnext/crm/doctype/opportunity/opportunity.py
index 8ce482a3f9f..a74a94afd68 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.py
+++ b/erpnext/crm/doctype/opportunity/opportunity.py
@@ -287,6 +287,24 @@ def make_request_for_quotation(source_name, target_doc=None):
return doclist
+@frappe.whitelist()
+def make_customer(source_name, target_doc=None):
+ def set_missing_values(source, target):
+ if source.opportunity_from == "Lead":
+ target.lead_name = source.party_name
+
+ doclist = get_mapped_doc("Opportunity", source_name, {
+ "Opportunity": {
+ "doctype": "Customer",
+ "field_map": {
+ "currency": "default_currency",
+ "customer_name": "customer_name"
+ }
+ }
+ }, target_doc, set_missing_values)
+
+ return doclist
+
@frappe.whitelist()
def make_supplier_quotation(source_name, target_doc=None):
doclist = get_mapped_doc("Opportunity", source_name, {
diff --git a/erpnext/selling/doctype/customer/customer.json b/erpnext/selling/doctype/customer/customer.json
index cd94ee101af..0d839fc8228 100644
--- a/erpnext/selling/doctype/customer/customer.json
+++ b/erpnext/selling/doctype/customer/customer.json
@@ -20,6 +20,7 @@
"tax_withholding_category",
"default_bank_account",
"lead_name",
+ "opportunity_name",
"image",
"column_break0",
"account_manager",
@@ -493,6 +494,14 @@
"fieldtype": "Link",
"label": "Tax Withholding Category",
"options": "Tax Withholding Category"
+ },
+ {
+ "fieldname": "opportunity_name",
+ "fieldtype": "Link",
+ "label": "From Opportunity",
+ "no_copy": 1,
+ "options": "Opportunity",
+ "print_hide": 1
}
],
"icon": "fa fa-user",
@@ -500,7 +509,7 @@
"image_field": "image",
"index_web_pages_for_search": 1,
"links": [],
- "modified": "2021-01-28 12:54:57.258959",
+ "modified": "2021-08-25 18:56:09.929905",
"modified_by": "Administrator",
"module": "Selling",
"name": "Customer",
From ad45ddcabe90c628344474ca5022fd67e27f43ad Mon Sep 17 00:00:00 2001
From: rohitwaghchaure
Date: Wed, 25 Aug 2021 20:07:18 +0530
Subject: [PATCH 47/80] fix: sequence of sub-operations in job card (#27138)
---
erpnext/manufacturing/doctype/job_card/job_card.py | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py
index 66e2394b847..3efbe88adaf 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card.py
+++ b/erpnext/manufacturing/doctype/job_card/job_card.py
@@ -26,17 +26,17 @@ class JobCard(Document):
self.set_status()
self.validate_operation_id()
self.validate_sequence_id()
- self.get_sub_operations()
+ self.set_sub_operations()
self.update_sub_operation_status()
- def get_sub_operations(self):
+ def set_sub_operations(self):
if self.operation:
self.sub_operations = []
- for row in frappe.get_all("Sub Operation",
- filters = {"parent": self.operation}, fields=["operation", "idx"]):
- row.status = "Pending"
+ for row in frappe.get_all('Sub Operation',
+ filters = {'parent': self.operation}, fields=['operation', 'idx'], order_by='idx'):
+ row.status = 'Pending'
row.sub_operation = row.operation
- self.append("sub_operations", row)
+ self.append('sub_operations', row)
def validate_time_logs(self):
self.total_time_in_mins = 0.0
@@ -690,7 +690,7 @@ def make_corrective_job_card(source_name, operation=None, for_operation=None, ta
target.set('time_logs', [])
target.set('employee', [])
target.set('items', [])
- target.get_sub_operations()
+ target.set_sub_operations()
target.get_required_items()
target.validate_time_logs()
From 81b28b899843dcbf66d5c2cc241429e363ab04ac Mon Sep 17 00:00:00 2001
From: Chillar Anand
Date: Wed, 25 Aug 2021 20:08:11 +0530
Subject: [PATCH 48/80] fix(healthcare): Removed ignore user permissions flag
in appointment (#27129)
---
.../healthcare_practitioner.json | 5 ++-
.../patient_appointment.json | 1 -
.../test_patient_appointment.py | 43 +++++++++++++++++--
3 files changed, 44 insertions(+), 5 deletions(-)
diff --git a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.json b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.json
index 8162f03f6dc..cb455eb5014 100644
--- a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.json
+++ b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.json
@@ -282,7 +282,7 @@
],
"image_field": "image",
"links": [],
- "modified": "2021-01-22 10:14:43.187675",
+ "modified": "2021-08-24 10:42:08.513054",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Healthcare Practitioner",
@@ -295,6 +295,7 @@
"read": 1,
"report": 1,
"role": "Laboratory User",
+ "select": 1,
"share": 1,
"write": 1
},
@@ -307,6 +308,7 @@
"read": 1,
"report": 1,
"role": "Physician",
+ "select": 1,
"share": 1,
"write": 1
},
@@ -319,6 +321,7 @@
"read": 1,
"report": 1,
"role": "Nursing User",
+ "select": 1,
"share": 1,
"write": 1
}
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json
index 6e996bd128b..73ec3bc325f 100644
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.json
@@ -142,7 +142,6 @@
{
"fieldname": "practitioner",
"fieldtype": "Link",
- "ignore_user_permissions": 1,
"in_standard_filter": 1,
"label": "Healthcare Practitioner",
"options": "Healthcare Practitioner",
diff --git a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
index 2df6921b14f..9c3392cd5b2 100644
--- a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
@@ -199,10 +199,33 @@ class TestPatientAppointment(unittest.TestCase):
assert new_invoice_count == invoice_count + 1
+ def test_patient_appointment_should_consider_permissions_while_fetching_appointments(self):
+ patient, medical_department, practitioner = create_healthcare_docs()
+ create_appointment(patient, practitioner, nowdate())
+
+ patient, medical_department, new_practitioner = create_healthcare_docs(practitioner_name='Dr. John')
+ create_appointment(patient, new_practitioner, nowdate())
+
+ roles = [{"doctype": "Has Role", "role": "Physician"}]
+ user = create_user(roles=roles)
+ new_practitioner = frappe.get_doc('Healthcare Practitioner', new_practitioner)
+ new_practitioner.user_id = user.email
+ new_practitioner.save()
+
+ frappe.set_user(user.name)
+ appointments = frappe.get_list('Patient Appointment')
+ assert len(appointments) == 1
+
+ frappe.set_user("Administrator")
+ appointments = frappe.get_list('Patient Appointment')
+ assert len(appointments) == 2
+
+def create_healthcare_docs(practitioner_name=None):
+ if not practitioner_name:
+ practitioner_name = '_Test Healthcare Practitioner'
-def create_healthcare_docs():
patient = create_patient()
- practitioner = frappe.db.exists('Healthcare Practitioner', '_Test Healthcare Practitioner')
+ practitioner = frappe.db.exists('Healthcare Practitioner', practitioner_name)
medical_department = frappe.db.exists('Medical Department', '_Test Medical Department')
if not medical_department:
@@ -213,7 +236,7 @@ def create_healthcare_docs():
if not practitioner:
practitioner = frappe.new_doc('Healthcare Practitioner')
- practitioner.first_name = '_Test Healthcare Practitioner'
+ practitioner.first_name = practitioner_name
practitioner.gender = 'Female'
practitioner.department = medical_department
practitioner.op_consulting_charge = 500
@@ -319,3 +342,17 @@ def create_appointment_type(args=None):
'price_list': args.get('price_list') or frappe.db.get_value("Price List", {"selling": 1}),
'items': args.get('items') or items
}).insert()
+
+def create_user(email=None, roles=None):
+ if not email:
+ email = '{}@frappe.com'.format(frappe.utils.random_string(10))
+ user = frappe.db.exists('User', email)
+ if not user:
+ user = frappe.get_doc({
+ "doctype": "User",
+ "email": email,
+ "first_name": "test_user",
+ "password": "password",
+ "roles": roles,
+ }).insert()
+ return user
From c101b42d4a086c1e328fcdd442d4af33bde1f9c0 Mon Sep 17 00:00:00 2001
From: Saqib Ansari
Date: Wed, 25 Aug 2021 20:08:28 +0530
Subject: [PATCH 49/80] 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 80f86e75a02..7d58506ce74 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 50/80] 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 2053dc0f00a..a1bb15f0d6b 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 87308465d8b361485b6d63a2fc11283eba0c2b00 Mon Sep 17 00:00:00 2001
From: Rohan
Date: Wed, 25 Aug 2021 20:11:05 +0530
Subject: [PATCH 51/80] fix: create zero-dollar invoices fro trial
subscriptions (#26441)
---
.../doctype/subscription/subscription.py | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py
index 7c4ff73d908..8bf7b78f585 100644
--- a/erpnext/accounts/doctype/subscription/subscription.py
+++ b/erpnext/accounts/doctype/subscription/subscription.py
@@ -367,21 +367,25 @@ class Subscription(Document):
)
# Discounts
- if self.additional_discount_percentage:
- invoice.additional_discount_percentage = self.additional_discount_percentage
+ if self.is_trialling():
+ invoice.additional_discount_percentage = 100
+ else:
+ if self.additional_discount_percentage:
+ invoice.additional_discount_percentage = self.additional_discount_percentage
- if self.additional_discount_amount:
- invoice.discount_amount = self.additional_discount_amount
+ if self.additional_discount_amount:
+ invoice.discount_amount = self.additional_discount_amount
- if self.additional_discount_percentage or self.additional_discount_amount:
- discount_on = self.apply_additional_discount
- invoice.apply_discount_on = discount_on if discount_on else 'Grand Total'
+ if self.additional_discount_percentage or self.additional_discount_amount:
+ discount_on = self.apply_additional_discount
+ invoice.apply_discount_on = discount_on if discount_on else 'Grand Total'
# Subscription period
invoice.from_date = self.current_invoice_start
invoice.to_date = self.current_invoice_end
invoice.flags.ignore_mandatory = True
+
invoice.save()
if self.submit_invoice:
From 7254368fc52dd9f828dfe3c3d9570ba3274f0ade Mon Sep 17 00:00:00 2001
From: Saqib Ansari
Date: Wed, 25 Aug 2021 20:15:23 +0530
Subject: [PATCH 52/80] 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 55e6f0482ca..798b9949205 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 53/80] 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 798b9949205..f4af8932b6d 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 842ceb1301c60f4442313c3c266d4fc194f5172c Mon Sep 17 00:00:00 2001
From: Ganga Manoj
Date: Wed, 25 Aug 2021 20:32:26 +0530
Subject: [PATCH 54/80] fix: cannot reconcile bank transactions against
internal transfer payment entries (#26932)
* fix: Only set Clearance Date for Payment Entries of type Internal Transfer if both Transactions have been reconciled
* fix: Reset clearance_date for intra-company Payment Entries that have only been reconciled with one Bank Transaction
* fix: indentation and args
Co-authored-by: Saqib
Co-authored-by: Nabin Hait
---
.../bank_transaction/bank_transaction.py | 16 +++++++
erpnext/patches.txt | 1 +
...e_date_for_intracompany_payment_entries.py | 45 +++++++++++++++++++
3 files changed, 62 insertions(+)
create mode 100644 erpnext/patches/v13_0/reset_clearance_date_for_intracompany_payment_entries.py
diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
index 0544a469d60..7ea71fc103a 100644
--- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
+++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
@@ -55,6 +55,11 @@ class BankTransaction(StatusUpdater):
self.clear_sales_invoice(payment_entry, for_cancel=for_cancel)
def clear_simple_entry(self, payment_entry, for_cancel=False):
+ if payment_entry.payment_document == "Payment Entry":
+ if frappe.db.get_value("Payment Entry", payment_entry.payment_entry, "payment_type") == "Internal Transfer":
+ if len(get_reconciled_bank_transactions(payment_entry)) < 2:
+ return
+
clearance_date = self.date if not for_cancel else None
frappe.db.set_value(
payment_entry.payment_document, payment_entry.payment_entry,
@@ -70,6 +75,17 @@ class BankTransaction(StatusUpdater):
),
"clearance_date", clearance_date)
+def get_reconciled_bank_transactions(payment_entry):
+ reconciled_bank_transactions = frappe.get_all(
+ 'Bank Transaction Payments',
+ filters = {
+ 'payment_entry': payment_entry.payment_entry
+ },
+ fields = ['parent']
+ )
+
+ return reconciled_bank_transactions
+
def get_total_allocated_amount(payment_entry):
return frappe.db.sql("""
SELECT
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index bf0446bb686..0a6a8bdbdca 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -295,5 +295,6 @@ 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.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/reset_clearance_date_for_intracompany_payment_entries.py b/erpnext/patches/v13_0/reset_clearance_date_for_intracompany_payment_entries.py
new file mode 100644
index 00000000000..1da5275761b
--- /dev/null
+++ b/erpnext/patches/v13_0/reset_clearance_date_for_intracompany_payment_entries.py
@@ -0,0 +1,45 @@
+# Copyright (c) 2019, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+
+import frappe
+
+def execute():
+ """
+ Reset Clearance Date for Payment Entries of type Internal Transfer that have only been reconciled with one Bank Transaction.
+ This will allow the Payment Entries to be reconciled with the second Bank Transaction using the Bank Reconciliation Tool.
+ """
+
+ intra_company_pe = get_intra_company_payment_entries_with_clearance_dates()
+ reconciled_bank_transactions = get_reconciled_bank_transactions(intra_company_pe)
+
+ for payment_entry in reconciled_bank_transactions:
+ if len(reconciled_bank_transactions[payment_entry]) == 1:
+ frappe.db.set_value('Payment Entry', payment_entry, 'clearance_date', None)
+
+def get_intra_company_payment_entries_with_clearance_dates():
+ return frappe.get_all(
+ 'Payment Entry',
+ filters = {
+ 'payment_type': 'Internal Transfer',
+ 'clearance_date': ["not in", None]
+ },
+ pluck = 'name'
+ )
+
+def get_reconciled_bank_transactions(intra_company_pe):
+ """Returns dictionary where each key:value pair is Payment Entry : List of Bank Transactions reconciled with Payment Entry"""
+
+ reconciled_bank_transactions = {}
+
+ for payment_entry in intra_company_pe:
+ reconciled_bank_transactions[payment_entry] = frappe.get_all(
+ 'Bank Transaction Payments',
+ filters = {
+ 'payment_entry': payment_entry
+ },
+ pluck='parent'
+ )
+
+ return reconciled_bank_transactions
\ No newline at end of file
From b99c0119475ed82895f479f89685977204fcdbba Mon Sep 17 00:00:00 2001
From: Ashish Shah
Date: Wed, 25 Aug 2021 21:33:08 +0530
Subject: [PATCH 55/80] fix: unable to create manual / auto asset depreciation
entry when cost_center is mandatory (#26912)
Summary : unable to create manual / auto asset depreciation entry when cost_center is mandatory
Reason: Though we are calculating value for depreciation_cost_center, it is not passed in credit_entry(it is passed in debit_entry) and this prevents creation of manual / auto asset depreciation entry when cost_center is mandatory
Solution : pass already calculated depreciation_cost_center value in credit_entry (in line with, already done as in debit_entry)
---
erpnext/assets/doctype/asset/depreciation.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py
index 8fdbbf95d47..9a61b79ed35 100644
--- a/erpnext/assets/doctype/asset/depreciation.py
+++ b/erpnext/assets/doctype/asset/depreciation.py
@@ -59,7 +59,7 @@ def make_depreciation_entry(asset_name, date=None):
"credit_in_account_currency": d.depreciation_amount,
"reference_type": "Asset",
"reference_name": asset.name,
- "cost_center": ""
+ "cost_center": depreciation_cost_center
}
debit_entry = {
From be7a38b662b82aac11a6a085f02eeffecd10872f Mon Sep 17 00:00:00 2001
From: Saqib Ansari
Date: Wed, 25 Aug 2021 21:35:32 +0530
Subject: [PATCH 56/80] 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 b48dc924f73..83f0222026d 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 57/80] 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 2f06e988804..cb00019cf5b 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 0d839fc8228..2acc64cb433 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 58/80] 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 c417a493c69..834227bb586 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 59/80] 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 b001bf024ce..d76b42e6836 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 5b9c17934fa..59586e0c31b 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 82e7136d6b9..4a178723a0e 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 05e2cd30df5..7db4fa616ad 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 9c3392cd5b2..157b3e11624 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 60/80] 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 00000000000..dea17a66fda
--- /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 17aca17afda..88f6b923e66 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 61/80] 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 c3d83c7d74c..053d42ee538 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 c77076cb90e..b90f3f09045 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 5ee1f2f7fb5..01486fcd65d 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 fc2cc97e0a5..4ea0e114b48 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 eddd048c74e..27feec1d15f 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 62/80] 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 5a19426eb06..43a5f5e2f6a 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 4ea0e114b48..844c40c8a64 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 b1a5b52f963..908ba270b04 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 91e7c006eef..dffc73020d6 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 63/80] 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 ed1e259c3c4..24f84e63b39 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 6e17f2a8314..b8f0db0de22 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 64/80] 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 765b51f435f..00000000000
--- 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 65/80] 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 43a5f5e2f6a..e06a3bb5b18 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 908ba270b04..5b337313d3d 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 dffc73020d6..e6736b2bab3 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 66/80] 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 e6736b2bab3..b333a6b57ea 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 67/80] 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 cda7c1d31ae..24b7b9aeb65 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 94b006c8944..e4381271ed2 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 27feec1d15f..48fd7d3d261 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 68/80] 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 24f84e63b39..1d7d451cc8e 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 b8f0db0de22..8408f10b187 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 a5b9ff845fc..78028039c48 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 3a334a530cd..c0ed6115340 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 69/80] 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 abacee985c6..5a183e2e513 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 70/80] 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 c587dd5c7ec..3de35e6062b 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 f662bbd1c79..db5caf91645 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 71/80] 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 0be9bd8f870..0ece0d8ee62 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 71ce5b8d04f..00000000000
--- 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 9ec264415a6..00000000000
--- 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 c20a7990e8c..00000000000
--- 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 f59999845af..00000000000
--- 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 0c60920cf98..00000000000
--- 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 305119e1370..00000000000
--- 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 12ca254c5ae..00000000000
--- 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 1970ca806dc..00000000000
--- 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 12546ce2e3a..00000000000
--- 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 eecabda751b..00000000000
--- 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 a7fcc8d8421..00000000000
--- 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 b075a015d60..00000000000
--- 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 460fedc97f9..00000000000
--- 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 57c6a7871dc..00000000000
--- 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 9fb7d4fcc8e..00000000000
--- 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 2986e5e4e3b..00000000000
--- 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 68934993914..00000000000
--- 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 a916b67522c..00000000000
--- 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 9321c14e1f0..00000000000
--- 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 f95d0d82138..00000000000
--- 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 f63fc54521c..00000000000
--- 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 070b595fc6a..00000000000
--- 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 b26e42aa37d..00000000000
--- 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 494a0ed21fb..00000000000
--- 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 48109b159c6..00000000000
--- 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 42e5b7f92f1..00000000000
--- 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 5449ab76a38..00000000000
--- 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 639c94ed10d..00000000000
--- 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 e5530fa0aa6..00000000000
--- 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 620afa2ba85..00000000000
--- 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 61c53120ea6..00000000000
--- 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 15d3df2a633..00000000000
--- 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 3ceb9a60507..00000000000
--- 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 5a751ea99c3..00000000000
--- 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 5142456d769..00000000000
--- 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 72d177deffe..00000000000
--- 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 eab98d43892..00000000000
--- 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 f70dcd2f322..00000000000
--- 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 a012c4b1ade..00000000000
--- 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 786c0471a47..00000000000
--- 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 29128eba27d..00000000000
--- 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 b5009a4ccd3..00000000000
--- 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 6119e382174..00000000000
--- 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 7e343b7519e..00000000000
--- 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 f9b38a1020e..00000000000
--- 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 4e80184ea7b..00000000000
--- 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 41bf69623ec..00000000000
--- 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 b9515763c42..00000000000
--- 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 7424ffe2b80..00000000000
--- 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 32831c61d2e..00000000000
--- 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 3c06b63e820..00000000000
--- 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 d942e2a1566..00000000000
--- 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 4c77c3d649f..00000000000
--- 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 2a2d5e1bfc0..00000000000
--- 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 6aaddd7df4d..00000000000
--- 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 aa4b868f932..00000000000
--- 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 3a1ede94dba..00000000000
--- 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 807af1fd983..00000000000
--- 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 51e9cf307d8..00000000000
--- 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 9dbf063e844..00000000000
--- 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 cc869a87fcf..00000000000
--- 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 c89c89e5d3c..00000000000
--- 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 786e67e9a37..00000000000
--- 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 216cc307991..00000000000
--- 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 5cdb67be482..00000000000
--- 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 4419d181167..00000000000
--- 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 d8d154fb9c8..00000000000
--- 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 a08ed33e8b6..00000000000
--- 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 d495b4ce7b1..00000000000
--- 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 61f41354c34..00000000000
--- 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 aea81a0714e..00000000000
--- 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 8d55104a0f3..00000000000
--- 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 509939c6b56..00000000000
--- 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 147d13952ab..00000000000
--- 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 94b5ab796ac..00000000000
--- 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 43f53a1dc77..00000000000
--- 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 dde63ecc4c6..00000000000
--- 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 e18d39aee07..00000000000
--- 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 9b25569961a..00000000000
--- 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 10be092bb92..00000000000
--- 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 4460b794786..00000000000
--- 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 bf9a62d0376..00000000000
--- 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 9c8990986e2..00000000000
--- 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 caa9399eb6c..00000000000
--- 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 b6daad8de48..00000000000
--- 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 dc91347336d..00000000000
--- 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 b71d7048076..00000000000
--- 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 433c5e2cda8..00000000000
--- 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 ea06ab2dc4e..00000000000
--- 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 b92103d7509..00000000000
--- 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 93274e55c7b..00000000000
--- 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 80ef3d55f2a..00000000000
--- 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 1dde8b5d867..00000000000
--- 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 9ff44d8da46..00000000000
--- 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 cacfef5b17d..00000000000
--- 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 ba54ab16faa..00000000000
--- 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 0ebb97438ca..00000000000
--- 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 75aa208ec16..00000000000
--- 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 a67a4117073..00000000000
--- 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 6db8f9e9c1a..00000000000
--- 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 ca10925e598..00000000000
--- 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 1ce9afa96d4..00000000000
--- 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 57cb22b2699..00000000000
--- 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 ace60de752a..00000000000
--- 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 7c2ec8c3483..00000000000
--- 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 1328dda2826..00000000000
--- 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 8cc7c40025c..00000000000
--- 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 6ab6d531dfb..00000000000
--- 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 fdf49718dc8..00000000000
--- 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 d57e5536c69..00000000000
--- 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 e1d9ecbd242..00000000000
--- 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 71fc1778455..00000000000
--- 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 1baabf7eef7..00000000000
--- 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 66dda09e256..00000000000
--- 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 32dac2c6526..00000000000
--- 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 009614ff5dd..00000000000
--- 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 4971e79198c..00000000000
--- 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 2b4aed756bf..00000000000
--- 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 c2cf406f96d..00000000000
--- 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 f4ab4466be4..00000000000
--- 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 8b2b83330f3..00000000000
--- 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 f1ebad41d41..00000000000
--- 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 ba0d1fd3e96..00000000000
--- 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 73a561c408c..00000000000
--- 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 2897139359b..00000000000
--- 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 e2dd5780e3c..00000000000
--- 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 bc0b7f8341d..00000000000
--- 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 d40ec61b086..00000000000
--- 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 82a6ae103ee..00000000000
--- 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 bebcaac400e..00000000000
--- 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 15335171473..00000000000
--- 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 e73779c97c6..00000000000
--- 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 00adf8293f7..00000000000
--- 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 ff9f61e66a6..00000000000
--- 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 1b9ec6f6d0c..00000000000
--- 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 d684fb2ad1b..00000000000
--- 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 245cb32971f..00000000000
--- 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 d15cef77dca..00000000000
--- 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 10912edb6ac..00000000000
--- 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 5f0a5baf818..00000000000
--- 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 d6c635951f7..00000000000
--- 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 66fd4508046..00000000000
--- 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 05a3e1a5738..00000000000
--- 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 00a334a63d7..00000000000
--- 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 f32640ba5c6..00000000000
--- 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 65879098e87..00000000000
--- 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 c093928f321..00000000000
--- 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 cafd9602cbe..00000000000
--- 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 ec0a8096890..00000000000
--- 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 5404a63bed1..00000000000
--- 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 1c8995b7967..00000000000
--- 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 936c21ccf05..00000000000
--- 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 77272877423..00000000000
--- 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 9c8cd70020c..00000000000
--- 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 846f9316f58..00000000000
--- 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 64320bcd92b..00000000000
--- 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 3a62b2fa221..00000000000
--- 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 cb1d7fb27a3..00000000000
--- 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 7e645918239..00000000000
--- 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 4d40cce086a..00000000000
--- 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 fba3e098d4b..00000000000
--- 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 e0f05b1abbd..00000000000
--- 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 51a0d948419..00000000000
--- 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 d220df2824f..00000000000
--- 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 5dc7805d226..00000000000
--- 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 2b2589eddd8..00000000000
--- 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 14c6e393847..00000000000
--- 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 ef7d64c92da..00000000000
--- 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 6cb65494af2..00000000000
--- 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 40e94864d49..00000000000
--- 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 f6a72a43271..00000000000
--- 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 e30d6a5bf9b..00000000000
--- 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 22dc18ed76a..00000000000
--- 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 24c85c61576..00000000000
--- 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 c18e1875854..00000000000
--- 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 b355e1c4366..00000000000
--- 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 3c808c0a560..00000000000
--- 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 10bc03701fd..00000000000
--- 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 e0e43c32e3b..00000000000
--- 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 274a3a38603..00000000000
--- 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 cec75087280..00000000000
--- 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 8a1a6d151dd..00000000000
--- 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 8c4ded96f38..00000000000
--- 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 a4b95d3cb10..00000000000
--- 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 c47d32d9965..00000000000
--- 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 2f52576c7a7..00000000000
--- 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 b7049b37e18..00000000000
--- 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 16494f62b60..00000000000
--- 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 c2198c452c0..00000000000
--- 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 bda510b921a..00000000000
--- 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 f6feaa48049..00000000000
--- 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 c081d6f8ea4..00000000000
--- 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 24c5fd355ff..00000000000
--- 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 00fcca6f326..00000000000
--- 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 65b81af32c1..00000000000
--- 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 57ed19b6965..00000000000
--- 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 3ed7b46e1d9..00000000000
--- 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 19fde2e1481..00000000000
--- 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 33634eb0f88..00000000000
--- 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 ea322e23d65..00000000000
--- 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 22b664b2e6d..00000000000
--- 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 c97dbc58c80..00000000000
--- 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 976dd2cc4f3..00000000000
--- 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 afcf74ccb47..00000000000
--- 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 c8485e73fa3..00000000000
--- 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 85812d69739..00000000000
--- 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 22977c08f75..00000000000
--- 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 b6d6d1af64f..00000000000
--- 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 af44278a59a..00000000000
--- 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 87318499fe4..00000000000
--- 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 3b3bf94f375..00000000000
--- 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 0254a367ccb..00000000000
--- 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 793cad0f3b6..00000000000
--- 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 fe4e07b3bdd..00000000000
--- 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 327484e6cc3..00000000000
--- 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 879c262ed2a..00000000000
--- 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 bf8293257c3..00000000000
--- 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 57d9fc61aab..00000000000
--- 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 4b5972ea716..00000000000
--- 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 2600a10fe0d..00000000000
--- 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 0787306c3ea..00000000000
--- 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 72/80] 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 94abf3b3c06..5467cb0bc5b 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 73/80] 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 1481f1c54f4..05123d5f856 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 2936e33b118..95643bf49fc 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 d198a6962a5..847004fc47f 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 032c9cd9a21..c17a8e959db 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 512048512ed..51c46f63ab7 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 d8d25fc6f83..4f5231e449c 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 7317152565a..032091f67e2 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 84b4088f233..9d7a58c1214 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 0ffa30158b0..ad7345234d1 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 0764f2e44a8..3f94764f089 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 7ef202ee4e7..1d2c27e3796 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 b532e6778c4..2e9592185ef 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 00000000000..ff9fdb9fd0c
--- /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 00000000000..be4fbff171f
--- /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 c63363e7cb2..d2756c92758 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 df244bb494a..67dd52eba2c 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 3de35e6062b..752a1fe732b 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 74/80] 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 771611a7860..878ae098891 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 108b4c0dd81..820c7405328 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 0a6a8bdbdca..311e785f8c6 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 00000000000..355421a1f42
--- /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 75/80] 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 d91e6bf9dc6..a65c56694e7 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 56a34007ffb..f77ad70633d 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 aaeaa692e63..c3466260d2b 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 b646ff9ebe6..994597dca7c 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 2b3029efdeb..7a745ae468e 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 f5df152050f..96976821a71 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 00000000000..e69de29bb2d
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 00000000000..d661b4304f6
--- /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 00000000000..21ede7129f1
--- /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 00000000000..986c3cb6e42
--- /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 00000000000..85a312fb174
--- /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 00000000000..a92e2668fe8
--- /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 00000000000..7ab31dff791
--- /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 00000000000..e69de29bb2d
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 00000000000..20a9d6793a5
--- /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 00000000000..5f58b06af60
--- /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 00000000000..e69de29bb2d
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 00000000000..04da387f7b8
--- /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 00000000000..6d34568e15c
--- /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 76/80] 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 53ecdf5a61f..6b3f18484ad 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 bba54018aef..5d44582aab4 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 77/80] 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 b4c663507ce..6b61c6d330f 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 c2e3e6d7124..8f946866247 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 78/80] 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 5a183e2e513..b259b11c638 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 79/80] 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 1d7d451cc8e..6e1c7dd81b1 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 311e785f8c6..0f6a606cb12 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 00000000000..4acbdd63a00
--- /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 80/80] 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 1898222916b..f43c80416f3 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 65792b42fb8..044a5a9886b 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 673e228395e..fd877a68d85 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 0445270b9ff..ea46aa24a6c 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 e69de29bb2d..00000000000
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 4e91b723844..00000000000
--- 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 d1706318191..00000000000
--- 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 c10da5c35e7..c240493e820 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 d63501a9314..2c11cbbe2c7 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 d730fcf1fa9..636ec0b5a66 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