From 14f46a3e2676a6b92abc74383c6c7afab4f21400 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 6 Apr 2022 15:14:37 +0530 Subject: [PATCH 01/41] fix: check null values in is_cancelled patch (#30594) (#30595) (cherry picked from commit bb875fe217d5d5ac61a01e564fb115c2f1989788) Co-authored-by: Ankush Menat --- erpnext/patches/v12_0/update_is_cancelled_field.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/patches/v12_0/update_is_cancelled_field.py b/erpnext/patches/v12_0/update_is_cancelled_field.py index b567823b062e..398dd700eda5 100644 --- a/erpnext/patches/v12_0/update_is_cancelled_field.py +++ b/erpnext/patches/v12_0/update_is_cancelled_field.py @@ -20,7 +20,7 @@ def execute(): """ UPDATE `tab{doctype}` SET is_cancelled = 0 - where is_cancelled in ('', NULL, 'No')""".format( + where is_cancelled in ('', 'No') or is_cancelled is NULL""".format( doctype=doctype ) ) From 52aa3561e32cab9b645dd6287f55bfd4623c6db4 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 6 Apr 2022 16:38:25 +0530 Subject: [PATCH 02/41] fix: hide pending qty only if original item is assigned (#30599) (#30600) (cherry picked from commit 8b090a9f7d18aa25ae0568c2e52395812eb32462) Co-authored-by: Ankush Menat --- erpnext/public/js/utils/serial_no_batch_selector.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js index cbecb11949b1..ecfc37ee5563 100644 --- a/erpnext/public/js/utils/serial_no_batch_selector.js +++ b/erpnext/public/js/utils/serial_no_batch_selector.js @@ -607,8 +607,8 @@ function check_can_calculate_pending_qty(me) { && erpnext.stock.bom && erpnext.stock.bom.name === doc.bom_no; const itemChecks = !!item - && !item.allow_alternative_item - && erpnext.stock.bom && erpnext.stock.items + && !item.original_item + && erpnext.stock.bom && erpnext.stock.bom.items && (item.item_code in erpnext.stock.bom.items); return docChecks && itemChecks; } From f89c1b2c0ce5365861b2f67f085e77401a477555 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 6 Apr 2022 18:28:54 +0530 Subject: [PATCH 03/41] fix: dont trigger closed WO check on new Job card --- erpnext/manufacturing/doctype/job_card/job_card.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/manufacturing/doctype/job_card/job_card.js b/erpnext/manufacturing/doctype/job_card/job_card.js index 768cea33daeb..c4541fa68e61 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.js +++ b/erpnext/manufacturing/doctype/job_card/job_card.js @@ -28,12 +28,12 @@ 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) { + if (!frm.is_new() && frm.doc.__onload.work_order_stopped) { frm.disable_save(); return; } - if (!frm.doc.__islocal && has_items && frm.doc.docstatus < 2) { + if (!frm.is_new() && 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; From f94afc1fff895b9e1255ef6b40f0f84cc32d0948 Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Wed, 6 Apr 2022 22:14:37 +0530 Subject: [PATCH 04/41] fix(pos): reload doc before set value --- .../v13_0/set_return_against_in_pos_invoice_references.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/patches/v13_0/set_return_against_in_pos_invoice_references.py b/erpnext/patches/v13_0/set_return_against_in_pos_invoice_references.py index 6af9617bcee9..fe9eb8b2cc1c 100644 --- a/erpnext/patches/v13_0/set_return_against_in_pos_invoice_references.py +++ b/erpnext/patches/v13_0/set_return_against_in_pos_invoice_references.py @@ -19,6 +19,8 @@ def execute(): if not open_pos_closing_entries: return + frappe.reload_doc("Accounts", "doctype", "pos_invoice_reference") + POSInvoiceReference = frappe.qb.DocType("POS Invoice Reference") POSInvoice = frappe.qb.DocType("POS Invoice") pos_invoice_references = ( From d720d15e3d1a12b31ca8e963591d991f164953e2 Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Wed, 6 Apr 2022 22:32:23 +0530 Subject: [PATCH 05/41] fix(pos): reload doc before set value (#30610) --- .../v13_0/set_return_against_in_pos_invoice_references.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/patches/v13_0/set_return_against_in_pos_invoice_references.py b/erpnext/patches/v13_0/set_return_against_in_pos_invoice_references.py index 6af9617bcee9..fe9eb8b2cc1c 100644 --- a/erpnext/patches/v13_0/set_return_against_in_pos_invoice_references.py +++ b/erpnext/patches/v13_0/set_return_against_in_pos_invoice_references.py @@ -19,6 +19,8 @@ def execute(): if not open_pos_closing_entries: return + frappe.reload_doc("Accounts", "doctype", "pos_invoice_reference") + POSInvoiceReference = frappe.qb.DocType("POS Invoice Reference") POSInvoice = frappe.qb.DocType("POS Invoice") pos_invoice_references = ( From c6f946e3e89808224392f59589c7e5c077434435 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 30 Mar 2022 16:18:26 +0530 Subject: [PATCH 06/41] feat: additional filters in payment terms status report (cherry picked from commit eaeadbc422293b08eeed32f2e1c6183f63d17c64) --- .../payment_terms_status_for_sales_order.js | 68 ++++++++++++++----- .../payment_terms_status_for_sales_order.py | 49 +++++++++++-- 2 files changed, 94 insertions(+), 23 deletions(-) diff --git a/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.js b/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.js index 0e36b3fe3d21..019bf45f06b7 100644 --- a/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.js +++ b/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.js @@ -27,28 +27,64 @@ function get_filters() { "default": frappe.datetime.get_today() }, { - "fieldname":"sales_order", - "label": __("Sales Order"), - "fieldtype": "MultiSelectList", + "fieldname":"customer_group", + "label": __("Customer Group"), + "fieldtype": "Link", "width": 100, - "options": "Sales Order", - "get_data": function(txt) { - return frappe.db.get_link_options("Sales Order", txt, this.filters()); - }, - "filters": () => { + "options": "Customer Group", + "get_query": () => { return { - docstatus: 1, - payment_terms_template: ['not in', ['']], - company: frappe.query_report.get_filter_value("company"), - transaction_date: ['between', [frappe.query_report.get_filter_value("period_start_date"), frappe.query_report.get_filter_value("period_end_date")]] + filters: { 'is_group': 0 } } - }, - on_change: function(){ - frappe.query_report.refresh(); + } + + }, + { + "fieldname":"customer", + "label": __("Customer"), + "fieldtype": "Link", + "width": 100, + "options": "Customer", + "get_query": () => { + filters = { + 'disabled': 0 + } + if(frappe.query_report.get_filter_value("customer_group") != "") { + filters['customer_group'] = frappe.query_report.get_filter_value("customer_group"); + } + return { 'filters': filters }; + } + }, + { + "fieldname":"item_group", + "label": __("Item Group"), + "fieldtype": "Link", + "width": 100, + "options": "Item Group", + "get_query": () => { + return { + filters: { 'is_group': 0 } + } + } + + }, + { + "fieldname":"item", + "label": __("Item"), + "fieldtype": "Link", + "width": 100, + "options": "Item", + "get_query": () => { + filters = { + 'disabled': 0 + } + if(frappe.query_report.get_filter_value("item_group") != "") { + filters['item_group'] = frappe.query_report.get_filter_value("item_group"); + } + return { 'filters': filters }; } } ] - return filters; } diff --git a/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.py b/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.py index 7f797f67eee8..5b9550019fd7 100644 --- a/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.py +++ b/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.py @@ -3,7 +3,7 @@ import frappe from frappe import _, qb, query_builder -from frappe.query_builder import functions +from frappe.query_builder import Criterion, functions def get_columns(): @@ -14,6 +14,12 @@ def get_columns(): "fieldtype": "Link", "options": "Sales Order", }, + { + "label": _("Customer"), + "fieldname": "customer", + "fieldtype": "Link", + "options": "Customer", + }, { "label": _("Posting Date"), "fieldname": "submitted", @@ -79,11 +85,29 @@ def get_conditions(filters): conditions.start_date = filters.period_start_date or frappe.utils.add_months( conditions.end_date, -1 ) - conditions.sales_order = filters.sales_order or [] return conditions +def build_filter_criterions(filters): + filters = frappe._dict(filters) if filters else frappe._dict({}) + qb_criterions = [] + + if filters.customer_group: + qb_criterions.append(qb.DocType("Customer").customer_group == filters.customer_group) + + if filters.customer: + qb_criterions.append(qb.DocType("Customer").name == filters.customer) + + if filters.item_group: + qb_criterions.append(qb.DocType("Item").item_group == filters.item_group) + + if filters.item: + qb_criterions.append(qb.DocType("Item").name == filters.item) + + return qb_criterions + + def get_so_with_invoices(filters): """ Get Sales Order with payment terms template with their associated Invoices @@ -92,16 +116,29 @@ def get_so_with_invoices(filters): so = qb.DocType("Sales Order") ps = qb.DocType("Payment Schedule") + cust = qb.DocType("Customer") + item = qb.DocType("Item") + soi = qb.DocType("Sales Order Item") + + conditions = get_conditions(filters) + filter_criterions = build_filter_criterions(filters) + datediff = query_builder.CustomFunction("DATEDIFF", ["cur_date", "due_date"]) ifelse = query_builder.CustomFunction("IF", ["condition", "then", "else"]) - conditions = get_conditions(filters) query_so = ( - qb.from_(so) + qb.from_(cust) + .join(so) + .on(so.customer == cust.name) + .join(soi) + .on(soi.parent == so.name) + .join(item) + .on(item.item_code == soi.item_code) .join(ps) .on(ps.parent == so.name) .select( so.name, + so.customer, so.transaction_date.as_("submitted"), ifelse(datediff(ps.due_date, functions.CurDate()) < 0, "Overdue", "Unpaid").as_("status"), ps.payment_term, @@ -117,12 +154,10 @@ def get_so_with_invoices(filters): & (so.company == conditions.company) & (so.transaction_date[conditions.start_date : conditions.end_date]) ) + .where(Criterion.all(filter_criterions)) .orderby(so.name, so.transaction_date, ps.due_date) ) - if conditions.sales_order != []: - query_so = query_so.where(so.name.isin(conditions.sales_order)) - sorders = query_so.run(as_dict=True) invoices = [] From 9336a3413f7b00c9f4a6c136d543e8334a1bd3f8 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 30 Mar 2022 18:49:40 +0530 Subject: [PATCH 07/41] refactor: adding new filters and column to test cases (cherry picked from commit 7558f1b07879da066676f503c0ecb11c51b8e0bc) --- .../test_payment_terms_status_for_sales_order.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/erpnext/selling/report/payment_terms_status_for_sales_order/test_payment_terms_status_for_sales_order.py b/erpnext/selling/report/payment_terms_status_for_sales_order/test_payment_terms_status_for_sales_order.py index 89940a6e872f..0b46e949b424 100644 --- a/erpnext/selling/report/payment_terms_status_for_sales_order/test_payment_terms_status_for_sales_order.py +++ b/erpnext/selling/report/payment_terms_status_for_sales_order/test_payment_terms_status_for_sales_order.py @@ -48,9 +48,9 @@ def create_payment_terms_template(self): template.insert() self.template = template - def test_payment_terms_status(self): + def test_01_payment_terms_status(self): self.create_payment_terms_template() - item = create_item(item_code="_Test Excavator", is_stock_item=0) + item = create_item(item_code="_Test Excavator 1", is_stock_item=0) so = make_sales_order( transaction_date="2021-06-15", delivery_date=add_days("2021-06-15", -30), @@ -78,13 +78,14 @@ def test_payment_terms_status(self): "company": "_Test Company", "period_start_date": "2021-06-01", "period_end_date": "2021-06-30", - "sales_order": [so.name], + "item": item.item_code, } ) expected_value = [ { "name": so.name, + "customer": so.customer, "submitted": datetime.date(2021, 6, 15), "status": "Completed", "payment_term": None, @@ -98,6 +99,7 @@ def test_payment_terms_status(self): }, { "name": so.name, + "customer": so.customer, "submitted": datetime.date(2021, 6, 15), "status": "Partly Paid", "payment_term": None, @@ -132,11 +134,11 @@ def create_exchange_rate(self, date): ) doc.insert() - def test_alternate_currency(self): + def test_02_alternate_currency(self): transaction_date = "2021-06-15" self.create_payment_terms_template() self.create_exchange_rate(transaction_date) - item = create_item(item_code="_Test Excavator", is_stock_item=0) + item = create_item(item_code="_Test Excavator 2", is_stock_item=0) so = make_sales_order( transaction_date=transaction_date, currency="USD", @@ -166,7 +168,7 @@ def test_alternate_currency(self): "company": "_Test Company", "period_start_date": "2021-06-01", "period_end_date": "2021-06-30", - "sales_order": [so.name], + "item": item.item_code, } ) @@ -174,6 +176,7 @@ def test_alternate_currency(self): expected_value = [ { "name": so.name, + "customer": so.customer, "submitted": datetime.date(2021, 6, 15), "status": "Completed", "payment_term": None, @@ -187,6 +190,7 @@ def test_alternate_currency(self): }, { "name": so.name, + "customer": so.customer, "submitted": datetime.date(2021, 6, 15), "status": "Partly Paid", "payment_term": None, From 00acb000dcefc55acaafaf6a8b151b43879a1066 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 4 Apr 2022 14:52:19 +0530 Subject: [PATCH 08/41] refactor: item filters are linked with group filters (cherry picked from commit e324d668d3b33eb6eaee955295ffceb632e50860) --- .../payment_terms_status_for_sales_order.js | 37 ++++++-------- .../payment_terms_status_for_sales_order.py | 49 +++++++++++++++++++ 2 files changed, 63 insertions(+), 23 deletions(-) diff --git a/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.js b/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.js index 019bf45f06b7..c068ae3b5a47 100644 --- a/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.js +++ b/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.js @@ -32,12 +32,6 @@ function get_filters() { "fieldtype": "Link", "width": 100, "options": "Customer Group", - "get_query": () => { - return { - filters: { 'is_group': 0 } - } - } - }, { "fieldname":"customer", @@ -46,13 +40,14 @@ function get_filters() { "width": 100, "options": "Customer", "get_query": () => { - filters = { - 'disabled': 0 - } - if(frappe.query_report.get_filter_value("customer_group") != "") { - filters['customer_group'] = frappe.query_report.get_filter_value("customer_group"); + var customer_group = frappe.query_report.get_filter_value('customer_group'); + return{ + "query": "erpnext.selling.report.payment_terms_status_for_sales_order.payment_terms_status_for_sales_order.get_customers_or_items", + "filters": [ + ['Customer', 'disabled', '=', '0'], + ['Customer Group','name', '=', customer_group] + ] } - return { 'filters': filters }; } }, { @@ -61,11 +56,6 @@ function get_filters() { "fieldtype": "Link", "width": 100, "options": "Item Group", - "get_query": () => { - return { - filters: { 'is_group': 0 } - } - } }, { @@ -75,13 +65,14 @@ function get_filters() { "width": 100, "options": "Item", "get_query": () => { - filters = { - 'disabled': 0 - } - if(frappe.query_report.get_filter_value("item_group") != "") { - filters['item_group'] = frappe.query_report.get_filter_value("item_group"); + var item_group = frappe.query_report.get_filter_value('item_group'); + return{ + "query": "erpnext.selling.report.payment_terms_status_for_sales_order.payment_terms_status_for_sales_order.get_customers_or_items", + "filters": [ + ['Item', 'disabled', '=', '0'], + ['Item Group','name', '=', item_group] + ] } - return { 'filters': filters }; } } ] diff --git a/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.py b/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.py index 5b9550019fd7..befbf40e2887 100644 --- a/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.py +++ b/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.py @@ -73,6 +73,55 @@ def get_columns(): return columns +def get_descendants_of(doctype, group_name): + group_doc = qb.DocType(doctype) + # get lft and rgt of group node + lft, rgt = ( + qb.from_(group_doc).select(group_doc.lft, group_doc.rgt).where(group_doc.name == group_name) + ).run()[0] + + # get all children of group node + query = ( + qb.from_(group_doc).select(group_doc.name).where((group_doc.lft >= lft) & (group_doc.rgt <= rgt)) + ) + + child_nodes = [] + for x in query.run(): + child_nodes.append(x[0]) + + return child_nodes + + +@frappe.whitelist() +@frappe.validate_and_sanitize_search_inputs +def get_customers_or_items(doctype, txt, searchfield, start, page_len, filters): + filter_list = [] + if isinstance(filters, list): + for item in filters: + if item[0] == doctype: + filter_list.append(item) + elif item[0] == "Customer Group": + if item[3] != "": + filter_list.append( + [doctype, "customer_group", "in", get_descendants_of("Customer Group", item[3])] + ) + elif item[0] == "Item Group": + if item[3] != "": + filter_list.append([doctype, "item_group", "in", get_descendants_of("Item Group", item[3])]) + + if searchfield and txt: + filter_list.append([doctype, searchfield, "like", "%%%s%%" % txt]) + + return frappe.desk.reportview.execute( + doctype, + filters=filter_list, + fields=["name", "customer_group"] if doctype == "Customer" else ["name", "item_group"], + limit_start=start, + limit_page_length=page_len, + as_list=True, + ) + + def get_conditions(filters): """ Convert filter options to conditions used in query From a9d5000eab4654fcf18261d275066d45e727e195 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 4 Apr 2022 16:21:46 +0530 Subject: [PATCH 09/41] refactor: use group fields from Sales Order and Sales Order Items (cherry picked from commit b2ed9fd3fe62a1f714150f75bc08d0875f3e46c1) --- .../payment_terms_status_for_sales_order.py | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.py b/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.py index befbf40e2887..cb22fb6a80f6 100644 --- a/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.py +++ b/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.py @@ -143,16 +143,24 @@ def build_filter_criterions(filters): qb_criterions = [] if filters.customer_group: - qb_criterions.append(qb.DocType("Customer").customer_group == filters.customer_group) + qb_criterions.append( + qb.DocType("Sales Order").customer_group.isin( + get_descendants_of("Customer Group", filters.customer_group) + ) + ) if filters.customer: - qb_criterions.append(qb.DocType("Customer").name == filters.customer) + qb_criterions.append(qb.DocType("Sales Order").customer == filters.customer) if filters.item_group: - qb_criterions.append(qb.DocType("Item").item_group == filters.item_group) + qb_criterions.append( + qb.DocType("Sales Order Item").item_group.isin( + get_descendants_of("Item Group", filters.item_group) + ) + ) if filters.item: - qb_criterions.append(qb.DocType("Item").name == filters.item) + qb_criterions.append(qb.DocType("Sales Order Item").item_code == filters.item) return qb_criterions @@ -165,8 +173,6 @@ def get_so_with_invoices(filters): so = qb.DocType("Sales Order") ps = qb.DocType("Payment Schedule") - cust = qb.DocType("Customer") - item = qb.DocType("Item") soi = qb.DocType("Sales Order Item") conditions = get_conditions(filters) @@ -176,13 +182,9 @@ def get_so_with_invoices(filters): ifelse = query_builder.CustomFunction("IF", ["condition", "then", "else"]) query_so = ( - qb.from_(cust) - .join(so) - .on(so.customer == cust.name) + qb.from_(so) .join(soi) .on(soi.parent == so.name) - .join(item) - .on(item.item_code == soi.item_code) .join(ps) .on(ps.parent == so.name) .select( From 39f8ee2ea660d8804ed230dad2e3520501f70149 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 5 Apr 2022 10:23:19 +0530 Subject: [PATCH 10/41] test: added test cases for group filters (cherry picked from commit 16bfb930f810e3e44e71192f3676d9636b100a79) --- ...st_payment_terms_status_for_sales_order.py | 136 +++++++++++++++++- 1 file changed, 135 insertions(+), 1 deletion(-) diff --git a/erpnext/selling/report/payment_terms_status_for_sales_order/test_payment_terms_status_for_sales_order.py b/erpnext/selling/report/payment_terms_status_for_sales_order/test_payment_terms_status_for_sales_order.py index 0b46e949b424..9d542f5079c4 100644 --- a/erpnext/selling/report/payment_terms_status_for_sales_order/test_payment_terms_status_for_sales_order.py +++ b/erpnext/selling/report/payment_terms_status_for_sales_order/test_payment_terms_status_for_sales_order.py @@ -11,10 +11,13 @@ ) from erpnext.stock.doctype.item.test_item import create_item -test_dependencies = ["Sales Order", "Item", "Sales Invoice", "Payment Terms Template"] +test_dependencies = ["Sales Order", "Item", "Sales Invoice", "Payment Terms Template", "Customer"] class TestPaymentTermsStatusForSalesOrder(FrappeTestCase): + def tearDown(self): + frappe.db.rollback() + def create_payment_terms_template(self): # create template for 50-50 payments template = None @@ -204,3 +207,134 @@ def test_02_alternate_currency(self): }, ] self.assertEqual(data, expected_value) + + def test_03_group_filters(self): + transaction_date = "2021-06-15" + self.create_payment_terms_template() + item1 = create_item(item_code="_Test Excavator 1", is_stock_item=0) + item1.item_group = "Products" + item1.save() + + so1 = make_sales_order( + transaction_date=transaction_date, + delivery_date=add_days(transaction_date, -30), + item=item1.item_code, + qty=1, + rate=1000000, + do_not_save=True, + ) + so1.po_no = "" + so1.taxes_and_charges = "" + so1.taxes = "" + so1.payment_terms_template = self.template.name + so1.save() + so1.submit() + + item2 = create_item(item_code="_Test Steel", is_stock_item=0) + item2.item_group = "Raw Material" + item2.save() + + so2 = make_sales_order( + customer="_Test Customer 1", + transaction_date=transaction_date, + delivery_date=add_days(transaction_date, -30), + item=item2.item_code, + qty=100, + rate=1000, + do_not_save=True, + ) + so2.po_no = "" + so2.taxes_and_charges = "" + so2.taxes = "" + so2.payment_terms_template = self.template.name + so2.save() + so2.submit() + + base_filters = { + "company": "_Test Company", + "period_start_date": "2021-06-01", + "period_end_date": "2021-06-30", + } + + expected_value_so1 = [ + { + "name": so1.name, + "customer": so1.customer, + "submitted": datetime.date(2021, 6, 15), + "status": "Overdue", + "payment_term": None, + "description": "_Test 50-50", + "due_date": datetime.date(2021, 6, 30), + "invoice_portion": 50.0, + "currency": "INR", + "base_payment_amount": 500000.0, + "paid_amount": 0.0, + "invoices": "", + }, + { + "name": so1.name, + "customer": so1.customer, + "submitted": datetime.date(2021, 6, 15), + "status": "Overdue", + "payment_term": None, + "description": "_Test 50-50", + "due_date": datetime.date(2021, 7, 15), + "invoice_portion": 50.0, + "currency": "INR", + "base_payment_amount": 500000.0, + "paid_amount": 0.0, + "invoices": "", + }, + ] + + expected_value_so2 = [ + { + "name": so2.name, + "customer": so2.customer, + "submitted": datetime.date(2021, 6, 15), + "status": "Overdue", + "payment_term": None, + "description": "_Test 50-50", + "due_date": datetime.date(2021, 6, 30), + "invoice_portion": 50.0, + "currency": "INR", + "base_payment_amount": 50000.0, + "paid_amount": 0.0, + "invoices": "", + }, + { + "name": so2.name, + "customer": so2.customer, + "submitted": datetime.date(2021, 6, 15), + "status": "Overdue", + "payment_term": None, + "description": "_Test 50-50", + "due_date": datetime.date(2021, 7, 15), + "invoice_portion": 50.0, + "currency": "INR", + "base_payment_amount": 50000.0, + "paid_amount": 0.0, + "invoices": "", + }, + ] + + group_filters = [ + {"customer_group": "All Customer Groups"}, + {"item_group": "All Item Groups"}, + {"item_group": "Products"}, + {"item_group": "Raw Material"}, + ] + + expected_values_for_group_filters = [ + expected_value_so1 + expected_value_so2, + expected_value_so1 + expected_value_so2, + expected_value_so1, + expected_value_so2, + ] + + for idx, g in enumerate(group_filters, 0): + # build filter + filters = frappe._dict({}).update(base_filters).update(g) + with self.subTest(filters=filters): + columns, data, message, chart = execute(filters) + self.assertEqual(data, expected_values_for_group_filters[idx]) From af039be03e68d8255c362931e23f35677c1f5dd6 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 7 Apr 2022 13:20:36 +0530 Subject: [PATCH 11/41] fix: fallback to item_name if description is not found (backport #30619) (#30622) * fix: strip html tags before checking for empty description (#30619) (cherry picked from commit e4c6d6a1a6b9d9ed9aa01d9f3290546bfa76e4bb) # Conflicts: # erpnext/stock/doctype/item/test_item.py * fix: resolve conflicts Co-authored-by: Ankush Menat --- erpnext/stock/doctype/item/item.py | 7 ++----- erpnext/stock/doctype/item/test_item.py | 7 +++++++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 4ee429191bac..65930a404b46 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -18,6 +18,7 @@ now_datetime, nowtime, strip, + strip_html, ) from frappe.utils.html_utils import clean_html @@ -69,10 +70,6 @@ def autoname(self): self.item_code = strip(self.item_code) self.name = self.item_code - def before_insert(self): - if not self.description: - self.description = self.item_name - def after_insert(self): """set opening stock and item price""" if self.standard_rate: @@ -86,7 +83,7 @@ def validate(self): if not self.item_name: self.item_name = self.item_code - if not self.description: + if not strip_html(cstr(self.description)).strip(): self.description = self.item_name self.validate_uom() diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py index 7ef24020ef6f..29d6bf2df8b8 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -683,6 +683,13 @@ def test_retain_sample(self): self.assertEqual(item.sample_quantity, None) item.delete() + def test_empty_description(self): + item = make_item(properties={"description": "

"}) + self.assertEqual(item.description, item.item_name) + item.description = "" + item.save() + self.assertEqual(item.description, item.item_name) + def set_item_variant_settings(fields): doc = frappe.get_doc("Item Variant Settings") From 0c163eef23a41de49ebcd8140427bf9be67c472a Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Thu, 7 Apr 2022 10:06:08 +0530 Subject: [PATCH 12/41] fix: enable Track Changes in Leave Allocation (cherry picked from commit f8f1c3d8b57d95f799696de436f8a0d0c1b0e714) # Conflicts: # erpnext/hr/doctype/leave_allocation/leave_allocation.json --- .../doctype/leave_allocation/leave_allocation.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.json b/erpnext/hr/doctype/leave_allocation/leave_allocation.json index 52ee463db027..5e74b1894c97 100644 --- a/erpnext/hr/doctype/leave_allocation/leave_allocation.json +++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.json @@ -237,7 +237,11 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], +<<<<<<< HEAD "modified": "2021-10-01 15:28:26.335104", +======= + "modified": "2022-04-07 09:50:33.145825", +>>>>>>> f8f1c3d8b5 (fix: enable Track Changes in Leave Allocation) "modified_by": "Administrator", "module": "HR", "name": "Leave Allocation", @@ -278,5 +282,13 @@ "show_name_in_global_search": 1, "sort_field": "modified", "sort_order": "DESC", +<<<<<<< HEAD "timeline_field": "employee" } +======= + "states": [], + "timeline_field": "employee", + "title_field": "employee_name", + "track_changes": 1 +} +>>>>>>> f8f1c3d8b5 (fix: enable Track Changes in Leave Allocation) From c68a38eb5bbc6095411a30793205497a7a147a7b Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Thu, 7 Apr 2022 10:06:51 +0530 Subject: [PATCH 13/41] fix: make New Leaves Allocated read-only if policy assignment is linked to the allocation and leave type is earned leave (cherry picked from commit 6203ffc8fab9a6061b991fa689c73391d1671cdf) --- erpnext/hr/doctype/leave_allocation/leave_allocation.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.js b/erpnext/hr/doctype/leave_allocation/leave_allocation.js index 9742387c16a6..aef44122513a 100755 --- a/erpnext/hr/doctype/leave_allocation/leave_allocation.js +++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.js @@ -34,6 +34,15 @@ frappe.ui.form.on("Leave Allocation", { }); } } + + // make new leaves allocated field read only if allocation is created via leave policy assignment + // and leave type is earned leave, since these leaves would be allocated via the scheduler + if (frm.doc.leave_policy_assignment) { + frappe.db.get_value("Leave Type", frm.doc.leave_type, "is_earned_leave", (r) => { + if (r && cint(r.is_earned_leave)) + frm.set_df_property("new_leaves_allocated", "read_only", 1); + }); + } }, expire_allocation: function(frm) { From 8393d113d41ed769dd73f41ed4d2967ffe3b6b03 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Thu, 7 Apr 2022 10:07:39 +0530 Subject: [PATCH 14/41] fix: show allocation history for earned leaves allocated via scheduler (cherry picked from commit ec65af5f38bc860701fc8a15f67212cbb4b357d2) --- erpnext/hr/utils.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py index 2524872ea2bb..f1c1608cdd05 100644 --- a/erpnext/hr/utils.py +++ b/erpnext/hr/utils.py @@ -489,6 +489,17 @@ def update_previous_leave_allocation( allocation.db_set("total_leaves_allocated", new_allocation, update_modified=False) create_additional_leave_ledger_entry(allocation, earned_leaves, today_date) + if e_leave_type.based_on_date_of_joining: + text = _("allocated {0} leave(s) via scheduler on {1} based on the date of joining").format( + frappe.bold(earned_leaves), frappe.bold(formatdate(today_date)) + ) + else: + text = _("allocated {0} leave(s) via scheduler on {1}").format( + frappe.bold(earned_leaves), frappe.bold(formatdate(today_date)) + ) + + allocation.add_comment(comment_type="Info", text=text) + def get_monthly_earned_leave(annual_leaves, frequency, rounding): earned_leaves = 0.0 From 07ff2cb1d3e90ad96ac4d58b889acb49e6a524dd Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Thu, 7 Apr 2022 13:01:02 +0530 Subject: [PATCH 15/41] fix: conflicts --- .../hr/doctype/leave_allocation/leave_allocation.json | 9 --------- 1 file changed, 9 deletions(-) diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.json b/erpnext/hr/doctype/leave_allocation/leave_allocation.json index 5e74b1894c97..3d5c1037f1f7 100644 --- a/erpnext/hr/doctype/leave_allocation/leave_allocation.json +++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.json @@ -237,11 +237,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], -<<<<<<< HEAD - "modified": "2021-10-01 15:28:26.335104", -======= "modified": "2022-04-07 09:50:33.145825", ->>>>>>> f8f1c3d8b5 (fix: enable Track Changes in Leave Allocation) "modified_by": "Administrator", "module": "HR", "name": "Leave Allocation", @@ -282,13 +278,8 @@ "show_name_in_global_search": 1, "sort_field": "modified", "sort_order": "DESC", -<<<<<<< HEAD - "timeline_field": "employee" -} -======= "states": [], "timeline_field": "employee", "title_field": "employee_name", "track_changes": 1 } ->>>>>>> f8f1c3d8b5 (fix: enable Track Changes in Leave Allocation) From 8932d7040fa6e45207364ee4863ee47241907dda Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Thu, 7 Apr 2022 13:01:39 +0530 Subject: [PATCH 16/41] fix: conflicts --- erpnext/hr/doctype/leave_allocation/leave_allocation.json | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.json b/erpnext/hr/doctype/leave_allocation/leave_allocation.json index 3d5c1037f1f7..4a9b54034af9 100644 --- a/erpnext/hr/doctype/leave_allocation/leave_allocation.json +++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.json @@ -278,7 +278,6 @@ "show_name_in_global_search": 1, "sort_field": "modified", "sort_order": "DESC", - "states": [], "timeline_field": "employee", "title_field": "employee_name", "track_changes": 1 From 4b77a4de2869ed606ab45f1d26656c6b372b8db3 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 7 Apr 2022 13:24:48 +0530 Subject: [PATCH 17/41] fix: update translation (backport #30474) (#30593) * fix: update translation (#30474) * fix: update translation * fix: update translation * fix: update translation * fix: update translation * fix: update translation * fix: update translation * fix: update translation * fix: update translation * fix: update translation * fix: update translation (cherry picked from commit 4895761d89df932e725f0923f0af900ada1486a8) * chore: fix translation csv file Co-authored-by: HENRY Florian Co-authored-by: Ankush Menat --- erpnext/translations/fr.csv | 49 +++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/erpnext/translations/fr.csv b/erpnext/translations/fr.csv index 3cdae454ab5d..4746e4f3d8ba 100644 --- a/erpnext/translations/fr.csv +++ b/erpnext/translations/fr.csv @@ -285,7 +285,7 @@ Asset scrapped via Journal Entry {0},Actif mis au rebut via Écriture de Journal "Asset {0} cannot be scrapped, as it is already {1}","L'actif {0} ne peut pas être mis au rebut, car il est déjà {1}", Asset {0} does not belong to company {1},L'actif {0} ne fait pas partie à la société {1}, Asset {0} must be submitted,L'actif {0} doit être soumis, -Assets,Les atouts, +Assets,Actifs - Immo., Assign,Assigner, Assign Salary Structure,Affecter la structure salariale, Assign To,Attribuer À, @@ -1211,7 +1211,7 @@ Hello,Bonjour, Help Results for,Aide Résultats pour, High,Haut, High Sensitivity,Haute sensibilité, -Hold,Tenir, +Hold,Mettre en attente, Hold Invoice,Facture en attente, Holiday,Vacances, Holiday List,Liste de vacances, @@ -4240,7 +4240,7 @@ For Default Supplier (Optional),Pour le fournisseur par défaut (facultatif), From date cannot be greater than To date,La Date Initiale ne peut pas être postérieure à la Date Finale, Group by,Grouper Par, In stock,En stock, -Item name,Nom de l'article, +Item name,Libellé de l'article, Loan amount is mandatory,Le montant du prêt est obligatoire, Minimum Qty,Quantité minimum, More details,Plus de détails, @@ -5473,7 +5473,7 @@ Percentage you are allowed to transfer more against the quantity ordered. For ex PUR-ORD-.YYYY.-,PUR-ORD-.YYYY.-, Get Items from Open Material Requests,Obtenir des Articles de Demandes Matérielles Ouvertes, Fetch items based on Default Supplier.,Récupérez les articles en fonction du fournisseur par défaut., -Required By,Requis Par, +Required By,Requis pour le, Order Confirmation No,No de confirmation de commande, Order Confirmation Date,Date de confirmation de la commande, Customer Mobile No,N° de Portable du Client, @@ -7223,8 +7223,8 @@ Basic Rate (Company Currency),Taux de Base (Devise de la Société ), Scrap %,% de Rebut, Original Item,Article original, BOM Operation,Opération LDM, -Operation Time ,Moment de l'opération, -In minutes,En quelques minutes, +Operation Time ,Durée de l'opération, +In minutes,En minutes, Batch Size,Taille du lot, Base Hour Rate(Company Currency),Taux Horaire de Base (Devise de la Société), Operating Cost(Company Currency),Coût d'Exploitation (Devise Société), @@ -9267,7 +9267,7 @@ Sales Order Analysis,Analyse des commandes clients, Amount Delivered,Montant livré, Delay (in Days),Retard (en jours), Group by Sales Order,Regrouper par commande client, - Sales Value,La valeur des ventes, +Sales Value,La valeur des ventes, Stock Qty vs Serial No Count,Quantité de stock vs numéro de série, Serial No Count,Numéro de série, Work Order Summary,Résumé de l'ordre de travail, @@ -9647,7 +9647,7 @@ Allow Multiple Sales Orders Against a Customer's Purchase Order,Autoriser plusie Validate Selling Price for Item Against Purchase Rate or Valuation Rate,Valider le prix de vente de l'article par rapport au taux d'achat ou au taux de valorisation, Hide Customer's Tax ID from Sales Transactions,Masquer le numéro d'identification fiscale du client dans les transactions de vente, "The percentage you are allowed to receive or deliver more against the quantity ordered. For example, if you have ordered 100 units, and your Allowance is 10%, then you are allowed to receive 110 units.","Le pourcentage que vous êtes autorisé à recevoir ou à livrer plus par rapport à la quantité commandée. Par exemple, si vous avez commandé 100 unités et que votre allocation est de 10%, vous êtes autorisé à recevoir 110 unités.", -Action If Quality Inspection Is Not Submitted,Action si l'inspection de la qualité n'est pas soumise, +Action If Quality Inspection Is Not Submitted,Action si l'inspection qualité n'est pas soumise, Auto Insert Price List Rate If Missing,Taux de liste de prix d'insertion automatique s'il est manquant, Automatically Set Serial Nos Based on FIFO,Définir automatiquement les numéros de série en fonction de FIFO, Set Qty in Transactions Based on Serial No Input,Définir la quantité dans les transactions en fonction du numéro de série, @@ -9838,3 +9838,36 @@ Enable European Access,Activer l'accès européen, Creating Purchase Order ...,Création d'une commande d'achat ..., "Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Sélectionnez un fournisseur parmi les fournisseurs par défaut des articles ci-dessous. Lors de la sélection, un bon de commande sera effectué contre des articles appartenant uniquement au fournisseur sélectionné.", Row #{}: You must select {} serial numbers for item {}.,Ligne n ° {}: vous devez sélectionner {} numéros de série pour l'article {}., +Update Rate as per Last Purchase,Mettre à jour avec les derniers prix d'achats +Company Shipping Address,Adresse d'expédition +Shipping Address Details,Détail d'adresse d'expédition +Company Billing Address,Adresse de la société de facturation +Supplier Address Details, +Bank Reconciliation Tool,Outil de réconcialiation d'écritures bancaires +Supplier Contact,Contact fournisseur +Subcontracting,Sous traitance +Order Status,Statut de la commande +Build,Personnalisations avancées +Dispatch Address Name,Adresse de livraison intermédiaire +Amount Eligible for Commission,Montant éligible à comission +Grant Commission,Eligible aux commissions +Stock Transactions Settings, Paramétre des transactions +Role Allowed to Over Deliver/Receive, Rôle autorisé à dépasser cette limite +Users with this role are allowed to over deliver/receive against orders above the allowance percentage,Rôle Utilisateur qui sont autorisé à livrée/commandé au-delà de la limite +Over Transfer Allowance,Autorisation de limite de transfert +"The percentage you are allowed to transfer more against the quantity ordered. For example, if you have ordered 100 units, and your Allowance is 10%, then you are allowed transfer 110 units","Le pourcentage de quantité que vous pourrez receptionné en plus de la quantité commandée" +Quality Inspection Settings,Paramétre de l'inspection qualité +Action If Quality Inspection Is Rejected,Action si l'inspection qualité est rejetée +Disable Serial No And Batch Selector,Désactiver le sélecteur de numéro de lot/série +Is Rate Adjustment Entry (Debit Note),Est un justement du prix de la note de débit +Issue a debit note with 0 qty against an existing Sales Invoice,Creer une note de débit avec une quatité à O pour la facture +Control Historical Stock Transactions,Controle de l'historique des stransaction de stock +No stock transactions can be created or modified before this date.,Aucune transaction ne peux être créée ou modifié avant cette date. +Stock transactions that are older than the mentioned days cannot be modified.,Les transactions de stock plus ancienne que le nombre de jours ci-dessus ne peuvent être modifiées +Role Allowed to Create/Edit Back-dated Transactions,Rôle autorisé à créer et modifier des transactions anti-datée +"If mentioned, the system will allow only the users with this Role to create or modify any stock transaction earlier than the latest stock transaction for a specific item and warehouse. If set as blank, it allows all users to create/edit back-dated transactions.","LEs utilisateur de ce role pourront creer et modifier des transactions dans le passé. Si vide tout les utilisateurs pourrons le faire" +Auto Insert Item Price If Missing,Création du prix de l'article dans les listes de prix si abscent +Update Existing Price List Rate,Mise a jour automatique du prix dans les listes de prix +Show Barcode Field in Stock Transactions,Afficher le champ Code Barre dans les transactions de stock +Convert Item Description to Clean HTML in Transactions,Convertir les descriptions d'articles en HTML valide lors des transactions +Have Default Naming Series for Batch ID?,Nom de série par défaut pour les Lots ou Séries From 30a86951c3632471e670f08139897d1efbeff65b Mon Sep 17 00:00:00 2001 From: Chillar Anand Date: Thu, 7 Apr 2022 14:58:38 +0530 Subject: [PATCH 18/41] test: Fix failing tests for healthcare service unit (#30625) --- .../healthcare_service_unit/healthcare_service_unit.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.json b/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.json index 8935ec7d3c98..9366b09d27e6 100644 --- a/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.json +++ b/erpnext/healthcare/doctype/healthcare_service_unit/healthcare_service_unit.json @@ -2,7 +2,6 @@ "actions": [], "allow_import": 1, "allow_rename": 1, - "autoname": "field:healthcare_service_unit_name", "beta": 1, "creation": "2016-09-21 13:48:14.731437", "description": "Healthcare Service Unit", @@ -207,7 +206,7 @@ ], "is_tree": 1, "links": [], - "modified": "2021-08-19 14:09:11.643464", + "modified": "2022-04-07 03:11:36.023277", "modified_by": "Administrator", "module": "Healthcare", "name": "Healthcare Service Unit", From 560c55935f3cb697a10d6e4057cc4108c523f2c3 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 7 Apr 2022 15:37:33 +0530 Subject: [PATCH 19/41] fix: warehouse naming when suffix is present (#30621) (#30629) (cherry picked from commit be04eaf723804e72226462472884c38b0c0d26ff) Co-authored-by: Ankush Menat --- erpnext/stock/doctype/warehouse/test_warehouse.py | 10 ++++++++++ erpnext/stock/doctype/warehouse/warehouse.py | 5 +++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/warehouse/test_warehouse.py b/erpnext/stock/doctype/warehouse/test_warehouse.py index 1e9d01aa4b6f..5a7228a50683 100644 --- a/erpnext/stock/doctype/warehouse/test_warehouse.py +++ b/erpnext/stock/doctype/warehouse/test_warehouse.py @@ -38,6 +38,16 @@ def test_warehouse_hierarchy(self): self.assertEqual(p_warehouse.name, child_warehouse.parent_warehouse) self.assertEqual(child_warehouse.is_group, 0) + def test_naming(self): + company = "Wind Power LLC" + warehouse_name = "Named Warehouse - WP" + wh = frappe.get_doc(doctype="Warehouse", warehouse_name=warehouse_name, company=company).insert() + self.assertEqual(wh.name, warehouse_name) + + warehouse_name = "Unnamed Warehouse" + wh = frappe.get_doc(doctype="Warehouse", warehouse_name=warehouse_name, company=company).insert() + self.assertIn(warehouse_name, wh.name) + def test_unlinking_warehouse_from_item_defaults(self): company = "_Test Company" diff --git a/erpnext/stock/doctype/warehouse/warehouse.py b/erpnext/stock/doctype/warehouse/warehouse.py index c892ba3ddcee..3b18a9ac26f2 100644 --- a/erpnext/stock/doctype/warehouse/warehouse.py +++ b/erpnext/stock/doctype/warehouse/warehouse.py @@ -21,8 +21,9 @@ def autoname(self): suffix = " - " + frappe.get_cached_value("Company", self.company, "abbr") if not self.warehouse_name.endswith(suffix): self.name = self.warehouse_name + suffix - else: - self.name = self.warehouse_name + return + + self.name = self.warehouse_name def onload(self): """load account name for General Ledger Report""" From 709fcd50510520bc2a956131cb1fa85fdd8dca76 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 7 Apr 2022 11:04:51 +0530 Subject: [PATCH 20/41] feat: Receivable/Payable Account column and filter in AR/AP report --- .../accounts_payable/accounts_payable.js | 16 +++++++++ .../accounts_receivable.js | 16 +++++++++ .../accounts_receivable.py | 36 ++++++++++++------- .../test_accounts_receivable.py | 11 ++++-- 4 files changed, 65 insertions(+), 14 deletions(-) diff --git a/erpnext/accounts/report/accounts_payable/accounts_payable.js b/erpnext/accounts/report/accounts_payable/accounts_payable.js index 81c60bb337d9..f6961eb95faf 100644 --- a/erpnext/accounts/report/accounts_payable/accounts_payable.js +++ b/erpnext/accounts/report/accounts_payable/accounts_payable.js @@ -53,6 +53,22 @@ frappe.query_reports["Accounts Payable"] = { } } }, + { + "fieldname": "party_account", + "label": __("Payable Account"), + "fieldtype": "Link", + "options": "Account", + get_query: () => { + var company = frappe.query_report.get_filter_value('company'); + return { + filters: { + 'company': company, + 'account_type': 'Payable', + 'is_group': 0 + } + }; + } + }, { "fieldname": "ageing_based_on", "label": __("Ageing Based On"), diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js index 570029851e83..748bcde4354a 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js @@ -66,6 +66,22 @@ frappe.query_reports["Accounts Receivable"] = { } } }, + { + "fieldname": "party_account", + "label": __("Receivable Account"), + "fieldtype": "Link", + "options": "Account", + get_query: () => { + var company = frappe.query_report.get_filter_value('company'); + return { + filters: { + 'company': company, + 'account_type': 'Receivable', + 'is_group': 0 + } + }; + } + }, { "fieldname": "ageing_based_on", "label": __("Ageing Based On"), diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index 7bf9539b7516..c9567f23a344 100755 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -111,6 +111,7 @@ def init_voucher_balance(self): voucher_type=gle.voucher_type, voucher_no=gle.voucher_no, party=gle.party, + party_account=gle.account, posting_date=gle.posting_date, account_currency=gle.account_currency, remarks=gle.remarks if self.filters.get("show_remarks") else None, @@ -777,18 +778,21 @@ def add_common_filters(self, conditions, values, party_type_field): conditions.append("party=%s") values.append(self.filters.get(party_type_field)) - # get GL with "receivable" or "payable" account_type - account_type = "Receivable" if self.party_type == "Customer" else "Payable" - accounts = [ - d.name - for d in frappe.get_all( - "Account", filters={"account_type": account_type, "company": self.filters.company} - ) - ] - - if accounts: - conditions.append("account in (%s)" % ",".join(["%s"] * len(accounts))) - values += accounts + if self.filters.party_account: + conditions.append("account =%s") + values.append(self.filters.party_account) + else: + # get GL with "receivable" or "payable" account_type + account_type = "Receivable" if self.party_type == "Customer" else "Payable" + accounts = [ + d.name + for d in frappe.get_all( + "Account", filters={"account_type": account_type, "company": self.filters.company} + ) + ] + if accounts: + conditions.append("account in (%s)" % ",".join(["%s"] * len(accounts))) + values += accounts def add_customer_filters(self, conditions, values): if self.filters.get("customer_group"): @@ -889,6 +893,14 @@ def get_columns(self): width=180, ) + self.add_column( + label="Receivable Account" if self.party_type == "Customer" else "Payable Account", + fieldname="party_account", + fieldtype="Link", + options="Account", + width=180, + ) + if self.party_naming_by == "Naming Series": self.add_column( _("{0} Name").format(self.party_type), diff --git a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py index 7a6989f9e546..f38890e980c1 100644 --- a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py @@ -50,12 +50,19 @@ def test_accounts_receivable(self): make_credit_note(name) report = execute(filters) - expected_data_after_credit_note = [100, 0, 0, 40, -40] + expected_data_after_credit_note = [100, 0, 0, 40, -40, "Debtors - _TC2"] row = report[1][0] self.assertEqual( expected_data_after_credit_note, - [row.invoice_grand_total, row.invoiced, row.paid, row.credit_note, row.outstanding], + [ + row.invoice_grand_total, + row.invoiced, + row.paid, + row.credit_note, + row.outstanding, + row.party_account, + ], ) From be438c08db74878be3da7c50ae6918eca43ddcfd Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Wed, 6 Apr 2022 20:51:51 +0530 Subject: [PATCH 21/41] fix: Exchange gain and loss button in Payment Entry (cherry picked from commit 8feb4f08c5c96f0ff5575e13931b07e2f67a25e4) --- erpnext/accounts/doctype/payment_entry/payment_entry.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index 345764fb4185..3a89ce8cd129 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -226,10 +226,7 @@ frappe.ui.form.on('Payment Entry', { (frm.doc.total_allocated_amount > party_amount))); frm.toggle_display("set_exchange_gain_loss", - (frm.doc.paid_amount && frm.doc.received_amount && frm.doc.difference_amount && - ((frm.doc.paid_from_account_currency != company_currency || - frm.doc.paid_to_account_currency != company_currency) && - frm.doc.paid_from_account_currency != frm.doc.paid_to_account_currency))); + frm.doc.paid_amount && frm.doc.received_amount && frm.doc.difference_amount); frm.refresh_fields(); }, From 4a7ae5c4a776245774e160ed1355d2cc2be47661 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 7 Apr 2022 13:30:24 +0000 Subject: [PATCH 22/41] fix: dont reassign mutable (list) to a different field (backport #30634) (#30635) This is an automatic backport of pull request #30634 done by [Mergify](https://mergify.com). Conflicts fixed. --- .../purchase_register/purchase_register.py | 18 +++++++++--------- erpnext/selling/doctype/customer/customer.py | 3 ++- .../selling/doctype/customer/test_customer.py | 3 ++- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py index c35995931039..a73c72c6d825 100644 --- a/erpnext/accounts/report/purchase_register/purchase_register.py +++ b/erpnext/accounts/report/purchase_register/purchase_register.py @@ -124,11 +124,10 @@ def get_columns(invoice_list, additional_table_columns): _("Purchase Receipt") + ":Link/Purchase Receipt:100", {"fieldname": "currency", "label": _("Currency"), "fieldtype": "Data", "width": 80}, ] - expense_accounts = ( - tax_accounts - ) = ( - expense_columns - ) = tax_columns = unrealized_profit_loss_accounts = unrealized_profit_loss_account_columns = [] + + expense_accounts = [] + tax_accounts = [] + unrealized_profit_loss_accounts = [] if invoice_list: expense_accounts = frappe.db.sql_list( @@ -163,10 +162,11 @@ def get_columns(invoice_list, additional_table_columns): unrealized_profit_loss_account_columns = [ (account + ":Currency/currency:120") for account in unrealized_profit_loss_accounts ] - - for account in tax_accounts: - if account not in expense_accounts: - tax_columns.append(account + ":Currency/currency:120") + tax_columns = [ + (account + ":Currency/currency:120") + for account in tax_accounts + if account not in expense_accounts + ] columns = ( columns diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index 2e5cbb80cb61..8889a5f939af 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -100,7 +100,8 @@ def validate(self): @frappe.whitelist() def get_customer_group_details(self): doc = frappe.get_doc("Customer Group", self.customer_group) - self.accounts = self.credit_limits = [] + self.accounts = [] + self.credit_limits = [] self.payment_terms = self.default_price_list = "" tables = [["accounts", "account"], ["credit_limits", "credit_limit"]] diff --git a/erpnext/selling/doctype/customer/test_customer.py b/erpnext/selling/doctype/customer/test_customer.py index 4979b8f976a7..f631a6ef5684 100644 --- a/erpnext/selling/doctype/customer/test_customer.py +++ b/erpnext/selling/doctype/customer/test_customer.py @@ -47,7 +47,8 @@ def test_get_customer_group_details(self): c_doc.customer_name = "Testing Customer" c_doc.customer_group = "_Testing Customer Group" c_doc.payment_terms = c_doc.default_price_list = "" - c_doc.accounts = c_doc.credit_limits = [] + c_doc.accounts = [] + c_doc.credit_limits = [] c_doc.insert() c_doc.get_customer_group_details() self.assertEqual(c_doc.payment_terms, "_Test Payment Term Template 3") From 341e8dffd3382e56c6ee38c343c93849aff0998d Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 8 Apr 2022 11:27:17 +0530 Subject: [PATCH 23/41] fix: remove bad defaults from BOM operation (#30644) (#30645) [skip ci] (cherry picked from commit 49560d20bc98470f46e24a1566122df19eba1161) Co-authored-by: Ankush Menat --- erpnext/manufacturing/doctype/bom_operation/bom_operation.json | 3 +-- erpnext/stock/doctype/item/item.json | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom_operation/bom_operation.json b/erpnext/manufacturing/doctype/bom_operation/bom_operation.json index 9877b2882afc..210c0ea6a722 100644 --- a/erpnext/manufacturing/doctype/bom_operation/bom_operation.json +++ b/erpnext/manufacturing/doctype/bom_operation/bom_operation.json @@ -100,7 +100,6 @@ "read_only": 1 }, { - "default": "5", "depends_on": "eval:parent.doctype == 'BOM'", "fieldname": "base_operating_cost", "fieldtype": "Currency", @@ -178,7 +177,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2022-03-10 06:19:08.462027", + "modified": "2022-04-08 01:18:33.547481", "modified_by": "Administrator", "module": "Manufacturing", "name": "BOM Operation", diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json index d364d8a7d950..e6f1f0a2952f 100644 --- a/erpnext/stock/doctype/item/item.json +++ b/erpnext/stock/doctype/item/item.json @@ -659,7 +659,6 @@ }, { "collapsible": 1, - "default": "eval:!doc.is_fixed_asset", "fieldname": "sales_details", "fieldtype": "Section Break", "label": "Sales Details", @@ -1026,4 +1025,4 @@ "sort_order": "DESC", "title_field": "item_name", "track_changes": 1 -} \ No newline at end of file +} From 8cac70a63c32a6cfcc229809ca25cc2298cd5add Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Fri, 8 Apr 2022 13:20:25 +0530 Subject: [PATCH 24/41] fix: prevent deleting repost queue for cancelled transactions (cherry picked from commit a281998bcb0901fa928cfd68b9da26b1ab507449) --- .../repost_item_valuation.py | 16 ++++++++++++++++ erpnext/stock/stock_ledger.py | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py index b11becd4cee7..508f26b5f1dc 100644 --- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py +++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py @@ -61,6 +61,22 @@ def on_submit(self): repost(self) + def before_cancel(self): + self.check_pending_repost_against_cancelled_transaction() + + def check_pending_repost_against_cancelled_transaction(self): + if self.status not in ("Queued", "In Progress"): + return + + if not (self.voucher_no and self.voucher_no): + return + + transaction_status = frappe.db.get_value(self.voucher_type, self.voucher_no, "docstatus") + if transaction_status == 2: + msg = _("Cannot cancel as processing of cancelled documents is pending.") + msg += "
" + _("Please try again in an hour.") + frappe.throw(msg, title=_("Pending processing")) + @frappe.whitelist() def restart_reposting(self): self.set_status("Queued", write=False) diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index b95bcab71496..597e2e28f1ba 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -175,9 +175,9 @@ def validate_cancellation(args): ) if repost_entry.status == "Queued": doc = frappe.get_doc("Repost Item Valuation", repost_entry.name) + doc.status = "Skipped" doc.flags.ignore_permissions = True doc.cancel() - doc.delete() def set_as_cancel(voucher_type, voucher_no): From 9b6c5f2e54895796d3a9bd163ce591b1c7a74726 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Fri, 8 Apr 2022 13:32:20 +0530 Subject: [PATCH 25/41] test: prevent cancelling RIV of cancelled voucher (cherry picked from commit d74181630a34306da4cc12e29434aada4d81f8ea) --- .../test_repost_item_valuation.py | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py index f3bebad5c09c..55117ceb2e38 100644 --- a/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py +++ b/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py @@ -1,20 +1,25 @@ # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -import unittest import frappe +from frappe.tests.utils import FrappeTestCase from frappe.utils import nowdate from erpnext.controllers.stock_controller import create_item_wise_repost_entries +from erpnext.stock.doctype.item.test_item import make_item from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt from erpnext.stock.doctype.repost_item_valuation.repost_item_valuation import ( in_configured_timeslot, ) +from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry from erpnext.stock.utils import PendingRepostingError -class TestRepostItemValuation(unittest.TestCase): +class TestRepostItemValuation(FrappeTestCase): + def tearDown(self): + frappe.flags.dont_execute_stock_reposts = False + def test_repost_time_slot(self): repost_settings = frappe.get_doc("Stock Reposting Settings") @@ -162,3 +167,22 @@ def test_stock_freeze_validation(self): self.assertRaises(PendingRepostingError, stock_settings.save) riv.set_status("Skipped") + + def test_prevention_of_cancelled_transaction_riv(self): + frappe.flags.dont_execute_stock_reposts = True + + item = make_item() + warehouse = "_Test Warehouse - _TC" + old = make_stock_entry(item_code=item.name, to_warehouse=warehouse, qty=2, rate=5) + _new = make_stock_entry(item_code=item.name, to_warehouse=warehouse, qty=5, rate=10) + + old.cancel() + + riv = frappe.get_last_doc( + "Repost Item Valuation", {"voucher_type": old.doctype, "voucher_no": old.name} + ) + self.assertRaises(frappe.ValidationError, riv.cancel) + + riv.db_set("status", "Skipped") + riv.reload() + riv.cancel() # it should cancel now From 2ccf58d6adb8c190c24b3fd029725b3e0d81ae66 Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Wed, 6 Apr 2022 14:44:10 +0530 Subject: [PATCH 26/41] fix: removed unused courses template (cherry picked from commit bce1c2a0284dcdb498b01d1e726522f9b535cc9b) --- erpnext/templates/pages/courses.html | 11 ----------- erpnext/templates/pages/courses.py | 18 ------------------ 2 files changed, 29 deletions(-) delete mode 100644 erpnext/templates/pages/courses.html delete mode 100644 erpnext/templates/pages/courses.py diff --git a/erpnext/templates/pages/courses.html b/erpnext/templates/pages/courses.html deleted file mode 100644 index 6592f7a2e5ca..000000000000 --- a/erpnext/templates/pages/courses.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends "templates/web.html" %} - -{% block header %} -

About

-{% endblock %} - -{% block page_content %} - -

{{ intro }}

- -{% endblock %} diff --git a/erpnext/templates/pages/courses.py b/erpnext/templates/pages/courses.py deleted file mode 100644 index fb1af387d229..000000000000 --- a/erpnext/templates/pages/courses.py +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - - -import frappe - - -def get_context(context): - course = frappe.get_doc("Course", frappe.form_dict.course) - sidebar_title = course.name - - context.no_cache = 1 - context.show_sidebar = True - course = frappe.get_doc("Course", frappe.form_dict.course) - course.has_permission("read") - context.doc = course - context.sidebar_title = sidebar_title - context.intro = course.course_intro From e4bb81d8303d6dda26024245fe6f8b3c10f0e1f2 Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Sat, 9 Apr 2022 16:13:29 +0530 Subject: [PATCH 27/41] fix(pos): cannot change paid amount in pos payments (#30657) --- erpnext/selling/page/point_of_sale/pos_controller.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/erpnext/selling/page/point_of_sale/pos_controller.js b/erpnext/selling/page/point_of_sale/pos_controller.js index 6974bed4f1f5..65e0cbb7a5c9 100644 --- a/erpnext/selling/page/point_of_sale/pos_controller.js +++ b/erpnext/selling/page/point_of_sale/pos_controller.js @@ -721,11 +721,14 @@ erpnext.PointOfSale.Controller = class { async save_and_checkout() { if (this.frm.is_dirty()) { + let save_error = false; + await this.frm.save(null, null, null, () => save_error = true); // only move to payment section if save is successful - frappe.route_hooks.after_save = () => this.payment.checkout(); - return this.frm.save( - null, null, null, () => this.cart.toggle_checkout_btn(true) // show checkout button on error - ); + !save_error && this.payment.checkout(); + // show checkout button on error + save_error && setTimeout(() => { + this.cart.toggle_checkout_btn(true); + }, 300); // wait for save to finish } else { this.payment.checkout(); } From e69849d3334c5a2451c7698e2eb87bc2c74a135b Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Sat, 9 Apr 2022 16:28:25 +0530 Subject: [PATCH 28/41] fix(pos): cannot change paid amount in pos payments (#30661) --- erpnext/selling/page/point_of_sale/pos_controller.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/erpnext/selling/page/point_of_sale/pos_controller.js b/erpnext/selling/page/point_of_sale/pos_controller.js index 6974bed4f1f5..65e0cbb7a5c9 100644 --- a/erpnext/selling/page/point_of_sale/pos_controller.js +++ b/erpnext/selling/page/point_of_sale/pos_controller.js @@ -721,11 +721,14 @@ erpnext.PointOfSale.Controller = class { async save_and_checkout() { if (this.frm.is_dirty()) { + let save_error = false; + await this.frm.save(null, null, null, () => save_error = true); // only move to payment section if save is successful - frappe.route_hooks.after_save = () => this.payment.checkout(); - return this.frm.save( - null, null, null, () => this.cart.toggle_checkout_btn(true) // show checkout button on error - ); + !save_error && this.payment.checkout(); + // show checkout button on error + save_error && setTimeout(() => { + this.cart.toggle_checkout_btn(true); + }, 300); // wait for save to finish } else { this.payment.checkout(); } From 1b25a7fe765d334fce990d43224f8a790ccf8119 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sat, 9 Apr 2022 19:20:51 +0530 Subject: [PATCH 29/41] fix: Implicit ignore pricing rule check on returns --- erpnext/controllers/sales_and_purchase_return.py | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py index bc2122824f37..0ad39949b6da 100644 --- a/erpnext/controllers/sales_and_purchase_return.py +++ b/erpnext/controllers/sales_and_purchase_return.py @@ -330,7 +330,6 @@ def set_missing_values(source, target): doc = frappe.get_doc(target) doc.is_return = 1 doc.return_against = source.name - doc.ignore_pricing_rule = 1 doc.set_warehouse = "" if doctype == "Sales Invoice" or doctype == "POS Invoice": doc.is_pos = source.is_pos From 37dc11e59a16f1ea0d037ac8019aa6409493d5c7 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 1 Apr 2022 14:46:26 +0530 Subject: [PATCH 30/41] fix: Ignore disabled tax categories (cherry picked from commit 9a6a181f145f345a9973afc8673590b59aec1617) --- erpnext/regional/india/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py index 4eeb83779b3a..6bbaa358cde4 100644 --- a/erpnext/regional/india/utils.py +++ b/erpnext/regional/india/utils.py @@ -341,7 +341,7 @@ def get_tax_template(master_doctype, company, is_inter_state, state_code): tax_categories = frappe.get_all( "Tax Category", fields=["name", "is_inter_state", "gst_state"], - filters={"is_inter_state": is_inter_state, "is_reverse_charge": 0}, + filters={"is_inter_state": is_inter_state, "is_reverse_charge": 0, "disabled": 0}, ) default_tax = "" From e91dea62b8d98e213428f579c8a64b6602e5f53b Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 11 Apr 2022 14:48:17 +0530 Subject: [PATCH 31/41] fix: update translation (#30654) (#30676) (cherry picked from commit 03c631d7238a0e058235a3e4057d88451cd97ee6) Co-authored-by: HENRY Florian --- erpnext/translations/fr.csv | 67 +++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/erpnext/translations/fr.csv b/erpnext/translations/fr.csv index 4746e4f3d8ba..90456c5c4eef 100644 --- a/erpnext/translations/fr.csv +++ b/erpnext/translations/fr.csv @@ -951,14 +951,14 @@ End time cannot be before start time,L'heure de fin ne peut pas être avant l'he Ends On date cannot be before Next Contact Date.,La date de fin ne peut pas être avant la prochaine date de contact, Energy,Énergie, Engineer,Ingénieur, -Enough Parts to Build,Pièces Suffisantes pour Construire, +Enough Parts to Build,Pièces Suffisantes pour Construire Enroll,Inscrire, Enrolling student,Inscrire un étudiant, Enrolling students,Inscription des étudiants, Enter depreciation details,Veuillez entrer les détails de l'amortissement, -Enter the Bank Guarantee Number before submittting.,Entrez le numéro de garantie bancaire avant de soumettre., -Enter the name of the Beneficiary before submittting.,Entrez le nom du bénéficiaire avant de soumettre., -Enter the name of the bank or lending institution before submittting.,Entrez le nom de la banque ou de l'institution de prêt avant de soumettre., +Enter the Bank Guarantee Number before submittting.,Entrez le numéro de garantie bancaire avant de valider. +Enter the name of the Beneficiary before submittting.,Entrez le nom du bénéficiaire avant de valider. +Enter the name of the bank or lending institution before submittting.,Entrez le nom de la banque ou de l'institution de prêt avant de valider., Enter value betweeen {0} and {1},Entrez une valeur entre {0} et {1}, Entertainment & Leisure,Divertissement et Loisir, Entertainment Expenses,Charges de Représentation, @@ -1068,7 +1068,7 @@ For Employee,Employé, For Quantity (Manufactured Qty) is mandatory,Pour Quantité (Qté Produite) est obligatoire, For Supplier,Pour Fournisseur, For Warehouse,Pour l’Entrepôt, -For Warehouse is required before Submit,Pour l’Entrepôt est requis avant de Soumettre, +For Warehouse is required before Submit,Pour l’Entrepôt est requis avant de Valider, "For an item {0}, quantity must be negative number","Pour l'article {0}, la quantité doit être un nombre négatif", "For an item {0}, quantity must be positive number","Pour un article {0}, la quantité doit être un nombre positif", "For job card {0}, you can only make the 'Material Transfer for Manufacture' type stock entry","Pour la carte de travail {0}, vous pouvez uniquement saisir une entrée de stock de type "Transfert d'article pour fabrication".", @@ -1693,7 +1693,7 @@ No Items with Bill of Materials to Manufacture,Aucun Article avec une Liste de M No Items with Bill of Materials.,Aucun article avec nomenclature., No Permission,Aucune autorisation, No Remarks,Aucune Remarque, -No Result to submit,Aucun résultat à soumettre, +No Result to submit,Aucun résultat à valider, No Salary Structure assigned for Employee {0} on given date {1},Aucune structure de salaire attribuée à l'employé {0} à la date donnée {1}, No Staffing Plans found for this Designation,Aucun plan de dotation trouvé pour cette désignation, No Student Groups created.,Aucun Groupe d'Étudiants créé., @@ -2847,12 +2847,12 @@ Sub Type,Sous type, Sub-contracting,Sous-traitant, Subcontract,Sous-traiter, Subject,Sujet, -Submit,Soumettre, -Submit Proof,Soumettre une preuve, -Submit Salary Slip,Soumettre la Fiche de Paie, -Submit this Work Order for further processing.,Soumettre cet ordre de travail pour continuer son traitement., -Submit this to create the Employee record,Soumettre pour créer la fiche employé, -Submitting Salary Slips...,Soumission des bulletins de salaire ..., +Submit,Valider, +Submit Proof,Valider une preuve, +Submit Salary Slip,Valider la Fiche de Paie, +Submit this Work Order for further processing.,Valider cet ordre de travail pour continuer son traitement., +Submit this to create the Employee record,Valider pour créer la fiche employé, +Submitting Salary Slips...,Validation des bulletins de salaire ..., Subscription,Abonnement, Subscription Management,Gestion des abonnements, Subscriptions,Abonnements, @@ -2954,7 +2954,7 @@ The Term End Date cannot be earlier than the Term Start Date. Please correct the The Term End Date cannot be later than the Year End Date of the Academic Year to which the term is linked (Academic Year {}). Please correct the dates and try again.,La Date de Fin de Terme ne peut pas être postérieure à la Date de Fin de l'Année Académique à laquelle le terme est lié (Année Académique {}). Veuillez corriger les dates et essayer à nouveau., The Term Start Date cannot be earlier than the Year Start Date of the Academic Year to which the term is linked (Academic Year {}). Please correct the dates and try again.,La Date de Début de Terme ne peut pas être antérieure à la Date de Début de l'Année Académique à laquelle le terme est lié (Année Académique {}). Veuillez corriger les dates et essayer à nouveau., The Year End Date cannot be earlier than the Year Start Date. Please correct the dates and try again.,La Date de Fin d'Année ne peut pas être antérieure à la Date de Début d’Année. Veuillez corriger les dates et essayer à nouveau., -The amount of {0} set in this payment request is different from the calculated amount of all payment plans: {1}. Make sure this is correct before submitting the document.,Le montant {0} défini dans cette requête de paiement est différent du montant calculé de tous les plans de paiement: {1}.\nVeuillez vérifier que c'est correct avant de soumettre le document., +The amount of {0} set in this payment request is different from the calculated amount of all payment plans: {1}. Make sure this is correct before submitting the document.,Le montant {0} défini dans cette requête de paiement est différent du montant calculé de tous les plans de paiement: {1}.\nVeuillez vérifier que c'est correct avant de valider le document., The day(s) on which you are applying for leave are holidays. You need not apply for leave.,Le(s) jour(s) pour le(s)quel(s) vous demandez un congé sont des jour(s) férié(s). Vous n’avez pas besoin d’effectuer de demande., The field From Shareholder cannot be blank,Le champ 'De l'actionnaire' ne peut pas être vide, The field To Shareholder cannot be blank,Le champ 'A l'actionnaire' ne peut pas être vide, @@ -3011,7 +3011,7 @@ This is based on transactions against this Healthcare Practitioner.,Ce graphique This is based on transactions against this Patient. See timeline below for details,Ceci est basé sur les transactions de ce patient. Voir la chronologie ci-dessous pour plus de détails, This is based on transactions against this Sales Person. See timeline below for details,Ceci est basé sur les transactions contre ce vendeur. Voir la chronologie ci-dessous pour plus de détails, This is based on transactions against this Supplier. See timeline below for details,Basé sur les transactions avec ce fournisseur. Voir la chronologie ci-dessous pour plus de détails, -This will submit Salary Slips and create accrual Journal Entry. Do you want to proceed?,Cela permettra de soumettre des bulletins de salaire et de créer une écriture de journal d'accumulation. Voulez-vous poursuivre?, +This will submit Salary Slips and create accrual Journal Entry. Do you want to proceed?,Cela permettra de valider des bulletins de salaire et de créer une écriture de journal d'accumulation. Voulez-vous poursuivre?, This {0} conflicts with {1} for {2} {3},Ce {0} est en conflit avec {1} pour {2} {3}, Time Sheet for manufacturing.,Feuille de Temps pour la production., Time Tracking,Suivi du temps, @@ -3312,7 +3312,7 @@ Work Order {0} must be cancelled before cancelling this Sales Order,L'ordre de t Work Order {0} must be submitted,L'ordre de travail {0} doit être soumis, Work Orders Created: {0},Ordres de travail créés: {0}, Work Summary for {0},Résumé de travail de {0}, -Work-in-Progress Warehouse is required before Submit,L'entrepôt des Travaux en Cours est nécessaire avant de Soumettre, +Work-in-Progress Warehouse is required before Submit,L'entrepôt des Travaux en Cours est nécessaire avant de Valider, Workflow,Flux de Travail, Working,Travail en cours, Working Hours,Heures de travail, @@ -3331,7 +3331,7 @@ You can only have Plans with the same billing cycle in a Subscription,Vous ne po You can only redeem max {0} points in this order.,Vous pouvez uniquement échanger un maximum de {0} points dans cet commande., You can only renew if your membership expires within 30 days,Vous ne pouvez renouveler que si votre abonnement expire dans les 30 jours, You can only select a maximum of one option from the list of check boxes.,Vous pouvez sélectionner au maximum une option dans la liste des cases à cocher., -You can only submit Leave Encashment for a valid encashment amount,Vous pouvez uniquement soumettre un encaissement de congé pour un montant d'encaissement valide, +You can only submit Leave Encashment for a valid encashment amount,Vous pouvez uniquement valider un encaissement de congé pour un montant d'encaissement valide, You can't redeem Loyalty Points having more value than the Grand Total.,Vous ne pouvez pas échanger des points de fidélité ayant plus de valeur que le total général., You cannot credit and debit same account at the same time,Vous ne pouvez pas créditer et débiter le même compte simultanément, You cannot delete Fiscal Year {0}. Fiscal Year {0} is set as default in Global Settings,Vous ne pouvez pas supprimer l'exercice fiscal {0}. L'exercice fiscal {0} est défini par défaut dans les Paramètres Globaux, @@ -3684,8 +3684,8 @@ Create Quality Inspection for Item {0},Créer un contrôle qualité pour l'artic Creating Accounts...,Création de comptes ..., Creating bank entries...,Création d'entrées bancaires ..., Credit limit is already defined for the Company {0},La limite de crédit est déjà définie pour la société {0}., -Ctrl + Enter to submit,Ctrl + Entrée pour soumettre, -Ctrl+Enter to submit,Ctrl + Entrée pour soumettre, +Ctrl + Enter to submit,Ctrl + Entrée pour valider, +Ctrl+Enter to submit,Ctrl + Entrée pour valider, Currency,Devise, Current Status,Statut Actuel, Customer PO,Bon de commande client, @@ -3709,7 +3709,7 @@ Dimension Filter,Filtre de dimension, Disabled,Desactivé, Disbursement and Repayment,Décaissement et remboursement, Distance cannot be greater than 4000 kms,La distance ne peut pas dépasser 4000 km, -Do you want to submit the material request,Voulez-vous soumettre la demande de matériel, +Do you want to submit the material request,Voulez-vous valider la demande de matériel, Doctype,Doctype, Document {0} successfully uncleared,Document {0} non effacé avec succès, Download Template,Télécharger le Modèle, @@ -4309,7 +4309,7 @@ Requested,Demandé, Partially Paid,Partiellement payé, Invalid Account Currency,Devise de compte non valide, "Row {0}: The item {1}, quantity must be positive number","Ligne {0}: l'article {1}, la quantité doit être un nombre positif", -"Please set {0} for Batched Item {1}, which is used to set {2} on Submit.","Veuillez définir {0} pour l'article par lots {1}, qui est utilisé pour définir {2} sur Soumettre.", +"Please set {0} for Batched Item {1}, which is used to set {2} on Submit.","Veuillez définir {0} pour l'article par lots {1}, qui est utilisé pour définir {2} sur Valider.", Expiry Date Mandatory,Date d'expiration obligatoire, Variant Item,Élément de variante, BOM 1 {0} and BOM 2 {1} should not be same,La nomenclature 1 {0} et la nomenclature 2 {1} ne doivent pas être identiques, @@ -4589,7 +4589,7 @@ Bank Transaction Entries,Ecritures de transactions bancaires, New Transactions,Nouvelles transactions, Match Transaction to Invoices,Faire correspondre la transaction aux factures, Create New Payment/Journal Entry,Créer un nouveau paiement / écriture de journal, -Submit/Reconcile Payments,Soumettre / rapprocher les paiements, +Submit/Reconcile Payments,Valider / rapprocher les paiements, Matching Invoices,Factures correspondantes, Payment Invoice Items,Articles de la facture de paiement, Reconciled Transactions,Transactions rapprochées, @@ -6208,7 +6208,7 @@ Collect Fee for Patient Registration,Collecter les honoraires pour l'inscription Checking this will create new Patients with a Disabled status by default and will only be enabled after invoicing the Registration Fee.,Cochez cette case pour créer de nouveaux patients avec un statut Désactivé par défaut et ne seront activés qu'après facturation des frais d'inscription., Registration Fee,Frais d'Inscription, Automate Appointment Invoicing,Automatiser la facturation des rendez-vous, -Manage Appointment Invoice submit and cancel automatically for Patient Encounter,Gérer les factures de rendez-vous soumettre et annuler automatiquement pour la consultation des patients, +Manage Appointment Invoice submit and cancel automatically for Patient Encounter,Gérer les factures de rendez-vous valider et annuler automatiquement pour la consultation des patients, Enable Free Follow-ups,Activer les suivis gratuits, Number of Patient Encounters in Valid Days,Nombre de rencontres de patients en jours valides, The number of free follow ups (Patient Encounters in valid days) allowed,Le nombre de suivis gratuits (rencontres de patients en jours valides) autorisés, @@ -8679,7 +8679,7 @@ Book Deferred Entries Based On,Enregistrer les entrées différées en fonction Days,Journées, Months,Mois, Book Deferred Entries Via Journal Entry,Enregistrer les écritures différées via l'écriture au journal, -Submit Journal Entries,Soumettre les entrées de journal, +Submit Journal Entries,Valider les entrées de journal, If this is unchecked Journal Entries will be saved in a Draft state and will have to be submitted manually,"Si cette case n'est pas cochée, les entrées de journal seront enregistrées dans un état Brouillon et devront être soumises manuellement", Enable Distributed Cost Center,Activer le centre de coûts distribués, Distributed Cost Center,Centre de coûts distribués, @@ -9065,7 +9065,7 @@ Rented To Date,Loué à ce jour, Monthly Eligible Amount,Montant mensuel admissible, Total Eligible HRA Exemption,Exemption HRA totale éligible, Validating Employee Attendance...,Validation de la présence des employés ..., -Submitting Salary Slips and creating Journal Entry...,Soumettre des fiches de salaire et créer une écriture au journal ..., +Submitting Salary Slips and creating Journal Entry...,Validation des fiches de salaire et créer une écriture au journal ..., Calculate Payroll Working Days Based On,Calculer les jours ouvrables de paie en fonction de, Consider Unmarked Attendance As,Considérez la participation non marquée comme, Fraction of Daily Salary for Half Day,Fraction du salaire journalier pour une demi-journée, @@ -9166,8 +9166,8 @@ Enter customer's phone number,Entrez le numéro de téléphone du client, Customer contact updated successfully.,Contact client mis à jour avec succès., Item will be removed since no serial / batch no selected.,L'article sera supprimé car aucun numéro de série / lot sélectionné., Discount (%),Remise (%), -You cannot submit the order without payment.,Vous ne pouvez pas soumettre la commande sans paiement., -You cannot submit empty order.,Vous ne pouvez pas soumettre de commande vide., +You cannot submit the order without payment.,Vous ne pouvez pas valider la commande sans paiement., +You cannot submit empty order.,Vous ne pouvez pas valider de commande vide., To Be Paid,Être payé, Create POS Opening Entry,Créer une entrée d'ouverture de PDV, Please add Mode of payments and opening balance details.,Veuillez ajouter le mode de paiement et les détails du solde d'ouverture., @@ -9305,7 +9305,7 @@ Courses updated,Cours mis à jour, {0} {1} has been added to all the selected topics successfully.,{0} {1} a bien été ajouté à tous les sujets sélectionnés., Topics updated,Sujets mis à jour, Academic Term and Program,Terme académique et programme, -Please remove this item and try to submit again or update the posting time.,Veuillez supprimer cet élément et réessayer de le soumettre ou mettre à jour l'heure de publication., +Please remove this item and try to submit again or update the posting time.,Veuillez supprimer cet élément et réessayer de le valider ou mettre à jour l'heure de publication., Failed to Authenticate the API key.,Échec de l'authentification de la clé API., Invalid Credentials,Les informations d'identification invalides, URL can only be a string,L'URL ne peut être qu'une chaîne, @@ -9416,7 +9416,7 @@ Import Italian Supplier Invoice.,Importer la facture du fournisseur italien., "Valuation Rate for the Item {0}, is required to do accounting entries for {1} {2}.",Le taux de valorisation de l'article {0} est requis pour effectuer des écritures comptables pour {1} {2}., Here are the options to proceed:,Voici les options pour continuer:, "If the item is transacting as a Zero Valuation Rate item in this entry, please enable 'Allow Zero Valuation Rate' in the {0} Item table.","Si l'article est traité comme un article à taux de valorisation nul dans cette entrée, veuillez activer "Autoriser le taux de valorisation nul" dans le {0} tableau des articles.", -"If not, you can Cancel / Submit this entry ","Sinon, vous pouvez annuler / soumettre cette entrée", +"If not, you can Cancel / Submit this entry ","Sinon, vous pouvez annuler / valider cette entrée", performing either one below:,effectuer l'un ou l'autre ci-dessous:, Create an incoming stock transaction for the Item.,Créez une transaction de stock entrante pour l'article., Mention Valuation Rate in the Item master.,Mentionnez le taux de valorisation dans la fiche article., @@ -9573,7 +9573,7 @@ Accounting entries are frozen up to this date. Nobody can create or modify entri Role Allowed to Set Frozen Accounts and Edit Frozen Entries,Rôle autorisé à définir des comptes gelés et à modifier les entrées gelées, Address used to determine Tax Category in transactions,Adresse utilisée pour déterminer la catégorie de taxe dans les transactions, "The percentage you are allowed to bill more against the amount ordered. For example, if the order value is $100 for an item and tolerance is set as 10%, then you are allowed to bill up to $110 ","Le pourcentage que vous êtes autorisé à facturer davantage par rapport au montant commandé. Par exemple, si la valeur de la commande est de 100 USD pour un article et que la tolérance est définie sur 10%, vous êtes autorisé à facturer jusqu'à 110 USD.", -This role is allowed to submit transactions that exceed credit limits,Ce rôle est autorisé à soumettre des transactions qui dépassent les limites de crédit, +This role is allowed to submit transactions that exceed credit limits,Ce rôle est autorisé à valider des transactions qui dépassent les limites de crédit, "If ""Months"" is selected, a fixed amount will be booked as deferred revenue or expense for each month irrespective of the number of days in a month. It will be prorated if deferred revenue or expense is not booked for an entire month","Si «Mois» est sélectionné, un montant fixe sera comptabilisé en tant que revenus ou dépenses différés pour chaque mois, quel que soit le nombre de jours dans un mois. Il sera calculé au prorata si les revenus ou les dépenses différés ne sont pas comptabilisés pour un mois entier", "If this is unchecked, direct GL entries will be created to book deferred revenue or expense","Si cette case n'est pas cochée, des entrées GL directes seront créées pour enregistrer les revenus ou les dépenses différés", Show Inclusive Tax in Print,Afficher la taxe incluse en version imprimée, @@ -9744,7 +9744,7 @@ Print Receipt,Imprimer le reçu, Edit Receipt,Modifier le reçu, Focus on search input,Focus sur l'entrée de recherche, Focus on Item Group filter,Focus sur le filtre de groupe d'articles, -Checkout Order / Submit Order / New Order,Commander la commande / Soumettre la commande / Nouvelle commande, +Checkout Order / Submit Order / New Order,Commander la commande / Valider la commande / Nouvelle commande, Add Order Discount,Ajouter une remise de commande, Item Code: {0} is not available under warehouse {1}.,Code d'article: {0} n'est pas disponible dans l'entrepôt {1}., Serial numbers unavailable for Item {0} under warehouse {1}. Please try changing warehouse.,Numéros de série non disponibles pour l'article {0} sous l'entrepôt {1}. Veuillez essayer de changer d’entrepôt., @@ -9787,11 +9787,11 @@ because expense is booked against this account in Purchase Receipt {},car les d as no Purchase Receipt is created against Item {}. ,car aucun reçu d'achat n'est créé pour l'article {}., This is done to handle accounting for cases when Purchase Receipt is created after Purchase Invoice,Ceci est fait pour gérer la comptabilité des cas où le reçu d'achat est créé après la facture d'achat, Purchase Order Required for item {},Bon de commande requis pour l'article {}, -To submit the invoice without purchase order please set {} ,"Pour soumettre la facture sans bon de commande, veuillez définir {}", +To submit the invoice without purchase order please set {} ,"Pour valider la facture sans bon de commande, veuillez définir {}", as {} in {},un péché {}, Mandatory Purchase Order,Bon de commande obligatoire, Purchase Receipt Required for item {},Reçu d'achat requis pour l'article {}, -To submit the invoice without purchase receipt please set {} ,"Pour soumettre la facture sans reçu d'achat, veuillez définir {}", +To submit the invoice without purchase receipt please set {} ,"Pour valider la facture sans reçu d'achat, veuillez définir {}", Mandatory Purchase Receipt,Reçu d'achat obligatoire, POS Profile {} does not belongs to company {},Le profil PDV {} n'appartient pas à l'entreprise {}, User {} is disabled. Please select valid user/cashier,L'utilisateur {} est désactivé. Veuillez sélectionner un utilisateur / caissier valide, @@ -9865,9 +9865,10 @@ Control Historical Stock Transactions,Controle de l'historique des stransact No stock transactions can be created or modified before this date.,Aucune transaction ne peux être créée ou modifié avant cette date. Stock transactions that are older than the mentioned days cannot be modified.,Les transactions de stock plus ancienne que le nombre de jours ci-dessus ne peuvent être modifiées Role Allowed to Create/Edit Back-dated Transactions,Rôle autorisé à créer et modifier des transactions anti-datée -"If mentioned, the system will allow only the users with this Role to create or modify any stock transaction earlier than the latest stock transaction for a specific item and warehouse. If set as blank, it allows all users to create/edit back-dated transactions.","LEs utilisateur de ce role pourront creer et modifier des transactions dans le passé. Si vide tout les utilisateurs pourrons le faire" +"If mentioned, the system will allow only the users with this Role to create or modify any stock transaction earlier than the latest stock transaction for a specific item and warehouse. If set as blank, it allows all users to create/edit back-dated transactions.","Les utilisateur de ce role pourront creer et modifier des transactions dans le passé. Si vide tout les utilisateurs pourrons le faire" Auto Insert Item Price If Missing,Création du prix de l'article dans les listes de prix si abscent Update Existing Price List Rate,Mise a jour automatique du prix dans les listes de prix Show Barcode Field in Stock Transactions,Afficher le champ Code Barre dans les transactions de stock Convert Item Description to Clean HTML in Transactions,Convertir les descriptions d'articles en HTML valide lors des transactions Have Default Naming Series for Batch ID?,Nom de série par défaut pour les Lots ou Séries +"The percentage you are allowed to transfer more against the quantity ordered. For example, if you have ordered 100 units, and your Allowance is 10%, then you are allowed transfer 110 units","Le pourcentage de quantité que vous pourrez réceptionner en plus de la quantité commandée. Par exemple, vous avez commandé 100 unités, votre pourcentage de dépassement est de 10%, vous pourrez réceptionner 110 unités" From c9af4e8ce54df7ad25db6008a5c503b961d1b428 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 11 Apr 2022 16:55:22 +0530 Subject: [PATCH 32/41] chore: broken link --- .../doctype/shopify_settings/shopify_settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.js b/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.js index a926a7e52a5d..a5b676e2e39a 100644 --- a/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.js +++ b/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.js @@ -37,7 +37,7 @@ frappe.ui.form.on("Shopify Settings", "refresh", function(frm){ } - let app_link = "Ecommerce Integrations" + let app_link = "Ecommerce Integrations" frm.dashboard.add_comment(__("Shopify Integration will be removed from ERPNext in Version 14. Please install {0} app to continue using it.", [app_link]), "yellow", true); }) From f6c9f052d24500ec80e5c06545981d882c019ee5 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Wed, 6 Apr 2022 17:33:46 +0530 Subject: [PATCH 33/41] fix: Deferred Revenue/Expense Account validation (cherry picked from commit 9bf5f76ac835914bf5124227e564770f93680113) --- erpnext/accounts/deferred_revenue.py | 3 +-- .../doctype/journal_entry/journal_entry.json | 13 +++++++++-- .../process_deferred_accounting.py | 4 ++-- .../sales_invoice/test_sales_invoice.py | 2 +- erpnext/controllers/accounts_controller.py | 22 +++++++++++++++++++ 5 files changed, 37 insertions(+), 7 deletions(-) diff --git a/erpnext/accounts/deferred_revenue.py b/erpnext/accounts/deferred_revenue.py index 0611f880c5ec..a8776fa3448e 100644 --- a/erpnext/accounts/deferred_revenue.py +++ b/erpnext/accounts/deferred_revenue.py @@ -386,7 +386,6 @@ def _book_deferred_revenue_or_expense( doc, credit_account, debit_account, - against, amount, base_amount, end_date, @@ -570,7 +569,6 @@ def book_revenue_via_journal_entry( doc, credit_account, debit_account, - against, amount, base_amount, posting_date, @@ -591,6 +589,7 @@ def book_revenue_via_journal_entry( journal_entry.voucher_type = ( "Deferred Revenue" if doc.doctype == "Sales Invoice" else "Deferred Expense" ) + journal_entry.process_deferred_accounting = deferred_process debit_entry = { "account": credit_account, diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.json b/erpnext/accounts/doctype/journal_entry/journal_entry.json index 335fd350defd..4493c7225449 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.json +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.json @@ -3,7 +3,7 @@ "allow_auto_repeat": 1, "allow_import": 1, "autoname": "naming_series:", - "creation": "2013-03-25 10:53:52", + "creation": "2022-01-25 10:29:58.717206", "doctype": "DocType", "document_type": "Document", "engine": "InnoDB", @@ -13,6 +13,7 @@ "voucher_type", "naming_series", "finance_book", + "process_deferred_accounting", "reversal_of", "tax_withholding_category", "column_break1", @@ -524,13 +525,20 @@ "label": "Reversal Of", "options": "Journal Entry", "read_only": 1 + }, + { + "fieldname": "process_deferred_accounting", + "fieldtype": "Link", + "label": "Process Deferred Accounting", + "options": "Process Deferred Accounting", + "read_only": 1 } ], "icon": "fa fa-file-text", "idx": 176, "is_submittable": 1, "links": [], - "modified": "2022-01-04 13:39:36.485954", + "modified": "2022-04-06 17:18:46.865259", "modified_by": "Administrator", "module": "Accounts", "name": "Journal Entry", @@ -578,6 +586,7 @@ "search_fields": "voucher_type,posting_date, due_date, cheque_no", "sort_field": "modified", "sort_order": "DESC", + "states": [], "title_field": "title", "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.py b/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.py index 08a7f4110f61..8ec726b36cd9 100644 --- a/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.py +++ b/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.py @@ -11,7 +11,7 @@ convert_deferred_expense_to_expense, convert_deferred_revenue_to_income, ) -from erpnext.accounts.general_ledger import make_reverse_gl_entries +from erpnext.accounts.general_ledger import make_gl_entries class ProcessDeferredAccounting(Document): @@ -34,4 +34,4 @@ def on_cancel(self): filters={"against_voucher_type": self.doctype, "against_voucher": self.name}, ) - make_reverse_gl_entries(gl_entries=gl_entries) + make_gl_entries(gl_entries=gl_entries, cancel=1) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 6ddc3e03ecd4..6e872d422f34 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -3017,7 +3017,7 @@ def test_multi_currency_deferred_revenue_via_journal_entry(self): acc_settings = frappe.get_single("Accounts Settings") acc_settings.book_deferred_entries_via_journal_entry = 0 - acc_settings.submit_journal_entriessubmit_journal_entries = 0 + acc_settings.submit_journal_entries = 0 acc_settings.save() frappe.db.set_value("Accounts Settings", None, "acc_frozen_upto", None) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 0dbff48f02a5..36887f444c8a 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -181,6 +181,7 @@ def validate(self): else: self.validate_deferred_start_and_end_date() + self.validate_deferred_income_expense_account() self.set_inter_company_account() if self.doctype == "Purchase Invoice": @@ -209,6 +210,27 @@ def on_trash(self): (self.doctype, self.name), ) + def validate_deferred_income_expense_account(self): + field_map = { + "Sales Invoice": "deferred_revenue_account", + "Purchase Invoice": "deferred_expense_account", + } + + for item in self.get("items"): + if item.get("enable_deferred_revenue") or item.get("enable_deferred_expense"): + if not item.get(field_map.get(self.doctype)): + default_deferred_account = frappe.db.get_value( + "Company", self.company, "default_" + field_map.get(self.doctype) + ) + if not default_deferred_account: + frappe.throw( + _( + "Row #{0}: Please update deferred revenue/expense account in item row or default account in company master" + ).format(item.idx) + ) + else: + item.set(field_map.get(self.doctype), default_deferred_account) + def validate_deferred_start_and_end_date(self): for d in self.items: if d.get("enable_deferred_revenue") or d.get("enable_deferred_expense"): From 4296fc36cc0df41e487734bb5cbb669eb9fac8d6 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 11 Apr 2022 15:29:20 +0530 Subject: [PATCH 34/41] test: Add test (cherry picked from commit 553178bfe72e7031a7fe775fc5d2136c9a5aefcf) --- .../accounts/doctype/sales_invoice/test_sales_invoice.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 6e872d422f34..fb2bb08c9050 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -2245,6 +2245,14 @@ def test_deferred_revenue(self): check_gl_entries(self, si.name, expected_gle, "2019-01-30") + def test_deferred_revenue_missing_account(self): + si = create_sales_invoice(posting_date="2019-01-10", do_not_submit=True) + si.items[0].enable_deferred_revenue = 1 + si.items[0].service_start_date = "2019-01-10" + si.items[0].service_end_date = "2019-03-15" + + self.assertRaises(frappe.ValidationError, si.save) + def test_fixed_deferred_revenue(self): deferred_account = create_account( account_name="Deferred Revenue", From d079d8771b092e30a6a09654e65246fbaf8487b3 Mon Sep 17 00:00:00 2001 From: marination Date: Mon, 11 Apr 2022 14:10:57 +0530 Subject: [PATCH 35/41] fix: Handle multiple item transfer in separate SEs against WO - Check for pending qty in child items to show/hide "Start" button - If no qty needed to transfer (FG qty is fulfilled), but RM qty pending: map pending in SE with For Quantity = 0 (cherry picked from commit dfff4beaf47da9a044f0a293a7fc50f8cda3c51e) --- erpnext/manufacturing/doctype/work_order/work_order.js | 6 ++++-- erpnext/stock/doctype/stock_entry/stock_entry.py | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js index 3f2f39e73afc..602319eda7a8 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.js +++ b/erpnext/manufacturing/doctype/work_order/work_order.js @@ -540,8 +540,10 @@ erpnext.work_order = { || frm.doc.transfer_material_against == 'Job Card') ? 0 : 1; if (show_start_btn) { - if ((flt(doc.material_transferred_for_manufacturing) < flt(doc.qty)) - && frm.doc.status != 'Stopped') { + let pending_to_transfer = frm.doc.required_items.some( + item => flt(item.transferred_qty) < flt(item.required_qty) + ) + if (pending_to_transfer && frm.doc.status != 'Stopped') { frm.has_start_btn = true; frm.add_custom_button(__('Create Pick List'), function() { erpnext.work_order.create_pick_list(frm); diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index cc7317a2cd8f..e3af675178a7 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -1802,7 +1802,9 @@ def get_pending_raw_materials(self, backflush_based_on=None): or (desire_to_transfer > 0 and backflush_based_on == "Material Transferred for Manufacture") or allow_overproduction ): - item_dict[item]["qty"] = desire_to_transfer + # "No need for transfer but qty still pending to transfer" case can occur + # when transferring multiple RM in different Stock Entries + item_dict[item]["qty"] = desire_to_transfer if (desire_to_transfer > 0) else pending_to_issue elif pending_to_issue > 0: item_dict[item]["qty"] = pending_to_issue else: From c674180f1a1e66a1f35a63ebb4351f69a8127469 Mon Sep 17 00:00:00 2001 From: marination Date: Mon, 11 Apr 2022 15:32:36 +0530 Subject: [PATCH 36/41] style: Missing Semicolon (cherry picked from commit be2e5ce966bb206777c35398ae6fb99f1dcd7e79) --- erpnext/manufacturing/doctype/work_order/work_order.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js index 602319eda7a8..9b0c8382c535 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.js +++ b/erpnext/manufacturing/doctype/work_order/work_order.js @@ -542,7 +542,7 @@ erpnext.work_order = { if (show_start_btn) { let pending_to_transfer = frm.doc.required_items.some( item => flt(item.transferred_qty) < flt(item.required_qty) - ) + ); if (pending_to_transfer && frm.doc.status != 'Stopped') { frm.has_start_btn = true; frm.add_custom_button(__('Create Pick List'), function() { From e322e7654a32ce0f52039393701878f5aec8dd12 Mon Sep 17 00:00:00 2001 From: marination Date: Mon, 11 Apr 2022 16:44:55 +0530 Subject: [PATCH 37/41] test: Multiple RM transfer in separate Stock Entries - Added test and acceptance of 0 as For Quantity in test helper (cherry picked from commit 5aa60bb65142a9dbd2fbbec5c26150cd559275e6) --- .../doctype/work_order/test_work_order.py | 50 +++++++++++++++++++ .../doctype/work_order/work_order.py | 6 ++- 2 files changed, 55 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 1e9b3ba11371..7131c335c8af 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -1100,6 +1100,56 @@ def test_manufacture_entry_mapped_idx_with_exploded_bom(self): for index, row in enumerate(ste_manu.get("items"), start=1): self.assertEqual(index, row.idx) + @change_settings( + "Manufacturing Settings", + {"backflush_raw_materials_based_on": "Material Transferred for Manufacture"}, + ) + def test_work_order_multiple_material_transfer(self): + """ + Test transferring multiple RMs in separate Stock Entries. + """ + work_order = make_wo_order_test_record(planned_start_date=now(), qty=1) + test_stock_entry.make_stock_entry( # stock up RM + item_code="_Test Item", + target="_Test Warehouse - _TC", + qty=1, + basic_rate=5000.0, + ) + test_stock_entry.make_stock_entry( # stock up RM + item_code="_Test Item Home Desktop 100", + target="_Test Warehouse - _TC", + qty=2, + basic_rate=1000.0, + ) + + transfer_entry = frappe.get_doc( + make_stock_entry(work_order.name, "Material Transfer for Manufacture", 1) + ) + del transfer_entry.get("items")[0] # transfer only one RM + transfer_entry.submit() + + # WO's "Material Transferred for Mfg" shows all is transferred, one RM is pending + work_order.reload() + self.assertEqual(work_order.material_transferred_for_manufacturing, 1) + self.assertEqual(work_order.required_items[0].transferred_qty, 0) + self.assertEqual(work_order.required_items[1].transferred_qty, 2) + + final_transfer_entry = frappe.get_doc( # transfer last RM with For Quantity = 0 + make_stock_entry(work_order.name, "Material Transfer for Manufacture", 0) + ) + final_transfer_entry.save() + + self.assertEqual(final_transfer_entry.fg_completed_qty, 0.0) + self.assertEqual(final_transfer_entry.items[0].qty, 1) + + final_transfer_entry.submit() + work_order.reload() + + # WO's "Material Transferred for Mfg" shows all is transferred, no RM is pending + self.assertEqual(work_order.material_transferred_for_manufacturing, 1) + self.assertEqual(work_order.required_items[0].transferred_qty, 1) + self.assertEqual(work_order.required_items[1].transferred_qty, 2) + def update_job_card(job_card, jc_qty=None): employee = frappe.db.get_value("Employee", {"status": "Active"}, "name") diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index 7ef39c26aa09..dc553c15ad5f 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -1174,7 +1174,11 @@ def make_stock_entry(work_order_id, purpose, qty=None): stock_entry.from_bom = 1 stock_entry.bom_no = work_order.bom_no stock_entry.use_multi_level_bom = work_order.use_multi_level_bom - stock_entry.fg_completed_qty = qty or (flt(work_order.qty) - flt(work_order.produced_qty)) + # accept 0 qty as well + stock_entry.fg_completed_qty = ( + qty if qty is not None else (flt(work_order.qty) - flt(work_order.produced_qty)) + ) + if work_order.bom_no: stock_entry.inspection_required = frappe.db.get_value( "BOM", work_order.bom_no, "inspection_required" From 9efc0d1043ffcf20e0254800f1f40a158de41df4 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 8 Apr 2022 17:14:10 +0530 Subject: [PATCH 38/41] fix: Download JSON for GSTR-1 report (cherry picked from commit b532ade3839d502a0aab5a67db77654a2077066a) --- erpnext/regional/report/gstr_1/gstr_1.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/regional/report/gstr_1/gstr_1.js b/erpnext/regional/report/gstr_1/gstr_1.js index 9999a6d167bf..943bd2c3d20a 100644 --- a/erpnext/regional/report/gstr_1/gstr_1.js +++ b/erpnext/regional/report/gstr_1/gstr_1.js @@ -78,8 +78,9 @@ frappe.query_reports["GSTR-1"] = { } }); - report.page.add_inner_button(__("Download as JSON"), function () { + let filters = report.get_values(); + frappe.call({ method: 'erpnext.regional.report.gstr_1.gstr_1.get_json', args: { From 21066a48b6e065795426ab314a67b75ce3104299 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 12 Apr 2022 11:16:59 +0530 Subject: [PATCH 39/41] fix: ignore item-less maintenance visit for sr no (#30684) (#30685) (cherry picked from commit 60fb71bd2a6bfb0a223b233759c8aa8cbda7a1bb) Co-authored-by: Ankush Menat --- .../maintenance/doctype/maintenance_visit/maintenance_visit.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js index f4a0d4d399c4..939df5c07c55 100644 --- a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js +++ b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js @@ -12,6 +12,9 @@ frappe.ui.form.on('Maintenance Visit', { // filters for serial no based on item code if (frm.doc.maintenance_type === "Scheduled") { let item_code = frm.doc.purposes[0].item_code; + if (!item_code) { + return; + } frappe.call({ method: "erpnext.maintenance.doctype.maintenance_schedule.maintenance_schedule.get_serial_nos_from_schedule", args: { From 2ab431ad36fde53784a4041beb96fb1a6f6e4b3d Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Thu, 7 Apr 2022 13:09:05 +0530 Subject: [PATCH 40/41] feat(india): e-invoicing for intra-state union territory transactions (cherry picked from commit 45fca6bed78ef162cf2969faf75086de94392180) --- .../doctype/gst_account/gst_account.json | 10 +++++++++- erpnext/regional/india/e_invoice/utils.py | 16 ++++++++++++---- erpnext/regional/india/utils.py | 2 +- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/gst_account/gst_account.json b/erpnext/accounts/doctype/gst_account/gst_account.json index b6ec8844e18f..be5124c2d4d9 100644 --- a/erpnext/accounts/doctype/gst_account/gst_account.json +++ b/erpnext/accounts/doctype/gst_account/gst_account.json @@ -10,6 +10,7 @@ "sgst_account", "igst_account", "cess_account", + "utgst_account", "is_reverse_charge_account" ], "fields": [ @@ -64,12 +65,18 @@ "fieldtype": "Check", "in_list_view": 1, "label": "Is Reverse Charge Account" + }, + { + "fieldname": "utgst_account", + "fieldtype": "Link", + "label": "UTGST Account", + "options": "Account" } ], "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2021-04-09 12:30:25.889993", + "modified": "2022-04-07 12:59:14.039768", "modified_by": "Administrator", "module": "Accounts", "name": "GST Account", @@ -78,5 +85,6 @@ "quick_entry": 1, "sort_field": "modified", "sort_order": "DESC", + "states": [], "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/regional/india/e_invoice/utils.py b/erpnext/regional/india/e_invoice/utils.py index 95cbcd51a9f1..2b5d17710ebb 100644 --- a/erpnext/regional/india/e_invoice/utils.py +++ b/erpnext/regional/india/e_invoice/utils.py @@ -315,10 +315,14 @@ def update_item_taxes(invoice, item): item.cess_rate += item_tax_rate item.cess_amount += abs(item_tax_amount_after_discount) - for tax_type in ["igst", "cgst", "sgst"]: + for tax_type in ["igst", "cgst", "sgst", "utgst"]: 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) + if tax_type == "utgst": + # utgst taxes are reported same as sgst tax + item["sgst_amount"] += abs(item_tax_amount) + else: + item[f"{tax_type}_amount"] += abs(item_tax_amount) else: # TODO: other charges per item pass @@ -360,11 +364,15 @@ def update_invoice_taxes(invoice, invoice_value_details): # 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"]: + for tax_type in ["igst", "cgst", "sgst", "utgst"]: if t.account_head in gst_accounts[f"{tax_type}_account"]: + if tax_type == "utgst": + invoice_value_details["total_sgst_amt"] += abs(tax_amount) + else: + invoice_value_details[f"total_{tax_type}_amt"] += abs(tax_amount) - 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) diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py index 6bbaa358cde4..45104b09681a 100644 --- a/erpnext/regional/india/utils.py +++ b/erpnext/regional/india/utils.py @@ -825,7 +825,7 @@ def get_gst_accounts( gst_settings_accounts = frappe.get_all( "GST Account", filters=filters, - fields=["cgst_account", "sgst_account", "igst_account", "cess_account"], + fields=["cgst_account", "sgst_account", "igst_account", "cess_account", "utgst_account"], ) if not gst_settings_accounts and not frappe.flags.in_test and not frappe.flags.in_migrate: From e650d99cdd4549513dda4fe32d51a784f5d52f1c Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 12 Apr 2022 12:24:47 +0530 Subject: [PATCH 41/41] feat: Ignore permlevel for specific fields (cherry picked from commit 993c6c0de9c1e3cfc3c4673e3bc16542204022be) --- erpnext/controllers/buying_controller.py | 3 +++ erpnext/controllers/selling_controller.py | 3 +++ 2 files changed, 6 insertions(+) diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 931b4f82d976..8e644814a549 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -22,6 +22,9 @@ class QtyMismatchError(ValidationError): class BuyingController(StockController, Subcontracting): + def __setup__(self): + self.flags.ignore_permlevel_for_fields = ["buying_price_list", "price_list_currency"] + def get_feed(self): if self.get("supplier_name"): return _("From {0} | {1} {2}").format(self.supplier_name, self.currency, self.grand_total) diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index 77e0be3663aa..e1c59cbf6729 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -16,6 +16,9 @@ class SellingController(StockController): + def __setup__(self): + self.flags.ignore_permlevel_for_fields = ["selling_price_list", "price_list_currency"] + def get_feed(self): return _("To {0} | {1} {2}").format(self.customer_name, self.currency, self.grand_total)