From bd464197c41329ddf3cff50cd3eb876df9c6c382 Mon Sep 17 00:00:00 2001 From: mahsem <137205921+mahsem@users.noreply.github.com> Date: Mon, 8 Jan 2024 18:45:39 +0100 Subject: [PATCH 01/22] Update purchase_taxes_and_charges.json label Rate to Tax Rate Change Rate label to existing Tax Rate label so it can be correctly translated in other languages --- .../purchase_taxes_and_charges.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json index 347cae05b7..249e7518f0 100644 --- a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json +++ b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json @@ -126,7 +126,7 @@ "fieldname": "rate", "fieldtype": "Float", "in_list_view": 1, - "label": "Rate", + "label": "Tax Rate", "oldfieldname": "rate", "oldfieldtype": "Currency" }, @@ -239,4 +239,4 @@ "sort_field": "modified", "sort_order": "DESC", "track_changes": 1 -} \ No newline at end of file +} From 6b5fa2c673accab13a174a2945b333bd1b991cdb Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 12 Jan 2024 12:43:54 +0530 Subject: [PATCH 02/22] refactor: prevent foreign currency subscription for a party --- .../doctype/subscription/subscription.py | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py index 72e574c299..ce56a7b0a2 100644 --- a/erpnext/accounts/doctype/subscription/subscription.py +++ b/erpnext/accounts/doctype/subscription/subscription.py @@ -16,6 +16,7 @@ from frappe.utils.data import ( date_diff, flt, get_last_day, + get_link_to_form, getdate, nowdate, ) @@ -317,6 +318,37 @@ class Subscription(Document): if self.is_new(): self.set_subscription_status() + self.validate_party_billing_currency() + + def validate_party_billing_currency(self): + """ + Subscription should be of the same currency as the Party's default billing currency or company default. + """ + if self.party: + party_billing_currency = frappe.get_cached_value( + self.party_type, self.party, "default_currency" + ) or frappe.get_cached_value("Company", self.company, "default_currency") + + plans = [x.plan for x in self.plans] + subscription_plan_currencies = frappe.db.get_all( + "Subscription Plan", filters={"name": ("in", plans)}, fields=["name", "currency"] + ) + unsupported_plans = [] + for x in subscription_plan_currencies: + if x.currency != party_billing_currency: + unsupported_plans.append("{0}".format(get_link_to_form("Subscription Plan", x.name))) + + if unsupported_plans: + unsupported_plans = [ + _( + "Below Subscription Plans are of different currency to the party default billing currency/Company currency: {0}" + ).format(frappe.bold(party_billing_currency)) + ] + unsupported_plans + + frappe.throw( + unsupported_plans, frappe.ValidationError, "Unsupported Subscription Plans", as_list=True + ) + def validate_trial_period(self) -> None: """ Runs sanity checks on trial period dates for the `Subscription` From cdd0acc672e471d94693c04079ab78ba48b82a30 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 12 Jan 2024 16:33:41 +0530 Subject: [PATCH 03/22] refactor: disallow bank transactions on different currencies --- .../doctype/bank_transaction/bank_transaction.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py index 1d6cb8e2c0..a049d4084a 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py @@ -48,6 +48,22 @@ class BankTransaction(Document): def validate(self): self.validate_duplicate_references() + self.validate_currency() + + def validate_currency(self): + """ + Bank Transaction should be on the same currency as the Bank Account. + """ + if self.currency and self.bank_account: + account = frappe.get_cached_value("Bank Account", self.bank_account, "account") + account_currency = frappe.get_cached_value("Account", account, "account_currency") + + if self.currency != account_currency: + frappe.throw( + _("Currency {0} cannot be different from Bank Account({1}) Currency: {2}").format( + frappe.bold(self.currency), frappe.bold(self.bank_account), frappe.bold(account_currency) + ) + ) def set_status(self): if self.docstatus == 2: From 566876ae7a9ac4ce70f0c72dd69c933ed022bf46 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Sun, 14 Jan 2024 10:15:50 +0530 Subject: [PATCH 04/22] fix: modified date was not set --- .../purchase_taxes_and_charges/purchase_taxes_and_charges.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json index 249e7518f0..f10e9842a4 100644 --- a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json +++ b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json @@ -230,7 +230,7 @@ "idx": 1, "istable": 1, "links": [], - "modified": "2021-08-05 20:04:36.618240", + "modified": "2021-08-06 20:04:36.618240", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Taxes and Charges", From 6827edb2c51ffe44f5af32fc63e065481bb85662 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Sun, 14 Jan 2024 10:45:43 +0530 Subject: [PATCH 05/22] fix: modified date --- .../purchase_taxes_and_charges/purchase_taxes_and_charges.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json index f10e9842a4..adab54b375 100644 --- a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json +++ b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json @@ -230,7 +230,7 @@ "idx": 1, "istable": 1, "links": [], - "modified": "2021-08-06 20:04:36.618240", + "modified": "2024-01-14 10:04:36.618240", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Taxes and Charges", From 641c3de0caf3dd542a353edd78c8c18f686b8cae Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Sun, 14 Jan 2024 15:52:37 +0530 Subject: [PATCH 06/22] fix: incorrect sql error if account name has '%' --- .../report/customer_ledger_summary/customer_ledger_summary.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py index a2c0f86f6c..f4a01759dd 100644 --- a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py +++ b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py @@ -376,6 +376,10 @@ class PartyLedgerSummaryReport(object): if not income_or_expense_accounts: # prevent empty 'in' condition income_or_expense_accounts.append("") + else: + # escape '%' in account name + # ignoring frappe.db.escape as it replaces single quotes with double quotes + income_or_expense_accounts = [x.replace("%", "%%") for x in income_or_expense_accounts] accounts_query = ( qb.from_(gl) From 19975dcb7bb688f5b93b8e7757d6a906cb68a2bc Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Sun, 14 Jan 2024 17:59:43 +0530 Subject: [PATCH 07/22] refactor: making currency mandatory for subcscription plans --- .../doctype/subscription_plan/subscription_plan.json | 7 +++++-- .../doctype/subscription_plan/subscription_plan.py | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/subscription_plan/subscription_plan.json b/erpnext/accounts/doctype/subscription_plan/subscription_plan.json index 563df79eec..bc1f579cf0 100644 --- a/erpnext/accounts/doctype/subscription_plan/subscription_plan.json +++ b/erpnext/accounts/doctype/subscription_plan/subscription_plan.json @@ -41,7 +41,8 @@ "fieldname": "currency", "fieldtype": "Link", "label": "Currency", - "options": "Currency" + "options": "Currency", + "reqd": 1 }, { "fieldname": "column_break_3", @@ -148,10 +149,11 @@ } ], "links": [], - "modified": "2021-12-10 15:24:15.794477", + "modified": "2024-01-14 17:59:34.687977", "modified_by": "Administrator", "module": "Accounts", "name": "Subscription Plan", + "naming_rule": "By fieldname", "owner": "Administrator", "permissions": [ { @@ -193,5 +195,6 @@ ], "sort_field": "modified", "sort_order": "DESC", + "states": [], "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/accounts/doctype/subscription_plan/subscription_plan.py b/erpnext/accounts/doctype/subscription_plan/subscription_plan.py index 118d254780..cdfa3e56d9 100644 --- a/erpnext/accounts/doctype/subscription_plan/subscription_plan.py +++ b/erpnext/accounts/doctype/subscription_plan/subscription_plan.py @@ -24,7 +24,7 @@ class SubscriptionPlan(Document): billing_interval_count: DF.Int cost: DF.Currency cost_center: DF.Link | None - currency: DF.Link | None + currency: DF.Link item: DF.Link payment_gateway: DF.Link | None plan_name: DF.Data From b4354cbc8dfb22fafaed2cd39b92c438e5f199db Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Sun, 14 Jan 2024 18:04:15 +0530 Subject: [PATCH 08/22] refactor: better error message --- erpnext/accounts/doctype/bank_transaction/bank_transaction.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py index a049d4084a..8f655a6987 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py @@ -60,7 +60,9 @@ class BankTransaction(Document): if self.currency != account_currency: frappe.throw( - _("Currency {0} cannot be different from Bank Account({1}) Currency: {2}").format( + _( + "Transaction currency: {0} cannot be different from Bank Account({1}) currency: {2}" + ).format( frappe.bold(self.currency), frappe.bold(self.bank_account), frappe.bold(account_currency) ) ) From a27a4db3de6d6df7dd340d4212c114b7f4c0762c Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Sun, 14 Jan 2024 18:09:19 +0530 Subject: [PATCH 09/22] refactor(test): supply default currency to Bank Transaction --- .../bank_reconciliation_tool/test_bank_reconciliation_tool.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/accounts/doctype/bank_reconciliation_tool/test_bank_reconciliation_tool.py b/erpnext/accounts/doctype/bank_reconciliation_tool/test_bank_reconciliation_tool.py index 5a6bb6976f..adf5925443 100644 --- a/erpnext/accounts/doctype/bank_reconciliation_tool/test_bank_reconciliation_tool.py +++ b/erpnext/accounts/doctype/bank_reconciliation_tool/test_bank_reconciliation_tool.py @@ -76,6 +76,7 @@ class TestBankReconciliationTool(AccountsTestMixin, FrappeTestCase): "deposit": 100, "bank_account": self.bank_account, "reference_number": "123", + "currency": "INR", } ) .save() From 114f2b432628b55201dfbfcac8c4e6a65c577cc7 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Sun, 14 Jan 2024 23:23:55 +0530 Subject: [PATCH 10/22] fix: batches not coming correctly in the batch selector --- erpnext/controllers/queries.py | 39 +++++++++++++++------------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index 2650753275..8ebdcc5875 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -421,23 +421,14 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters): meta = frappe.get_meta(doctype, cached=True) searchfields = meta.get_search_fields() - query = get_batches_from_stock_ledger_entries(searchfields, txt, filters) - bundle_query = get_batches_from_serial_and_batch_bundle(searchfields, txt, filters) - - data = ( - frappe.qb.from_((query) + (bundle_query)) - .select("batch_no", "qty", "manufacturing_date", "expiry_date") - .offset(start) - .limit(page_len) + batches = get_batches_from_stock_ledger_entries(searchfields, txt, filters, start, page_len) + batches.extend( + get_batches_from_serial_and_batch_bundle(searchfields, txt, filters, start, page_len) ) - for field in searchfields: - data = data.select(field) + filtered_batches = get_filterd_batches(batches) - data = data.run() - data = get_filterd_batches(data) - - return data + return filtered_batches def get_filterd_batches(data): @@ -457,7 +448,7 @@ def get_filterd_batches(data): return filterd_batch -def get_batches_from_stock_ledger_entries(searchfields, txt, filters): +def get_batches_from_stock_ledger_entries(searchfields, txt, filters, start=0, page_len=100): stock_ledger_entry = frappe.qb.DocType("Stock Ledger Entry") batch_table = frappe.qb.DocType("Batch") @@ -479,6 +470,8 @@ def get_batches_from_stock_ledger_entries(searchfields, txt, filters): & (stock_ledger_entry.batch_no.isnotnull()) ) .groupby(stock_ledger_entry.batch_no, stock_ledger_entry.warehouse) + .offset(start) + .limit(page_len) ) query = query.select( @@ -493,16 +486,16 @@ def get_batches_from_stock_ledger_entries(searchfields, txt, filters): query = query.select(batch_table[field]) if txt: - txt_condition = batch_table.name.like(txt) + txt_condition = batch_table.name.like("%{0}%".format(txt)) for field in searchfields + ["name"]: - txt_condition |= batch_table[field].like(txt) + txt_condition |= batch_table[field].like("%{0}%".format(txt)) query = query.where(txt_condition) - return query + return query.run(as_list=1) or [] -def get_batches_from_serial_and_batch_bundle(searchfields, txt, filters): +def get_batches_from_serial_and_batch_bundle(searchfields, txt, filters, start=0, page_len=100): bundle = frappe.qb.DocType("Serial and Batch Entry") stock_ledger_entry = frappe.qb.DocType("Stock Ledger Entry") batch_table = frappe.qb.DocType("Batch") @@ -527,6 +520,8 @@ def get_batches_from_serial_and_batch_bundle(searchfields, txt, filters): & (stock_ledger_entry.serial_and_batch_bundle.isnotnull()) ) .groupby(bundle.batch_no, bundle.warehouse) + .offset(start) + .limit(page_len) ) bundle_query = bundle_query.select( @@ -541,13 +536,13 @@ def get_batches_from_serial_and_batch_bundle(searchfields, txt, filters): bundle_query = bundle_query.select(batch_table[field]) if txt: - txt_condition = batch_table.name.like(txt) + txt_condition = batch_table.name.like("%{0}%".format(txt)) for field in searchfields + ["name"]: - txt_condition |= batch_table[field].like(txt) + txt_condition |= batch_table[field].like("%{0}%".format(txt)) bundle_query = bundle_query.where(txt_condition) - return bundle_query + return bundle_query.run(as_list=1) @frappe.whitelist() From aef87cced7da0524c7ca2dadfcd111aaf13ef0c2 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Mon, 15 Jan 2024 11:54:26 +0530 Subject: [PATCH 11/22] ci: bump node in release workflow --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 37bb37e1d2..93b1732368 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,7 +16,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v2 with: - node-version: 18 + node-version: 20 - name: Setup dependencies run: | npm install @semantic-release/git @semantic-release/exec --no-save From 2e03af7ac470a770e42fd0367c87f9b27eb369ff Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 15 Jan 2024 14:35:28 +0530 Subject: [PATCH 12/22] perf: use iterator for stock ageing report (#39346) --- .../stock/report/stock_ageing/stock_ageing.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py index d0929a082c..f055c6c628 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.py +++ b/erpnext/stock/report/stock_ageing/stock_ageing.py @@ -3,7 +3,7 @@ from operator import itemgetter -from typing import Dict, List, Tuple, Union +from typing import Dict, Iterator, List, Tuple, Union import frappe from frappe import _ @@ -231,10 +231,12 @@ class FIFOSlots: consumed/updated and maintained via FIFO. ** } """ - if self.sle is None: - self.sle = self.__get_stock_ledger_entries() - for d in self.sle: + stock_ledger_entries = self.sle + if stock_ledger_entries is None: + stock_ledger_entries = self.__get_stock_ledger_entries() + + for d in stock_ledger_entries: key, fifo_queue, transferred_item_key = self.__init_key_stores(d) if d.voucher_type == "Stock Reconciliation": @@ -251,6 +253,9 @@ class FIFOSlots: self.__update_balances(d, key) + # Note that stock_ledger_entries is an iterator, you can not reuse it like a list + del stock_ledger_entries + if not self.filters.get("show_warehouse_wise_stock"): # (Item 1, WH 1), (Item 1, WH 2) => (Item 1) self.item_details = self.__aggregate_details_by_item(self.item_details) @@ -381,7 +386,7 @@ class FIFOSlots: return item_aggregated_data - def __get_stock_ledger_entries(self) -> List[Dict]: + def __get_stock_ledger_entries(self) -> Iterator[Dict]: sle = frappe.qb.DocType("Stock Ledger Entry") item = self.__get_item_query() # used as derived table in sle query @@ -418,7 +423,7 @@ class FIFOSlots: sle_query = sle_query.orderby(sle.posting_date, sle.posting_time, sle.creation, sle.actual_qty) - return sle_query.run(as_dict=True) + return sle_query.run(as_dict=True, as_iterator=True) def __get_item_query(self) -> str: item_table = frappe.qb.DocType("Item") From 1387b0ba7f9edf71f838a270e5c8aa40b30b3a70 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Sun, 14 Jan 2024 18:00:45 +0530 Subject: [PATCH 13/22] refactor(test): supply default currency for subscription plans --- .../doctype/subscription/test_subscription.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/doctype/subscription/test_subscription.py b/erpnext/accounts/doctype/subscription/test_subscription.py index 785fd04b82..37326fd035 100644 --- a/erpnext/accounts/doctype/subscription/test_subscription.py +++ b/erpnext/accounts/doctype/subscription/test_subscription.py @@ -463,7 +463,7 @@ class TestSubscription(FrappeTestCase): subscription = create_subscription( start_date="2018-01-01", generate_invoice_at="Beginning of the current subscription period", - plans=[{"plan": "_Test Plan Multicurrency", "qty": 1}], + plans=[{"plan": "_Test Plan Multicurrency", "qty": 1, "currency": "USD"}], party="_Test Subscription Customer", ) @@ -528,13 +528,21 @@ class TestSubscription(FrappeTestCase): def make_plans(): - create_plan(plan_name="_Test Plan Name", cost=900) - create_plan(plan_name="_Test Plan Name 2", cost=1999) + create_plan(plan_name="_Test Plan Name", cost=900, currency="INR") + create_plan(plan_name="_Test Plan Name 2", cost=1999, currency="INR") create_plan( - plan_name="_Test Plan Name 3", cost=1999, billing_interval="Day", billing_interval_count=14 + plan_name="_Test Plan Name 3", + cost=1999, + billing_interval="Day", + billing_interval_count=14, + currency="INR", ) create_plan( - plan_name="_Test Plan Name 4", cost=20000, billing_interval="Month", billing_interval_count=3 + plan_name="_Test Plan Name 4", + cost=20000, + billing_interval="Month", + billing_interval_count=3, + currency="INR", ) create_plan( plan_name="_Test Plan Multicurrency", cost=50, billing_interval="Month", currency="USD" From d91813c2779ae81f544d35c6925bb5580ebf4f95 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 15 Jan 2024 16:50:14 +0530 Subject: [PATCH 14/22] feat: Income account filter in item-wise reports --- .../item_wise_sales_register.js | 16 +++++++++++++- .../item_wise_sales_register.py | 21 ++++++++++++++++--- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js index 39fb3ca5ee..06f426b71e 100644 --- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js +++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js @@ -59,7 +59,21 @@ frappe.query_reports["Item-wise Sales Register"] = { "fieldname": "group_by", "fieldtype": "Select", "options": ["Customer Group", "Customer", "Item Group", "Item", "Territory", "Invoice"] - } + }, + { + "fieldname": "income_account", + "label": __("Income Account"), + "fieldtype": "Link", + "options": "Account", + get_query: () => { + let company = frappe.query_report.get_filter_value('company'); + return { + filters: { + 'company': company, + } + }; + } + }, ], "formatter": function(value, row, column, data, default_formatter) { value = default_formatter(value, row, column, data); diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py index ce22d7566c..56ae41a5e1 100644 --- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py +++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py @@ -83,9 +83,7 @@ def _execute(filters=None, additional_table_columns=None, additional_conditions= "company": d.company, "sales_order": d.sales_order, "delivery_note": d.delivery_note, - "income_account": d.unrealized_profit_loss_account - if d.is_internal_customer == 1 - else d.income_account, + "income_account": get_income_account(d), "cost_center": d.cost_center, "stock_qty": d.stock_qty, "stock_uom": d.stock_uom, @@ -150,6 +148,15 @@ def _execute(filters=None, additional_table_columns=None, additional_conditions= return columns, data, None, None, None, skip_total_row +def get_income_account(row): + if row.enable_deferred_revenue: + return row.deferred_revenue_account + elif row.is_internal_customer == 1: + return row.unrealized_profit_loss_account + else: + return row.income_account + + def get_columns(additional_table_columns, filters): columns = [] @@ -358,6 +365,13 @@ def get_conditions(filters, additional_conditions=None): if filters.get("item_group"): conditions += """and ifnull(`tabSales Invoice Item`.item_group, '') = %(item_group)s""" + if filters.get("income_account"): + conditions += """ + and (ifnull(`tabSales Invoice Item`.income_account, '') = %(income_account)s + or ifnull(`tabSales Invoice Item`.deferred_revenue_account, '') = %(income_account)s + or ifnull(`tabSales Invoice`.unrealized_profit_loss_account, '') = %(income_account)s) + """ + if not filters.get("group_by"): conditions += ( "ORDER BY `tabSales Invoice`.posting_date desc, `tabSales Invoice Item`.item_group desc" @@ -399,6 +413,7 @@ def get_items(filters, additional_query_columns, additional_conditions=None): `tabItem`.`item_name` as i_item_name, `tabItem`.`item_group` as i_item_group, `tabSales Invoice Item`.sales_order, `tabSales Invoice Item`.delivery_note, `tabSales Invoice Item`.income_account, `tabSales Invoice Item`.cost_center, + `tabSales Invoice Item`.enable_deferred_revenue, `tabSales Invoice Item`.deferred_revenue_account, `tabSales Invoice Item`.stock_qty, `tabSales Invoice Item`.stock_uom, `tabSales Invoice Item`.base_net_rate, `tabSales Invoice Item`.base_net_amount, `tabSales Invoice`.customer_name, `tabSales Invoice`.customer_group, `tabSales Invoice Item`.so_detail, From 60b26ad8b262752e7d491b3fe21b398c0928bfaf Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 15 Jan 2024 20:22:30 +0530 Subject: [PATCH 15/22] fix: possible typerror in utils.js and remove unwanted debugging statements --- .../report/budget_variance_report/budget_variance_report.js | 4 ---- erpnext/public/js/utils.js | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/erpnext/accounts/report/budget_variance_report/budget_variance_report.js b/erpnext/accounts/report/budget_variance_report/budget_variance_report.js index 9c356bf28e..d6a4755d6a 100644 --- a/erpnext/accounts/report/budget_variance_report/budget_variance_report.js +++ b/erpnext/accounts/report/budget_variance_report/budget_variance_report.js @@ -84,10 +84,6 @@ function get_filters() { options: budget_against_options, default: "Cost Center", reqd: 1, - get_data: function() { - console.log(this.options); - return ["Emacs", "Rocks"]; - }, on_change: function() { frappe.query_report.set_filter_value("budget_against_filter", []); frappe.query_report.refresh(); diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index 598167b337..de46271e47 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -21,7 +21,7 @@ $.extend(erpnext, { }, toggle_naming_series: function() { - if(cur_frm.fields_dict.naming_series) { + if(cur_frm && cur_frm.fields_dict.naming_series) { cur_frm.toggle_display("naming_series", cur_frm.doc.__islocal?true:false); } }, From bdd382bdfd2fb6b333902daf4ce980d295492b28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9?= Date: Mon, 15 Jan 2024 16:40:45 +0100 Subject: [PATCH 16/22] fix: Untranslated columns in Global Ledger --- erpnext/accounts/report/general_ledger/general_ledger.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 6636b8e042..f5b034ab01 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -449,6 +449,10 @@ def get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map): for gle in gl_entries: group_by_value = gle.get(group_by) gle.voucher_type = _(gle.voucher_type) + gle.voucher_subtype = _(gle.voucher_subtype) + gle.against_voucher_type = _(gle.against_voucher_type) + gle.remarks = _(gle.remarks) + gle.party_type = _(gle.party_type) if gle.posting_date < from_date or (cstr(gle.is_opening) == "Yes" and not show_opening_entries): if not group_by_voucher_consolidated: From 4970b5d5bcadefb90239a2d81161f2f379a1304e Mon Sep 17 00:00:00 2001 From: Alexandre Lumertz Damiani Date: Tue, 16 Jan 2024 02:13:33 -0300 Subject: [PATCH 17/22] fix: translate (#39398) --- .../warehouse_capacity_summary/warehouse_capacity_summary.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/page/warehouse_capacity_summary/warehouse_capacity_summary.js b/erpnext/stock/page/warehouse_capacity_summary/warehouse_capacity_summary.js index 61927f51a8..c175a4ad64 100644 --- a/erpnext/stock/page/warehouse_capacity_summary/warehouse_capacity_summary.js +++ b/erpnext/stock/page/warehouse_capacity_summary/warehouse_capacity_summary.js @@ -1,7 +1,7 @@ frappe.pages['warehouse-capacity-summary'].on_page_load = function(wrapper) { var page = frappe.ui.make_app_page({ parent: wrapper, - title: 'Warehouse Capacity Summary', + title: __('Warehouse Capacity Summary'), single_column: true }); page.set_secondary_action('Refresh', () => page.capacity_dashboard.refresh(), 'refresh'); From b719585a2f60ab6f469a2456ffc8d7f703fccc1e Mon Sep 17 00:00:00 2001 From: Alexandre Lumertz Damiani Date: Tue, 16 Jan 2024 02:14:17 -0300 Subject: [PATCH 18/22] fix: translate (#39397) --- erpnext/setup/doctype/vehicle/vehicle.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/setup/doctype/vehicle/vehicle.json b/erpnext/setup/doctype/vehicle/vehicle.json index b19d45924f..bf1a8c184d 100644 --- a/erpnext/setup/doctype/vehicle/vehicle.json +++ b/erpnext/setup/doctype/vehicle/vehicle.json @@ -57,7 +57,7 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Make", + "label": "Manufacturer", "length": 0, "no_copy": 0, "permlevel": 0, From 00619342e1447dbffcae5ba65597950eab7c7a58 Mon Sep 17 00:00:00 2001 From: Alexandre Lumertz Damiani Date: Tue, 16 Jan 2024 02:14:59 -0300 Subject: [PATCH 19/22] fix: translate (#39396) --- .../warehouse_capacity_summary_header.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/erpnext/stock/page/warehouse_capacity_summary/warehouse_capacity_summary_header.html b/erpnext/stock/page/warehouse_capacity_summary/warehouse_capacity_summary_header.html index 1183ad4496..1883004de9 100644 --- a/erpnext/stock/page/warehouse_capacity_summary/warehouse_capacity_summary_header.html +++ b/erpnext/stock/page/warehouse_capacity_summary/warehouse_capacity_summary_header.html @@ -1,19 +1,19 @@
- Warehouse + {{ __("Warehouse") }}
- Item + {{ __("Item") }}
- Stock Capacity + {{ __("Stock Capacity") }}
- Balance Stock Qty + {{ __("Balance Stock Qty") }}
- % Occupied + {{ __("% Occupied") }}
From 80f5026208120ac2690aa0bd4e0f9b9a855f4e1e Mon Sep 17 00:00:00 2001 From: Alexandre Lumertz Damiani Date: Tue, 16 Jan 2024 02:16:00 -0300 Subject: [PATCH 20/22] fix: translate (#39395) --- erpnext/selling/page/sales_funnel/sales_funnel.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/selling/page/sales_funnel/sales_funnel.js b/erpnext/selling/page/sales_funnel/sales_funnel.js index e3d0a55c3a..a0a1222eb3 100644 --- a/erpnext/selling/page/sales_funnel/sales_funnel.js +++ b/erpnext/selling/page/sales_funnel/sales_funnel.js @@ -126,9 +126,9 @@ erpnext.SalesFunnel = class SalesFunnel { if (me.options.chart == 'sales_funnel'){ me.render_funnel(); } else if (me.options.chart == 'opp_by_lead_source'){ - me.render_chart("Sales Opportunities by Source"); + me.render_chart(__("Sales Opportunities by Source")); } else if (me.options.chart == 'sales_pipeline'){ - me.render_chart("Sales Pipeline by Stage"); + me.render_chart(__("Sales Pipeline by Stage")); } } From e5aeab7e7e142f888b04e18930ff6d6341f6eb21 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 16 Jan 2024 11:07:26 +0530 Subject: [PATCH 21/22] fix: broken multi currency test case in subscription --- erpnext/accounts/doctype/subscription/test_subscription.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/subscription/test_subscription.py b/erpnext/accounts/doctype/subscription/test_subscription.py index 37326fd035..a46642ad50 100644 --- a/erpnext/accounts/doctype/subscription/test_subscription.py +++ b/erpnext/accounts/doctype/subscription/test_subscription.py @@ -460,11 +460,13 @@ class TestSubscription(FrappeTestCase): self.assertEqual(len(subscription.invoices), 1) def test_multi_currency_subscription(self): + party = "_Test Subscription Customer" + frappe.db.set_value("Customer", party, "default_currency", "USD") subscription = create_subscription( start_date="2018-01-01", generate_invoice_at="Beginning of the current subscription period", plans=[{"plan": "_Test Plan Multicurrency", "qty": 1, "currency": "USD"}], - party="_Test Subscription Customer", + party=party, ) subscription.process() From ed927f102eb8beb89e47b634a417b45d4f314c63 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 16 Jan 2024 11:43:35 +0530 Subject: [PATCH 22/22] perf: use unbuffered_cursor for stock_ageing report (#39399) perf: use unbuffered_cursor for stock stock_ageing report Unbuffered cursor lets us load one row at a time in memory from mysql instead of lowing all at once. This makes it possible to run the report for large number of SLEs. --- .../stock/report/stock_ageing/stock_ageing.py | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py index f055c6c628..02ac8c6bae 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.py +++ b/erpnext/stock/report/stock_ageing/stock_ageing.py @@ -233,28 +233,30 @@ class FIFOSlots: """ stock_ledger_entries = self.sle - if stock_ledger_entries is None: - stock_ledger_entries = self.__get_stock_ledger_entries() - for d in stock_ledger_entries: - key, fifo_queue, transferred_item_key = self.__init_key_stores(d) + with frappe.db.unbuffered_cursor(): + if stock_ledger_entries is None: + stock_ledger_entries = self.__get_stock_ledger_entries() - if d.voucher_type == "Stock Reconciliation": - # get difference in qty shift as actual qty - prev_balance_qty = self.item_details[key].get("qty_after_transaction", 0) - d.actual_qty = flt(d.qty_after_transaction) - flt(prev_balance_qty) + for d in stock_ledger_entries: + key, fifo_queue, transferred_item_key = self.__init_key_stores(d) - serial_nos = get_serial_nos(d.serial_no) if d.serial_no else [] + if d.voucher_type == "Stock Reconciliation": + # get difference in qty shift as actual qty + prev_balance_qty = self.item_details[key].get("qty_after_transaction", 0) + d.actual_qty = flt(d.qty_after_transaction) - flt(prev_balance_qty) - if d.actual_qty > 0: - self.__compute_incoming_stock(d, fifo_queue, transferred_item_key, serial_nos) - else: - self.__compute_outgoing_stock(d, fifo_queue, transferred_item_key, serial_nos) + serial_nos = get_serial_nos(d.serial_no) if d.serial_no else [] - self.__update_balances(d, key) + if d.actual_qty > 0: + self.__compute_incoming_stock(d, fifo_queue, transferred_item_key, serial_nos) + else: + self.__compute_outgoing_stock(d, fifo_queue, transferred_item_key, serial_nos) - # Note that stock_ledger_entries is an iterator, you can not reuse it like a list - del stock_ledger_entries + self.__update_balances(d, key) + + # Note that stock_ledger_entries is an iterator, you can not reuse it like a list + del stock_ledger_entries if not self.filters.get("show_warehouse_wise_stock"): # (Item 1, WH 1), (Item 1, WH 2) => (Item 1)