From 23af036894ef61f590278fa7e84402f0be3ff50d Mon Sep 17 00:00:00 2001 From: Anupam Date: Fri, 29 Oct 2021 17:27:17 +0530 Subject: [PATCH 01/30] feat: provision to close the Work Order --- .../doctype/work_order/work_order.js | 48 +++++++++++-------- .../doctype/work_order/work_order.json | 5 +- .../doctype/work_order/work_order.py | 31 +++++++++++- 3 files changed, 60 insertions(+), 24 deletions(-) diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js index 51c46f63ab7..d4235731ae1 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.js +++ b/erpnext/manufacturing/doctype/work_order/work_order.js @@ -135,24 +135,26 @@ frappe.ui.form.on("Work Order", { frm.set_intro(__("Submit this Work Order for further processing.")); } - if (frm.doc.docstatus===1) { - frm.trigger('show_progress_for_items'); - frm.trigger('show_progress_for_operations'); - } + if (frm.doc.status != "Closed") { + if (frm.doc.docstatus===1) { + frm.trigger('show_progress_for_items'); + frm.trigger('show_progress_for_operations'); + } - if (frm.doc.docstatus === 1 - && frm.doc.operations && frm.doc.operations.length) { + if (frm.doc.docstatus === 1 + && frm.doc.operations && frm.doc.operations.length) { - const not_completed = frm.doc.operations.filter(d => { - if(d.status != 'Completed') { - return true; + const not_completed = frm.doc.operations.filter(d => { + if(d.status != 'Completed') { + return true; + } + }); + + if(not_completed && not_completed.length) { + frm.add_custom_button(__('Create Job Card'), () => { + frm.trigger("make_job_card"); + }).addClass('btn-primary'); } - }); - - if(not_completed && not_completed.length) { - frm.add_custom_button(__('Create Job Card'), () => { - frm.trigger("make_job_card"); - }).addClass('btn-primary'); } } @@ -517,14 +519,19 @@ frappe.ui.form.on("Work Order Operation", { erpnext.work_order = { set_custom_buttons: function(frm) { var doc = frm.doc; - if (doc.docstatus === 1) { + if (doc.docstatus === 1 && doc.status != "Closed") { + console.log("check"); + frm.add_custom_button(__('Close'), function() { + erpnext.work_order.change_work_order_status(frm, "Closed"); + }, __("Status")); + if (doc.status != 'Stopped' && doc.status != 'Completed') { frm.add_custom_button(__('Stop'), function() { - erpnext.work_order.stop_work_order(frm, "Stopped"); + erpnext.work_order.change_work_order_status(frm, "Stopped"); }, __("Status")); } else if (doc.status == 'Stopped') { frm.add_custom_button(__('Re-open'), function() { - erpnext.work_order.stop_work_order(frm, "Resumed"); + erpnext.work_order.change_work_order_status(frm, "Resumed"); }, __("Status")); } @@ -713,9 +720,10 @@ erpnext.work_order = { }); }, - stop_work_order: function(frm, status) { + change_work_order_status: function(frm, status) { + let method_name = status=="Closed" ? "close_work_order" : "stop_unstop"; frappe.call({ - method: "erpnext.manufacturing.doctype.work_order.work_order.stop_unstop", + method: `erpnext.manufacturing.doctype.work_order.work_order.${method_name}`, freeze: true, freeze_message: __("Updating Work Order status"), args: { diff --git a/erpnext/manufacturing/doctype/work_order/work_order.json b/erpnext/manufacturing/doctype/work_order/work_order.json index 7f8e816a22a..df7ee53b92d 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.json +++ b/erpnext/manufacturing/doctype/work_order/work_order.json @@ -99,7 +99,7 @@ "no_copy": 1, "oldfieldname": "status", "oldfieldtype": "Select", - "options": "\nDraft\nSubmitted\nNot Started\nIn Process\nCompleted\nStopped\nCancelled", + "options": "\nDraft\nSubmitted\nNot Started\nIn Process\nCompleted\nStopped\nClosed\nCancelled", "read_only": 1, "reqd": 1, "search_index": 1 @@ -573,7 +573,8 @@ "image_field": "image", "is_submittable": 1, "links": [], - "modified": "2021-10-27 19:21:35.139888", + "migration_hash": "a18118963f4fcdb7f9d326de5f4063ba", + "modified": "2021-10-29 15:12:32.203605", "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 f881e1bf16a..6901d71ad4a 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -175,7 +175,7 @@ class WorkOrder(Document): def update_status(self, status=None): '''Update status of work order if unknown''' - if status != "Stopped": + if status != "Stopped" and status != "Closed": status = self.get_status(status) if status != self.status: @@ -624,7 +624,6 @@ class WorkOrder(Document): def validate_operation_time(self): for d in self.operations: if not d.time_in_mins > 0: - print(self.bom_no, self.production_item) frappe.throw(_("Operation Time must be greater than 0 for Operation {0}").format(d.operation)) def update_required_items(self): @@ -967,6 +966,10 @@ def stop_unstop(work_order, status): frappe.throw(_("Not permitted"), frappe.PermissionError) pro_order = frappe.get_doc("Work Order", work_order) + + if pro_order.status == "Closed": + frappe.throw(_("Closed Work Order can not be stopped or Re-opened")) + pro_order.update_status(status) pro_order.update_planned_qty() frappe.msgprint(_("Work Order has been {0}").format(status)) @@ -1001,6 +1004,30 @@ def make_job_card(work_order, operations): if row.job_card_qty > 0: create_job_card(work_order, row, auto_create=True) +@frappe.whitelist() +def close_work_order(work_order, status): + if not frappe.has_permission("Work Order", "write"): + frappe.throw(_("Not permitted"), frappe.PermissionError) + + work_order = frappe.get_doc("Work Order", work_order) + if work_order.get("operations"): + job_cards = frappe.get_list("Job Card", + filters={ + "work_order": work_order.name, + "status": "Work In Progress" + }, + pluck='name') + + if job_cards: + job_cards = ", ".join(job_cards) + frappe.throw(_("Can not close Work Order. Since {0} Job Cards are in Work In Progress state.").format(job_cards)) + + work_order.update_status(status) + work_order.update_planned_qty() + frappe.msgprint(_("Work Order has been {0}").format(status)) + work_order.notify_update() + return work_order.status + def split_qty_based_on_batch_size(wo_doc, row, qty): if not cint(frappe.db.get_value("Operation", row.operation, "create_job_card_based_on_batch_size")): From 5d4c5652aff59d6f051adf34dd60094cce96af07 Mon Sep 17 00:00:00 2001 From: Anupam Date: Sun, 31 Oct 2021 14:20:03 +0530 Subject: [PATCH 02/30] feat: added confirm dialog on closing of workorder --- erpnext/manufacturing/doctype/work_order/work_order.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js index d4235731ae1..9ab81619f99 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.js +++ b/erpnext/manufacturing/doctype/work_order/work_order.js @@ -520,9 +520,12 @@ erpnext.work_order = { set_custom_buttons: function(frm) { var doc = frm.doc; if (doc.docstatus === 1 && doc.status != "Closed") { - console.log("check"); frm.add_custom_button(__('Close'), function() { - erpnext.work_order.change_work_order_status(frm, "Closed"); + frappe.confirm(__("Once the Work Order is Closed. It can't be resumed."), + () => { + erpnext.work_order.change_work_order_status(frm, "Closed"); + } + ); }, __("Status")); if (doc.status != 'Stopped' && doc.status != 'Completed') { From e290fe0721a2db994171e0be5a98d7fce272a3c7 Mon Sep 17 00:00:00 2001 From: Anupam Date: Sun, 31 Oct 2021 14:42:10 +0530 Subject: [PATCH 03/30] fix: sider issue --- erpnext/manufacturing/doctype/work_order/work_order.js | 4 ++-- erpnext/manufacturing/doctype/work_order/work_order.py | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js index 9ab81619f99..bfce1b8cbec 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.js +++ b/erpnext/manufacturing/doctype/work_order/work_order.js @@ -145,12 +145,12 @@ frappe.ui.form.on("Work Order", { && frm.doc.operations && frm.doc.operations.length) { const not_completed = frm.doc.operations.filter(d => { - if(d.status != 'Completed') { + if (d.status != 'Completed') { return true; } }); - if(not_completed && not_completed.length) { + if (not_completed && not_completed.length) { frm.add_custom_button(__('Create Job Card'), () => { frm.trigger("make_job_card"); }).addClass('btn-primary'); diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index 6901d71ad4a..af80c4ef0be 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -1015,8 +1015,7 @@ def close_work_order(work_order, status): filters={ "work_order": work_order.name, "status": "Work In Progress" - }, - pluck='name') + }, pluck='name') if job_cards: job_cards = ", ".join(job_cards) From 55e97dce8a7cffd12180b36586ee277b3188cda5 Mon Sep 17 00:00:00 2001 From: Anupam Date: Sun, 31 Oct 2021 14:45:36 +0530 Subject: [PATCH 04/30] fix: sider issue --- erpnext/manufacturing/doctype/work_order/work_order.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index af80c4ef0be..117e2a227a8 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -1012,10 +1012,10 @@ def close_work_order(work_order, status): work_order = frappe.get_doc("Work Order", work_order) if work_order.get("operations"): job_cards = frappe.get_list("Job Card", - filters={ - "work_order": work_order.name, - "status": "Work In Progress" - }, pluck='name') + filters={ + "work_order": work_order.name, + "status": "Work In Progress" + }, pluck='name') if job_cards: job_cards = ", ".join(job_cards) From 264b0df9ffe5074542c28b46c6ead2c3436e27ed Mon Sep 17 00:00:00 2001 From: Anupam Date: Sun, 31 Oct 2021 16:11:11 +0530 Subject: [PATCH 05/30] fix: sider issue --- erpnext/manufacturing/doctype/work_order/work_order.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index 117e2a227a8..48703bc621b 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -1015,7 +1015,7 @@ def close_work_order(work_order, status): filters={ "work_order": work_order.name, "status": "Work In Progress" - }, pluck='name') + }, pluck='name') if job_cards: job_cards = ", ".join(job_cards) From 530a0f481e8901d2b525a54c663251a477cc3758 Mon Sep 17 00:00:00 2001 From: Anupam Date: Tue, 2 Nov 2021 12:39:13 +0530 Subject: [PATCH 06/30] fix: added testcase --- erpnext/manufacturing/doctype/work_order/test_work_order.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index 85b5bfb9bfc..dc817296816 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -14,6 +14,7 @@ from erpnext.manufacturing.doctype.work_order.work_order import ( StockOverProductionError, make_stock_entry, stop_unstop, + close_work_order, ) from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order from erpnext.stock.doctype.item.test_item import create_item, make_item @@ -800,6 +801,10 @@ class TestWorkOrder(unittest.TestCase): if row.is_scrap_item: self.assertEqual(row.qty, 1) + def test_close_work_order(self): + close_work_order(self.wo_order.name, "Stopped") + self.assertEqual(self.wo_order.status, "Closed") + def update_job_card(job_card): job_card_doc = frappe.get_doc('Job Card', job_card) job_card_doc.set('scrap_items', [ From 59e4fd980c1c411f82df1f588bc2c80e17d8e317 Mon Sep 17 00:00:00 2001 From: Anupam Date: Tue, 2 Nov 2021 12:46:00 +0530 Subject: [PATCH 07/30] fix: linter issues --- erpnext/manufacturing/doctype/work_order/test_work_order.py | 2 +- erpnext/manufacturing/doctype/work_order/work_order.py | 1 + 2 files changed, 2 insertions(+), 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 dc817296816..f5851dae36c 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -12,9 +12,9 @@ from erpnext.manufacturing.doctype.work_order.work_order import ( ItemHasVariantError, OverProductionError, StockOverProductionError, + close_work_order, make_stock_entry, stop_unstop, - close_work_order, ) from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order from erpnext.stock.doctype.item.test_item import create_item, make_item diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index 48703bc621b..36dae99a691 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -1011,6 +1011,7 @@ def close_work_order(work_order, status): work_order = frappe.get_doc("Work Order", work_order) if work_order.get("operations"): + job_cards = frappe.get_list("Job Card", filters={ "work_order": work_order.name, From e36da4d13749afd0fb0e1523aa6d2ecc33ab730c Mon Sep 17 00:00:00 2001 From: Anupam Date: Tue, 2 Nov 2021 12:53:00 +0530 Subject: [PATCH 08/30] fix: linter issues --- erpnext/manufacturing/doctype/work_order/work_order.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index 36dae99a691..0090f4d04ee 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -1011,8 +1011,7 @@ def close_work_order(work_order, status): work_order = frappe.get_doc("Work Order", work_order) if work_order.get("operations"): - - job_cards = frappe.get_list("Job Card", + job_cards = frappe.get_list("Job Card", filters={ "work_order": work_order.name, "status": "Work In Progress" From 9c0906f1b51431f67c3bc009a1410e1129a80744 Mon Sep 17 00:00:00 2001 From: Anupam Date: Tue, 2 Nov 2021 20:43:00 +0530 Subject: [PATCH 09/30] fix: test cases --- 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 f5851dae36c..b6a8700baca 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -802,7 +802,7 @@ class TestWorkOrder(unittest.TestCase): self.assertEqual(row.qty, 1) def test_close_work_order(self): - close_work_order(self.wo_order.name, "Stopped") + close_work_order(self.wo_order.name, "Closed") self.assertEqual(self.wo_order.status, "Closed") def update_job_card(job_card): From 9b4c7e479650851228181cdf562647364ba51cf9 Mon Sep 17 00:00:00 2001 From: Anupam Date: Wed, 3 Nov 2021 13:27:50 +0530 Subject: [PATCH 10/30] fix: validate job card --- .../doctype/job_card/job_card.js | 5 +++ .../doctype/job_card/job_card.py | 14 +++++++ .../doctype/work_order/test_work_order.py | 39 ++++++++++++++++++- 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/erpnext/manufacturing/doctype/job_card/job_card.js b/erpnext/manufacturing/doctype/job_card/job_card.js index 35be38813e5..df35028ca72 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.js +++ b/erpnext/manufacturing/doctype/job_card/job_card.js @@ -28,6 +28,11 @@ frappe.ui.form.on('Job Card', { frappe.flags.resume_job = 0; let has_items = frm.doc.items && frm.doc.items.length; + if (frm.doc.__onload.work_order_stopped) { + frm.disable_save(); + return + } + if (!frm.doc.__islocal && has_items && frm.doc.docstatus < 2) { let to_request = frm.doc.for_quantity > frm.doc.transferred_qty; let excess_transfer_allowed = frm.doc.__onload.job_card_excess_transfer; diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index e1d79be81c4..dd1df20216b 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -37,6 +37,7 @@ class JobCard(Document): def onload(self): excess_transfer = frappe.db.get_single_value("Manufacturing Settings", "job_card_excess_transfer") self.set_onload("job_card_excess_transfer", excess_transfer) + self.set_onload("work_order_stopped", self.is_work_order_stopped()) def validate(self): self.validate_time_logs() @@ -45,6 +46,7 @@ class JobCard(Document): self.validate_sequence_id() self.set_sub_operations() self.update_sub_operation_status() + self.validate_work_order() def set_sub_operations(self): if self.operation: @@ -549,6 +551,18 @@ class JobCard(Document): frappe.throw(_("{0}, complete the operation {1} before the operation {2}.") .format(message, bold(row.operation), bold(self.operation)), OperationSequenceError) + def validate_work_order(self): + if self.is_work_order_stopped(): + frappe.throw(_("You can't make any changes to Job Card since Work Order is stopped.")) + + def is_work_order_stopped(self): + if self.work_order: + status = frappe.get_value('Work Order', self.work_order) + + if status == "Closed": + return True + + return False @frappe.whitelist() def make_time_log(args): diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index b6a8700baca..3dbbf317576 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -802,8 +802,43 @@ class TestWorkOrder(unittest.TestCase): self.assertEqual(row.qty, 1) def test_close_work_order(self): - close_work_order(self.wo_order.name, "Closed") - self.assertEqual(self.wo_order.status, "Closed") + items = ['Test FG Item for Closed WO', 'Test RM Item 1 for Closed WO', + 'Test RM Item 2 for Closed WO'] + + company = '_Test Company with perpetual inventory' + for item_code in items: + create_item(item_code = item_code, is_stock_item = 1, + is_purchase_item=1, opening_stock=100, valuation_rate=10, company=company, warehouse='Stores - TCP1') + + item = 'Test FG Item for Closed WO' + raw_materials = ['Test RM Item 1 for Closed WO', 'Test RM Item 2 for Closed WO'] + if not frappe.db.get_value('BOM', {'item': item}): + bom = make_bom(item=item, source_warehouse='Stores - TCP1', raw_materials=raw_materials, do_not_save=True) + bom.with_operations = 1 + bom.append('operations', { + 'operation': '_Test Operation 1', + 'workstation': '_Test Workstation 1', + 'hour_rate': 20, + 'time_in_mins': 60 + }) + + bom.submit() + + wo_order = make_wo_order_test_record(item=item, company=company, planned_start_date=now(), qty=20, skip_transfer=1) + job_cards = frappe.db.get_value('Job Card', {'work_order': wo_order.name}, 'name') + + for jc in job_cards: + job_card_doc = frappe.get_doc('Job Card', jc) + job_card_doc.append('time_logs', { + 'from_time': now(), + 'time_in_mins': 60, + 'completed_qty': job_card_doc.for_quantity + }) + + job_card_doc.submit() + + close_work_order(wo_order, "Closed") + self.assertEqual(wo_order.get('status'), "Closed") def update_job_card(job_card): job_card_doc = frappe.get_doc('Job Card', job_card) From ba47bd02b6999411736aa864303a181addc225f3 Mon Sep 17 00:00:00 2001 From: Anupam Date: Wed, 3 Nov 2021 13:41:22 +0530 Subject: [PATCH 11/30] fix: sider isuue --- erpnext/manufacturing/doctype/job_card/job_card.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/job_card/job_card.js b/erpnext/manufacturing/doctype/job_card/job_card.js index df35028ca72..e3eed92d7e1 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.js +++ b/erpnext/manufacturing/doctype/job_card/job_card.js @@ -30,7 +30,7 @@ frappe.ui.form.on('Job Card', { if (frm.doc.__onload.work_order_stopped) { frm.disable_save(); - return + return; } if (!frm.doc.__islocal && has_items && frm.doc.docstatus < 2) { From cc15cf6ae2915ba01188a36c427ab19d7fd89e2b Mon Sep 17 00:00:00 2001 From: Anupam Date: Wed, 3 Nov 2021 13:54:46 +0530 Subject: [PATCH 12/30] fix: linter isuue --- erpnext/manufacturing/doctype/work_order/test_work_order.py | 1 - 1 file changed, 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 3dbbf317576..4f675077553 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -826,7 +826,6 @@ class TestWorkOrder(unittest.TestCase): wo_order = make_wo_order_test_record(item=item, company=company, planned_start_date=now(), qty=20, skip_transfer=1) job_cards = frappe.db.get_value('Job Card', {'work_order': wo_order.name}, 'name') - for jc in job_cards: job_card_doc = frappe.get_doc('Job Card', jc) job_card_doc.append('time_logs', { From 7044ae5e39669a0edf59f3abd19b5b52e1de233b Mon Sep 17 00:00:00 2001 From: Anupam Date: Wed, 3 Nov 2021 17:41:04 +0530 Subject: [PATCH 13/30] fix: testcases: --- erpnext/manufacturing/doctype/work_order/test_work_order.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index 4f675077553..c3f3917b5c8 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -826,6 +826,7 @@ class TestWorkOrder(unittest.TestCase): wo_order = make_wo_order_test_record(item=item, company=company, planned_start_date=now(), qty=20, skip_transfer=1) job_cards = frappe.db.get_value('Job Card', {'work_order': wo_order.name}, 'name') + self.assertEqual(len(job_cards), len(bom.operations)) for jc in job_cards: job_card_doc = frappe.get_doc('Job Card', jc) job_card_doc.append('time_logs', { From b7a44fe0a3e9756eef5ac9000913b0e7d7b86db0 Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Wed, 3 Nov 2021 18:17:31 +0530 Subject: [PATCH 14/30] perf: improve financial statement loading time --- erpnext/accounts/report/financial_statements.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py index 2cb8a6802a7..352b1c8392f 100644 --- a/erpnext/accounts/report/financial_statements.py +++ b/erpnext/accounts/report/financial_statements.py @@ -425,8 +425,7 @@ def set_gl_entries_by_account( {additional_conditions} and posting_date <= %(to_date)s and is_cancelled = 0 - {distributed_cost_center_query} - order by account, posting_date""".format( + {distributed_cost_center_query}""".format( additional_conditions=additional_conditions, distributed_cost_center_query=distributed_cost_center_query), gl_filters, as_dict=True) #nosec From c81d4734c48656b7ca9766a01ce33ed4d2ac00ed Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 8 Nov 2021 17:14:03 +0530 Subject: [PATCH 15/30] fix: KSA VAT setup issues --- erpnext/regional/report/ksa_vat/ksa_vat.js | 1 - erpnext/regional/report/ksa_vat/ksa_vat.py | 4 +- erpnext/regional/saudi_arabia/setup.py | 55 ++++++++++--------- .../wizard/data/ksa_vat_settings.json | 4 +- .../operations/setup_ksa_vat_setting.py | 3 - .../setup_wizard/data/country_wise_tax.json | 4 ++ 6 files changed, 38 insertions(+), 33 deletions(-) diff --git a/erpnext/regional/report/ksa_vat/ksa_vat.js b/erpnext/regional/report/ksa_vat/ksa_vat.js index d46d260ac1e..59e72c3e638 100644 --- a/erpnext/regional/report/ksa_vat/ksa_vat.js +++ b/erpnext/regional/report/ksa_vat/ksa_vat.js @@ -49,7 +49,6 @@ frappe.query_reports["KSA VAT"] = { value = $(`${value}`); var $value = $(value).css("font-weight", "bold"); value = $value.wrap("

").parent().html(); - console.log($value) return value } }else{ diff --git a/erpnext/regional/report/ksa_vat/ksa_vat.py b/erpnext/regional/report/ksa_vat/ksa_vat.py index 198b0b2b1b1..b41b2b0428f 100644 --- a/erpnext/regional/report/ksa_vat/ksa_vat.py +++ b/erpnext/regional/report/ksa_vat/ksa_vat.py @@ -118,14 +118,14 @@ def get_tax_data_for_each_vat_setting(vat_setting, filters, doctype): total_taxable_adjustment_amount = 0 total_tax = 0 # Fetch All Invoices - invoices = frappe.get_list(doctype, + invoices = frappe.get_all(doctype, filters ={ 'docstatus': 1, 'posting_date': ['between', [from_date, to_date]] }, fields =['name', 'is_return']) for invoice in invoices: - invoice_items = frappe.get_list(f'{doctype} Item', + invoice_items = frappe.get_all(f'{doctype} Item', filters ={ 'docstatus': 1, 'parent': invoice.name, diff --git a/erpnext/regional/saudi_arabia/setup.py b/erpnext/regional/saudi_arabia/setup.py index 0c52ee178ba..38a089c6326 100644 --- a/erpnext/regional/saudi_arabia/setup.py +++ b/erpnext/regional/saudi_arabia/setup.py @@ -5,13 +5,12 @@ import frappe from frappe.permissions import add_permission, update_permission_property from erpnext.regional.united_arab_emirates.setup import make_custom_fields as uae_custom_fields, add_print_formats from erpnext.regional.saudi_arabia.wizard.operations.setup_ksa_vat_setting import create_ksa_vat_setting -from frappe.custom.doctype.custom_field.custom_field import create_custom_field +from frappe.custom.doctype.custom_field.custom_field import create_custom_fields def setup(company=None, patch=True): uae_custom_fields() add_print_formats() add_permissions() - create_ksa_vat_setting(company) make_custom_fields() def add_permissions(): @@ -31,28 +30,34 @@ def make_custom_fields(): - Company Name in Arabic - Address in Arabic """ - qr_code = dict( - fieldname='qr_code', - label='QR Code', - fieldtype='Attach Image', - read_only=1, no_copy=1, hidden=1) + custom_fields = { + 'Sales Invoice': [ + dict( + fieldname='qr_code', + label='QR Code', + fieldtype='Attach Image', + read_only=1, no_copy=1, hidden=1 + ) + ], + 'Address': [ + dict( + fieldname='address_in_arabic', + label='Address in Arabic', + fieldtype='Data', + insert_after='address_line2' + ) + ], + 'Company': [ + dict( + fieldname='company_name_in_arabic', + label='Company Name In Arabic', + fieldtype='Data', + insert_after='company_name' + ) + ] + } - create_custom_field('Sales Invoice', qr_code) + create_custom_fields(custom_fields, update=True) - company_name_in_arabic = dict( - fieldname='company_name_in_arabic', - label='Company Name In Arabic', - fieldtype='Data', - insert_after='company_name' - ) - - create_custom_field('Company', company_name_in_arabic) - - address_in_arabic = dict( - fieldname='address_in_arabic', - label='Address in Arabic', - fieldtype='Data', - insert_after='address_line2' - ) - - create_custom_field('Address', address_in_arabic) +def update_regional_tax_settings(country, company): + create_ksa_vat_setting(company) diff --git a/erpnext/regional/saudi_arabia/wizard/data/ksa_vat_settings.json b/erpnext/regional/saudi_arabia/wizard/data/ksa_vat_settings.json index 709d65be041..60951a9ceca 100644 --- a/erpnext/regional/saudi_arabia/wizard/data/ksa_vat_settings.json +++ b/erpnext/regional/saudi_arabia/wizard/data/ksa_vat_settings.json @@ -15,7 +15,7 @@ { "title": "Exempted sales", "item_tax_template": "KSA VAT Exempted", - "account": "VAT Zero" + "account": "VAT Exempted" } ] }, @@ -40,7 +40,7 @@ { "title": "Exempted purchases", "item_tax_template": "KSA VAT Exempted", - "account": "VAT Zero" + "account": "VAT Exempted" } ] } diff --git a/erpnext/regional/saudi_arabia/wizard/operations/setup_ksa_vat_setting.py b/erpnext/regional/saudi_arabia/wizard/operations/setup_ksa_vat_setting.py index 3c89edd37ed..97300dc3782 100644 --- a/erpnext/regional/saudi_arabia/wizard/operations/setup_ksa_vat_setting.py +++ b/erpnext/regional/saudi_arabia/wizard/operations/setup_ksa_vat_setting.py @@ -3,14 +3,11 @@ import os import frappe -from erpnext.setup.setup_wizard.operations.taxes_setup import setup_taxes_and_charges - def create_ksa_vat_setting(company): """On creation of first company. Creates KSA VAT Setting""" company = frappe.get_doc('Company', company) - setup_taxes_and_charges(company.name, company.country) file_path = os.path.join(os.path.dirname(__file__), '..', 'data', 'ksa_vat_settings.json') with open(file_path, 'r') as json_file: diff --git a/erpnext/setup/setup_wizard/data/country_wise_tax.json b/erpnext/setup/setup_wizard/data/country_wise_tax.json index 8a1338583ba..14b79510c12 100644 --- a/erpnext/setup/setup_wizard/data/country_wise_tax.json +++ b/erpnext/setup/setup_wizard/data/country_wise_tax.json @@ -2120,6 +2120,10 @@ "account_name": "VAT 15%", "tax_rate": 15.00 }, + "KSA VAT 5%": { + "account_name": "VAT 5%", + "tax_rate": 5.00 + }, "KSA VAT Zero": { "account_name": "VAT Zero", "tax_rate": 0.00 From 508832e90a3863e0a2030b999a6772d291afd84b Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 8 Nov 2021 17:46:24 +0530 Subject: [PATCH 16/30] fix: Add patch to make custom fields --- erpnext/patches.txt | 1 + .../patches/v13_0/create_ksa_vat_custom_fields.py | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 erpnext/patches/v13_0/create_ksa_vat_custom_fields.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 2c21ab6c3ae..a60b851c5a2 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -309,3 +309,4 @@ erpnext.patches.v14_0.delete_healthcare_doctypes erpnext.patches.v13_0.update_category_in_ltds_certificate erpnext.patches.v13_0.create_pan_field_for_india #2 erpnext.patches.v14_0.delete_hub_doctypes +erpnext.patches.v13_0.create_ksa_vat_custom_fields diff --git a/erpnext/patches/v13_0/create_ksa_vat_custom_fields.py b/erpnext/patches/v13_0/create_ksa_vat_custom_fields.py new file mode 100644 index 00000000000..f33b4b3ea0d --- /dev/null +++ b/erpnext/patches/v13_0/create_ksa_vat_custom_fields.py @@ -0,0 +1,12 @@ +import frappe + +from erpnext.regional.saudi_arabia.setup import make_custom_fields + + +def execute(): + company = frappe.get_all('Company', filters = {'country': 'Saudi Arabia'}) + if not company: + return + + make_custom_fields() + From 75e9100a5389eacca8f51c4a7ebe268f641cf2b8 Mon Sep 17 00:00:00 2001 From: Subin Tom Date: Mon, 8 Nov 2021 09:49:11 +0530 Subject: [PATCH 17/30] fix: Fixed customer address variable, sales invoice item field currency issue (cherry picked from commit 904010ab645fdb16f09072c062269945f7747712) --- .../doctype/taxjar_settings/taxjar_settings.py | 4 ++-- erpnext/erpnext_integrations/taxjar_integration.py | 2 +- erpnext/patches/v13_0/custom_fields_for_taxjar_integration.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.py b/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.py index bfc5e6f98df..b9f24b65b38 100644 --- a/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.py +++ b/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.py @@ -80,9 +80,9 @@ def make_custom_fields(update=True): dict(fieldname='product_tax_category', fieldtype='Link', insert_after='description', options='Product Tax Category', label='Product Tax Category', fetch_from='item_code.product_tax_category'), dict(fieldname='tax_collectable', fieldtype='Currency', insert_after='net_amount', - label='Tax Collectable', read_only=1), + label='Tax Collectable', read_only=1, options='currency'), dict(fieldname='taxable_amount', fieldtype='Currency', insert_after='tax_collectable', - label='Taxable Amount', read_only=1) + label='Taxable Amount', read_only=1, options='currency') ], 'Item': [ dict(fieldname='product_tax_category', fieldtype='Link', insert_after='item_group', options='Product Tax Category', diff --git a/erpnext/erpnext_integrations/taxjar_integration.py b/erpnext/erpnext_integrations/taxjar_integration.py index 2a7243c2430..39aac0c4073 100644 --- a/erpnext/erpnext_integrations/taxjar_integration.py +++ b/erpnext/erpnext_integrations/taxjar_integration.py @@ -262,7 +262,7 @@ def get_shipping_address_details(doc): if doc.shipping_address_name: shipping_address = frappe.get_doc("Address", doc.shipping_address_name) elif doc.customer_address: - shipping_address = frappe.get_doc("Address", doc.customer_address_name) + shipping_address = frappe.get_doc("Address", doc.customer_address) else: shipping_address = get_company_address_details(doc) diff --git a/erpnext/patches/v13_0/custom_fields_for_taxjar_integration.py b/erpnext/patches/v13_0/custom_fields_for_taxjar_integration.py index fba9e2c4430..1625e4f17e7 100644 --- a/erpnext/patches/v13_0/custom_fields_for_taxjar_integration.py +++ b/erpnext/patches/v13_0/custom_fields_for_taxjar_integration.py @@ -21,9 +21,9 @@ def execute(): dict(fieldname='product_tax_category', fieldtype='Link', insert_after='description', options='Product Tax Category', label='Product Tax Category', fetch_from='item_code.product_tax_category'), dict(fieldname='tax_collectable', fieldtype='Currency', insert_after='net_amount', - label='Tax Collectable', read_only=1), + label='Tax Collectable', read_only=1, options='currency'), dict(fieldname='taxable_amount', fieldtype='Currency', insert_after='tax_collectable', - label='Taxable Amount', read_only=1) + label='Taxable Amount', read_only=1, options='currency') ], 'Item': [ dict(fieldname='product_tax_category', fieldtype='Link', insert_after='item_group', options='Product Tax Category', From e51c4ba8a9c96dd28580a8a6e3fcffdb45c7bdb4 Mon Sep 17 00:00:00 2001 From: Subin Tom Date: Mon, 8 Nov 2021 15:16:20 +0530 Subject: [PATCH 18/30] fix: Added company field, filtered account heads (cherry picked from commit 902c03cd375c7b1b2f35cff4dfbc5f1ff3e4cd56) --- .../taxjar_settings/taxjar_settings.js | 17 ++++++++++++++ .../taxjar_settings/taxjar_settings.json | 22 ++++++++++++++----- .../taxjar_integration.py | 6 +++++ .../custom_fields_for_taxjar_integration.py | 4 ++++ 4 files changed, 44 insertions(+), 5 deletions(-) diff --git a/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.js b/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.js index d49598932fe..a362ba1f0b4 100644 --- a/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.js +++ b/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.js @@ -7,6 +7,23 @@ frappe.ui.form.on('TaxJar Settings', { frm.toggle_reqd("sandbox_api_key", frm.doc.is_sandbox); }, + on_load: (frm) => { + frm.set_query('shipping_account_head', function() { + return { + filters: { + 'company': frm.doc.current_company + } + }; + }); + frm.set_query('tax_account_head', function() { + return { + filters: { + 'company': frm.doc.current_company + } + }; + }); + }, + refresh: (frm) => { frm.add_custom_button(__('Update Nexus List'), function() { frm.call({ diff --git a/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.json b/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.json index 2d17f2ed832..1fda8929e90 100644 --- a/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.json +++ b/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.json @@ -14,6 +14,8 @@ "cb_keys", "sandbox_api_key", "configuration", + "current_company", + "column_break_10", "tax_account_head", "configuration_cb", "shipping_account_head", @@ -67,10 +69,6 @@ "fieldtype": "Password", "label": "Sandbox API Key" }, - { - "fieldname": "configuration_cb", - "fieldtype": "Column Break" - }, { "default": "0", "depends_on": "taxjar_calculate_tax", @@ -104,11 +102,25 @@ "label": "Nexus", "options": "TaxJar Nexus", "read_only": 1 + }, + { + "fieldname": "current_company", + "fieldtype": "Link", + "label": "Company", + "options": "Company" + }, + { + "fieldname": "configuration_cb", + "fieldtype": "Column Break" + }, + { + "fieldname": "column_break_10", + "fieldtype": "Column Break" } ], "issingle": 1, "links": [], - "modified": "2021-10-06 10:59:13.475442", + "modified": "2021-11-08 14:40:15.684224", "modified_by": "Administrator", "module": "ERPNext Integrations", "name": "TaxJar Settings", diff --git a/erpnext/erpnext_integrations/taxjar_integration.py b/erpnext/erpnext_integrations/taxjar_integration.py index 39aac0c4073..794b281c55a 100644 --- a/erpnext/erpnext_integrations/taxjar_integration.py +++ b/erpnext/erpnext_integrations/taxjar_integration.py @@ -19,6 +19,8 @@ SUPPORTED_STATE_CODES = ['AL', 'AK', 'AZ', 'AR', 'CA', 'CO', 'CT', 'DE', 'DC', ' 'IN', 'IA', 'KS', 'KY', 'LA', 'ME', 'MD', 'MA', 'MI', 'MN', 'MS', 'MO', 'MT', 'NE', 'NV', 'NH', 'NJ', 'NM', 'NY', 'NC', 'ND', 'OH', 'OK', 'OR', 'PA', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VT', 'VA', 'WA', 'WV', 'WI', 'WY'] +USA_COMPANIES = frappe.get_all('Company', filters = {'country': 'United States'}, fields=['name'], pluck='name') + def get_client(): @@ -158,6 +160,10 @@ def set_sales_tax(doc, method): if not TAXJAR_CALCULATE_TAX: return + taxjar_settings_company = frappe.db.get_single_value('TaxJar Settings','current_company') + if taxjar_settings_company not in USA_COMPANIES: + return + if not doc.items: return diff --git a/erpnext/patches/v13_0/custom_fields_for_taxjar_integration.py b/erpnext/patches/v13_0/custom_fields_for_taxjar_integration.py index 1625e4f17e7..775e4d8cd56 100644 --- a/erpnext/patches/v13_0/custom_fields_for_taxjar_integration.py +++ b/erpnext/patches/v13_0/custom_fields_for_taxjar_integration.py @@ -28,6 +28,10 @@ def execute(): 'Item': [ dict(fieldname='product_tax_category', fieldtype='Link', insert_after='item_group', options='Product Tax Category', label='Product Tax Category') + ], + 'TaxJar Settings': [ + dict(fieldname='current_company', fieldtype='Link', insert_after='configuration', options='Company', + label='Company') ] } create_custom_fields(custom_fields, update=True) From d2915c6bc7330eb245d398dc61bd1d63d13a3b48 Mon Sep 17 00:00:00 2001 From: Subin Tom Date: Mon, 8 Nov 2021 17:59:03 +0530 Subject: [PATCH 19/30] fix: fixed company field, updated patch (cherry picked from commit 7f2d304f32fdf580a354c1dbba58189cdd4f35f2) # Conflicts: # erpnext/patches.txt --- .../doctype/taxjar_settings/taxjar_settings.js | 4 ++-- .../doctype/taxjar_settings/taxjar_settings.json | 9 +-------- erpnext/erpnext_integrations/taxjar_integration.py | 6 ++---- erpnext/patches.txt | 4 ++++ .../v13_0/custom_fields_for_taxjar_integration.py | 2 +- 5 files changed, 10 insertions(+), 15 deletions(-) diff --git a/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.js b/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.js index a362ba1f0b4..2925db82e33 100644 --- a/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.js +++ b/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.js @@ -11,14 +11,14 @@ frappe.ui.form.on('TaxJar Settings', { frm.set_query('shipping_account_head', function() { return { filters: { - 'company': frm.doc.current_company + 'company': frm.doc.company } }; }); frm.set_query('tax_account_head', function() { return { filters: { - 'company': frm.doc.current_company + 'company': frm.doc.company } }; }); diff --git a/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.json b/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.json index 1fda8929e90..d9ae5b601cc 100644 --- a/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.json +++ b/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.json @@ -14,7 +14,6 @@ "cb_keys", "sandbox_api_key", "configuration", - "current_company", "column_break_10", "tax_account_head", "configuration_cb", @@ -103,12 +102,6 @@ "options": "TaxJar Nexus", "read_only": 1 }, - { - "fieldname": "current_company", - "fieldtype": "Link", - "label": "Company", - "options": "Company" - }, { "fieldname": "configuration_cb", "fieldtype": "Column Break" @@ -120,7 +113,7 @@ ], "issingle": 1, "links": [], - "modified": "2021-11-08 14:40:15.684224", + "modified": "2021-11-08 17:57:17.323275", "modified_by": "Administrator", "module": "ERPNext Integrations", "name": "TaxJar Settings", diff --git a/erpnext/erpnext_integrations/taxjar_integration.py b/erpnext/erpnext_integrations/taxjar_integration.py index 794b281c55a..1adc1ddb140 100644 --- a/erpnext/erpnext_integrations/taxjar_integration.py +++ b/erpnext/erpnext_integrations/taxjar_integration.py @@ -6,7 +6,7 @@ from frappe import _ from frappe.contacts.doctype.address.address import get_company_address from frappe.utils import cint, flt -from erpnext import get_default_company +from erpnext import get_default_company, get_region TAX_ACCOUNT_HEAD = frappe.db.get_single_value("TaxJar Settings", "tax_account_head") SHIP_ACCOUNT_HEAD = frappe.db.get_single_value("TaxJar Settings", "shipping_account_head") @@ -19,7 +19,6 @@ SUPPORTED_STATE_CODES = ['AL', 'AK', 'AZ', 'AR', 'CA', 'CO', 'CT', 'DE', 'DC', ' 'IN', 'IA', 'KS', 'KY', 'LA', 'ME', 'MD', 'MA', 'MI', 'MN', 'MS', 'MO', 'MT', 'NE', 'NV', 'NH', 'NJ', 'NM', 'NY', 'NC', 'ND', 'OH', 'OK', 'OR', 'PA', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VT', 'VA', 'WA', 'WV', 'WI', 'WY'] -USA_COMPANIES = frappe.get_all('Company', filters = {'country': 'United States'}, fields=['name'], pluck='name') @@ -160,8 +159,7 @@ def set_sales_tax(doc, method): if not TAXJAR_CALCULATE_TAX: return - taxjar_settings_company = frappe.db.get_single_value('TaxJar Settings','current_company') - if taxjar_settings_company not in USA_COMPANIES: + if get_region(doc.company): return if not doc.items: diff --git a/erpnext/patches.txt b/erpnext/patches.txt index a60b851c5a2..0dcd3b73a30 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -283,8 +283,12 @@ erpnext.patches.v13_0.reset_clearance_date_for_intracompany_payment_entries erpnext.patches.v13_0.einvoicing_deprecation_warning execute:frappe.reload_doc("erpnext_integrations", "doctype", "TaxJar Settings") execute:frappe.reload_doc("erpnext_integrations", "doctype", "Product Tax Category") +<<<<<<< HEAD erpnext.patches.v13_0.custom_fields_for_taxjar_integration erpnext.patches.v14_0.delete_einvoicing_doctypes +======= +erpnext.patches.v13_0.custom_fields_for_taxjar_integration #08-11-2021 +>>>>>>> 7f2d304f32 (fix: fixed company field, updated patch) erpnext.patches.v13_0.set_operation_time_based_on_operating_cost erpnext.patches.v13_0.validate_options_for_data_field erpnext.patches.v13_0.create_gst_payment_entry_fields diff --git a/erpnext/patches/v13_0/custom_fields_for_taxjar_integration.py b/erpnext/patches/v13_0/custom_fields_for_taxjar_integration.py index 775e4d8cd56..078c558d885 100644 --- a/erpnext/patches/v13_0/custom_fields_for_taxjar_integration.py +++ b/erpnext/patches/v13_0/custom_fields_for_taxjar_integration.py @@ -30,7 +30,7 @@ def execute(): label='Product Tax Category') ], 'TaxJar Settings': [ - dict(fieldname='current_company', fieldtype='Link', insert_after='configuration', options='Company', + dict(fieldname='company', fieldtype='Link', insert_after='configuration', options='Company', label='Company') ] } From 45fd819729a73be9e334194e64ad00e81b36dabc Mon Sep 17 00:00:00 2001 From: Subin Tom Date: Mon, 8 Nov 2021 18:03:44 +0530 Subject: [PATCH 20/30] fix: company condition fix, added company field (cherry picked from commit 7ad2717accea61883f98d418b4abed47ca3937a8) --- .../doctype/taxjar_settings/taxjar_settings.json | 9 ++++++++- erpnext/erpnext_integrations/taxjar_integration.py | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.json b/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.json index d9ae5b601cc..23ccb7e4dac 100644 --- a/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.json +++ b/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.json @@ -14,6 +14,7 @@ "cb_keys", "sandbox_api_key", "configuration", + "company", "column_break_10", "tax_account_head", "configuration_cb", @@ -109,11 +110,17 @@ { "fieldname": "column_break_10", "fieldtype": "Column Break" + }, + { + "fieldname": "company", + "fieldtype": "Link", + "label": "Company", + "options": "Company" } ], "issingle": 1, "links": [], - "modified": "2021-11-08 17:57:17.323275", + "modified": "2021-11-08 18:02:29.232090", "modified_by": "Administrator", "module": "ERPNext Integrations", "name": "TaxJar Settings", diff --git a/erpnext/erpnext_integrations/taxjar_integration.py b/erpnext/erpnext_integrations/taxjar_integration.py index 1adc1ddb140..a4e21579e32 100644 --- a/erpnext/erpnext_integrations/taxjar_integration.py +++ b/erpnext/erpnext_integrations/taxjar_integration.py @@ -159,7 +159,7 @@ def set_sales_tax(doc, method): if not TAXJAR_CALCULATE_TAX: return - if get_region(doc.company): + if get_region(doc.company) != 'United States': return if not doc.items: From 94d70bca9ed8bfbaf28d70569970bd19cf4e23fe Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Mon, 8 Nov 2021 18:48:46 +0530 Subject: [PATCH 21/30] fix: Resolve conflicts --- erpnext/patches.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 0dcd3b73a30..1006e2180ff 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -283,12 +283,8 @@ erpnext.patches.v13_0.reset_clearance_date_for_intracompany_payment_entries erpnext.patches.v13_0.einvoicing_deprecation_warning execute:frappe.reload_doc("erpnext_integrations", "doctype", "TaxJar Settings") execute:frappe.reload_doc("erpnext_integrations", "doctype", "Product Tax Category") -<<<<<<< HEAD -erpnext.patches.v13_0.custom_fields_for_taxjar_integration erpnext.patches.v14_0.delete_einvoicing_doctypes -======= erpnext.patches.v13_0.custom_fields_for_taxjar_integration #08-11-2021 ->>>>>>> 7f2d304f32 (fix: fixed company field, updated patch) erpnext.patches.v13_0.set_operation_time_based_on_operating_cost erpnext.patches.v13_0.validate_options_for_data_field erpnext.patches.v13_0.create_gst_payment_entry_fields From 27709a1c71a9943cb95deb8ef1b563c465489dcb Mon Sep 17 00:00:00 2001 From: Anupam Date: Tue, 9 Nov 2021 09:56:58 +0530 Subject: [PATCH 22/30] fix: test cases --- .../doctype/work_order/test_work_order.py | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index c3f3917b5c8..f4a88dc4598 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -826,19 +826,20 @@ class TestWorkOrder(unittest.TestCase): wo_order = make_wo_order_test_record(item=item, company=company, planned_start_date=now(), qty=20, skip_transfer=1) job_cards = frappe.db.get_value('Job Card', {'work_order': wo_order.name}, 'name') - self.assertEqual(len(job_cards), len(bom.operations)) - for jc in job_cards: - job_card_doc = frappe.get_doc('Job Card', jc) - job_card_doc.append('time_logs', { - 'from_time': now(), - 'time_in_mins': 60, - 'completed_qty': job_card_doc.for_quantity - }) - job_card_doc.submit() + if len(job_cards) == len(bom.operations): + for jc in job_cards: + job_card_doc = frappe.get_doc('Job Card', jc) + job_card_doc.append('time_logs', { + 'from_time': now(), + 'time_in_mins': 60, + 'completed_qty': job_card_doc.for_quantity + }) - close_work_order(wo_order, "Closed") - self.assertEqual(wo_order.get('status'), "Closed") + job_card_doc.submit() + + close_work_order(wo_order, "Closed") + self.assertEqual(wo_order.get('status'), "Closed") def update_job_card(job_card): job_card_doc = frappe.get_doc('Job Card', job_card) From 0e8e7e21c3bf020497be7c599d43650ff5ff0b91 Mon Sep 17 00:00:00 2001 From: Bibin <17405044+bibinqcs@users.noreply.github.com> Date: Tue, 9 Nov 2021 08:32:05 +0400 Subject: [PATCH 23/30] fix: filter only submitted fees in student fee collection report (#28280) * Update student_fee_collection.json Fix: filter and show only submitted fees documents * fix: add total row for the student fee collection --- .../student_fee_collection/student_fee_collection.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/education/report/student_fee_collection/student_fee_collection.json b/erpnext/education/report/student_fee_collection/student_fee_collection.json index 8deb865ebcd..c0229a2ee26 100644 --- a/erpnext/education/report/student_fee_collection/student_fee_collection.json +++ b/erpnext/education/report/student_fee_collection/student_fee_collection.json @@ -1,5 +1,5 @@ { - "add_total_row": 0, + "add_total_row": 1, "creation": "2016-06-22 02:58:41.024538", "disable_prepared_report": 0, "disabled": 0, @@ -13,7 +13,7 @@ "name": "Student Fee Collection", "owner": "Administrator", "prepared_report": 0, - "query": "SELECT\n student as \"Student:Link/Student:200\",\n student_name as \"Student Name::200\",\n sum(grand_total) - sum(outstanding_amount) as \"Paid Amount:Currency:150\",\n sum(outstanding_amount) as \"Outstanding Amount:Currency:150\",\n sum(grand_total) as \"Grand Total:Currency:150\"\nFROM\n `tabFees` \nGROUP BY\n student", + "query": "SELECT\n student as \"Student:Link/Student:200\",\n student_name as \"Student Name::200\",\n sum(grand_total) - sum(outstanding_amount) as \"Paid Amount:Currency:150\",\n sum(outstanding_amount) as \"Outstanding Amount:Currency:150\",\n sum(grand_total) as \"Grand Total:Currency:150\"\nFROM\n `tabFees` \nWHERE\n docstatus=1 \nGROUP BY\n student", "ref_doctype": "Fees", "report_name": "Student Fee Collection", "report_type": "Query Report", @@ -22,4 +22,4 @@ "role": "Academics User" } ] -} \ No newline at end of file +} From 663a7afe4df81fe3956af4eb18ca1eaa0614b626 Mon Sep 17 00:00:00 2001 From: Anupam Date: Tue, 9 Nov 2021 10:50:38 +0530 Subject: [PATCH 24/30] fix: get_planned_qty chnages --- erpnext/stock/stock_balance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/stock_balance.py b/erpnext/stock/stock_balance.py index 1cb0f0d0a49..51c20b02506 100644 --- a/erpnext/stock/stock_balance.py +++ b/erpnext/stock/stock_balance.py @@ -161,7 +161,7 @@ def get_ordered_qty(item_code, warehouse): def get_planned_qty(item_code, warehouse): planned_qty = frappe.db.sql(""" select sum(qty - produced_qty) from `tabWork Order` - where production_item = %s and fg_warehouse = %s and status not in ("Stopped", "Completed") + where production_item = %s and fg_warehouse = %s and status not in ("Stopped", "Completed", "Closed") and docstatus=1 and qty > produced_qty""", (item_code, warehouse)) return flt(planned_qty[0][0]) if planned_qty else 0 From 34f5283c1773b79463fcf77a037c6ae258e329dc Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 9 Nov 2021 11:55:33 +0530 Subject: [PATCH 25/30] fix: show full item name in search widget (#28283) --- erpnext/controllers/queries.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index 22e02b4a745..76a7d1a95ff 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -210,12 +210,15 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals meta = frappe.get_meta("Item", cached=True) searchfields = meta.get_search_fields() - if "description" in searchfields: - searchfields.remove("description") + # these are handled separately + ignored_search_fields = ("item_name", "description") + for ignored_field in ignored_search_fields: + if ignored_field in searchfields: + searchfields.remove(ignored_field) columns = '' extra_searchfields = [field for field in searchfields - if not field in ["name", "item_group", "description"]] + if not field in ["name", "item_group", "description", "item_name"]] if extra_searchfields: columns = ", " + ", ".join(extra_searchfields) @@ -252,10 +255,8 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals if frappe.db.count('Item', cache=True) < 50000: # scan description only if items are less than 50000 description_cond = 'or tabItem.description LIKE %(txt)s' - return frappe.db.sql("""select tabItem.name, - if(length(tabItem.item_name) > 40, - concat(substr(tabItem.item_name, 1, 40), "..."), item_name) as item_name, - tabItem.item_group, + return frappe.db.sql("""select + tabItem.name, tabItem.item_name, tabItem.item_group, if(length(tabItem.description) > 40, \ concat(substr(tabItem.description, 1, 40), "..."), description) as description {columns} From 4a3cef6436287b7d0be69b5e0965c4f989957931 Mon Sep 17 00:00:00 2001 From: Saqib Date: Tue, 9 Nov 2021 14:16:38 +0530 Subject: [PATCH 26/30] fix: update 'current_invoice_end' after processing invoice (#28278) --- erpnext/accounts/doctype/subscription/subscription.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py index 63b714e68c6..1dae87f2a44 100644 --- a/erpnext/accounts/doctype/subscription/subscription.py +++ b/erpnext/accounts/doctype/subscription/subscription.py @@ -519,8 +519,6 @@ class Subscription(Document): 2. Change the `Subscription` status to 'Past Due Date' 3. Change the `Subscription` status to 'Cancelled' """ - if getdate() > getdate(self.current_invoice_end) and self.is_prepaid_to_invoice(): - self.update_subscription_period(add_days(self.current_invoice_end, 1)) if not self.is_current_invoice_generated(self.current_invoice_start, self.current_invoice_end) \ and (self.is_postpaid_to_invoice() or self.is_prepaid_to_invoice()): @@ -528,6 +526,9 @@ class Subscription(Document): prorate = frappe.db.get_single_value('Subscription Settings', 'prorate') self.generate_invoice(prorate) + if getdate() > getdate(self.current_invoice_end) and self.is_prepaid_to_invoice(): + self.update_subscription_period(add_days(self.current_invoice_end, 1)) + if self.cancel_at_period_end and getdate() > getdate(self.current_invoice_end): self.cancel_subscription_at_period_end() From 17acb08545a5bab991a5eb2f0f3e720886006bc4 Mon Sep 17 00:00:00 2001 From: Jannat Patel <31363128+pateljannat@users.noreply.github.com> Date: Tue, 9 Nov 2021 15:21:51 +0530 Subject: [PATCH 27/30] fix: sum of components in salary register (#28237) * fix: sum of components in salary register * fix: sum of deduction components Co-authored-by: Rucha Mahabal --- .../report/salary_register/salary_register.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/erpnext/payroll/report/salary_register/salary_register.py b/erpnext/payroll/report/salary_register/salary_register.py index 13ee691d876..78deb227783 100644 --- a/erpnext/payroll/report/salary_register/salary_register.py +++ b/erpnext/payroll/report/salary_register/salary_register.py @@ -134,11 +134,11 @@ def get_ss_earning_map(salary_slips, currency, company_currency): ss_earning_map = {} for d in ss_earnings: - ss_earning_map.setdefault(d.parent, frappe._dict()).setdefault(d.salary_component, []) + ss_earning_map.setdefault(d.parent, frappe._dict()).setdefault(d.salary_component, 0.0) if currency == company_currency: - ss_earning_map[d.parent][d.salary_component] = flt(d.amount) * flt(d.exchange_rate if d.exchange_rate else 1) + ss_earning_map[d.parent][d.salary_component] += flt(d.amount) * flt(d.exchange_rate if d.exchange_rate else 1) else: - ss_earning_map[d.parent][d.salary_component] = flt(d.amount) + ss_earning_map[d.parent][d.salary_component] += flt(d.amount) return ss_earning_map @@ -149,10 +149,10 @@ def get_ss_ded_map(salary_slips, currency, company_currency): ss_ded_map = {} for d in ss_deductions: - ss_ded_map.setdefault(d.parent, frappe._dict()).setdefault(d.salary_component, []) + ss_ded_map.setdefault(d.parent, frappe._dict()).setdefault(d.salary_component, 0.0) if currency == company_currency: - ss_ded_map[d.parent][d.salary_component] = flt(d.amount) * flt(d.exchange_rate if d.exchange_rate else 1) + ss_ded_map[d.parent][d.salary_component] += flt(d.amount) * flt(d.exchange_rate if d.exchange_rate else 1) else: - ss_ded_map[d.parent][d.salary_component] = flt(d.amount) + ss_ded_map[d.parent][d.salary_component] += flt(d.amount) return ss_ded_map From da22744e0fd7e19a6536aa653ebd78a83fafbac1 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Tue, 9 Nov 2021 15:49:32 +0530 Subject: [PATCH 28/30] fix: specify fields to be set in Lead (#28288) --- erpnext/shopping_cart/cart.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/shopping_cart/cart.py b/erpnext/shopping_cart/cart.py index a7d90ea201a..ebbe233ca3a 100644 --- a/erpnext/shopping_cart/cart.py +++ b/erpnext/shopping_cart/cart.py @@ -194,7 +194,9 @@ def add_new_address(doc): def create_lead_for_item_inquiry(lead, subject, message): lead = frappe.parse_json(lead) lead_doc = frappe.new_doc('Lead') - lead_doc.update(lead) + for fieldname in ("lead_name", "company_name", "email_id", "phone"): + lead_doc.set(fieldname, lead.get(fieldname)) + lead_doc.set('lead_owner', '') if not frappe.db.exists('Lead Source', 'Product Inquiry'): @@ -202,6 +204,7 @@ def create_lead_for_item_inquiry(lead, subject, message): 'doctype': 'Lead Source', 'source_name' : 'Product Inquiry' }).insert(ignore_permissions=True) + lead_doc.set('source', 'Product Inquiry') try: From 88b5bda34b80fb83e71f94a984184304e5b4c853 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Tue, 9 Nov 2021 16:04:52 +0530 Subject: [PATCH 29/30] fix(India setup): setup company independent fixtures for patch --- erpnext/regional/india/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py index 42ee27171fb..316bb6b1977 100644 --- a/erpnext/regional/india/setup.py +++ b/erpnext/regional/india/setup.py @@ -12,7 +12,7 @@ from frappe.utils import today def setup(company=None, patch=True): # Company independent fixtures should be called only once at the first company setup - if frappe.db.count('Company', {'country': 'India'}) <=1: + if patch or frappe.db.count('Company', {'country': 'India'}) <=1: setup_company_independent_fixtures(patch=patch) if not patch: From 6907ad8adb2e15239598df8908eec16b56e106f1 Mon Sep 17 00:00:00 2001 From: Wolfram Schmidt Date: Tue, 9 Nov 2021 13:02:57 +0100 Subject: [PATCH 30/30] fix: add Email option to contact email field (#28296) * Update warranty_claim.json Added the Email in option field of Contact Email so you are able to create a notification mapping to this field as reciever. * Update warranty_claim.json --- erpnext/support/doctype/warranty_claim/warranty_claim.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/support/doctype/warranty_claim/warranty_claim.json b/erpnext/support/doctype/warranty_claim/warranty_claim.json index 88ee4a3bebd..45485ca2c2f 100644 --- a/erpnext/support/doctype/warranty_claim/warranty_claim.json +++ b/erpnext/support/doctype/warranty_claim/warranty_claim.json @@ -256,6 +256,7 @@ "fieldname": "contact_email", "fieldtype": "Data", "label": "Contact Email", + "options": "Email", "read_only": 1 }, { @@ -361,7 +362,7 @@ ], "icon": "fa fa-bug", "idx": 1, - "modified": "2020-09-18 17:26:09.703215", + "modified": "2021-11-09 17:26:09.703215", "modified_by": "Administrator", "module": "Support", "name": "Warranty Claim", @@ -385,4 +386,4 @@ "sort_order": "DESC", "timeline_field": "customer", "title_field": "customer_name" -} \ No newline at end of file +}