From 91a748d9bfe9264454e7fa39afd052df6c60674d Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 21 Apr 2026 17:35:34 +0530 Subject: [PATCH 01/56] refactor(test): remove explicit sql delete calls (cherry picked from commit b16dd3f2ddf02ba342f682c4aa9704f9936dc6c2) --- .../test_period_closing_voucher.py | 16 ------------ .../test_pos_closing_entry.py | 1 - .../doctype/pos_invoice/test_pos_invoice.py | 1 - .../pos_invoice/test_pos_invoice_merge.py | 4 +-- .../doctype/pricing_rule/test_pricing_rule.py | 11 -------- .../sales_invoice/test_sales_invoice.py | 4 --- .../share_transfer/test_share_transfer.py | 2 -- .../account_balance/test_account_balance.py | 3 --- .../balance_sheet/test_balance_sheet.py | 3 --- .../test_purchase_register.py | 9 ------- .../trial_balance/test_trial_balance.py | 3 --- .../test_asset_capitalization.py | 1 - .../test_supplier_scorecard.py | 21 --------------- .../test_supplier_scorecard_criteria.py | 26 ------------------- erpnext/crm/doctype/contract/test_contract.py | 1 - erpnext/crm/doctype/lead/test_lead.py | 9 ------- erpnext/manufacturing/doctype/bom/test_bom.py | 3 --- .../activity_cost/test_activity_cost.py | 2 -- .../selling/doctype/customer/test_customer.py | 8 ------ .../report/sales_analytics/test_analytics.py | 2 -- erpnext/setup/doctype/company/test_company.py | 9 ------- erpnext/stock/doctype/item/test_item.py | 6 ----- .../test_stock_ledger_entry.py | 11 +------- 23 files changed, 2 insertions(+), 154 deletions(-) diff --git a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py index 1fcff98a467..3258a8cbe8a 100644 --- a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py +++ b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py @@ -18,9 +18,6 @@ class TestPeriodClosingVoucher(ERPNextTestSuite): frappe.db.set_single_value("Accounts Settings", "use_legacy_controller_for_pcv", 1) def test_closing_entry(self): - frappe.db.sql("delete from `tabGL Entry` where company='Test PCV Company'") - frappe.db.sql("delete from `tabPeriod Closing Voucher` where company='Test PCV Company'") - company = create_company() cost_center = create_cost_center("Test Cost Center 1") @@ -70,9 +67,6 @@ class TestPeriodClosingVoucher(ERPNextTestSuite): self.assertEqual(pcv_gle, expected_gle) def test_cost_center_wise_posting(self): - frappe.db.sql("delete from `tabGL Entry` where company='Test PCV Company'") - frappe.db.sql("delete from `tabPeriod Closing Voucher` where company='Test PCV Company'") - company = create_company() surplus_account = create_account() @@ -136,9 +130,6 @@ class TestPeriodClosingVoucher(ERPNextTestSuite): ) def test_period_closing_with_finance_book_entries(self): - frappe.db.sql("delete from `tabGL Entry` where company='Test PCV Company'") - frappe.db.sql("delete from `tabPeriod Closing Voucher` where company='Test PCV Company'") - company = create_company() surplus_account = create_account() cost_center = create_cost_center("Test Cost Center 1") @@ -190,9 +181,6 @@ class TestPeriodClosingVoucher(ERPNextTestSuite): self.assertSequenceEqual(pcv_gle, expected_gle) def test_gl_entries_restrictions(self): - frappe.db.sql("delete from `tabGL Entry` where company='Test PCV Company'") - frappe.db.sql("delete from `tabPeriod Closing Voucher` where company='Test PCV Company'") - company = create_company() cost_center = create_cost_center("Test Cost Center 1") @@ -213,10 +201,6 @@ class TestPeriodClosingVoucher(ERPNextTestSuite): self.assertRaises(frappe.ValidationError, jv1.submit) def test_closing_balance_with_dimensions_and_test_reposting_entry(self): - frappe.db.sql("delete from `tabGL Entry` where company='Test PCV Company'") - frappe.db.sql("delete from `tabPeriod Closing Voucher` where company='Test PCV Company'") - frappe.db.sql("delete from `tabAccount Closing Balance` where company='Test PCV Company'") - company = create_company() cost_center1 = create_cost_center("Test Cost Center 1") cost_center2 = create_cost_center("Test Cost Center 2") diff --git a/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py index 05e24d16a3a..1e402d59ae0 100644 --- a/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py +++ b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py @@ -201,7 +201,6 @@ class TestPOSClosingEntry(ERPNextTestSuite): ) from erpnext.stock.doctype.batch.batch import get_batch_qty - frappe.db.sql("delete from `tabPOS Invoice`") item_doc = make_item( "_Test Item With Batch FOR POS Merge Test", properties={ diff --git a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py index 8cf4d0cb90f..e306e03db34 100644 --- a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py @@ -37,7 +37,6 @@ class POSInvoiceTestMixin(ERPNextTestSuite): frappe.db.set_single_value("Selling Settings", "validate_selling_price", 0) frappe.db.set_single_value("POS Settings", "invoice_type", "POS Invoice") make_stock_entry(target="_Test Warehouse - _TC", item_code="_Test Item", qty=800, basic_rate=100) - frappe.db.sql("delete from `tabTax Rule`") mode_of_payment = frappe.get_doc("Mode of Payment", "Bank Draft") set_default_account_for_mode_of_payment(mode_of_payment, "_Test Company", "_Test Bank - _TC") diff --git a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice_merge.py b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice_merge.py index 5c490d303be..2ab8486b06a 100644 --- a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice_merge.py +++ b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice_merge.py @@ -34,7 +34,6 @@ class TestPOSInvoiceMerging(POSInvoiceTestMixin): consolidate_pos_invoices, ) - frappe.db.sql("delete from `tabPOS Invoice`") test_user, pos_profile = init_user_and_profile() pos_inv = create_pos_invoice(rate=300, additional_discount_percentage=10, do_not_submit=1) pos_inv.append("payments", {"mode_of_payment": "Cash", "amount": 270}) @@ -64,7 +63,6 @@ class TestPOSInvoiceMerging(POSInvoiceTestMixin): consolidate_pos_invoices, ) - frappe.db.sql("delete from `tabPOS Invoice`") test_user, pos_profile = init_user_and_profile() pos_inv = create_pos_invoice(rate=300, do_not_submit=1) pos_inv.append("payments", {"mode_of_payment": "Cash", "amount": 300}) @@ -123,7 +121,7 @@ class TestPOSInvoiceMerging(POSInvoiceTestMixin): item = "Test Selling Price Validation" make_item(item, {"is_stock_item": 1}) make_purchase_receipt(item_code=item, warehouse="_Test Warehouse - _TC", qty=1, rate=300) - frappe.db.sql("delete from `tabPOS Invoice`") + test_user, pos_profile = init_user_and_profile() pos_inv = create_pos_invoice(item=item, rate=300, do_not_submit=1) pos_inv.append("payments", {"mode_of_payment": "Cash", "amount": 300}) diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py index 6ff1ed85d55..3e5550611ac 100644 --- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py @@ -17,7 +17,6 @@ from erpnext.tests.utils import ERPNextTestSuite class TestPricingRule(ERPNextTestSuite): def setUp(self): - delete_existing_pricing_rules() setup_pricing_rule_data() self.enterClassContext(self.change_settings("Selling Settings", validate_selling_price=0)) @@ -1586,16 +1585,6 @@ def setup_pricing_rule_data(): ).insert() -def delete_existing_pricing_rules(): - for doctype in [ - "Pricing Rule", - "Pricing Rule Item Code", - "Pricing Rule Item Group", - "Pricing Rule Brand", - ]: - frappe.db.sql(f"delete from `tab{doctype}`") - - def make_item_price(item, price_list_name, item_price): frappe.get_doc( { diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 03d8b2e7eb5..cf22b186b97 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -2025,10 +2025,6 @@ class TestSalesInvoice(ERPNextTestSuite): ) def test_multiple_uom_in_selling(self): - frappe.db.sql( - """delete from `tabItem Price` - where price_list='_Test Price List' and item_code='_Test Item'""" - ) item_price = frappe.new_doc("Item Price") item_price.price_list = "_Test Price List" item_price.item_code = "_Test Item" diff --git a/erpnext/accounts/doctype/share_transfer/test_share_transfer.py b/erpnext/accounts/doctype/share_transfer/test_share_transfer.py index a227a9f3059..3c1a395f93a 100644 --- a/erpnext/accounts/doctype/share_transfer/test_share_transfer.py +++ b/erpnext/accounts/doctype/share_transfer/test_share_transfer.py @@ -10,8 +10,6 @@ from erpnext.tests.utils import ERPNextTestSuite class TestShareTransfer(ERPNextTestSuite): def setUp(self): - frappe.db.sql("delete from `tabShare Transfer`") - frappe.db.sql("delete from `tabShare Balance`") share_transfers = [ { "doctype": "Share Transfer", diff --git a/erpnext/accounts/report/account_balance/test_account_balance.py b/erpnext/accounts/report/account_balance/test_account_balance.py index f166421b0de..49d81f0c625 100644 --- a/erpnext/accounts/report/account_balance/test_account_balance.py +++ b/erpnext/accounts/report/account_balance/test_account_balance.py @@ -10,9 +10,6 @@ from erpnext.tests.utils import ERPNextTestSuite class TestAccountBalance(ERPNextTestSuite): def test_account_balance(self): - frappe.db.sql("delete from `tabSales Invoice` where company='_Test Company 2'") - frappe.db.sql("delete from `tabGL Entry` where company='_Test Company 2'") - filters = { "company": "_Test Company 2", "report_date": getdate(), diff --git a/erpnext/accounts/report/balance_sheet/test_balance_sheet.py b/erpnext/accounts/report/balance_sheet/test_balance_sheet.py index dce9d8ab0fa..683aeecffbd 100644 --- a/erpnext/accounts/report/balance_sheet/test_balance_sheet.py +++ b/erpnext/accounts/report/balance_sheet/test_balance_sheet.py @@ -13,9 +13,6 @@ COMPANY_SHORT_NAME = "_TC6" class TestBalanceSheet(ERPNextTestSuite): def test_balance_sheet(self): - frappe.db.sql(f"delete from `tabJournal Entry` where company='{COMPANY}'") - frappe.db.sql(f"delete from `tabGL Entry` where company='{COMPANY}'") - create_account("VAT Liabilities", f"Duties and Taxes - {COMPANY_SHORT_NAME}", COMPANY) create_account("Advance VAT Paid", f"Duties and Taxes - {COMPANY_SHORT_NAME}", COMPANY) create_account("My Bank", f"Bank Accounts - {COMPANY_SHORT_NAME}", COMPANY) diff --git a/erpnext/accounts/report/purchase_register/test_purchase_register.py b/erpnext/accounts/report/purchase_register/test_purchase_register.py index e4ce5ffcfe3..9e0e2002f60 100644 --- a/erpnext/accounts/report/purchase_register/test_purchase_register.py +++ b/erpnext/accounts/report/purchase_register/test_purchase_register.py @@ -11,9 +11,6 @@ from erpnext.tests.utils import ERPNextTestSuite class TestPurchaseRegister(ERPNextTestSuite): def test_purchase_register(self): - frappe.db.sql("delete from `tabPurchase Invoice` where company='_Test Company 6'") - frappe.db.sql("delete from `tabGL Entry` where company='_Test Company 6'") - filters = frappe._dict(company="_Test Company 6", from_date=add_months(today(), -1), to_date=today()) pi = make_purchase_invoice() @@ -28,9 +25,6 @@ class TestPurchaseRegister(ERPNextTestSuite): self.assertEqual(first_row.grand_total, 1100) def test_purchase_register_ignores_tax_rows_from_other_doctype(self): - frappe.db.sql("delete from `tabPurchase Invoice` where company='_Test Company 6'") - frappe.db.sql("delete from `tabGL Entry` where company='_Test Company 6'") - filters = frappe._dict(company="_Test Company 6", from_date=add_months(today(), -1), to_date=today()) pi = make_purchase_invoice() @@ -74,9 +68,6 @@ class TestPurchaseRegister(ERPNextTestSuite): self.assertEqual(first_row.grand_total, 1100) def test_purchase_register_ledger_view(self): - frappe.db.sql("delete from `tabPurchase Invoice` where company='_Test Company 6'") - frappe.db.sql("delete from `tabGL Entry` where company='_Test Company 6'") - filters = frappe._dict( company="_Test Company 6", from_date=add_months(today(), -1), diff --git a/erpnext/accounts/report/trial_balance/test_trial_balance.py b/erpnext/accounts/report/trial_balance/test_trial_balance.py index c37f9d5a46a..ec8f48c2413 100644 --- a/erpnext/accounts/report/trial_balance/test_trial_balance.py +++ b/erpnext/accounts/report/trial_balance/test_trial_balance.py @@ -42,9 +42,6 @@ class TestTrialBalance(ERPNextTestSuite): """ from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice - frappe.db.sql("delete from `tabSales Invoice` where company='Trial Balance Company'") - frappe.db.sql("delete from `tabGL Entry` where company='Trial Balance Company'") - branch1 = frappe.new_doc("Branch") branch1.branch = "Location 1" branch1.insert(ignore_if_duplicate=True) diff --git a/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py index e37ac4c2bf3..e297fc94634 100644 --- a/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py +++ b/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py @@ -26,7 +26,6 @@ class TestAssetCapitalization(ERPNextTestSuite): def setUp(self): set_depreciation_settings_in_company() create_asset_capitalization_data() - frappe.db.sql("delete from `tabTax Rule`") def test_capitalization_with_perpetual_inventory(self): company = "_Test Company with perpetual inventory" diff --git a/erpnext/buying/doctype/supplier_scorecard/test_supplier_scorecard.py b/erpnext/buying/doctype/supplier_scorecard/test_supplier_scorecard.py index a1d1dfc4709..92da4dd318d 100644 --- a/erpnext/buying/doctype/supplier_scorecard/test_supplier_scorecard.py +++ b/erpnext/buying/doctype/supplier_scorecard/test_supplier_scorecard.py @@ -13,7 +13,6 @@ class TestSupplierScorecard(ERPNextTestSuite): self.assertEqual(doc.name, valid_scorecard[0].get("supplier")) def test_criteria_weight(self): - delete_test_scorecards() my_doc = make_supplier_scorecard() for d in my_doc.criteria: d.weight = 0 @@ -33,26 +32,6 @@ def make_supplier_scorecard(): return my_doc -def delete_test_scorecards(): - my_doc = make_supplier_scorecard() - if frappe.db.exists("Supplier Scorecard", my_doc.name): - # Delete all the periods, then delete the scorecard - frappe.db.sql( - """delete from `tabSupplier Scorecard Period` where scorecard = %(scorecard)s""", - {"scorecard": my_doc.name}, - ) - frappe.db.sql( - """delete from `tabSupplier Scorecard Scoring Criteria` where parenttype = 'Supplier Scorecard Period'""" - ) - frappe.db.sql( - """delete from `tabSupplier Scorecard Scoring Standing` where parenttype = 'Supplier Scorecard Period'""" - ) - frappe.db.sql( - """delete from `tabSupplier Scorecard Scoring Variable` where parenttype = 'Supplier Scorecard Period'""" - ) - frappe.delete_doc(my_doc.doctype, my_doc.name) - - valid_scorecard = [ { "standings": [ diff --git a/erpnext/buying/doctype/supplier_scorecard_criteria/test_supplier_scorecard_criteria.py b/erpnext/buying/doctype/supplier_scorecard_criteria/test_supplier_scorecard_criteria.py index 951d33ed901..0d2a547c634 100644 --- a/erpnext/buying/doctype/supplier_scorecard_criteria/test_supplier_scorecard_criteria.py +++ b/erpnext/buying/doctype/supplier_scorecard_criteria/test_supplier_scorecard_criteria.py @@ -9,41 +9,15 @@ from erpnext.tests.utils import ERPNextTestSuite class TestSupplierScorecardCriteria(ERPNextTestSuite): def test_variables_exist(self): - delete_test_scorecards() for d in test_good_criteria: frappe.get_doc(d).insert() self.assertRaises(frappe.ValidationError, frappe.get_doc(test_bad_criteria[0]).insert) def test_formula_validate(self): - delete_test_scorecards() self.assertRaises(frappe.ValidationError, frappe.get_doc(test_bad_criteria[1]).insert) -def delete_test_scorecards(): - # Delete all the periods so we can delete all the criteria - frappe.db.sql("""delete from `tabSupplier Scorecard Period`""") - frappe.db.sql( - """delete from `tabSupplier Scorecard Scoring Criteria` where parenttype = 'Supplier Scorecard Period'""" - ) - frappe.db.sql( - """delete from `tabSupplier Scorecard Scoring Standing` where parenttype = 'Supplier Scorecard Period'""" - ) - frappe.db.sql( - """delete from `tabSupplier Scorecard Scoring Variable` where parenttype = 'Supplier Scorecard Period'""" - ) - - for d in test_good_criteria: - if frappe.db.exists("Supplier Scorecard Criteria", d.get("name")): - # Delete all the periods, then delete the scorecard - frappe.delete_doc(d.get("doctype"), d.get("name")) - - for d in test_bad_criteria: - if frappe.db.exists("Supplier Scorecard Criteria", d.get("name")): - # Delete all the periods, then delete the scorecard - frappe.delete_doc(d.get("doctype"), d.get("name")) - - test_good_criteria = [ { "name": "Delivery", diff --git a/erpnext/crm/doctype/contract/test_contract.py b/erpnext/crm/doctype/contract/test_contract.py index f6aa0ef0979..79993d6f87c 100644 --- a/erpnext/crm/doctype/contract/test_contract.py +++ b/erpnext/crm/doctype/contract/test_contract.py @@ -10,7 +10,6 @@ from erpnext.tests.utils import ERPNextTestSuite class TestContract(ERPNextTestSuite): def setUp(self): - frappe.db.sql("delete from `tabContract`") self.contract_doc = get_contract() def test_validate_start_date_before_end_date(self): diff --git a/erpnext/crm/doctype/lead/test_lead.py b/erpnext/crm/doctype/lead/test_lead.py index 5da10ff9ea2..e85efc94faa 100644 --- a/erpnext/crm/doctype/lead/test_lead.py +++ b/erpnext/crm/doctype/lead/test_lead.py @@ -87,9 +87,6 @@ class TestLead(ERPNextTestSuite): self.assertEqual(len(address_1.get("links")), 1) def test_prospect_creation_from_lead(self): - frappe.db.sql("delete from `tabLead` where lead_name='Rahul Tripathi'") - frappe.db.sql("delete from `tabProspect` where name='Prospect Company'") - lead = make_lead( first_name="Rahul", last_name="Tripathi", @@ -109,9 +106,6 @@ class TestLead(ERPNextTestSuite): self.assertEqual(event.event_participants[1].reference_docname, prospect) def test_opportunity_from_lead(self): - frappe.db.sql("delete from `tabLead` where lead_name='Rahul Tripathi'") - frappe.db.sql("delete from `tabOpportunity` where party_name='Rahul Tripathi'") - lead = make_lead( first_name="Rahul", last_name="Tripathi", @@ -139,9 +133,6 @@ class TestLead(ERPNextTestSuite): ) def test_copy_events_from_lead_to_prospect(self): - frappe.db.sql("delete from `tabLead` where lead_name='Rahul Tripathi'") - frappe.db.sql("delete from `tabProspect` where name='Prospect Company'") - lead = make_lead( first_name="Rahul", last_name="Tripathi", diff --git a/erpnext/manufacturing/doctype/bom/test_bom.py b/erpnext/manufacturing/doctype/bom/test_bom.py index 3296559afc5..78d8795162b 100644 --- a/erpnext/manufacturing/doctype/bom/test_bom.py +++ b/erpnext/manufacturing/doctype/bom/test_bom.py @@ -165,9 +165,6 @@ class TestBOM(ERPNextTestSuite): def test_bom_cost_multi_uom_multi_currency_based_on_price_list(self): frappe.db.set_value("Price List", "_Test Price List", "price_not_uom_dependent", 1) for item_code, rate in (("_Test Item", 3600), ("_Test Item Home Desktop Manufactured", 3000)): - frappe.db.sql( - "delete from `tabItem Price` where price_list='_Test Price List' and item_code=%s", item_code - ) item_price = frappe.new_doc("Item Price") item_price.price_list = "_Test Price List" item_price.item_code = item_code diff --git a/erpnext/projects/doctype/activity_cost/test_activity_cost.py b/erpnext/projects/doctype/activity_cost/test_activity_cost.py index 73736e305b4..22bd9f4e946 100644 --- a/erpnext/projects/doctype/activity_cost/test_activity_cost.py +++ b/erpnext/projects/doctype/activity_cost/test_activity_cost.py @@ -15,7 +15,6 @@ class TestActivityCost(ERPNextTestSuite): "Activity Type", filters={"activity_type": "_Test Activity Type 1"} )[0].name - frappe.db.sql("delete from `tabActivity Cost`") activity_cost1 = frappe.new_doc("Activity Cost") activity_cost1.update( { @@ -29,4 +28,3 @@ class TestActivityCost(ERPNextTestSuite): activity_cost1.insert() activity_cost2 = frappe.copy_doc(activity_cost1) self.assertRaises(DuplicationError, activity_cost2.insert) - frappe.db.sql("delete from `tabActivity Cost`") diff --git a/erpnext/selling/doctype/customer/test_customer.py b/erpnext/selling/doctype/customer/test_customer.py index 5eef7f95651..e3efd4a5b21 100644 --- a/erpnext/selling/doctype/customer/test_customer.py +++ b/erpnext/selling/doctype/customer/test_customer.py @@ -137,12 +137,6 @@ class TestCustomer(ERPNextTestSuite): # delete communication linked to these 2 customers new_name = "_Test Customer 1 Renamed" - for name in ("_Test Customer 1", new_name): - frappe.db.sql( - """delete from `tabComment` - where reference_doctype=%s and reference_name=%s""", - ("Customer", name), - ) # add comments comment = frappe.get_doc("Customer", "_Test Customer 1").add_comment( @@ -209,8 +203,6 @@ class TestCustomer(ERPNextTestSuite): so.save() def test_duplicate_customer(self): - frappe.db.sql("delete from `tabCustomer` where customer_name='_Test Customer 1'") - if not frappe.db.get_value("Customer", "_Test Customer 1"): test_customer_1 = frappe.get_doc(get_customer_dict("_Test Customer 1")).insert( ignore_permissions=True diff --git a/erpnext/selling/report/sales_analytics/test_analytics.py b/erpnext/selling/report/sales_analytics/test_analytics.py index cada5c07c81..3e687954133 100644 --- a/erpnext/selling/report/sales_analytics/test_analytics.py +++ b/erpnext/selling/report/sales_analytics/test_analytics.py @@ -11,8 +11,6 @@ from erpnext.tests.utils import ERPNextTestSuite class TestAnalytics(ERPNextTestSuite): def test_sales_analytics(self): - frappe.db.sql("delete from `tabSales Order` where company='_Test Company 2'") - create_sales_orders() self.compare_result_for_customer() diff --git a/erpnext/setup/doctype/company/test_company.py b/erpnext/setup/doctype/company/test_company.py index 36606e90755..db4e8c07482 100644 --- a/erpnext/setup/doctype/company/test_company.py +++ b/erpnext/setup/doctype/company/test_company.py @@ -44,7 +44,6 @@ class TestCompany(ERPNextTestSuite): for prop, val in acc_property.items(): self.assertEqual(acc.get(prop), val) - self.delete_mode_of_payment("COA from Existing Company") frappe.delete_doc("Company", "COA from Existing Company") def test_coa_based_on_country_template(self): @@ -95,16 +94,8 @@ class TestCompany(ERPNextTestSuite): self.assertTrue(has_matching_accounts, msg=error_message) finally: - self.delete_mode_of_payment(template) frappe.delete_doc("Company", template) - def delete_mode_of_payment(self, company): - frappe.db.sql( - """ delete from `tabMode of Payment Account` - where company =%s """, - (company), - ) - def test_basic_tree(self, records=None): self.load_test_records("Company") min_lft = 1 diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py index b580582339d..6868916103a 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -459,11 +459,6 @@ class TestItem(ERPNextTestSuite): frappe.delete_doc_if_exists("Item", "_Test Numeric Template Item") frappe.delete_doc_if_exists("Item Attribute", "Test Item Length") - frappe.db.sql( - """delete from `tabItem Variant Attribute` - where attribute='Test Item Length' """ - ) - frappe.flags.attribute_values = None # make item attribute @@ -607,7 +602,6 @@ class TestItem(ERPNextTestSuite): def test_add_item_barcode(self): # Clean up - frappe.db.sql("""delete from `tabItem Barcode`""") item_code = "Test Item Barcode" if frappe.db.exists("Item", item_code): frappe.delete_doc("Item", item_code) diff --git a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py index 8f4b39dd5b8..1a694f77f37 100644 --- a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py +++ b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py @@ -33,18 +33,9 @@ from erpnext.tests.utils import ERPNextTestSuite class TestStockLedgerEntry(ERPNextTestSuite, StockTestMixin): def setUp(self): - items = create_items() + create_items() reset("Stock Entry") - # delete SLE and BINs for all items - frappe.db.sql( - "delete from `tabStock Ledger Entry` where item_code in (%s)" % (", ".join(["%s"] * len(items))), - items, - ) - frappe.db.sql( - "delete from `tabBin` where item_code in (%s)" % (", ".join(["%s"] * len(items))), items - ) - def test_item_cost_reposting(self): company = "_Test Company" From 090aab33fb7f70731dcc00a531c1672ad696b4f1 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 14:41:13 +0000 Subject: [PATCH 02/56] fix: py error on stock ageing report (backport #54467) (#54469) fix: py error on stock ageing report (#54467) (cherry picked from commit f5357c233dfc3df45da332d578cbf388a475ae60) Co-authored-by: Mihir Kandoi --- erpnext/stock/report/stock_ageing/stock_ageing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py index 2ea52e91a8d..9b230b8b094 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.py +++ b/erpnext/stock/report/stock_ageing/stock_ageing.py @@ -615,5 +615,5 @@ class FIFOSlots: sr_item = frappe.db.get_value( "Stock Reconciliation Item", row.voucher_detail_no, ["current_qty", "qty"], as_dict=True ) - if sr_item.qty and sr_item.current_qty: + if sr_item and sr_item.qty and sr_item.current_qty: self.stock_reco_voucher_wise_count[row.voucher_detail_no] = sr_item.current_qty From 386f49978ef6849bffbef52ed444e46506baca08 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 22 Apr 2026 21:36:51 +0530 Subject: [PATCH 03/56] fix: delivery schedule in the sales order (cherry picked from commit 435db260ee4a3e3dfcfa24bea784d57b9355f8f9) --- .../doctype/sales_order/sales_order.js | 46 +++++++++---------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 5fe7fe6543b..c557ea33d6f 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -716,29 +716,32 @@ frappe.ui.form.on("Sales Order", { if (!frequency) { frappe.throw(__("Please select a frequency for delivery schedule")); } - if (!first_delivery_date) { frappe.throw(__("Please enter the first delivery date")); } - if (no_of_deliveries <= 0) { frappe.throw(__("Please enter a valid number of deliveries")); } + const month_mapper = { + Monthly: 1, + Quarterly: 3, + "Half Yearly": 6, + Yearly: 12, + }; + frm.schedule_dialog.fields_dict.delivery_schedule.df.data = []; let qty_to_deliver = row.qty; let qty_per_delivery = qty_to_deliver / no_of_deliveries; - for (let i = 0; i < no_of_deliveries; i++) { - let qty = qty_per_delivery; - if (must_be_whole_number) { - qty = cint(qty); - } - if (i === no_of_deliveries - 1) { - // Last delivery, adjust the quantity to deliver the remaining amount + for (let i = 0; i < no_of_deliveries; i++) { + let qty; + const is_last = i === no_of_deliveries - 1; + + if (is_last) { qty = qty_to_deliver; - qty_to_deliver = 0; } else { + qty = must_be_whole_number ? cint(qty_per_delivery) : qty_per_delivery; qty_to_deliver -= qty; } @@ -747,20 +750,15 @@ frappe.ui.form.on("Sales Order", { qty: qty, }); - if (frequency === "Weekly") { - first_delivery_date = frappe.datetime.add_days(first_delivery_date, i + 1 * 7); - } else { - let month_mapper = { - Monthly: 1, - Quarterly: 3, - Half_Yearly: 6, - Yearly: 12, - }; - - first_delivery_date = frappe.datetime.add_months( - first_delivery_date, - month_mapper[frequency] * i + 1 - ); + if (!is_last) { + if (frequency === "Weekly") { + first_delivery_date = frappe.datetime.add_days(first_delivery_date, 7); + } else { + first_delivery_date = frappe.datetime.add_months( + first_delivery_date, + month_mapper[frequency] + ); + } } } From 9276cd7343ac4788b564345de8011d457ad73e50 Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Tue, 21 Apr 2026 17:28:56 +0530 Subject: [PATCH 04/56] refactor: use consistent report column names (cherry picked from commit 6dca96b423887da5464d482a1cbad1bbd34517a2) --- .../tax_withholding_details.py | 22 +++++++++++++------ .../test_tax_withholding_details.py | 2 +- .../tds_computation_summary.py | 22 +++++++++---------- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py index 70813aaeb1d..e6e3d834638 100644 --- a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py +++ b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py @@ -46,8 +46,8 @@ def get_tax_withholding_data(filters): party_info = party_details.get((entry.party_type, entry.party), {}) row = { - "section_code": entry.tax_withholding_category, - "entity_type": party_info.get("entity_type"), + "tax_withholding_category": entry.tax_withholding_category, + "party_entity_type": party_info.get("party_entity_type"), "rate": entry.tax_rate, "total_amount": entry.taxable_amount, "grand_total": doc_details.get("grand_total", 0), @@ -70,7 +70,11 @@ def get_tax_withholding_data(filters): # Sort by section code, transaction date, then withholding_name for deterministic ordering data.sort( - key=lambda x: (x["section_code"] or "", x["transaction_date"] or "", x["withholding_name"] or "") + key=lambda x: ( + x["tax_withholding_category"] or "", + x["transaction_date"] or "", + x["withholding_name"] or "", + ) ) return data @@ -94,9 +98,13 @@ def get_party_details(entries): fields = [doctype.name] if party_type == "Supplier": - fields.extend([doctype.supplier_type.as_("entity_type"), doctype.supplier_name.as_("party_name")]) + fields.extend( + [doctype.supplier_type.as_("party_entity_type"), doctype.supplier_name.as_("party_name")] + ) elif party_type == "Customer": - fields.extend([doctype.customer_type.as_("entity_type"), doctype.customer_name.as_("party_name")]) + fields.extend( + [doctype.customer_type.as_("party_entity_type"), doctype.customer_name.as_("party_name")] + ) query = frappe.qb.from_(doctype).select(*fields).where(doctype.name.isin(party_set)) party_details = query.run(as_dict=True) @@ -113,7 +121,7 @@ def get_columns(filters): { "label": _("Section Code"), "options": "Tax Withholding Category", - "fieldname": "section_code", + "fieldname": "tax_withholding_category", "fieldtype": "Link", "width": 90, }, @@ -133,7 +141,7 @@ def get_columns(filters): }, { "label": _("Entity Type"), - "fieldname": "entity_type", + "fieldname": "party_entity_type", "fieldtype": "Data", "width": 100, }, diff --git a/erpnext/accounts/report/tax_withholding_details/test_tax_withholding_details.py b/erpnext/accounts/report/tax_withholding_details/test_tax_withholding_details.py index 91683867188..fe33a83b39e 100644 --- a/erpnext/accounts/report/tax_withholding_details/test_tax_withholding_details.py +++ b/erpnext/accounts/report/tax_withholding_details/test_tax_withholding_details.py @@ -124,7 +124,7 @@ class TestTaxWithholdingDetails(ERPNextTestSuite, AccountsTestMixin): voucher_expected_values = expected_values[i] voucher_actual_values = ( voucher.ref_no, - voucher.section_code, + voucher.tax_withholding_category, voucher.rate, voucher.base_total, voucher.tax_amount, diff --git a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py index 59296602b3d..d0819650470 100644 --- a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py +++ b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py @@ -36,26 +36,26 @@ def group_by_party_and_category(data, filters): for row in data: party_category_wise_map.setdefault( - (row.get("party"), row.get("section_code")), + (row.get("party"), row.get("tax_withholding_category")), { "tax_id": row.get("tax_id"), "party": row.get("party"), "party_name": row.get("party_name"), - "section_code": row.get("section_code"), - "entity_type": row.get("entity_type"), + "tax_withholding_category": row.get("tax_withholding_category"), + "party_entity_type": row.get("party_entity_type"), "rate": row.get("rate"), "total_amount": 0.0, "tax_amount": 0.0, }, ) - party_category_wise_map.get((row.get("party"), row.get("section_code")))["total_amount"] += row.get( - "total_amount", 0.0 - ) + party_category_wise_map.get((row.get("party"), row.get("tax_withholding_category")))[ + "total_amount" + ] += row.get("total_amount", 0.0) - party_category_wise_map.get((row.get("party"), row.get("section_code")))["tax_amount"] += row.get( - "tax_amount", 0.0 - ) + party_category_wise_map.get((row.get("party"), row.get("tax_withholding_category")))[ + "tax_amount" + ] += row.get("tax_amount", 0.0) final_result = get_final_result(party_category_wise_map) @@ -89,13 +89,13 @@ def get_columns(filters): { "label": _("Section Code"), "options": "Tax Withholding Category", - "fieldname": "section_code", + "fieldname": "tax_withholding_category", "fieldtype": "Link", "width": 180, }, { "label": _("Entity Type"), - "fieldname": "entity_type", + "fieldname": "party_entity_type", "fieldtype": "Data", "width": 180, }, From be0e58fb234adc24c562b877c85d7ff66fcd0d19 Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Tue, 21 Apr 2026 18:04:02 +0530 Subject: [PATCH 05/56] refactor: how data is built (cherry picked from commit c3e7f7f02f9fabdbfc579ae0498350b1ad21857f) --- .../tax_withholding_details.py | 56 +++++++------------ 1 file changed, 19 insertions(+), 37 deletions(-) diff --git a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py index e6e3d834638..e3ef0dd3938 100644 --- a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py +++ b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py @@ -39,34 +39,9 @@ def get_tax_withholding_data(filters): party_details = get_party_details(entries) for entry in entries: - doc_details = frappe._dict() - if entry.taxable_name: - doc_details = doc_info.get((entry.taxable_doctype, entry.taxable_name), {}) - + doc_details = doc_info.get((entry.transaction_type, entry.ref_no), {}) if entry.ref_no else {} party_info = party_details.get((entry.party_type, entry.party), {}) - - row = { - "tax_withholding_category": entry.tax_withholding_category, - "party_entity_type": party_info.get("party_entity_type"), - "rate": entry.tax_rate, - "total_amount": entry.taxable_amount, - "grand_total": doc_details.get("grand_total", 0), - "base_total": doc_details.get("base_total", 0), - "tax_amount": entry.withholding_amount, - "transaction_date": entry.withholding_date, - "transaction_type": entry.taxable_doctype, - "ref_no": entry.taxable_name, - "taxable_date": entry.taxable_date, - "supplier_invoice_no": doc_details.get("bill_no"), - "supplier_invoice_date": doc_details.get("bill_date"), - "withholding_doctype": entry.withholding_doctype, - "withholding_name": entry.withholding_name, - "party_name": party_info.get("party_name"), - "tax_id": entry.tax_id, - "party": entry.party, - "party_type": entry.party_type, - } - data.append(row) + data.append({**entry, **doc_details, **party_info}) # Sort by section code, transaction date, then withholding_name for deterministic ordering data.sort( @@ -110,7 +85,7 @@ def get_party_details(entries): party_details = query.run(as_dict=True) for party in party_details: - party_map[(party_type, party.name)] = party + party_map[(party_type, party.pop("name"))] = party return party_map @@ -235,11 +210,11 @@ def get_tax_withholding_entries(filters): IfNull(twe.tax_id, "").as_("tax_id"), twe.tax_withholding_category, IfNull(twe.tax_withholding_group, "").as_("tax_withholding_group"), - twe.taxable_amount, - twe.tax_rate, - twe.withholding_amount, - IfNull(twe.taxable_doctype, "").as_("taxable_doctype"), - IfNull(twe.taxable_name, "").as_("taxable_name"), + twe.taxable_amount.as_("total_amount"), + twe.tax_rate.as_("rate"), + twe.withholding_amount.as_("tax_amount"), + IfNull(twe.taxable_doctype, "").as_("transaction_type"), + IfNull(twe.taxable_name, "").as_("ref_no"), twe.taxable_date, IfNull(twe.under_withheld_reason, "").as_("under_withheld_reason"), IfNull(twe.lower_deduction_certificate, "").as_("lower_deduction_certificate"), @@ -279,8 +254,8 @@ def get_additional_doc_info(entries): # Group documents by type for entry in entries: - if entry.taxable_name and entry.taxable_doctype in docs_by_type: - docs_by_type[entry.taxable_doctype].add(entry.taxable_name) + if entry.ref_no and entry.transaction_type in docs_by_type: + docs_by_type[entry.transaction_type].add(entry.ref_no) for doctype_name, voucher_set in docs_by_type.items(): if voucher_set: @@ -295,7 +270,14 @@ def _fetch_doc_info(doctype_name, voucher_set, doc_info): # Add doctype-specific fields if doctype_name == "Purchase Invoice": - fields.extend([doctype.grand_total, doctype.base_total, doctype.bill_no, doctype.bill_date]) + fields.extend( + [ + doctype.grand_total, + doctype.base_total, + doctype.bill_no.as_("supplier_invoice_no"), + doctype.bill_date.as_("supplier_invoice_date"), + ] + ) elif doctype_name == "Sales Invoice": fields.extend([doctype.grand_total, doctype.base_total]) elif doctype_name == "Payment Entry": @@ -311,4 +293,4 @@ def _fetch_doc_info(doctype_name, voucher_set, doc_info): entries = query.run(as_dict=True) for entry in entries: - doc_info[(doctype_name, entry.name)] = entry + doc_info[(doctype_name, entry.pop("name"))] = entry From fffaf834fd477368bf686031c5ad2ace7296d608 Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Tue, 21 Apr 2026 18:29:50 +0530 Subject: [PATCH 06/56] refactor: better label for entity type (cherry picked from commit 53666974a354166c4a4f69ab8f1d99742660f79a) --- .../report/tax_withholding_details/tax_withholding_details.py | 2 +- .../report/tds_computation_summary/tds_computation_summary.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py index e3ef0dd3938..4d385575d57 100644 --- a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py +++ b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py @@ -115,7 +115,7 @@ def get_columns(filters): "width": 180, }, { - "label": _("Entity Type"), + "label": _(f"{filters.get('party_type', 'Party')} Type"), "fieldname": "party_entity_type", "fieldtype": "Data", "width": 100, diff --git a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py index d0819650470..f09dfe7258b 100644 --- a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py +++ b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py @@ -94,7 +94,7 @@ def get_columns(filters): "width": 180, }, { - "label": _("Entity Type"), + "label": _(f"{filters.get('party_type', 'Party')} Type"), "fieldname": "party_entity_type", "fieldtype": "Data", "width": 180, From e6cfdb8e4deebe05360eed50d69d0af6019d063f Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Tue, 21 Apr 2026 18:45:26 +0530 Subject: [PATCH 07/56] refactor: updated key for withholding_date (cherry picked from commit 07b023a934d85f3b209de2c8c714ac427e2bc1e8) --- .../report/tax_withholding_details/tax_withholding_details.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py index 4d385575d57..675be4f5a3e 100644 --- a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py +++ b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py @@ -220,8 +220,7 @@ def get_tax_withholding_entries(filters): IfNull(twe.lower_deduction_certificate, "").as_("lower_deduction_certificate"), IfNull(twe.withholding_doctype, "").as_("withholding_doctype"), IfNull(twe.withholding_name, "").as_("withholding_name"), - twe.withholding_date, - twe.status, + twe.withholding_date.as_("transaction_date"), ) .where(twe.docstatus == 1) .where(twe.withholding_date >= filters.from_date) From 40466be9ef6ec159385aa1d867af3ddbdd25b45a Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Tue, 21 Apr 2026 19:33:29 +0530 Subject: [PATCH 08/56] test: None is better than zero, as no values exist (cherry picked from commit b5550f747ed84f19d6ade02e28979dc480cc4696) --- .../tax_withholding_details/test_tax_withholding_details.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/report/tax_withholding_details/test_tax_withholding_details.py b/erpnext/accounts/report/tax_withholding_details/test_tax_withholding_details.py index fe33a83b39e..de03aaef77e 100644 --- a/erpnext/accounts/report/tax_withholding_details/test_tax_withholding_details.py +++ b/erpnext/accounts/report/tax_withholding_details/test_tax_withholding_details.py @@ -40,7 +40,7 @@ class TestTaxWithholdingDetails(ERPNextTestSuite, AccountsTestMixin): expected_values = [ [jv.name, "TCS", 0.075, 1000.75, 0.75, 1000.75], - ["", "TCS", 0.075, 0, 0.75, 0], + ["", "TCS", 0.075, None, 0.75, None], [si.name, "TCS", 0.075, 1000.0, 0.75, 1000.75], ] self.check_expected_values(result, expected_values) From 6392126ca5328b06d1509e7dabdfbbb29743eae8 Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Wed, 22 Apr 2026 12:04:35 +0530 Subject: [PATCH 09/56] refactor: make report extensible by regional apps (cherry picked from commit f0ea20e579c1fab4dd479a39bde1d0e25b9593fb) --- .../tax_withholding_details.py | 508 +++++++++--------- .../tds_computation_summary.py | 176 +++--- 2 files changed, 324 insertions(+), 360 deletions(-) diff --git a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py index 675be4f5a3e..554a669512a 100644 --- a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py +++ b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py @@ -6,290 +6,282 @@ from frappe import _ from frappe.query_builder.functions import IfNull -def execute(filters=None): - """Generate Tax Withholding Details report""" - validate_filters(filters) +class TaxWithholdingDetailsReport: + party_types = ("Customer", "Supplier") + document_types = ("Purchase Invoice", "Sales Invoice", "Payment Entry", "Journal Entry") - # Process and format data - data = get_tax_withholding_data(filters) - columns = get_columns(filters) + def __init__(self, filters=None): + self.filters = frappe._dict(filters or {}) + self.entries = [] + self.doc_info = {} + self.party_details = {} - return columns, data + @classmethod + def execute(cls, filters=None): + return cls(filters).run() + def run(self): + self.validate_filters() + return self.get_columns(), self.get_data() -def validate_filters(filters): - """Validate report filters""" - filters = frappe._dict(filters or {}) + def validate_filters(self): + if not self.filters.from_date or not self.filters.to_date: + frappe.throw(_("From Date and To Date are required")) - if not filters.from_date or not filters.to_date: - frappe.throw(_("From Date and To Date are required")) + if self.filters.from_date > self.filters.to_date: + frappe.throw(_("From Date must be before To Date")) - if filters.from_date > filters.to_date: - frappe.throw(_("From Date must be before To Date")) + def get_data(self): + self.entries = self.get_entries_query().run(as_dict=True) + if not self.entries: + return [] + self.doc_info = self.fetch_additional_doc_info() + self.party_details = self.fetch_party_details() + return self.build_rows() -def get_tax_withholding_data(filters): - """Process entries into final report format""" - data = [] - entries = get_tax_withholding_entries(filters) - if not entries: - return data + def build_rows(self): + rows = [] + for entry in self.entries: + doc_details = ( + self.doc_info.get((entry.transaction_type, entry.ref_no), {}) if entry.ref_no else {} + ) + party_info = self.party_details.get((entry.party_type, entry.party), {}) + rows.append({**entry, **doc_details, **party_info}) - doc_info = get_additional_doc_info(entries) - party_details = get_party_details(entries) - - for entry in entries: - doc_details = doc_info.get((entry.transaction_type, entry.ref_no), {}) if entry.ref_no else {} - party_info = party_details.get((entry.party_type, entry.party), {}) - data.append({**entry, **doc_details, **party_info}) - - # Sort by section code, transaction date, then withholding_name for deterministic ordering - data.sort( - key=lambda x: ( - x["tax_withholding_category"] or "", - x["transaction_date"] or "", - x["withholding_name"] or "", + rows.sort( + key=lambda x: ( + x["tax_withholding_category"] or "", + x["transaction_date"] or "", + x["withholding_name"] or "", + ) ) - ) - return data + return rows + def get_entries_query(self): + twe = frappe.qb.DocType("Tax Withholding Entry") + query = ( + frappe.qb.from_(twe) + .select( + twe.party_type, + twe.party, + IfNull(twe.tax_id, "").as_("tax_id"), + twe.tax_withholding_category, + twe.taxable_amount.as_("total_amount"), + twe.tax_rate.as_("rate"), + twe.withholding_amount.as_("tax_amount"), + IfNull(twe.taxable_doctype, "").as_("transaction_type"), + IfNull(twe.taxable_name, "").as_("ref_no"), + twe.taxable_date, + IfNull(twe.withholding_doctype, "").as_("withholding_doctype"), + IfNull(twe.withholding_name, "").as_("withholding_name"), + twe.withholding_date.as_("transaction_date"), + ) + .where(twe.docstatus == 1) + .where(twe.withholding_date >= self.filters.from_date) + .where(twe.withholding_date <= self.filters.to_date) + .where(IfNull(twe.withholding_name, "") != "") + .where(twe.status != "Duplicate") + ) -def get_party_details(entries): - """Fetch party details in batch for all entries""" - party_map = frappe._dict() - parties_by_type = {"Customer": set(), "Supplier": set()} + if self.filters.company: + query = query.where(twe.company == self.filters.company) + if self.filters.party_type: + query = query.where(twe.party_type == self.filters.party_type) + if self.filters.party: + query = query.where(twe.party == self.filters.party) - # Group parties by type - for entry in entries: - if entry.party_type in parties_by_type and entry.party: - parties_by_type[entry.party_type].add(entry.party) + return query - # Batch fetch for each party type - for party_type, party_set in parties_by_type.items(): - if not party_type or not party_set: - continue + def fetch_party_details(self): + parties_by_type = {pt: set() for pt in self.party_types} + for entry in self.entries: + if entry.party_type in parties_by_type and entry.party: + parties_by_type[entry.party_type].add(entry.party) + party_map = {} + for party_type, party_set in parties_by_type.items(): + if not party_set: + continue + + query = self.get_party_query(party_type, party_set) + if query is None: + continue + + for row in query.run(as_dict=True): + party_map[(party_type, row.pop("name"))] = row + + return party_map + + def get_party_query(self, party_type, party_set): doctype = frappe.qb.DocType(party_type) fields = [doctype.name] if party_type == "Supplier": fields.extend( - [doctype.supplier_type.as_("party_entity_type"), doctype.supplier_name.as_("party_name")] + [ + doctype.supplier_type.as_("party_entity_type"), + doctype.supplier_name.as_("party_name"), + ] ) elif party_type == "Customer": fields.extend( - [doctype.customer_type.as_("party_entity_type"), doctype.customer_name.as_("party_name")] + [ + doctype.customer_type.as_("party_entity_type"), + doctype.customer_name.as_("party_name"), + ] ) + else: + return None - query = frappe.qb.from_(doctype).select(*fields).where(doctype.name.isin(party_set)) - party_details = query.run(as_dict=True) + return frappe.qb.from_(doctype).select(*fields).where(doctype.name.isin(party_set)) - for party in party_details: - party_map[(party_type, party.pop("name"))] = party + def fetch_additional_doc_info(self): + docs_by_type = {dt: set() for dt in self.document_types} + for entry in self.entries: + if entry.ref_no and entry.transaction_type in docs_by_type: + docs_by_type[entry.transaction_type].add(entry.ref_no) - return party_map + doc_info = {} + for doctype_name, voucher_set in docs_by_type.items(): + if not voucher_set: + continue + + query = self.get_doc_info_query(doctype_name, voucher_set) + if query is None: + continue + + for row in query.run(as_dict=True): + doc_info[(doctype_name, row.pop("name"))] = row + + return doc_info + + def get_doc_info_query(self, doctype_name, voucher_set): + if doctype_name == "Purchase Invoice": + get_doc_fields = self.get_purchase_invoice_fields + elif doctype_name == "Sales Invoice": + get_doc_fields = self.get_sales_invoice_fields + elif doctype_name == "Payment Entry": + get_doc_fields = self.get_payment_entry_fields + elif doctype_name == "Journal Entry": + get_doc_fields = self.get_journal_entry_fields + else: + return None + + doctype = frappe.qb.DocType(doctype_name) + fields = [doctype.name, *get_doc_fields(doctype)] + return frappe.qb.from_(doctype).select(*fields).where(doctype.name.isin(voucher_set)) + + def get_purchase_invoice_fields(self, doctype): + return [ + doctype.grand_total, + doctype.base_total, + doctype.bill_no.as_("supplier_invoice_no"), + doctype.bill_date.as_("supplier_invoice_date"), + ] + + def get_sales_invoice_fields(self, doctype): + return [doctype.grand_total, doctype.base_total] + + def get_payment_entry_fields(self, doctype): + return [ + doctype.paid_amount_after_tax.as_("grand_total"), + doctype.base_paid_amount.as_("base_total"), + ] + + def get_journal_entry_fields(self, doctype): + return [doctype.total_debit.as_("grand_total"), doctype.total_debit.as_("base_total")] + + def get_columns(self): + party_type = self.filters.get("party_type", "Party") + return [ + { + "label": _("Tax Withholding Category"), + "options": "Tax Withholding Category", + "fieldname": "tax_withholding_category", + "fieldtype": "Link", + "width": 90, + }, + {"label": _("Tax Id"), "fieldname": "tax_id", "fieldtype": "Data", "width": 60}, + { + "label": _(f"{party_type} Name"), + "fieldname": "party_name", + "fieldtype": "Data", + "width": 180, + }, + { + "label": _(party_type), + "fieldname": "party", + "fieldtype": "Dynamic Link", + "options": "party_type", + "width": 180, + }, + { + "label": _(f"{party_type} Type"), + "fieldname": "party_entity_type", + "fieldtype": "Data", + "width": 100, + }, + { + "label": _("Supplier Invoice No"), + "fieldname": "supplier_invoice_no", + "fieldtype": "Data", + "width": 120, + }, + { + "label": _("Supplier Invoice Date"), + "fieldname": "supplier_invoice_date", + "fieldtype": "Date", + "width": 120, + }, + {"label": _("Tax Rate %"), "fieldname": "rate", "fieldtype": "Percent", "width": 60}, + { + "label": _("Taxable Amount"), + "fieldname": "total_amount", + "fieldtype": "Currency", + "width": 120, + }, + {"label": _("Tax Amount"), "fieldname": "tax_amount", "fieldtype": "Currency", "width": 120}, + { + "label": _("Grand Total (Company Currency)"), + "fieldname": "base_total", + "fieldtype": "Currency", + "width": 150, + }, + { + "label": _("Grand Total (Transaction Currency)"), + "fieldname": "grand_total", + "fieldtype": "Currency", + "width": 170, + }, + {"label": _("Reference Date"), "fieldname": "taxable_date", "fieldtype": "Date", "width": 100}, + { + "label": _("Transaction Type"), + "fieldname": "transaction_type", + "fieldtype": "Data", + "width": 130, + }, + { + "label": _("Reference No."), + "fieldname": "ref_no", + "fieldtype": "Dynamic Link", + "options": "transaction_type", + "width": 180, + }, + { + "label": _("Date of Transaction"), + "fieldname": "transaction_date", + "fieldtype": "Date", + "width": 100, + }, + { + "label": _("Withholding Document"), + "fieldname": "withholding_name", + "fieldtype": "Dynamic Link", + "options": "withholding_doctype", + "width": 150, + }, + ] -def get_columns(filters): - """Generate report columns based on filters""" - columns = [ - { - "label": _("Section Code"), - "options": "Tax Withholding Category", - "fieldname": "tax_withholding_category", - "fieldtype": "Link", - "width": 90, - }, - {"label": _("Tax Id"), "fieldname": "tax_id", "fieldtype": "Data", "width": 60}, - { - "label": _(f"{filters.get('party_type', 'Party')} Name"), - "fieldname": "party_name", - "fieldtype": "Data", - "width": 180, - }, - { - "label": _(filters.get("party_type", "Party")), - "fieldname": "party", - "fieldtype": "Dynamic Link", - "options": "party_type", - "width": 180, - }, - { - "label": _(f"{filters.get('party_type', 'Party')} Type"), - "fieldname": "party_entity_type", - "fieldtype": "Data", - "width": 100, - }, - { - "label": _("Supplier Invoice No"), - "fieldname": "supplier_invoice_no", - "fieldtype": "Data", - "width": 120, - }, - { - "label": _("Supplier Invoice Date"), - "fieldname": "supplier_invoice_date", - "fieldtype": "Date", - "width": 120, - }, - { - "label": _("Tax Rate %"), - "fieldname": "rate", - "fieldtype": "Percent", - "width": 60, - }, - { - "label": _("Taxable Amount"), - "fieldname": "total_amount", - "fieldtype": "Currency", - "width": 120, - }, - { - "label": _("Tax Amount"), - "fieldname": "tax_amount", - "fieldtype": "Currency", - "width": 120, - }, - { - "label": _("Grand Total (Company Currency)"), - "fieldname": "base_total", - "fieldtype": "Currency", - "width": 150, - }, - { - "label": _("Grand Total (Transaction Currency)"), - "fieldname": "grand_total", - "fieldtype": "Currency", - "width": 170, - }, - { - "label": _("Reference Date"), - "fieldname": "taxable_date", - "fieldtype": "Date", - "width": 100, - }, - { - "label": _("Transaction Type"), - "fieldname": "transaction_type", - "fieldtype": "Data", - "width": 130, - }, - { - "label": _("Reference No."), - "fieldname": "ref_no", - "fieldtype": "Dynamic Link", - "options": "transaction_type", - "width": 180, - }, - { - "label": _("Date of Transaction"), - "fieldname": "transaction_date", - "fieldtype": "Date", - "width": 100, - }, - { - "label": _("Withholding Document"), - "fieldname": "withholding_name", - "fieldtype": "Dynamic Link", - "options": "withholding_doctype", - "width": 150, - }, - ] - - return columns - - -def get_tax_withholding_entries(filters): - twe = frappe.qb.DocType("Tax Withholding Entry") - query = ( - frappe.qb.from_(twe) - .select( - twe.company, - twe.party_type, - twe.party, - IfNull(twe.tax_id, "").as_("tax_id"), - twe.tax_withholding_category, - IfNull(twe.tax_withholding_group, "").as_("tax_withholding_group"), - twe.taxable_amount.as_("total_amount"), - twe.tax_rate.as_("rate"), - twe.withholding_amount.as_("tax_amount"), - IfNull(twe.taxable_doctype, "").as_("transaction_type"), - IfNull(twe.taxable_name, "").as_("ref_no"), - twe.taxable_date, - IfNull(twe.under_withheld_reason, "").as_("under_withheld_reason"), - IfNull(twe.lower_deduction_certificate, "").as_("lower_deduction_certificate"), - IfNull(twe.withholding_doctype, "").as_("withholding_doctype"), - IfNull(twe.withholding_name, "").as_("withholding_name"), - twe.withholding_date.as_("transaction_date"), - ) - .where(twe.docstatus == 1) - .where(twe.withholding_date >= filters.from_date) - .where(twe.withholding_date <= filters.to_date) - .where(IfNull(twe.withholding_name, "") != "") - .where(twe.status != "Duplicate") - ) - - if filters.get("company"): - query = query.where(twe.company == filters.get("company")) - - if filters.get("party_type"): - query = query.where(twe.party_type == filters.get("party_type")) - - if filters.get("party"): - query = query.where(twe.party == filters.get("party")) - - return query.run(as_dict=True) - - -def get_additional_doc_info(entries): - """Fetch additional document information in batch""" - doc_info = {} - docs_by_type = { - "Purchase Invoice": set(), - "Sales Invoice": set(), - "Payment Entry": set(), - "Journal Entry": set(), - } - - # Group documents by type - for entry in entries: - if entry.ref_no and entry.transaction_type in docs_by_type: - docs_by_type[entry.transaction_type].add(entry.ref_no) - - for doctype_name, voucher_set in docs_by_type.items(): - if voucher_set: - _fetch_doc_info(doctype_name, voucher_set, doc_info) - - return doc_info - - -def _fetch_doc_info(doctype_name, voucher_set, doc_info): - doctype = frappe.qb.DocType(doctype_name) - fields = [doctype.name] - - # Add doctype-specific fields - if doctype_name == "Purchase Invoice": - fields.extend( - [ - doctype.grand_total, - doctype.base_total, - doctype.bill_no.as_("supplier_invoice_no"), - doctype.bill_date.as_("supplier_invoice_date"), - ] - ) - elif doctype_name == "Sales Invoice": - fields.extend([doctype.grand_total, doctype.base_total]) - elif doctype_name == "Payment Entry": - fields.extend( - [doctype.paid_amount_after_tax.as_("grand_total"), doctype.base_paid_amount.as_("base_total")] - ) - elif doctype_name == "Journal Entry": - fields.extend([doctype.total_debit.as_("grand_total"), doctype.total_debit.as_("base_total")]) - else: - return - - query = frappe.qb.from_(doctype).select(*fields).where(doctype.name.isin(voucher_set)) - entries = query.run(as_dict=True) - - for entry in entries: - doc_info[(doctype_name, entry.pop("name"))] = entry +execute = TaxWithholdingDetailsReport.execute diff --git a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py index f09dfe7258b..227f9bcb3fa 100644 --- a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py +++ b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py @@ -2,121 +2,93 @@ import frappe from frappe import _ from erpnext.accounts.report.tax_withholding_details.tax_withholding_details import ( - get_tax_withholding_data, + TaxWithholdingDetailsReport, ) from erpnext.accounts.utils import get_fiscal_year -def execute(filters=None): - validate_filters(filters) +class TDSComputationSummaryReport(TaxWithholdingDetailsReport): + GROUP_BY_FIELDS = ("party", "tax_withholding_category") + CARRY_OVER_FIELDS = ( + "tax_id", + "party", + "party_name", + "tax_withholding_category", + "party_entity_type", + "rate", + ) + AGGREGATE_FIELDS = ("total_amount", "tax_amount") - data = get_tax_withholding_data(filters) - columns = get_columns(filters) + def validate_filters(self): + if self.filters.from_date > self.filters.to_date: + frappe.throw(_("From Date must be before To Date")) - final_result = group_by_party_and_category(data, filters) + from_year = get_fiscal_year(self.filters.from_date)[0] + to_year = get_fiscal_year(self.filters.to_date)[0] + if from_year != to_year: + frappe.throw(_("From Date and To Date lie in different Fiscal Year")) - return columns, final_result + self.filters.fiscal_year = from_year + def get_data(self): + return self.group_rows(super().get_data()) -def validate_filters(filters): - """Validate if dates are properly set and lie in the same fiscal year""" - if filters.from_date > filters.to_date: - frappe.throw(_("From Date must be before To Date")) + def group_rows(self, data): + grouped = {} + for row in data: + key = tuple(row.get(f) for f in self.GROUP_BY_FIELDS) + bucket = grouped.setdefault( + key, + { + **{f: row.get(f) for f in self.CARRY_OVER_FIELDS}, + **{f: 0.0 for f in self.AGGREGATE_FIELDS}, + }, + ) - from_year = get_fiscal_year(filters.from_date)[0] - to_year = get_fiscal_year(filters.to_date)[0] - if from_year != to_year: - frappe.throw(_("From Date and To Date lie in different Fiscal Year")) + for f in self.AGGREGATE_FIELDS: + bucket[f] += row.get(f) or 0.0 - filters["fiscal_year"] = from_year + return list(grouped.values()) - -def group_by_party_and_category(data, filters): - party_category_wise_map = {} - - for row in data: - party_category_wise_map.setdefault( - (row.get("party"), row.get("tax_withholding_category")), + def get_columns(self): + party_type = self.filters.get("party_type", "Party") + return [ + {"label": _("Tax Id"), "fieldname": "tax_id", "fieldtype": "Data", "width": 90}, { - "tax_id": row.get("tax_id"), - "party": row.get("party"), - "party_name": row.get("party_name"), - "tax_withholding_category": row.get("tax_withholding_category"), - "party_entity_type": row.get("party_entity_type"), - "rate": row.get("rate"), - "total_amount": 0.0, - "tax_amount": 0.0, + "label": _(party_type), + "fieldname": "party", + "fieldtype": "Dynamic Link", + "options": "party_type", + "width": 180, }, - ) - - party_category_wise_map.get((row.get("party"), row.get("tax_withholding_category")))[ - "total_amount" - ] += row.get("total_amount", 0.0) - - party_category_wise_map.get((row.get("party"), row.get("tax_withholding_category")))[ - "tax_amount" - ] += row.get("tax_amount", 0.0) - - final_result = get_final_result(party_category_wise_map) - - return final_result + { + "label": _(f"{party_type} Name"), + "fieldname": "party_name", + "fieldtype": "Data", + "width": 180, + }, + { + "label": _("Tax Withholding Category"), + "options": "Tax Withholding Category", + "fieldname": "tax_withholding_category", + "fieldtype": "Link", + "width": 180, + }, + { + "label": _(f"{party_type} Type"), + "fieldname": "party_entity_type", + "fieldtype": "Data", + "width": 180, + }, + {"label": _("Tax Rate %"), "fieldname": "rate", "fieldtype": "Percent", "width": 120}, + { + "label": _("Total Taxable Amount"), + "fieldname": "total_amount", + "fieldtype": "Float", + "width": 120, + }, + {"label": _("Tax Amount"), "fieldname": "tax_amount", "fieldtype": "Float", "width": 120}, + ] -def get_final_result(party_category_wise_map): - out = [] - for _key, value in party_category_wise_map.items(): - out.append(value) - - return out - - -def get_columns(filters): - columns = [ - {"label": _("Tax Id"), "fieldname": "tax_id", "fieldtype": "Data", "width": 90}, - { - "label": _(filters.get("party_type")), - "fieldname": "party", - "fieldtype": "Dynamic Link", - "options": "party_type", - "width": 180, - }, - { - "label": _(f"{filters.get('party_type', 'Party')} Name"), - "fieldname": "party_name", - "fieldtype": "Data", - "width": 180, - }, - { - "label": _("Section Code"), - "options": "Tax Withholding Category", - "fieldname": "tax_withholding_category", - "fieldtype": "Link", - "width": 180, - }, - { - "label": _(f"{filters.get('party_type', 'Party')} Type"), - "fieldname": "party_entity_type", - "fieldtype": "Data", - "width": 180, - }, - { - "label": _("Tax Rate %"), - "fieldname": "rate", - "fieldtype": "Percent", - "width": 120, - }, - { - "label": _("Total Taxable Amount"), - "fieldname": "total_amount", - "fieldtype": "Float", - "width": 120, - }, - { - "label": _("Tax Amount"), - "fieldname": "tax_amount", - "fieldtype": "Float", - "width": 120, - }, - ] - - return columns +execute = TDSComputationSummaryReport.execute From c6d48028576e726d1e8c1977f06f04ceafaed2a9 Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Wed, 22 Apr 2026 12:06:38 +0530 Subject: [PATCH 10/56] fix: add party type for dynamic link support (cherry picked from commit b925469c4d1ddb9c482b7506c1ec554c54838275) --- .../report/tds_computation_summary/tds_computation_summary.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py index 227f9bcb3fa..3ab3986b013 100644 --- a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py +++ b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py @@ -8,10 +8,11 @@ from erpnext.accounts.utils import get_fiscal_year class TDSComputationSummaryReport(TaxWithholdingDetailsReport): - GROUP_BY_FIELDS = ("party", "tax_withholding_category") + GROUP_BY_FIELDS = ("party_type", "party", "tax_withholding_category") CARRY_OVER_FIELDS = ( "tax_id", "party", + "party_type", "party_name", "tax_withholding_category", "party_entity_type", From 055ff56ce4c32a731e0708f764bf740aa9602a39 Mon Sep 17 00:00:00 2001 From: Abdeali Chharchhodawala <99460106+Abdeali099@users.noreply.github.com> Date: Thu, 23 Apr 2026 17:15:41 +0530 Subject: [PATCH 11/56] feat: Add XLSX styling support to custom financial report templates (#52612) (cherry picked from commit c35221852a334778f60872fa0c58a7adac0ddbfa) --- .../financial_report_engine.py | 132 +++++++++++++++++- .../report/balance_sheet/balance_sheet.py | 1 + .../accounts/report/cash_flow/cash_flow.py | 1 + .../custom_financial_statement.py | 1 + .../profit_and_loss_statement.py | 1 + erpnext/public/js/financial_statements.js | 1 + 6 files changed, 134 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py b/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py index b5bd3a00a9f..46369b07cd9 100644 --- a/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py +++ b/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py @@ -6,7 +6,7 @@ import json import math from abc import ABC, abstractmethod from dataclasses import dataclass, field -from functools import reduce +from functools import cache, reduce from typing import Any, Union import frappe @@ -15,6 +15,7 @@ from frappe.database.operator_map import OPERATOR_MAP from frappe.query_builder import Case from frappe.query_builder.functions import Sum from frappe.utils import cstr, date_diff, flt, getdate +from frappe.utils.xlsxutils import XLSXMetadata, XLSXStyleBuilder from pypika.terms import Bracket, LiteralValue from erpnext import get_company_currency @@ -38,6 +39,9 @@ from erpnext.accounts.report.financial_statements import ( ) from erpnext.accounts.utils import get_children, get_currency_precision +DEFAULT_BULLET_PREFIX = "• " +SEGMENT_PREFIX = "seg_" + # ============================================================================ # DATA MODELS # ============================================================================ @@ -141,7 +145,7 @@ class SegmentData: @property def id(self) -> str: - return f"seg_{self.index}" + return f"{SEGMENT_PREFIX}{self.index}" @dataclass @@ -1392,7 +1396,8 @@ class FormattingEngine: condition=lambda rd: getattr(rd.row, "italic_text", False), format_properties={"italic": True} ), FormattingRule( - condition=lambda rd: rd.is_detail_row, format_properties={"is_detail": True, "prefix": "• "} + condition=lambda rd: rd.is_detail_row, + format_properties={"is_detail": True, "prefix": DEFAULT_BULLET_PREFIX}, ), FormattingRule( condition=lambda rd: getattr(rd.row, "warn_if_negative", False), @@ -1838,3 +1843,124 @@ class GrowthViewTransformer: return 0.0 else: return flt(((current_value - previous_value) / abs(previous_value)) * 100, 2) + + +# ============================================================================ +# XLSX EXPORT STYLING +# ============================================================================ + + +def get_xlsx_styles(metadata: XLSXMetadata) -> dict | None: + """ + Generate XLSX styles for financial report templates. + + NOTE: Currently only custom report generated with "Report Template" filter will have styles applied. + """ + # skip styling + if not metadata.filters.get("report_template"): + return + + builder = XLSXStyleBuilder(metadata, default_styling=False) + builder.apply_default_styles(currency_formatting=False) + + # currency is fixed for all columns (only if report template filter is applied) + currency = get_company_currency(metadata.filters.get("company")) + + styles = { + "bold": builder.register_style({"bold": True}), + "italic": builder.register_style({"italic": True}), + "warning": builder.register_style({"font_color": "#dc3545"}), # text-danger + } + + fieldtype_formats = { + "Int": builder.register_style({"num_format": "General"}), + "Float": builder.register_style({"num_format": builder.get_number_format("Float")}), + "Percent": builder.register_style({"num_format": builder.get_number_format("Percent")}), + "Currency": builder.register_style({"num_format": builder.get_number_format("Currency", currency)}), + } + + # quick access for hot loop + style_cell = builder.style_cell + + @cache + def get_color_style(color: str) -> int: + return builder.register_style({"font_color": color}) + + @cache + def get_prefix_style(prefix: str) -> int: + prefix = f"{prefix or DEFAULT_BULLET_PREFIX}@" + + return builder.register_style({"num_format": prefix}) + + @cache + def get_indent_style(indent: int) -> int: + return builder.register_style({"align": "left", "indent": indent}) + + # column level styling of currency columns + for col_idx, col in metadata.column_map.items(): + if col.get("fieldtype") != "Currency": + continue + + builder.style_column(col_idx, fieldtype_formats["Currency"]) + + # cell level styling + for row_idx, row in metadata.row_map.items(): + # skip total row + if metadata.has_total_row and row_idx == builder.last_row_index: + continue + + is_segmented = (row.get("_segment_info", {}).get("total_segments", 1) or 1) > 1 + segment_values = row.get("segment_values", {}) or {} + + for col_idx, col in metadata.column_map.items(): + fieldname = col.get("fieldname") + is_account = fieldname == "account" + + # determine formatting bucket + if is_segmented and fieldname.startswith(SEGMENT_PREFIX): + formatting = row.copy() + + _, seg_idx, seg_fieldname = fieldname.split("_", 2) + is_account = seg_fieldname == "account" + formatting.update(segment_values.get(f"{SEGMENT_PREFIX}{seg_idx}", {}) or {}) + else: + formatting = row # default formatting bucket. + + if not is_account and formatting.get("is_blank_line"): + continue + + col_fieldtype = col.get("fieldtype") + cell_fieldtype = formatting.get("fieldtype") or col_fieldtype + cell_value = row.get(fieldname) + + if cell_value in (None, ""): + continue + + # account column and other fieldtype styling + if is_account: + if formatting.get("is_detail") or (prefix := formatting.get("prefix")): + style_cell(row_idx, col_idx, get_prefix_style(prefix)) + + # custom indentation (different segment might have different indentation levels) + if is_segmented and (indent := formatting.get("indent")) and indent > 0: + style_cell(row_idx, col_idx, get_indent_style(indent)) + else: + if col_fieldtype != cell_fieldtype and cell_fieldtype in fieldtype_formats: + style_cell(row_idx, col_idx, fieldtype_formats[cell_fieldtype]) + + # text styles + for style_key in ("bold", "italic"): + if formatting.get(style_key): + style_cell(row_idx, col_idx, styles[style_key]) + + # color styles + if ( + formatting.get("warn_if_negative") + and cell_fieldtype in frappe.model.numeric_fieldtypes + and flt(cell_value) < 0 + ): + style_cell(row_idx, col_idx, styles["warning"]) + elif color := formatting.get("color"): + style_cell(row_idx, col_idx, get_color_style(color)) + + return builder.result diff --git a/erpnext/accounts/report/balance_sheet/balance_sheet.py b/erpnext/accounts/report/balance_sheet/balance_sheet.py index 97a903133da..a8531e58acb 100644 --- a/erpnext/accounts/report/balance_sheet/balance_sheet.py +++ b/erpnext/accounts/report/balance_sheet/balance_sheet.py @@ -8,6 +8,7 @@ from frappe.utils import cint, flt from erpnext.accounts.doctype.financial_report_template.financial_report_engine import ( FinancialReportEngine, + get_xlsx_styles, #! DO NOT REMOVE - hook for styling ) from erpnext.accounts.report.financial_statements import ( compute_growth_view_data, diff --git a/erpnext/accounts/report/cash_flow/cash_flow.py b/erpnext/accounts/report/cash_flow/cash_flow.py index 462d34b874f..a62867ba91c 100644 --- a/erpnext/accounts/report/cash_flow/cash_flow.py +++ b/erpnext/accounts/report/cash_flow/cash_flow.py @@ -12,6 +12,7 @@ from pypika import Order from erpnext.accounts.doctype.financial_report_template.financial_report_engine import ( FinancialReportEngine, + get_xlsx_styles, #! DO NOT REMOVE - hook for styling ) from erpnext.accounts.report.financial_statements import ( get_columns, diff --git a/erpnext/accounts/report/custom_financial_statement/custom_financial_statement.py b/erpnext/accounts/report/custom_financial_statement/custom_financial_statement.py index dc506071f01..eeb5a336a8e 100644 --- a/erpnext/accounts/report/custom_financial_statement/custom_financial_statement.py +++ b/erpnext/accounts/report/custom_financial_statement/custom_financial_statement.py @@ -3,6 +3,7 @@ from erpnext.accounts.doctype.financial_report_template.financial_report_engine import ( FinancialReportEngine, + get_xlsx_styles, #! DO NOT REMOVE - hook for styling ) diff --git a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py index 74290ec21b4..9ce6cd77e5b 100644 --- a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py +++ b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py @@ -8,6 +8,7 @@ from frappe.utils import flt from erpnext.accounts.doctype.financial_report_template.financial_report_engine import ( FinancialReportEngine, + get_xlsx_styles, #! DO NOT REMOVE - hook for styling ) from erpnext.accounts.report.financial_statements import ( compute_growth_view_data, diff --git a/erpnext/public/js/financial_statements.js b/erpnext/public/js/financial_statements.js index 0c8366d4e95..cdfb8f8a2ca 100644 --- a/erpnext/public/js/financial_statements.js +++ b/erpnext/public/js/financial_statements.js @@ -455,6 +455,7 @@ function get_filters() { label: __("Currency"), fieldtype: "Select", options: erpnext.get_presentation_currency_list(), + depends_on: "eval: !doc.report_template", }, { fieldname: "cost_center", From 96bab08ae0f4fd2cc71d64ba60bb12cc80b56aea Mon Sep 17 00:00:00 2001 From: Abdeali Chharchhodawala <99460106+Abdeali099@users.noreply.github.com> Date: Thu, 23 Apr 2026 17:34:37 +0530 Subject: [PATCH 12/56] feat: enhance account category with root type (#53190) (cherry picked from commit f6639db0e95d9769a8c13768e131379c7a1e3c8c) --- erpnext/accounts/doctype/account/account.js | 22 +++++++++++-- .../account_category/account_category.json | 19 +++++++++-- .../account_category/account_category.py | 1 + .../account_categories.json | 31 +++++++++++++++++- erpnext/patches.txt | 1 + .../set_root_type_in_account_categories.py | 32 +++++++++++++++++++ 6 files changed, 101 insertions(+), 5 deletions(-) create mode 100644 erpnext/patches/v16_0/set_root_type_in_account_categories.py diff --git a/erpnext/accounts/doctype/account/account.js b/erpnext/accounts/doctype/account/account.js index ff44723afee..ae5d0e35523 100644 --- a/erpnext/accounts/doctype/account/account.js +++ b/erpnext/accounts/doctype/account/account.js @@ -5,8 +5,7 @@ frappe.ui.form.on("Account", { setup: function (frm) { frm.add_fetch("parent_account", "report_type", "report_type"); frm.add_fetch("parent_account", "root_type", "root_type"); - }, - onload: function (frm) { + frm.set_query("parent_account", function (doc) { return { filters: { @@ -15,7 +14,18 @@ frappe.ui.form.on("Account", { }, }; }); + + frm.set_query("account_category", function () { + if (!frm.doc.root_type) return; + + return { + filters: { + root_type: ["in", [frm.doc.root_type, ""]], + }, + }; + }); }, + refresh: function (frm) { frm.toggle_display("account_name", frm.is_new()); @@ -58,12 +68,20 @@ frappe.ui.form.on("Account", { } } }, + account_type: function (frm) { if (frm.doc.is_group == 0) { frm.toggle_display(["tax_rate"], frm.doc.account_type == "Tax"); frm.toggle_display("warehouse", frm.doc.account_type == "Stock"); } }, + + root_type: function (frm) { + if (frm.doc.account_category) { + frm.set_value("account_category", ""); + } + }, + add_toolbar_buttons: function (frm) { frm.add_custom_button( __("Chart of Accounts"), diff --git a/erpnext/accounts/doctype/account_category/account_category.json b/erpnext/accounts/doctype/account_category/account_category.json index cc8f4103f21..694ac06b082 100644 --- a/erpnext/accounts/doctype/account_category/account_category.json +++ b/erpnext/accounts/doctype/account_category/account_category.json @@ -7,6 +7,8 @@ "engine": "InnoDB", "field_order": [ "account_category_name", + "root_type", + "column_break_qluu", "description" ], "fields": [ @@ -14,6 +16,7 @@ "fieldname": "account_category_name", "fieldtype": "Data", "in_list_view": 1, + "in_standard_filter": 1, "label": "Account Category Name", "reqd": 1, "unique": 1 @@ -22,6 +25,18 @@ "fieldname": "description", "fieldtype": "Small Text", "label": "Description" + }, + { + "fieldname": "column_break_qluu", + "fieldtype": "Column Break" + }, + { + "fieldname": "root_type", + "fieldtype": "Select", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Root Type", + "options": "\nAsset\nLiability\nIncome\nExpense\nEquity" } ], "grid_page_length": 50, @@ -32,7 +47,7 @@ "link_fieldname": "account_category" } ], - "modified": "2026-02-23 01:19:49.589393", + "modified": "2026-03-05 06:49:34.430723", "modified_by": "Administrator", "module": "Accounts", "name": "Account Category", @@ -69,7 +84,7 @@ } ], "row_format": "Dynamic", - "search_fields": "account_category_name, description", + "search_fields": "account_category_name, root_type", "sort_field": "creation", "sort_order": "DESC", "states": [] diff --git a/erpnext/accounts/doctype/account_category/account_category.py b/erpnext/accounts/doctype/account_category/account_category.py index 8be84d0f8e2..f11ac18969e 100644 --- a/erpnext/accounts/doctype/account_category/account_category.py +++ b/erpnext/accounts/doctype/account_category/account_category.py @@ -21,6 +21,7 @@ class AccountCategory(Document): account_category_name: DF.Data description: DF.SmallText | None + root_type: DF.Literal["", "Asset", "Liability", "Income", "Expense", "Equity"] # end: auto-generated types def after_rename(self, old_name, new_name, merge): diff --git a/erpnext/accounts/financial_report_template/account_categories.json b/erpnext/accounts/financial_report_template/account_categories.json index f9af2698f10..37eb7baf3cc 100644 --- a/erpnext/accounts/financial_report_template/account_categories.json +++ b/erpnext/accounts/financial_report_template/account_categories.json @@ -1,118 +1,147 @@ [ { "account_category_name": "Cash and Cash Equivalents", + "root_type": "Asset", "description": "Cash on hand, demand deposits, and short-term highly liquid investments readily convertible to cash with original maturities of three months or less. Examples: Cash in hand, bank current accounts, money market funds, treasury bills \u22643 months." }, { "account_category_name": "Cost of Goods Sold", + "root_type": "Expense", "description": "Direct costs attributable to cost of goods sold. Examples: Raw materials, stock in trade." }, { "account_category_name": "Current Tax Liabilities", + "root_type": "Liability", "description": "Income tax obligations for current and prior periods. Examples: Provision for income tax, advance tax paid, tax deducted at source." }, { "account_category_name": "Finance Costs", + "root_type": "Expense", "description": "Interest and financing-related expenses. Examples: Interest on borrowings, bank charges, lease interest, foreign exchange losses." }, { "account_category_name": "Intangible Assets", + "root_type": "Asset", "description": "Identifiable non-monetary assets without physical substance. Examples: Software, patents, trademarks, licenses, development costs." }, { "account_category_name": "Investment Income", + "root_type": "Income", "description": "Returns generated from financial investments and cash management. Examples: Interest income, dividend income, rental income, fair value gains." }, { "account_category_name": "Long-term Borrowings", + "root_type": "Liability", "description": "Interest-bearing debt obligations with maturity beyond one year. Examples: Term loans, bonds, debentures, mortgages." }, { "account_category_name": "Long-term Investments", + "root_type": "Asset", "description": "Investments held for strategic purposes or extended periods. Examples: Equity investments, bonds, associates, joint ventures, deposits." }, { "account_category_name": "Long-term Provisions", + "root_type": "Liability", "description": "Present obligations beyond one year with uncertain timing/amount. Examples: Asset retirement obligations, environmental remediation, legal settlements." }, { "account_category_name": "Operating Expenses", + "root_type": "Expense", "description": "Costs incurred in ordinary business operations excluding direct costs. Examples: Selling expenses, administrative costs, marketing, utilities, rent." }, { "account_category_name": "Other Current Assets", + "root_type": "Asset", "description": "Current assets not classified elsewhere including prepaid expenses and advances. Examples: Prepaid insurance, prepaid rent, advance to suppliers, security deposits recoverable within one year." }, { "account_category_name": "Other Current Liabilities", + "root_type": "Liability", "description": "Short-term obligations not classified elsewhere. Examples: Accrued expenses, statutory liabilities, employee payables." }, { "account_category_name": "Other Direct Costs", + "root_type": "Expense", "description": "Direct costs excluding cost of goods sold. Examples: Direct labor, manufacturing overhead, freight inward." }, { "account_category_name": "Other Non-current Assets", + "root_type": "Asset", "description": "Long-term assets not classified elsewhere. Examples: Security deposits, long-term prepayments, advances for capital goods." }, { "account_category_name": "Other Non-current Liabilities", + "root_type": "Liability", "description": "Long-term obligations not classified elsewhere. Examples: Long-term deposits, deferred income, government grants." }, { "account_category_name": "Other Operating Income", + "root_type": "Income", "description": "Incidental income related to business operations but not core revenue. Examples: Scrap sales, government grants, insurance claims, foreign exchange gains." }, { "account_category_name": "Other Payables", + "root_type": "Liability", "description": "Non-trade payables and obligations to parties other than suppliers. Examples: Employee payables, accrued expenses, customer advances, security deposits received." }, { "account_category_name": "Other Receivables", + "root_type": "Asset", "description": "Non-trade amounts due to the entity excluding financing arrangements. Examples: Employee advances, insurance claims, tax refunds, deposits recoverable." }, { "account_category_name": "Reserves and Surplus", + "root_type": "Equity", "description": "Accumulated profits and other reserves created from profits or share premium. Examples: General reserves, retained earnings, statutory reserves, share premium." }, { "account_category_name": "Revenue from Operations", + "root_type": "Income", "description": "Income from primary business activities in ordinary course. Examples: Sales of goods, service revenue, commission income, royalty income." }, { "account_category_name": "Share Capital", + "root_type": "Equity", "description": "Nominal value of issued and paid-up equity shares. Examples: Common stock, ordinary shares, preference shares." }, { "account_category_name": "Short-term Borrowings", + "root_type": "Liability", "description": "Interest-bearing debt obligations due within one year. Examples: Bank overdrafts, short-term loans, current portion of long-term debt." }, { "account_category_name": "Short-term Investments", + "root_type": "Asset", "description": "Financial instruments held for short-term investment purposes, readily convertible to cash. Examples: Marketable securities, fixed deposits >3 months, mutual funds." }, { "account_category_name": "Short-term Provisions", + "root_type": "Liability", "description": "Present obligations due within one year with uncertain timing or amount. Examples: Warranty provisions, legal claims, restructuring costs." }, { "account_category_name": "Stock Assets", + "root_type": "Asset", "description": "Inventory and stock-related assets including raw materials, work in progress, finished goods, and stock in trade. Examples: Raw materials, finished goods, trading merchandise, consumables." }, { "account_category_name": "Tangible Assets", + "root_type": "Asset", "description": "Physical assets used in business operations including property, plant, and equipment. Examples: Land, buildings, machinery, equipment, vehicles, furniture, capital work in progress." }, { "account_category_name": "Tax Expense", + "root_type": "Expense", "description": "Current and deferred income tax obligations. Examples: Current tax provision, deferred tax expense, withholding taxes." }, { "account_category_name": "Trade Payables", + "root_type": "Liability", "description": "Amounts owed to suppliers. Examples: Supplier invoices, accrued purchases, bills payable." }, { "account_category_name": "Trade Receivables", + "root_type": "Asset", "description": "Amounts due from customers for goods sold or services provided in ordinary course of business. Examples: Accounts receivable, notes receivable from customers, unbilled revenue." } -] \ No newline at end of file +] diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 61b93b292b1..20a73010a5a 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -476,3 +476,4 @@ erpnext.patches.v16_0.co_by_product_patch erpnext.patches.v16_0.depends_on_inv_dimensions erpnext.patches.v16_0.uom_category erpnext.patches.v16_0.merge_repost_settings_to_accounts_settings +erpnext.patches.v16_0.set_root_type_in_account_categories diff --git a/erpnext/patches/v16_0/set_root_type_in_account_categories.py b/erpnext/patches/v16_0/set_root_type_in_account_categories.py new file mode 100644 index 00000000000..44eb6678d06 --- /dev/null +++ b/erpnext/patches/v16_0/set_root_type_in_account_categories.py @@ -0,0 +1,32 @@ +import json +from pathlib import Path + +import frappe + + +def execute(): + base_path = Path(frappe.get_app_path("erpnext", "accounts")).resolve() + categories_file = (base_path / "financial_report_template" / "account_categories.json").resolve() + + if not categories_file.exists(): + return + + categories = json.loads(frappe.read_file(str(categories_file))) + + valid_root_types = set(frappe.get_meta("Account Category").get_field("root_type").options.split("\n")) + + root_type_categories = {} + for category in categories: + if (root_type := category.get("root_type")) and root_type in valid_root_types: + root_type_categories.setdefault(root_type, []).append(category["account_category_name"]) + + if not root_type_categories: + return + + for root_type, category_names in root_type_categories.items(): + frappe.db.set_value( + "Account Category", + {"name": ["in", category_names], "root_type": ["is", "not set"]}, + "root_type", + root_type, + ) From f7b87ed0e341da57f32873073e9f0f20af656c63 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 18:19:28 +0530 Subject: [PATCH 13/56] fix(stock): show available qty in warehouse link field (backport #54474) (#54484) fix(stock): show available qty in warehouse link field (#54474) (cherry picked from commit ab19b16fe272f558ea77342c8d2abaad93326667) Co-authored-by: Sudharsanan Ashok <135326972+Sudharsanan11@users.noreply.github.com> --- erpnext/public/js/utils/serial_no_batch_selector.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js index 6610078b9b4..0d262020007 100644 --- a/erpnext/public/js/utils/serial_no_batch_selector.js +++ b/erpnext/public/js/utils/serial_no_batch_selector.js @@ -106,10 +106,12 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { }, get_query: () => { return { - filters: { - is_group: 0, - company: this.frm.doc.company, - }, + query: "erpnext.controllers.queries.warehouse_query", + filters: [ + ["Bin", "item_code", "=", this.item.item_code], + ["Warehouse", "is_group", "=", 0], + ["Warehouse", "company", "=", this.frm.doc.company], + ], }; }, }); From ddc9ea16cc263bd4b7bef472642f9ea2e4fb7d26 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 13:29:15 +0000 Subject: [PATCH 14/56] ci: test correctness pattern (backport #54186) (#54473) Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com> --- semgrep/test-correctness.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/semgrep/test-correctness.yml b/semgrep/test-correctness.yml index 34eb82fa1d6..90a32af93e9 100644 --- a/semgrep/test-correctness.yml +++ b/semgrep/test-correctness.yml @@ -10,9 +10,15 @@ rules: languages: [python] severity: ERROR - id: Dont-override-teardown - pattern: | - def tearDown(...): - ... + patterns: + - pattern: | + def tearDown(...): + ... + - pattern-not: | + def tearDown(...): + ... + super().tearDown() + ... message: ERPNextTestSuite forces rollback on each tearDown, which ensures idempotency. Don't override tearDown. languages: [python] severity: ERROR From 2a244d162b5915090f1d434f867064458738cf66 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 15:36:35 +0000 Subject: [PATCH 15/56] fix(edi): restrict Code List imports to files and trusted backend URLs (backport #54137) (#54266) Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com> fix(edi): restrict Code List imports to files and trusted backend URLs (#54137) fix(edi): hardcode "Code List" DocType in importer (#54488) --- .../edi/doctype/code_list/code_list_import.js | 1 + .../edi/doctype/code_list/code_list_import.py | 154 ++++++++++---- .../code_list/test_code_list_import.py | 200 ++++++++++++++++++ .../edi/doctype/common_code/common_code.py | 14 +- 4 files changed, 317 insertions(+), 52 deletions(-) create mode 100644 erpnext/edi/doctype/code_list/test_code_list_import.py diff --git a/erpnext/edi/doctype/code_list/code_list_import.js b/erpnext/edi/doctype/code_list/code_list_import.js index 4a33f3e2fe6..917e815fc97 100644 --- a/erpnext/edi/doctype/code_list/code_list_import.js +++ b/erpnext/edi/doctype/code_list/code_list_import.js @@ -10,6 +10,7 @@ erpnext.edi.import_genericode = function (listview_or_form) { method: "erpnext.edi.doctype.code_list.code_list_import.import_genericode", doctype: doctype, docname: docname, + allow_web_link: false, allow_toggle_private: false, allow_take_photo: false, on_success: function (_file_doc, r) { diff --git a/erpnext/edi/doctype/code_list/code_list_import.py b/erpnext/edi/doctype/code_list/code_list_import.py index 71cb7d0f82d..0f6a51fc993 100644 --- a/erpnext/edi/doctype/code_list/code_list_import.py +++ b/erpnext/edi/doctype/code_list/code_list_import.py @@ -1,48 +1,106 @@ import json +from urllib.parse import urlsplit import frappe import requests from frappe import _ from frappe.utils import escape_html +from frappe.utils.file_manager import save_file from lxml import etree -URL_PREFIXES = ("http://", "https://") +GENERICODE_FETCH_TIMEOUT = 15 +LOCAL_FILE_PREFIXES = ("/files/", "/private/files/") + + +class RemoteGenericodeUrlNotAllowedError(Exception): + pass + + +class CodeListSelectionMismatchError(Exception): + pass @frappe.whitelist() def import_genericode(): - doctype = frappe.form_dict.doctype - docname = frappe.form_dict.docname - content = frappe.local.uploaded_file - - # recover the content, if it's a link - if (file_url := frappe.local.uploaded_file_url) and file_url.startswith(URL_PREFIXES): - try: - # If it's a URL, fetch the content and make it a local file (for durable audit) - response = requests.get(frappe.local.uploaded_file_url) - response.raise_for_status() - frappe.local.uploaded_file = content = response.content - frappe.local.uploaded_filename = frappe.local.uploaded_file_url.split("/")[-1] - frappe.local.uploaded_file_url = None - except Exception as e: - frappe.throw(f"
{e!s}
", title=_("Fetching Error")) - - if file_url := frappe.local.uploaded_file_url: - file_path = frappe.utils.file_manager.get_file_path(file_url) - with open(file_path.encode(), mode="rb") as f: - content = f.read() - - # Parse the xml content - parser = etree.XMLParser( - remove_blank_text=True, - resolve_entities=False, - load_dtd=False, - no_network=True, - ) try: - root = etree.fromstring(content, parser=parser) - except Exception as e: - frappe.throw(f"
{e!s}
", title=_("Parsing Error")) + content, file_name = get_uploaded_genericode_file() + + return import_genericode_content( + doctype="Code List", + docname=frappe.form_dict.docname, + content=content, + file_name=file_name, + ) + except RemoteGenericodeUrlNotAllowedError: + frappe.throw( + _("Importing Code Lists from remote URLs is not allowed."), + title=_("Invalid Upload"), + ) + except CodeListSelectionMismatchError: + frappe.throw(_("The uploaded file does not match the selected Code List.")) + except etree.XMLSyntaxError: + frappe.throw( + _("The uploaded file could not be parsed as a genericode XML document."), + title=_("Parsing Error"), + ) + + +def import_genericode_from_url( + url: str, + doctype: str = "Code List", + docname: str | None = None, +): + """Import a Code List from a trusted backend URL.""" + content = fetch_genericode_from_url(url) + file_name = urlsplit(url).path.rsplit("/", 1)[-1] or "genericode.xml" + + return import_genericode_content( + doctype=doctype, + docname=docname, + content=content, + file_name=file_name, + ) + + +def get_uploaded_genericode_file() -> tuple[bytes, str | None]: + uploaded_data = frappe.local.uploaded_file + file_name = frappe.local.uploaded_filename + if uploaded_data and file_name: + return uploaded_data, file_name + + file_url = frappe.local.uploaded_file_url + if not file_url: + raise frappe.ValidationError(_("No file uploaded or URL provided.")) + + if not is_local_file_url(file_url): + raise RemoteGenericodeUrlNotAllowedError + + file_doc = frappe.get_doc("File", {"file_url": file_url}) + file_doc.check_permission("read") + return file_doc.get_content(encodings=()), file_name + + +def is_local_file_url(file_url: str | None) -> bool: + if not file_url: + return False + + parsed = urlsplit(file_url.strip()) + return not parsed.scheme and not parsed.netloc and parsed.path.startswith(LOCAL_FILE_PREFIXES) + + +def fetch_genericode_from_url(url: str) -> bytes: + response = requests.get(url, timeout=GENERICODE_FETCH_TIMEOUT) + response.raise_for_status() + return response.content + + +def import_genericode_content( + doctype: str, + docname: str | None, + content: bytes, + file_name: str | None, +): + root = parse_genericode_content(content) # Extract the name (CanonicalVersionUri) from the parsed XML name = root.find(".//CanonicalVersionUri").text @@ -51,7 +109,7 @@ def import_genericode(): if frappe.db.exists(doctype, docname): code_list = frappe.get_doc(doctype, docname) if code_list.name != name: - frappe.throw(_("The uploaded file does not match the selected Code List.")) + raise CodeListSelectionMismatchError else: # Create a new Code List document with the extracted name code_list = frappe.new_doc(doctype) @@ -60,19 +118,13 @@ def import_genericode(): code_list.from_genericode(root) code_list.save() - # Attach the file and provide a recoverable identifier - file_doc = frappe.get_doc( - { - "doctype": "File", - "attached_to_doctype": "Code List", - "attached_to_name": code_list.name, - "folder": frappe.db.get_value("File", {"is_attachments_folder": 1}), - "file_name": frappe.local.uploaded_filename, - "file_url": frappe.local.uploaded_file_url, - "is_private": 1, - "content": content, - } - ).save() + file_doc = save_file( + fname=file_name, + content=content, + dt=doctype, + dn=code_list.name, + is_private=1, + ) # Get available columns and example values columns, example_values, filterable_columns = get_genericode_columns_and_examples(root) @@ -87,6 +139,16 @@ def import_genericode(): } +def parse_genericode_content(content: bytes): + parser = etree.XMLParser( + remove_blank_text=True, + resolve_entities=False, + load_dtd=False, + no_network=True, + ) + return etree.fromstring(content, parser=parser) + + @frappe.whitelist() def process_genericode_import( code_list_name: str, diff --git a/erpnext/edi/doctype/code_list/test_code_list_import.py b/erpnext/edi/doctype/code_list/test_code_list_import.py new file mode 100644 index 00000000000..949544bd633 --- /dev/null +++ b/erpnext/edi/doctype/code_list/test_code_list_import.py @@ -0,0 +1,200 @@ +# Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt + +from unittest.mock import Mock, patch + +import frappe +import requests + +from erpnext.edi.doctype.code_list import code_list_import +from erpnext.tests.utils import ERPNextTestSuite + +SAMPLE_GENERICODE = b""" + + + Test Code List + 1.0 + test-code-list + Code list for tests + + Test Agency + TEST + + https://example.com/codelists/test.xml + + test-code-list-v1 + + + + + + + + A + Alpha + Group 1 + + + B + Beta + Group 2 + + + C + Gamma + Group 1 + + + +""" + + +class TestCodeListImport(ERPNextTestSuite): + def test_import_genericode_rejects_remote_file_url(self): + self.set_upload_context( + file_name="trusted.xml", + file_url="https://example.com/codelists/trusted.xml", + ) + + with patch("erpnext.edi.doctype.code_list.code_list_import.requests.get") as mock_get: + with self.assertRaisesRegex( + frappe.ValidationError, "Importing Code Lists from remote URLs is not allowed." + ): + code_list_import.import_genericode() + + mock_get.assert_not_called() + + def test_import_genericode_rejects_file_scheme_url(self): + self.set_upload_context( + file_name="trusted.xml", + file_url="file:///tmp/trusted.xml", + ) + + with patch("erpnext.edi.doctype.code_list.code_list_import.requests.get") as mock_get: + with self.assertRaisesRegex( + frappe.ValidationError, "Importing Code Lists from remote URLs is not allowed." + ): + code_list_import.import_genericode() + + mock_get.assert_not_called() + + def test_import_genericode_from_trusted_url(self): + response = Mock() + response.content = SAMPLE_GENERICODE + response.raise_for_status.return_value = None + + with patch( + "erpnext.edi.doctype.code_list.code_list_import.requests.get", + return_value=response, + ) as mock_get: + import_result = code_list_import.import_genericode_from_url( + "https://example.com/codelists/trusted.xml" + ) + + self.assert_import_response(import_result) + mock_get.assert_called_once_with( + "https://example.com/codelists/trusted.xml", + timeout=code_list_import.GENERICODE_FETCH_TIMEOUT, + ) + + file_doc = frappe.get_doc("File", import_result["file"]) + self.assertEqual(file_doc.get_content(encodings=()), SAMPLE_GENERICODE) + self.assertFalse(file_doc.file_url.startswith("https://")) + + def test_import_genericode_from_trusted_url_propagates_fetch_errors(self): + with patch( + "erpnext.edi.doctype.code_list.code_list_import.requests.get", + side_effect=requests.Timeout, + ): + with self.assertRaises(requests.Timeout): + code_list_import.import_genericode_from_url("https://example.com/codelists/trusted.xml") + + def test_import_genericode_from_uploaded_file_returns_metadata(self): + self.set_upload_context(content=SAMPLE_GENERICODE, file_name="uploaded_genericode.xml") + + import_result = code_list_import.import_genericode() + + self.assert_import_response(import_result) + + file_doc = frappe.get_doc("File", import_result["file"]) + self.assertEqual(file_doc.get_content(encodings=()), SAMPLE_GENERICODE) + + def test_process_genericode_import_reads_file_doc_content(self): + self.set_upload_context(content=SAMPLE_GENERICODE, file_name="uploaded_genericode.xml") + + import_result = code_list_import.import_genericode() + count = code_list_import.process_genericode_import( + code_list_name=import_result["code_list"], + file_name=import_result["file"], + code_column="code", + title_column="name", + ) + + self.assertEqual(count, 3) + self.assertEqual(frappe.db.count("Common Code", {"code_list": import_result["code_list"]}), 3) + self.assertEqual( + frappe.db.get_value( + "Common Code", + {"code_list": import_result["code_list"], "common_code": "A"}, + "title", + ), + "Alpha", + ) + + def test_import_genericode_from_local_file_url(self): + source_file = frappe.get_doc( + { + "doctype": "File", + "file_name": "library_genericode.xml", + "content": SAMPLE_GENERICODE, + "is_private": 1, + } + ).insert() + self.set_upload_context(file_name=source_file.file_name, file_url=source_file.file_url) + + import_result = code_list_import.import_genericode() + + self.assert_import_response(import_result) + + def set_upload_context( + self, + content: bytes | None = None, + file_name: str = "genericode.xml", + file_url: str | None = None, + docname: str | None = None, + ): + attrs = ("form_dict", "uploaded_file", "uploaded_file_url", "uploaded_filename") + originals = {attr: getattr(frappe.local, attr, None) for attr in attrs} + + frappe.local.form_dict = frappe._dict(doctype="Code List", docname=docname) + frappe.local.uploaded_file = content + frappe.local.uploaded_file_url = file_url + frappe.local.uploaded_filename = file_name + + def restore(): + for attr, value in originals.items(): + setattr(frappe.local, attr, value) + + self.addCleanup(restore) + + def assert_import_response(self, import_result): + self.assertEqual( + set(import_result), + { + "code_list", + "code_list_title", + "file", + "columns", + "example_values", + "filterable_columns", + }, + ) + self.assertEqual(import_result["code_list"], "test-code-list-v1") + self.assertEqual(import_result["code_list_title"], "Test Code List") + self.assertEqual(import_result["columns"], ["code", "name", "category"]) + self.assertEqual(import_result["example_values"]["code"], ["A", "B", "C"]) + self.assertEqual(import_result["example_values"]["name"], ["Alpha", "Beta", "Gamma"]) + self.assertEqual(import_result["example_values"]["category"], ["Group 1", "Group 2", "Group 1"]) + self.assertCountEqual(import_result["filterable_columns"]["category"], ["Group 1", "Group 2"]) + self.assertTrue(frappe.db.exists("Code List", import_result["code_list"])) + self.assertTrue(frappe.db.exists("File", import_result["file"])) diff --git a/erpnext/edi/doctype/common_code/common_code.py b/erpnext/edi/doctype/common_code/common_code.py index d1fd88350be..57e5e32f33a 100644 --- a/erpnext/edi/doctype/common_code/common_code.py +++ b/erpnext/edi/doctype/common_code/common_code.py @@ -9,6 +9,8 @@ from frappe.model.document import Document from frappe.utils.data import get_link_to_form from lxml import etree +from erpnext.edi.doctype.code_list.code_list_import import parse_genericode_content + class CommonCode(Document): # begin: auto-generated types @@ -86,15 +88,15 @@ def simple_hash(input_string, length=6): def import_genericode(code_list: str, file_name: str, column_map: dict, filters: dict | None = None): """Import genericode file and create Common Code entries""" - file_path = frappe.utils.file_manager.get_file_path(file_name) - parser = etree.XMLParser(remove_blank_text=True) - tree = etree.parse(file_path, parser=parser) - root = tree.getroot() + file_doc = frappe.get_doc("File", file_name) + file_doc.check_permission("read") + root = parse_genericode_content(file_doc.get_content(encodings=())) # Construct the XPath expression xpath_expr = ".//SimpleCodeList/Row" filter_conditions = [ - f"Value[@ColumnRef='{column_ref}']/SimpleValue='{value}'" for column_ref, value in filters.items() + f"Value[@ColumnRef='{column_ref}']/SimpleValue='{value}'" + for column_ref, value in (filters or {}).items() ] if filter_conditions: xpath_expr += "[" + " and ".join(filter_conditions) + "]" @@ -102,7 +104,7 @@ def import_genericode(code_list: str, file_name: str, column_map: dict, filters: elements = root.xpath(xpath_expr) total_elements = len(elements) for i, xml_element in enumerate(elements, start=1): - common_code: "CommonCode" = frappe.new_doc("Common Code") + common_code: CommonCode = frappe.new_doc("Common Code") common_code.code_list = code_list common_code.from_genericode(column_map, xml_element) common_code.save() From 456e99b3521d16b7c127edff6d1c5cbdc103d865 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 17:37:04 +0000 Subject: [PATCH 16/56] fix: preserve inventory dimensions when raw materials are reset (backport #54440) (#54493) fix: preserve inventory dimensions when raw materials are reset (#54440) * fix: preserve inventory dimensions when raw materials are reset * test: add test case (cherry picked from commit 0e20e35842bf090241d7b296c19f2714b6fd2588) Co-authored-by: Mihir Kandoi --- erpnext/patches.txt | 1 + erpnext/patches/v16_0/scr_inv_dimension.py | 24 +++++++++++ .../inventory_dimension.py | 15 +++++-- .../test_inventory_dimension.py | 1 - .../subcontracting_receipt.js | 6 +++ .../subcontracting_receipt.py | 32 +++++++++++++++ .../test_subcontracting_receipt.py | 41 +++++++++++++++++++ 7 files changed, 115 insertions(+), 5 deletions(-) create mode 100644 erpnext/patches/v16_0/scr_inv_dimension.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 20a73010a5a..4cffef36951 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -477,3 +477,4 @@ erpnext.patches.v16_0.depends_on_inv_dimensions erpnext.patches.v16_0.uom_category erpnext.patches.v16_0.merge_repost_settings_to_accounts_settings erpnext.patches.v16_0.set_root_type_in_account_categories +erpnext.patches.v16_0.scr_inv_dimension diff --git a/erpnext/patches/v16_0/scr_inv_dimension.py b/erpnext/patches/v16_0/scr_inv_dimension.py new file mode 100644 index 00000000000..f4b320f674b --- /dev/null +++ b/erpnext/patches/v16_0/scr_inv_dimension.py @@ -0,0 +1,24 @@ +import frappe + +from erpnext.stock.doctype.inventory_dimension.inventory_dimension import get_inventory_dimensions + + +def execute(): + for dimension in get_inventory_dimensions(): + if frappe.db.exists( + "Custom Field", + { + "fieldname": dimension.source_fieldname, + "dt": "Subcontracting Receipt Supplied Item", + "reqd": 1, + }, + ): + frappe.set_value( + "Custom Field", + { + "fieldname": dimension.source_fieldname, + "dt": "Subcontracting Receipt Supplied Item", + "reqd": 1, + }, + {"reqd": 0, "mandatory_depends_on": "eval:doc.reference_name"}, + ) diff --git a/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py b/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py index fc5038db069..86ce5c3eb85 100644 --- a/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py +++ b/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py @@ -167,6 +167,13 @@ class InventoryDimension(Document): if label_start_with: label = f"{label_start_with} {self.dimension_name}" + mandatory_depends_on = self.mandatory_depends_on + if self.reqd: + if doctype == "Stock Entry Detail": + mandatory_depends_on = "eval:doc.s_warehouse" + elif doctype == "Subcontracting Receipt Supplied Item": + mandatory_depends_on = "eval:doc.reference_name" + dimension_fields = [ dict( fieldname="inventory_dimension", @@ -184,11 +191,11 @@ class InventoryDimension(Document): depends_on="eval:doc.s_warehouse" if doctype == "Stock Entry Detail" else "", search_index=1, reqd=1 - if self.reqd and not self.mandatory_depends_on and doctype != "Stock Entry Detail" + if self.reqd + and not self.mandatory_depends_on + and doctype not in ["Stock Entry Detail", "Subcontracting Receipt Supplied Item"] else 0, - mandatory_depends_on="eval:doc.s_warehouse" - if self.reqd and doctype == "Stock Entry Detail" - else self.mandatory_depends_on, + mandatory_depends_on=mandatory_depends_on, ), ] diff --git a/erpnext/stock/doctype/inventory_dimension/test_inventory_dimension.py b/erpnext/stock/doctype/inventory_dimension/test_inventory_dimension.py index bfe6864486b..2a69c450b3d 100644 --- a/erpnext/stock/doctype/inventory_dimension/test_inventory_dimension.py +++ b/erpnext/stock/doctype/inventory_dimension/test_inventory_dimension.py @@ -225,7 +225,6 @@ class TestInventoryDimension(ERPNextTestSuite): ) ) - doc.load_from_db doc.reqd = 0 doc.save() diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js index 5bb7c2f0cc2..0c2a10705c4 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js @@ -435,6 +435,12 @@ frappe.ui.form.on("Subcontracting Receipt Item", { set_missing_values(frm); }, + before_items_remove(frm, cdt, cdn) { + const filtered_rows = frm.doc.supplied_items.filter((item) => item.reference_name !== cdn); + frm.doc.supplied_items = filtered_rows; + frm.refresh_field("supplied_items"); + }, + items_delete(frm) { set_missing_values(frm); }, diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index 664adf254f8..23a3830c951 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -15,6 +15,7 @@ from erpnext.buying.utils import check_on_hold_or_closed_status from erpnext.controllers.subcontracting_controller import SubcontractingController from erpnext.setup.doctype.brand.brand import get_brand_defaults from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults +from erpnext.stock.doctype.inventory_dimension.inventory_dimension import get_inventory_dimensions from erpnext.stock.doctype.item.item import get_item_defaults from erpnext.stock.get_item_details import get_default_cost_center, get_default_expense_account from erpnext.stock.stock_ledger import get_valuation_rate @@ -119,6 +120,7 @@ class SubcontractingReceipt(SubcontractingController): ) def before_validate(self): + self.save_inventory_dimensions() super().before_validate() self.validate_items_qty() self.set_items_bom() @@ -159,6 +161,7 @@ class SubcontractingReceipt(SubcontractingController): self.set_supplied_items_expense_account() self.set_supplied_items_cost_center() + self.set_supplied_items_inventory_dimensions() def on_submit(self): self.validate_closed_subcontracting_order() @@ -312,6 +315,22 @@ class SubcontractingReceipt(SubcontractingController): self.company, ) + def set_supplied_items_inventory_dimensions(self): + if hasattr(self, "inventory_dimensions") and (inventory_dimensions := get_inventory_dimensions()): + for item in self.supplied_items: + key = ( + item.reference_name, + item.rm_item_code, + item.main_item_code, + item.batch_no, + item.serial_no, + ) + + for dimension in inventory_dimensions: + dimension_values = self.inventory_dimensions.get(dimension.source_fieldname, {}) + if key in dimension_values: + item.set(dimension.source_fieldname, dimension_values[key]) + def set_supplied_items_expense_account(self): for item in self.supplied_items: if not item.expense_account: @@ -328,6 +347,19 @@ class SubcontractingReceipt(SubcontractingController): get_brand_defaults(item.rm_item_code, self.company), ) + def save_inventory_dimensions(self): + if inventory_dimensions := get_inventory_dimensions(): + if not getattr(self, "inventory_dimensions", None): + self.inventory_dimensions = {} + + for dimension in inventory_dimensions: + self.inventory_dimensions[dimension.source_fieldname] = { + (d.reference_name, d.rm_item_code, d.main_item_code, d.batch_no, d.serial_no): d.get( + dimension.source_fieldname + ) + for d in self.supplied_items + } + def reset_supplied_items(self): if ( frappe.db.get_single_value("Buying Settings", "backflush_raw_materials_of_subcontract_based_on") diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py index b4b0c930082..7105eca2e13 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py @@ -2036,6 +2036,47 @@ class TestSubcontractingReceipt(ERPNextTestSuite): scr.submit() frappe.flags["args"].pop("items", None) + def test_inventory_dimensions(self): + """ + The subcontracting controller resets the supplied items table on each save causing the inventory dimensions to be lost. + This test ensures that the inventory dimensions are retained on each save. + """ + from erpnext.stock.doctype.inventory_dimension.test_inventory_dimension import ( + create_inventory_dimension, + ) + + inventory_dimension = create_inventory_dimension( + apply_to_all_doctypes=1, + dimension_name="Inv Site", + reference_document="Inv Site", + document_type="Inv Site", + ) + + inventory_dimension.reqd = 1 + inventory_dimension.save() + + set_backflush_based_on("BOM") + + sco = get_subcontracting_order() + rm_items = get_rm_items(sco.supplied_items) + itemwise_details = make_stock_in_entry(rm_items=rm_items) + make_stock_transfer_entry( + sco_no=sco.name, + rm_items=rm_items, + itemwise_details=copy.deepcopy(itemwise_details), + ) + scr = make_subcontracting_receipt(sco.name) + scr.items[0].inv_site = "Site 1" + scr.save() + + scr.supplied_items[0].inv_site = "Site 1" + scr.save() + + self.assertEqual(scr.supplied_items[0].inv_site, "Site 1") + + inventory_dimension.reqd = 0 + inventory_dimension.save() + def make_return_subcontracting_receipt(**args): args = frappe._dict(args) From c4010b0581ce60f547eb6d0f1cc15e7c58f67239 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 22:31:16 +0000 Subject: [PATCH 17/56] ci: fix timezone for python mariadb tests (backport #54464) (#54465) ci: fix timezone for python mariadb tests (#54464) (cherry picked from commit 0d2da6d86c99e3dd7c39f9959fea0d1c627b127f) Co-authored-by: diptanilsaha --- .github/workflows/server-tests-mariadb.yml | 2 ++ erpnext/tests/utils.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/server-tests-mariadb.yml b/.github/workflows/server-tests-mariadb.yml index b8e88d1b5f3..cfef2e05f5b 100644 --- a/.github/workflows/server-tests-mariadb.yml +++ b/.github/workflows/server-tests-mariadb.yml @@ -41,6 +41,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 env: + TZ: 'Asia/Kolkata' NODE_ENV: "production" WITH_COVERAGE: ${{ github.event_name != 'pull_request' }} @@ -56,6 +57,7 @@ jobs: mysql: image: mariadb:10.6 env: + TZ: 'Asia/Kolkata' MARIADB_ROOT_PASSWORD: 'root' ports: - 3306:3306 diff --git a/erpnext/tests/utils.py b/erpnext/tests/utils.py index 15c89a24b4f..297caa15b98 100644 --- a/erpnext/tests/utils.py +++ b/erpnext/tests/utils.py @@ -151,6 +151,7 @@ class BootStrapTestData: frappe.db.commit() # nosemgrep def make_master_data(self): + self.update_system_settings() self.make_fiscal_year() self.make_holiday_list() self.make_company() @@ -203,7 +204,6 @@ class BootStrapTestData: self.update_support_settings() self.update_selling_settings() self.update_stock_settings() - self.update_system_settings() frappe.db.commit() # nosemgrep From 1b146738c4024cc1e517811bf7c3e763bda4039a Mon Sep 17 00:00:00 2001 From: nareshkannasln Date: Wed, 11 Mar 2026 11:59:14 +0530 Subject: [PATCH 18/56] fix: skip BudgetValidation when cancelling GL entries (cherry picked from commit fa34ebea94d9de3e020c1d0f779967bc8b5e8670) --- erpnext/accounts/general_ledger.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index 7c5dcedaf74..de7f5941fca 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -36,7 +36,8 @@ def make_gl_entries( ): if gl_map: if ( - not cint(frappe.get_single_value("Accounts Settings", "use_legacy_budget_controller")) + not cancel + and not cint(frappe.get_single_value("Accounts Settings", "use_legacy_budget_controller")) and gl_map[0].voucher_type != "Period Closing Voucher" ): bud_val = BudgetValidation(gl_map=gl_map) From 719d982a07e6888bbf24e9077cff50c0251e7b47 Mon Sep 17 00:00:00 2001 From: ljain112 Date: Thu, 23 Apr 2026 13:35:46 +0530 Subject: [PATCH 19/56] fix: ensure tax withholding entries respect date range of category (cherry picked from commit 9ead8d4e3f55432baf68d31088933482fea36658) --- .../test_tax_withholding_category.py | 196 ++++++++++++++++-- .../tax_withholding_entry.py | 1 + 2 files changed, 179 insertions(+), 18 deletions(-) diff --git a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py index 2d0450107bc..13697084cbf 100644 --- a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py +++ b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py @@ -5,8 +5,7 @@ import datetime from unittest.mock import patch import frappe -from frappe.custom.doctype.custom_field.custom_field import create_custom_fields -from frappe.utils import add_days, add_months, today +from frappe.utils import add_days, add_months, getdate, today from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry from erpnext.accounts.utils import get_fiscal_year @@ -1922,7 +1921,6 @@ class TestTaxWithholdingCategory(ERPNextTestSuite): def set_previous_fy_and_tax_category(self): test_company = "_Test Company" - category = "Cumulative Threshold TDS" def add_company_to_fy(fy, company): if not [x.company for x in fy.companies if x.company == company]: @@ -1948,20 +1946,6 @@ class TestTaxWithholdingCategory(ERPNextTestSuite): ) self.prev_fy.save() - # setup tax withholding category for previous fiscal year - cat = frappe.get_doc("Tax Withholding Category", category) - cat.append( - "rates", - { - "from_date": self.prev_fy.year_start_date, - "to_date": self.prev_fy.year_end_date, - "tax_withholding_rate": 10, - "single_threshold": 0, - "cumulative_threshold": 30000, - }, - ) - cat.save() - def test_tds_across_fiscal_year(self): """ Advance TDS on previous fiscal year should be properly allocated on Invoices in upcoming fiscal year @@ -1972,6 +1956,14 @@ class TestTaxWithholdingCategory(ERPNextTestSuite): supplier = "Test TDS Supplier" # Cumulative threshold 30000 and tax rate 10% category = "Cumulative Threshold TDS" + create_tax_withholding_category( + category_name=category, + rate=10, + from_date=self.prev_fy.year_start_date, + to_date=self.prev_fy.year_end_date, + account="TDS - _TC", + cumulative_threshold=30000, + ) frappe.db.set_value( "Supplier", supplier, @@ -2043,6 +2035,158 @@ class TestTaxWithholdingCategory(ERPNextTestSuite): self.assertEqual(pi2.taxes, []) self.assertEqual(payment.taxes[0].tax_amount, 6000) + def test_threshold_resets_in_new_fiscal_year(self): + """ + Threshold entries from a previous FY must not carry over into the new FY. + """ + self.set_previous_fy_and_tax_category() + invoices = [] + supplier = "Test TDS Supplier" + category = "Cumulative Threshold TDS" + create_tax_withholding_category( + category_name=category, + rate=10, + from_date=self.prev_fy.year_start_date, + to_date=self.prev_fy.year_end_date, + account="TDS - _TC", + cumulative_threshold=30000, + ) + self.setup_party_with_category("Supplier", supplier, category) + prev_fy_date = add_days(self.prev_fy.year_end_date, -10) + + # Previous FY: 3 invoices to cross the 30000 cumulative threshold + for _ in range(3): + pi = create_purchase_invoice(supplier=supplier, posting_date=prev_fy_date, set_posting_time=True) + pi.submit() + invoices.append(pi) + + # Third invoice crosses the threshold - 3000 TDS deducted across all three + self.validate_tax_deduction(invoices[-1], 3000) + + # Current FY: 10000 invoice - must be Under Withheld, threshold resets + pi_curr = create_purchase_invoice(supplier=supplier) + pi_curr.submit() + invoices.append(pi_curr) + self.validate_tax_deduction(pi_curr, 0) + + self.validate_tax_withholding_entries( + "Purchase Invoice", + pi_curr.name, + [ + self.get_tax_withholding_entry( + tax_withholding_category=category, + party_type="Supplier", + party=supplier, + taxable_doctype="Purchase Invoice", + taxable_name=pi_curr.name, + tax_rate=10.0, + taxable_amount=10000.0, + withholding_amount=0.0, + status="Under Withheld", + withholding_doctype=None, + withholding_name=None, + under_withheld_reason=None, + ) + ], + ) + self.cleanup_invoices(invoices) + + def test_tax_on_excess_threshold_resets_in_new_fiscal_year(self): + """ + For tax-on-excess categories, unused threshold must reset each FY. + """ + self.set_previous_fy_and_tax_category() + invoices = [] + supplier = "Test TDS Supplier3" + category = "New TDS Category" + create_tax_withholding_category( + category_name=category, + rate=10, + from_date=self.prev_fy.year_start_date, + to_date=self.prev_fy.year_end_date, + account="TDS - _TC", + cumulative_threshold=30000, + tax_on_excess_amount=1, + round_off_tax_amount=1, + ) + self.setup_party_with_category("Supplier", supplier, category) + prev_fy_date = add_days(self.prev_fy.year_end_date, -10) + + for _ in range(2): + pi = create_purchase_invoice(supplier=supplier, posting_date=prev_fy_date, set_posting_time=True) + pi.submit() + invoices.append(pi) + + pi3 = create_purchase_invoice( + supplier=supplier, rate=20000, posting_date=prev_fy_date, set_posting_time=True + ) + pi3.submit() + invoices.append(pi3) + + self.validate_tax_deduction(pi3, 1000) + self.validate_tax_withholding_entries( + "Purchase Invoice", + pi3.name, + [ + self.get_tax_withholding_entry( + tax_withholding_category=category, + party_type="Supplier", + party=supplier, + taxable_doctype="Purchase Invoice", + taxable_name=pi3.name, + tax_rate=10.0, + taxable_amount=10000.0, + withholding_amount=0.0, + status="Settled", + withholding_doctype="Purchase Invoice", + withholding_name=pi3.name, + under_withheld_reason="Threshold Exemption", + ), + self.get_tax_withholding_entry( + tax_withholding_category=category, + party_type="Supplier", + party=supplier, + taxable_doctype="Purchase Invoice", + taxable_name=pi3.name, + tax_rate=10.0, + taxable_amount=10000.0, + withholding_amount=1000.0, + status="Settled", + withholding_doctype="Purchase Invoice", + withholding_name=pi3.name, + under_withheld_reason=None, + ), + ], + ) + + # no excess, so no TDS + pi_curr = create_purchase_invoice(supplier=supplier, rate=30000) + pi_curr.submit() + invoices.append(pi_curr) + self.validate_tax_deduction(pi_curr, 0) + + self.validate_tax_withholding_entries( + "Purchase Invoice", + pi_curr.name, + [ + self.get_tax_withholding_entry( + tax_withholding_category=category, + party_type="Supplier", + party=supplier, + taxable_doctype="Purchase Invoice", + taxable_name=pi_curr.name, + tax_rate=10.0, + taxable_amount=30000.0, + withholding_amount=0.0, + status="Settled", + withholding_doctype="Purchase Invoice", + withholding_name=pi_curr.name, + under_withheld_reason="Threshold Exemption", + ), + ], + ) + self.cleanup_invoices(invoices) + @ERPNextTestSuite.change_settings("Accounts Settings", {"delete_linked_ledger_entries": 1}) def test_tds_payment_entry_cancellation(self): """ @@ -3997,7 +4141,7 @@ def create_tax_withholding_category( tax_deduction_basis="Net Total", ): if not frappe.db.exists("Tax Withholding Category", category_name): - frappe.get_doc( + doc = frappe.get_doc( { "doctype": "Tax Withholding Category", "name": category_name, @@ -4018,6 +4162,22 @@ def create_tax_withholding_category( "accounts": [{"company": "_Test Company", "account": account}], } ).insert() + else: + doc = frappe.get_doc("Tax Withholding Category", category_name) + if not any(getdate(r.from_date) == getdate(from_date) for r in doc.rates): + doc.append( + "rates", + { + "from_date": from_date, + "to_date": to_date, + "tax_withholding_rate": rate, + "single_threshold": single_threshold, + "cumulative_threshold": cumulative_threshold, + }, + ) + doc.save() + + return doc def create_lower_deduction_certificate( diff --git a/erpnext/accounts/doctype/tax_withholding_entry/tax_withholding_entry.py b/erpnext/accounts/doctype/tax_withholding_entry/tax_withholding_entry.py index 8f8ee7898af..941d9da08f7 100644 --- a/erpnext/accounts/doctype/tax_withholding_entry/tax_withholding_entry.py +++ b/erpnext/accounts/doctype/tax_withholding_entry/tax_withholding_entry.py @@ -640,6 +640,7 @@ class TaxWithholdingController: .where(entry.tax_withholding_category == category.name) .where(entry.company == self.doc.company) .where(entry.docstatus == 1) + .where(entry.taxable_date.between(category.from_date, category.to_date)) .groupby(entry.status) ) From f3996fb97151549e505c9cb4954bbc0bc8b3394a Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Sat, 25 Apr 2026 00:08:27 +0530 Subject: [PATCH 20/56] fix(PCV): set correct filters of `from_date` and `to_date` on General Ledger Report on clicking `Ledger` button (backport #54522) (#54524) Co-authored-by: diptanilsaha fix(PCV): set correct filters of `from_date` and `to_date` on General Ledger Report on clicking `Ledger` button (#54522) --- .../doctype/period_closing_voucher/period_closing_voucher.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.js b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.js index 57b05d19d83..7433f18c5ac 100644 --- a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.js +++ b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.js @@ -46,8 +46,8 @@ frappe.ui.form.on("Period Closing Voucher", { function () { frappe.route_options = { voucher_no: frm.doc.name, - from_date: frm.doc.posting_date, - to_date: moment(frm.doc.modified).format("YYYY-MM-DD"), + from_date: frm.doc.period_start_date, + to_date: frm.doc.period_end_date, company: frm.doc.company, categorize_by: "", show_cancelled_entries: frm.doc.docstatus === 2, From 8de9ac4e347e1f3a1dd91b455abb0d2bfe8cd9e0 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Sat, 25 Apr 2026 18:01:07 +0530 Subject: [PATCH 21/56] refactor(UX): selling settings form (backport #54412) (#54527) --- .../selling_settings/selling_settings.json | 156 ++++++++++++------ 1 file changed, 106 insertions(+), 50 deletions(-) diff --git a/erpnext/selling/doctype/selling_settings/selling_settings.json b/erpnext/selling/doctype/selling_settings/selling_settings.json index d501f8abd51..bd5cea337a1 100644 --- a/erpnext/selling/doctype/selling_settings/selling_settings.json +++ b/erpnext/selling/doctype/selling_settings/selling_settings.json @@ -6,6 +6,7 @@ "document_type": "Other", "engine": "InnoDB", "field_order": [ + "customer_defaults_tab", "customer_defaults_section", "cust_master_name", "customer_group", @@ -14,12 +15,14 @@ "item_price_tab", "item_price_settings_section", "selling_price_list", - "maintain_same_rate_action", - "role_to_override_stop_action", - "column_break_15", - "maintain_same_sales_rate", "fallback_to_default_price_list", "editable_price_list_rate", + "section_break_lpfl", + "maintain_same_sales_rate", + "column_break_hkqv", + "maintain_same_rate_action", + "role_to_override_stop_action", + "section_break_htyx", "validate_selling_price", "editable_bundle_item_rates", "allow_negative_rates_for_items", @@ -28,20 +31,25 @@ "so_required", "dn_required", "sales_update_frequency", - "blanket_order_allowance", - "enable_tracking_sales_commissions", "column_break_5", "allow_multiple_items", "allow_against_multiple_purchase_orders", + "hide_tax_id", + "section_break_jcmi", "allow_sales_order_creation_for_expired_quotation", "dont_reserve_sales_order_qty_on_sales_return", - "hide_tax_id", - "enable_discount_accounting", "enable_cutoff_date_on_bulk_delivery_note_creation", - "allow_zero_qty_in_quotation", - "allow_zero_qty_in_sales_order", "set_zero_rate_for_expired_batch", + "section_break_zero_qty", + "allow_zero_qty_in_quotation", + "column_break_zwvf", + "allow_zero_qty_in_sales_order", + "blanket_orders_section", + "blanket_order_allowance", + "advanced_features_tab", "section_break_avhb", + "enable_tracking_sales_commissions", + "enable_discount_accounting", "enable_utm", "experimental_section", "use_legacy_js_reactivity", @@ -61,6 +69,7 @@ "options": "Customer Name\nNaming Series\nAuto Name" }, { + "documentation_url": "https://docs.frappe.io/erpnext/selling-settings#2-default-customer-group", "fieldname": "customer_group", "fieldtype": "Link", "in_list_view": 1, @@ -69,6 +78,7 @@ "options": "Customer Group" }, { + "documentation_url": "https://docs.frappe.io/erpnext/selling-settings#3-default-territory", "fieldname": "territory", "fieldtype": "Link", "in_list_view": 1, @@ -80,6 +90,7 @@ "fieldtype": "Link", "in_list_view": 1, "label": "Default Price List", + "link_filters": "[[\"Price List\", \"selling\", \"=\", 1]]", "options": "Price List" }, { @@ -89,66 +100,72 @@ { "fieldname": "so_required", "fieldtype": "Select", - "label": "Is Sales Order Required for Sales Invoice & Delivery Note Creation?", + "label": "Is Sales Order required to create Sales Invoice/Delivery Note?", "options": "No\nYes" }, { "fieldname": "dn_required", "fieldtype": "Select", - "label": "Is Delivery Note Required for Sales Invoice Creation?", + "label": "Is Delivery Note required to create Sales Invoice?", "options": "No\nYes" }, { "default": "Daily", - "description": "How often should Project and Company be updated based on Sales Transactions?", + "description": "The frequency at which project progress and company transaction details will be updated. Set it to daily or monthly if you post a lot of transactions.", "fieldname": "sales_update_frequency", "fieldtype": "Select", - "label": "Sales Update Frequency in Company and Project", + "label": "How often should sales data be updated in Company/Project?", "options": "Monthly\nEach Transaction\nDaily", "reqd": 1 }, { + "bold": 1, "default": "0", + "description": "Warn or stop if Item rate is changed in Delivery Notes and Sales Invoices generated from a Sales Order.", "fieldname": "maintain_same_sales_rate", "fieldtype": "Check", - "label": "Maintain Same Rate Throughout Sales Cycle" + "label": "Maintain same rate throughout sales cycle" }, { + "bold": 1, "default": "0", "fieldname": "editable_price_list_rate", "fieldtype": "Check", - "label": "Allow User to Edit Price List Rate in Transactions" + "label": "Allow editing Price List rate in transactions" }, { "default": "0", "fieldname": "allow_multiple_items", "fieldtype": "Check", - "label": "Allow Item to be Added Multiple Times in a Transaction" + "label": "Allow same Item to be added multiple times in a transaction" }, { "default": "0", "fieldname": "allow_against_multiple_purchase_orders", "fieldtype": "Check", - "label": "Allow Multiple Sales Orders Against a Customer's Purchase Order" + "label": "Allow multiple Sales Orders against a customer's Purchase Order" }, { "default": "0", + "description": "Enable this to block transactions where the selling price is less than the purchase or valuation rate", "fieldname": "validate_selling_price", "fieldtype": "Check", - "label": "Validate Selling Price for Item Against Purchase Rate or Valuation Rate" + "label": "Validate selling price for Item against purchase or valuation rate" }, { "default": "0", + "description": "Most Customers have a unique Tax ID that is fetched into selling transactions. Enable this setting if you do not want Customer Tax IDs to appear in sales transactions.", "fieldname": "hide_tax_id", "fieldtype": "Check", - "label": "Hide Customer's Tax ID from Sales Transactions" + "label": "Hide Customer's Tax ID from sales transactions", + "show_description_on_click": 1 }, { "default": "Stop", "depends_on": "maintain_same_sales_rate", "fieldname": "maintain_same_rate_action", "fieldtype": "Select", - "label": "Action if Same Rate is Not Maintained Throughout Sales Cycle", + "label": "Action if same rate is not maintained throughout sales cycle", "mandatory_depends_on": "maintain_same_sales_rate", "options": "Stop\nWarn" }, @@ -156,13 +173,12 @@ "depends_on": "eval: doc.maintain_same_sales_rate && doc.maintain_same_rate_action == 'Stop'", "fieldname": "role_to_override_stop_action", "fieldtype": "Link", - "label": "Role Allowed to Override Stop Action", + "label": "Role allowed to override stop action", "options": "Role" }, { "fieldname": "customer_defaults_section", - "fieldtype": "Section Break", - "label": "Customer Defaults" + "fieldtype": "Section Break" }, { "fieldname": "column_break_4", @@ -170,12 +186,7 @@ }, { "fieldname": "item_price_settings_section", - "fieldtype": "Section Break", - "label": "Item Price Settings" - }, - { - "fieldname": "column_break_15", - "fieldtype": "Column Break" + "fieldtype": "Section Break" }, { "fieldname": "sales_transactions_settings_section", @@ -184,34 +195,41 @@ }, { "default": "0", + "description": "Enabling this will do the following:\n
    \n
  • Make the rate column of all Packed/Bundle Items tables editable.
  • \n
  • Calculate the prices of all Product Bundles in the Items table, based on the prices of its child Items, specified in the Packed/Bundle Items table.
  • \n
\nNote: If this is enabled, updating the rate of the Product Bundle in the Items table will not change its price. It will get reset to the price based on its Child Items on saving the doc.", + "documentation_url": "https://docs.frappe.io/erpnext/selling-settings#7-calculate-product-bundle-price-based-on-child-items-rates", "fieldname": "editable_bundle_item_rates", "fieldtype": "Check", - "label": "Calculate Product Bundle Price based on Child Items' Rates" + "label": "Calculate Product Bundle price based on child Item's rates", + "show_description_on_click": 1 }, { "default": "0", "description": "If enabled, additional ledger entries will be made for discounts in a separate Discount Account", "fieldname": "enable_discount_accounting", "fieldtype": "Check", - "label": "Enable Discount Accounting for Selling" + "label": "Enable discount accounting for selling" }, { "default": "0", + "description": "This allows creation of sales orders from quotations that have passed their expiration date, providing flexibility in processing orders despite outdated quotes.", "fieldname": "allow_sales_order_creation_for_expired_quotation", "fieldtype": "Check", - "label": "Allow Sales Order Creation For Expired Quotation" + "label": "Allow Sales Order creation for expired Quotation" }, { "default": "0", + "description": "Prevents the automatic reservation of stock quantities from sales orders when processing sales returns.", "fieldname": "dont_reserve_sales_order_qty_on_sales_return", "fieldtype": "Check", - "label": "Don't Reserve Sales Order Qty on Sales Return" + "label": "Don't reserve Sales Order qty on sales return" }, { "default": "0", + "description": "Enable this option to permit the use of negative rates for items in sales transactions. This setting is useful for applying substantial discounts, processing refunds or returns, and handling special promotional pricing.", "fieldname": "allow_negative_rates_for_items", "fieldtype": "Check", - "label": "Allow Negative rates for Items" + "label": "Allow negative rates for Items", + "show_description_on_click": 1 }, { "description": "Percentage you are allowed to sell beyond the Blanket Order quantity.", @@ -221,9 +239,10 @@ }, { "default": "0", + "description": "When enabled, it adds a cutoff date filter to Delivery Notes created in bulk from Sales Orders. This allows you to process orders only with a transaction date up to the specified cutoff date, which is useful for period-end processing and batch fulfillment.", "fieldname": "enable_cutoff_date_on_bulk_delivery_note_creation", "fieldtype": "Check", - "label": "Enable Cut-Off Date on Bulk Delivery Note Creation" + "label": "Enable cut-off date on creating bulk Delivery Notes" }, { "fieldname": "experimental_section", @@ -232,29 +251,26 @@ }, { "default": "0", - "description": "Allows users to submit Sales Orders with zero quantity. Useful when rates are fixed but the quantities are not. Eg. Rate Contracts.", "fieldname": "allow_zero_qty_in_sales_order", "fieldtype": "Check", - "label": "Allow Sales Order with Zero Quantity" + "label": "Allow Sales Order with zero quantity" }, { "default": "0", - "description": "Allows users to submit Quotations with zero quantity. Useful when rates are fixed but the quantities are not. Eg. Rate Contracts.", "fieldname": "allow_zero_qty_in_quotation", "fieldtype": "Check", - "label": "Allow Quotation with Zero Quantity" + "label": "Allow Quotation with zero quantity" }, { "fieldname": "section_break_zwh6", - "fieldtype": "Section Break", - "label": "Subcontracting Inward Settings" + "fieldtype": "Section Break" }, { "default": "0", "description": "If enabled, system will allow user to deliver the entire quantity of the finished goods produced against the Subcontracting Inward Order. If disabled, system will allow delivery of only the ordered quantity.", "fieldname": "allow_delivery_of_overproduced_qty", "fieldtype": "Check", - "label": "Allow Delivery of Overproduced Qty" + "label": "Allow delivery of overproduced quantity" }, { "fieldname": "column_break_mla9", @@ -277,9 +293,10 @@ }, { "default": "0", + "description": "If no Item Price is found for an item in the Price List set in the transaction, prices from the Default Price List will be fetched.", "fieldname": "fallback_to_default_price_list", "fieldtype": "Check", - "label": "Use Prices from Default Price List as Fallback" + "label": "Use prices from Default Price List as fallback" }, { "default": "0", @@ -292,7 +309,7 @@ "description": "If enabled, system will set incoming rate as zero for stand-alone credit notes with expired batch item.", "fieldname": "set_zero_rate_for_expired_batch", "fieldtype": "Check", - "label": "Set Incoming Rate as Zero for Expired Batch" + "label": "Set incoming rate as zero for expired Batch" }, { "default": "0", @@ -303,8 +320,7 @@ }, { "fieldname": "section_break_avhb", - "fieldtype": "Section Break", - "label": "Analytics" + "fieldtype": "Section Break" }, { "default": "0", @@ -319,17 +335,57 @@ "description": "If enabled, the Secondary Items generated against a Finished Good will also be added in the Stock Entry when delivering that Finished Good.", "fieldname": "deliver_secondary_items", "fieldtype": "Check", - "label": "Deliver Secondary Items" + "label": "Deliver secondary Items" + }, + { + "fieldname": "customer_defaults_tab", + "fieldtype": "Tab Break", + "label": "Customer Defaults" + }, + { + "fieldname": "section_break_lpfl", + "fieldtype": "Section Break" + }, + { + "fieldname": "column_break_hkqv", + "fieldtype": "Column Break" + }, + { + "fieldname": "section_break_htyx", + "fieldtype": "Section Break" + }, + { + "fieldname": "advanced_features_tab", + "fieldtype": "Tab Break", + "label": "Advanced Features" + }, + { + "description": "Allow sales transactions with zero quantities if the rate is fixed but the quantities are not. e.g. Rate Contracts", + "fieldname": "section_break_zero_qty", + "fieldtype": "Section Break", + "label": "Zero-Quantity Line Items" + }, + { + "fieldname": "section_break_jcmi", + "fieldtype": "Section Break" + }, + { + "fieldname": "column_break_zwvf", + "fieldtype": "Column Break" + }, + { + "fieldname": "blanket_orders_section", + "fieldtype": "Section Break", + "label": "Blanket Orders" } ], "grid_page_length": 50, - "hide_toolbar": 0, "icon": "fa fa-cog", "idx": 1, "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2026-03-16 13:28:18.988883", + "modified": "2026-04-21 21:29:32.890098", "modified_by": "Administrator", "module": "Selling", "name": "Selling Settings", From 85d1eb8379813d2bcdf33a7fdb95d6198209b5fa Mon Sep 17 00:00:00 2001 From: Sudharsanan11 Date: Sun, 26 Apr 2026 00:01:09 +0530 Subject: [PATCH 22/56] fix(stock): show item code in serial and batch selector dialog (cherry picked from commit f572bc51e185147b9de356d787d8c69d5f49f6a0) --- erpnext/public/js/utils/serial_no_batch_selector.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js index 0d262020007..6d08648c6e0 100644 --- a/erpnext/public/js/utils/serial_no_batch_selector.js +++ b/erpnext/public/js/utils/serial_no_batch_selector.js @@ -87,7 +87,16 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { } get_dialog_fields() { - let fields = []; + let fields = [ + { + fieldname: "item_code", + read_only: 1, + fieldtype: "Link", + options: "Item", + label: __("Item Code"), + default: this.item.item_code, + }, + ]; fields.push({ fieldtype: "Link", From 62bbe28a728a5cad956c752b72cdc2363464d4c3 Mon Sep 17 00:00:00 2001 From: Sudharsanan11 Date: Sun, 26 Apr 2026 00:02:10 +0530 Subject: [PATCH 23/56] fix(stock): add stock entry in batch master connection (cherry picked from commit fee5bcadb217107dfd45b3c9ddc8304398ea4806) --- erpnext/stock/doctype/batch/batch_dashboard.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/batch/batch_dashboard.py b/erpnext/stock/doctype/batch/batch_dashboard.py index a222c422177..db739e54126 100644 --- a/erpnext/stock/doctype/batch/batch_dashboard.py +++ b/erpnext/stock/doctype/batch/batch_dashboard.py @@ -7,7 +7,7 @@ def get_data(): "transactions": [ {"label": _("Buy"), "items": ["Purchase Invoice", "Purchase Receipt"]}, {"label": _("Sell"), "items": ["Sales Invoice", "Delivery Note"]}, - {"label": _("Move"), "items": ["Serial and Batch Bundle"]}, + {"label": _("Move"), "items": ["Stock Entry", "Serial and Batch Bundle"]}, {"label": _("Quality"), "items": ["Quality Inspection"]}, ], } From cabea2f2889b8d00a982d4e4d647ef3bebf3e1f9 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Sun, 26 Apr 2026 20:24:52 +0530 Subject: [PATCH 24/56] fix(stock): set incoming rate as zero for outward sle (backport #54514) (#54533) fix(stock): set incoming rate as zero for outward sle (cherry picked from commit ce37530e70b1fa6141a525e0e819d88d6f8fc08c) Co-authored-by: Sudharsanan11 --- erpnext/stock/stock_ledger.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index edde90de391..cfad2e98cc6 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -955,6 +955,9 @@ class update_entries_after: if not self.wh_data.qty_after_transaction: self.wh_data.stock_value = 0.0 + if sle.actual_qty < 0: + sle.incoming_rate = 0 + stock_value_difference = self.wh_data.stock_value - self.wh_data.prev_stock_value self.wh_data.prev_stock_value = self.wh_data.stock_value From 5c0d2cb47419ce57def83321c39be7dc53b0ca39 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Sun, 26 Apr 2026 21:06:52 +0530 Subject: [PATCH 25/56] feat: danish_bosnian_address_template (backport #54093) (#54516) feat: danish_bosnian_address_template (#54093) (cherry picked from commit e517eeaaa2025e96820c97e7e439abce8ce508a9) Co-authored-by: mahsem <137205921+mahsem@users.noreply.github.com> --- .../address_template/templates/bosnia_and_herzegovina.html | 4 ++++ erpnext/regional/address_template/templates/denmark.html | 4 ++++ 2 files changed, 8 insertions(+) create mode 100644 erpnext/regional/address_template/templates/bosnia_and_herzegovina.html create mode 100644 erpnext/regional/address_template/templates/denmark.html diff --git a/erpnext/regional/address_template/templates/bosnia_and_herzegovina.html b/erpnext/regional/address_template/templates/bosnia_and_herzegovina.html new file mode 100644 index 00000000000..0c2ed73f0ae --- /dev/null +++ b/erpnext/regional/address_template/templates/bosnia_and_herzegovina.html @@ -0,0 +1,4 @@ +{{ address_line1 }}
+{% if address_line2 %}{{ address_line2 }}
{% endif -%} +{{ pincode }} {{ city | upper }}
+{{ country | upper }} \ No newline at end of file diff --git a/erpnext/regional/address_template/templates/denmark.html b/erpnext/regional/address_template/templates/denmark.html new file mode 100644 index 00000000000..0c2ed73f0ae --- /dev/null +++ b/erpnext/regional/address_template/templates/denmark.html @@ -0,0 +1,4 @@ +{{ address_line1 }}
+{% if address_line2 %}{{ address_line2 }}
{% endif -%} +{{ pincode }} {{ city | upper }}
+{{ country | upper }} \ No newline at end of file From 23cac0df83d1b1857b2989562f12df5a603eaa33 Mon Sep 17 00:00:00 2001 From: MochaMind Date: Sun, 26 Apr 2026 22:25:31 +0530 Subject: [PATCH 26/56] chore: update POT file (#54535) --- erpnext/locale/main.pot | 1999 +++++++++++++++++++++------------------ 1 file changed, 1077 insertions(+), 922 deletions(-) diff --git a/erpnext/locale/main.pot b/erpnext/locale/main.pot index bacf12f631e..0ab380aea3e 100644 --- a/erpnext/locale/main.pot +++ b/erpnext/locale/main.pot @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: ERPNext VERSION\n" "Report-Msgid-Bugs-To: hello@frappe.io\n" -"POT-Creation-Date: 2026-04-19 09:47+0000\n" -"PO-Revision-Date: 2026-04-19 09:47+0000\n" +"POT-Creation-Date: 2026-04-26 09:48+0000\n" +"PO-Revision-Date: 2026-04-26 09:48+0000\n" "Last-Translator: hello@frappe.io\n" "Language-Team: hello@frappe.io\n" "MIME-Version: 1.0\n" @@ -106,7 +106,7 @@ msgstr "" msgid "\"Is Fixed Asset\" cannot be unchecked, as Asset record exists against the item" msgstr "" -#: erpnext/public/js/utils/serial_no_batch_selector.js:262 +#: erpnext/public/js/utils/serial_no_batch_selector.js:273 msgid "\"SN-01::10\" for \"SN-01\" to \"SN-10\"" msgstr "" @@ -267,7 +267,7 @@ msgstr "" msgid "% of materials delivered against this Sales Order" msgstr "" -#: erpnext/controllers/accounts_controller.py:2381 +#: erpnext/controllers/accounts_controller.py:2384 msgid "'Account' in the Accounting section of Customer {0}" msgstr "" @@ -275,7 +275,7 @@ msgstr "" msgid "'Allow Multiple Sales Orders Against a Customer's Purchase Order'" msgstr "" -#: erpnext/controllers/trends.py:56 +#: erpnext/controllers/trends.py:62 msgid "'Based On' and 'Group By' can not be same" msgstr "" @@ -283,11 +283,11 @@ msgstr "" msgid "'Days Since Last Order' must be greater than or equal to zero" msgstr "" -#: erpnext/controllers/accounts_controller.py:2386 +#: erpnext/controllers/accounts_controller.py:2389 msgid "'Default {0} Account' in Company {1}" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1229 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1230 msgid "'Entries' cannot be empty" msgstr "" @@ -602,8 +602,8 @@ msgstr "" msgid "90 Above" msgstr "" -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1330 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1331 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1338 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1339 msgid "<0" msgstr "" @@ -768,7 +768,7 @@ msgstr "" msgid "
  • Clearance date must be after cheque date for row(s): {0}
  • " msgstr "" -#: erpnext/controllers/accounts_controller.py:2264 +#: erpnext/controllers/accounts_controller.py:2267 msgid "
  • Item {0} in row(s) {1} billed more than {2}
  • " msgstr "" @@ -785,7 +785,7 @@ msgstr "" msgid "
  • {}
  • " msgstr "" -#: erpnext/controllers/accounts_controller.py:2261 +#: erpnext/controllers/accounts_controller.py:2264 msgid "

    Cannot overbill for the following Items:

    " msgstr "" @@ -822,7 +822,7 @@ msgstr "" msgid "

    Please correct the following row(s):

      " msgstr "" -#: erpnext/controllers/buying_controller.py:121 +#: erpnext/controllers/buying_controller.py:125 msgid "

      Posting Date {0} cannot be before Purchase Order date for the following:

        " msgstr "" @@ -830,7 +830,7 @@ msgstr "" msgid "

        Price List Rate has not been set as editable in Selling Settings. In this scenario, setting Update Price List Based On to Price List Rate will prevent auto-updation of Item Price.

        Are you sure you want to continue?" msgstr "" -#: erpnext/controllers/accounts_controller.py:2273 +#: erpnext/controllers/accounts_controller.py:2276 msgid "

        To allow over-billing, please set allowance in Accounts Settings.

        " msgstr "" @@ -1004,7 +1004,7 @@ msgstr "" msgid "A Reconciliation Job {0} is running for the same filters. Cannot reconcile now" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1763 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1764 msgid "A Reverse Journal Entry {0} already exists for this Journal Entry." msgstr "" @@ -1138,7 +1138,7 @@ msgstr "" msgid "Abbreviation: {0} must appear only once" msgstr "" -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1327 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1335 msgid "Above" msgstr "" @@ -1335,7 +1335,7 @@ msgid "Account Manager" msgstr "" #: erpnext/accounts/doctype/sales_invoice/sales_invoice.py:1007 -#: erpnext/controllers/accounts_controller.py:2390 +#: erpnext/controllers/accounts_controller.py:2393 msgid "Account Missing" msgstr "" @@ -1532,11 +1532,11 @@ msgstr "" msgid "Account {0} is frozen" msgstr "" -#: erpnext/controllers/accounts_controller.py:1467 +#: erpnext/controllers/accounts_controller.py:1468 msgid "Account {0} is invalid. Account Currency must be {1}" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:353 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:354 msgid "Account {0} should be of type Expense" msgstr "" @@ -1556,11 +1556,11 @@ msgstr "" msgid "Account {0}: You can not assign itself as parent account" msgstr "" -#: erpnext/accounts/general_ledger.py:464 +#: erpnext/accounts/general_ledger.py:465 msgid "Account: {0} is capital Work in progress and can not be updated by Journal Entry" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:371 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:372 msgid "Account: {0} can only be updated via Stock Transactions" msgstr "" @@ -1568,7 +1568,7 @@ msgstr "" msgid "Account: {0} is not permitted under Payment Entry" msgstr "" -#: erpnext/controllers/accounts_controller.py:3279 +#: erpnext/controllers/accounts_controller.py:3282 msgid "Account: {0} with currency: {1} can not be selected" msgstr "" @@ -1858,7 +1858,7 @@ msgstr "" msgid "Accounting Entry for LCV in Stock Entry {0}" msgstr "" -#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:910 +#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:942 msgid "Accounting Entry for Landed Cost Voucher for SCR {0}" msgstr "" @@ -1880,7 +1880,7 @@ msgstr "" #: erpnext/stock/doctype/purchase_receipt/purchase_receipt.py:936 #: erpnext/stock/doctype/stock_entry/stock_entry.py:2001 #: erpnext/stock/doctype/stock_entry/stock_entry.py:2015 -#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:745 +#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:777 msgid "Accounting Entry for Stock" msgstr "" @@ -1888,7 +1888,7 @@ msgstr "" msgid "Accounting Entry for {0}" msgstr "" -#: erpnext/controllers/accounts_controller.py:2431 +#: erpnext/controllers/accounts_controller.py:2434 msgid "Accounting Entry for {0}: {1} can only be made in currency: {2}" msgstr "" @@ -1995,7 +1995,7 @@ msgstr "" #: erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts_with_account_number.py:256 #: erpnext/accounts/doctype/journal_entry/journal_entry.json #: erpnext/accounts/report/accounts_payable/accounts_payable.json -#: erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js:113 +#: erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js:124 #: erpnext/buying/doctype/supplier/supplier.js:110 #: erpnext/workspace_sidebar/financial_reports.json #: erpnext/workspace_sidebar/invoicing.json @@ -2004,7 +2004,7 @@ msgid "Accounts Payable" msgstr "" #. Name of a report -#: erpnext/accounts/report/accounts_payable/accounts_payable.js:164 +#: erpnext/accounts/report/accounts_payable/accounts_payable.js:175 #: erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.json msgid "Accounts Payable Summary" msgstr "" @@ -2020,7 +2020,7 @@ msgstr "" #: erpnext/accounts/doctype/journal_entry/journal_entry.json #: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json #: erpnext/accounts/report/accounts_receivable/accounts_receivable.json -#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:136 +#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:147 #: erpnext/selling/doctype/customer/customer.js:162 #: erpnext/workspace_sidebar/financial_reports.json #: erpnext/workspace_sidebar/invoicing.json @@ -2047,7 +2047,7 @@ msgid "Accounts Receivable Discounted Account" msgstr "" #. Name of a report -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:191 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:202 #: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.json msgid "Accounts Receivable Summary" msgstr "" @@ -2083,7 +2083,7 @@ msgstr "" msgid "Accounts Setup" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1328 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1329 msgid "Accounts table cannot be blank." msgstr "" @@ -2247,7 +2247,7 @@ msgstr "" #. Label of the maintain_same_rate_action (Select) field in DocType 'Selling #. Settings' #: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "Action if Same Rate is Not Maintained Throughout Sales Cycle" +msgid "Action if same rate is not maintained throughout sales cycle" msgstr "" #. Label of the action_on_new_invoice (Select) field in DocType 'POS Profile' @@ -2389,7 +2389,7 @@ msgstr "" msgid "Actual End Date (via Timesheet)" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:225 +#: erpnext/manufacturing/doctype/work_order/work_order.py:229 msgid "Actual End Date cannot be before Actual Start Date" msgstr "" @@ -2892,7 +2892,7 @@ msgstr "" msgid "Additional Discount Amount (Company Currency)" msgstr "" -#: erpnext/controllers/taxes_and_totals.py:836 +#: erpnext/controllers/taxes_and_totals.py:850 msgid "Additional Discount Amount ({discount_amount}) cannot exceed the total before such discount ({total_before_discount})" msgstr "" @@ -2987,7 +2987,7 @@ msgstr "" msgid "Additional Information updated successfully." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:829 +#: erpnext/manufacturing/doctype/work_order/work_order.js:836 msgid "Additional Material Transfer" msgstr "" @@ -3010,7 +3010,7 @@ msgstr "" msgid "Additional Transferred Qty" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:694 +#: erpnext/manufacturing/doctype/work_order/work_order.py:710 msgid "" "Additional Transferred Qty {0}\n" "\t\t\t\t\tcannot be greater than {1}.\n" @@ -3024,7 +3024,7 @@ msgstr "" msgid "Additional information regarding the customer." msgstr "" -#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:627 +#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:659 msgid "Additional {0} {1} of item {2} required as per BOM to complete this transaction" msgstr "" @@ -3255,7 +3255,7 @@ msgstr "" #: erpnext/accounts/doctype/pos_invoice/pos_invoice.json #: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json #: erpnext/accounts/doctype/sales_invoice/sales_invoice.json -#: erpnext/controllers/accounts_controller.py:284 +#: erpnext/controllers/accounts_controller.py:285 #: erpnext/setup/doctype/company/company.json msgid "Advance Payments" msgstr "" @@ -3291,11 +3291,11 @@ msgstr "" msgid "Advance amount" msgstr "" -#: erpnext/controllers/taxes_and_totals.py:973 +#: erpnext/controllers/taxes_and_totals.py:987 msgid "Advance amount cannot be greater than {0} {1}" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:876 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:877 msgid "Advance paid against {0} {1} cannot be greater than Grand Total {2}" msgstr "" @@ -3308,6 +3308,12 @@ msgstr "" msgid "Advance payments allocated against orders will only be fetched" msgstr "" +#. Label of the advanced_features_tab (Tab Break) field in DocType 'Selling +#. Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "Advanced Features" +msgstr "" + #. Label of the advanced_filtering (Check) field in DocType 'Financial Report #. Row' #: erpnext/accounts/doctype/financial_report_row/financial_report_row.json @@ -3421,7 +3427,7 @@ msgstr "" msgid "Against Income Account" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:738 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:739 #: erpnext/accounts/doctype/payment_entry/payment_entry.py:777 msgid "Against Journal Entry {0} does not have any unmatched {1} entry" msgstr "" @@ -3507,7 +3513,7 @@ msgstr "" #: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts_accounts_receivable.html:154 #: erpnext/accounts/report/accounts_receivable/accounts_receivable.html:133 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1268 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1276 msgid "Age (Days)" msgstr "" @@ -3518,16 +3524,16 @@ msgstr "" #. Label of the ageing_based_on (Select) field in DocType 'Process Statement Of #. Accounts' #: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json -#: erpnext/accounts/report/accounts_payable/accounts_payable.js:55 +#: erpnext/accounts/report/accounts_payable/accounts_payable.js:66 #: erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js:21 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:84 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:95 #: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:21 msgid "Ageing Based On" msgstr "" -#: erpnext/accounts/report/accounts_payable/accounts_payable.js:69 +#: erpnext/accounts/report/accounts_payable/accounts_payable.js:80 #: erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js:35 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:98 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:109 #: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:35 #: erpnext/stock/report/stock_ageing/stock_ageing.js:58 msgid "Ageing Range" @@ -3631,7 +3637,7 @@ msgstr "" msgid "All Activities HTML" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:390 +#: erpnext/manufacturing/doctype/bom/bom.py:391 msgid "All BOMs" msgstr "" @@ -3776,7 +3782,7 @@ msgstr "" msgid "All items have already been received" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:3335 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:3337 msgid "All items have already been transferred for this Work Order." msgstr "" @@ -3802,7 +3808,7 @@ msgstr "" msgid "All the items have been already returned." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:1267 +#: erpnext/manufacturing/doctype/work_order/work_order.js:1274 msgid "All the required items (raw materials) will be fetched from BOM and populated in this table. Here you can also change the Source Warehouse for any item. And during the production, you can track transferred raw materials from this table." msgstr "" @@ -3953,12 +3959,6 @@ msgstr "" msgid "Allow Continuous Material Consumption" msgstr "" -#. Label of the allow_delivery_of_overproduced_qty (Check) field in DocType -#. 'Selling Settings' -#: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "Allow Delivery of Overproduced Qty" -msgstr "" - #. Label of the allow_editing_of_items_and_quantities_in_work_order (Check) #. field in DocType 'Manufacturing Settings' #: erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json @@ -3997,12 +3997,6 @@ msgstr "" msgid "Allow Item to Be Added Multiple Times in a Transaction" msgstr "" -#. Label of the allow_multiple_items (Check) field in DocType 'Selling -#. Settings' -#: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "Allow Item to be Added Multiple Times in a Transaction" -msgstr "" - #. Label of the allow_lead_duplication_based_on_emails (Check) field in DocType #. 'CRM Settings' #: erpnext/crm/doctype/crm_settings/crm_settings.json @@ -4013,12 +4007,6 @@ msgstr "" msgid "Allow Multiple Material Consumption" msgstr "" -#. Label of the allow_against_multiple_purchase_orders (Check) field in DocType -#. 'Selling Settings' -#: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "Allow Multiple Sales Orders Against a Customer's Purchase Order" -msgstr "" - #. Label of the allow_negative_stock (Check) field in DocType 'Item' #. Label of the allow_negative_stock (Check) field in DocType 'Repost Item #. Valuation' @@ -4039,10 +4027,7 @@ msgstr "" #. Label of the allow_negative_rates_for_items (Check) field in DocType 'Buying #. Settings' -#. Label of the allow_negative_rates_for_items (Check) field in DocType -#. 'Selling Settings' #: erpnext/buying/doctype/buying_settings/buying_settings.json -#: erpnext/selling/doctype/selling_settings/selling_settings.json msgid "Allow Negative rates for Items" msgstr "" @@ -4101,7 +4086,7 @@ msgstr "" #. Label of the allow_zero_qty_in_quotation (Check) field in DocType 'Selling #. Settings' #: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "Allow Quotation with Zero Quantity" +msgid "Allow Quotation with zero quantity" msgstr "" #. Label of the allow_rename_attribute_value (Check) field in DocType 'Item @@ -4145,13 +4130,13 @@ msgstr "" #. Label of the allow_sales_order_creation_for_expired_quotation (Check) field #. in DocType 'Selling Settings' #: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "Allow Sales Order Creation For Expired Quotation" +msgid "Allow Sales Order creation for expired Quotation" msgstr "" #. Label of the allow_zero_qty_in_sales_order (Check) field in DocType 'Selling #. Settings' #: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "Allow Sales Order with Zero Quantity" +msgid "Allow Sales Order with zero quantity" msgstr "" #. Label of the allow_stale (Check) field in DocType 'Accounts Settings' @@ -4176,12 +4161,6 @@ msgstr "" msgid "Allow User to Edit Discount" msgstr "" -#. Label of the editable_price_list_rate (Check) field in DocType 'Selling -#. Settings' -#: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "Allow User to Edit Price List Rate in Transactions" -msgstr "" - #. Label of the allow_rate_change (Check) field in DocType 'POS Profile' #: erpnext/accounts/doctype/pos_profile/pos_profile.json msgid "Allow User to Edit Rate" @@ -4223,6 +4202,18 @@ msgstr "" msgid "Allow Zero Valuation Rate" msgstr "" +#. Label of the allow_delivery_of_overproduced_qty (Check) field in DocType +#. 'Selling Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "Allow delivery of overproduced quantity" +msgstr "" + +#. Label of the editable_price_list_rate (Check) field in DocType 'Selling +#. Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "Allow editing Price List rate in transactions" +msgstr "" + #. Label of the allow_existing_serial_no (Check) field in DocType 'Stock #. Settings' #: erpnext/stock/doctype/stock_settings/stock_settings.json @@ -4241,6 +4232,30 @@ msgstr "" msgid "Allow multi-currency invoices against single party account " msgstr "" +#. Label of the allow_against_multiple_purchase_orders (Check) field in DocType +#. 'Selling Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "Allow multiple Sales Orders against a customer's Purchase Order" +msgstr "" + +#. Label of the allow_negative_rates_for_items (Check) field in DocType +#. 'Selling Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "Allow negative rates for Items" +msgstr "" + +#. Description of the 'Zero-Quantity Line Items' (Section Break) field in +#. DocType 'Selling Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "Allow sales transactions with zero quantities if the rate is fixed but the quantities are not. e.g. Rate Contracts" +msgstr "" + +#. Label of the allow_multiple_items (Check) field in DocType 'Selling +#. Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "Allow same Item to be added multiple times in a transaction" +msgstr "" + #. Label of the allow_to_edit_stock_uom_qty_for_purchase (Check) field in #. DocType 'Stock Settings' #: erpnext/stock/doctype/stock_settings/stock_settings.json @@ -4308,24 +4323,12 @@ msgstr "" msgid "Allows users to submit Purchase Orders with zero quantity. Useful when rates are fixed but the quantities are not. Eg. Rate Contracts." msgstr "" -#. Description of the 'Allow Quotation with Zero Quantity' (Check) field in -#. DocType 'Selling Settings' -#: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "Allows users to submit Quotations with zero quantity. Useful when rates are fixed but the quantities are not. Eg. Rate Contracts." -msgstr "" - #. Description of the 'Allow Request for Quotation with Zero Quantity' (Check) #. field in DocType 'Buying Settings' #: erpnext/buying/doctype/buying_settings/buying_settings.json msgid "Allows users to submit Request for Quotations with zero quantity. Useful when rates are fixed but the quantities are not. Eg. Rate Contracts." msgstr "" -#. Description of the 'Allow Sales Order with Zero Quantity' (Check) field in -#. DocType 'Selling Settings' -#: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "Allows users to submit Sales Orders with zero quantity. Useful when rates are fixed but the quantities are not. Eg. Rate Contracts." -msgstr "" - #. Description of the 'Allow Supplier Quotation with Zero Quantity' (Check) #. field in DocType 'Buying Settings' #: erpnext/buying/doctype/buying_settings/buying_settings.json @@ -4555,8 +4558,8 @@ msgstr "" #: erpnext/selling/page/point_of_sale/pos_item_cart.js:52 #: erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py:52 #: erpnext/selling/report/sales_order_analysis/sales_order_analysis.py:290 -#: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py:53 -#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py:69 +#: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py:164 +#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py:43 #: erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.py:68 #: erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py:109 #: erpnext/stock/doctype/delivery_note_item/delivery_note_item.json @@ -4742,8 +4745,8 @@ msgstr "" msgid "Ampere-Second" msgstr "" -#: erpnext/controllers/trends.py:277 erpnext/controllers/trends.py:289 -#: erpnext/controllers/trends.py:298 +#: erpnext/controllers/trends.py:283 erpnext/controllers/trends.py:295 +#: erpnext/controllers/trends.py:304 msgid "Amt" msgstr "" @@ -5276,6 +5279,7 @@ msgid "Assembly Items" msgstr "" #. Option for the 'Root Type' (Select) field in DocType 'Account' +#. Option for the 'Root Type' (Select) field in DocType 'Account Category' #. Option for the 'Reference Type' (Select) field in DocType 'Journal Entry #. Account' #. Option for the 'Root Type' (Select) field in DocType 'Ledger Merge' @@ -5293,6 +5297,7 @@ msgstr "" #. Label of the asset (Link) field in DocType 'Serial No' #. Label of a Workspace Sidebar Item #: erpnext/accounts/doctype/account/account.json +#: erpnext/accounts/doctype/account_category/account_category.json #: erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json #: erpnext/accounts/doctype/ledger_merge/ledger_merge.json #: erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.json @@ -5797,7 +5802,7 @@ msgstr "" msgid "Asset {0} must be submitted" msgstr "" -#: erpnext/controllers/buying_controller.py:1034 +#: erpnext/controllers/buying_controller.py:1041 msgid "Asset {assets_link} created for {item_code}" msgstr "" @@ -5822,7 +5827,7 @@ msgstr "" #. Title of a Workspace Sidebar #: erpnext/accounts/doctype/accounts_settings/accounts_settings.json #: erpnext/accounts/doctype/finance_book/finance_book_dashboard.py:9 -#: erpnext/accounts/report/balance_sheet/balance_sheet.py:250 +#: erpnext/accounts/report/balance_sheet/balance_sheet.py:251 #: erpnext/assets/doctype/asset_capitalization/asset_capitalization.json #: erpnext/assets/doctype/asset_movement/asset_movement.json #: erpnext/assets/workspace/assets/assets.json erpnext/desktop_icon/assets.json @@ -5835,11 +5840,11 @@ msgstr "" msgid "Assets Setup" msgstr "" -#: erpnext/controllers/buying_controller.py:1052 +#: erpnext/controllers/buying_controller.py:1059 msgid "Assets not created for {item_code}. You will have to create asset manually." msgstr "" -#: erpnext/controllers/buying_controller.py:1039 +#: erpnext/controllers/buying_controller.py:1046 msgid "Assets {assets_link} created for {item_code}" msgstr "" @@ -5961,7 +5966,7 @@ msgstr "" msgid "Atmosphere" msgstr "" -#: erpnext/public/js/utils/serial_no_batch_selector.js:244 +#: erpnext/public/js/utils/serial_no_batch_selector.js:255 #: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.js:73 msgid "Attach CSV File" msgstr "" @@ -6125,7 +6130,7 @@ msgstr "" msgid "Auto Creation of Contact" msgstr "" -#: erpnext/public/js/utils/serial_no_batch_selector.js:368 +#: erpnext/public/js/utils/serial_no_batch_selector.js:379 msgid "Auto Fetch" msgstr "" @@ -6529,6 +6534,7 @@ msgstr "" #. field in DocType 'Buying Settings' #. Label of the bom (Link) field in DocType 'Purchase Order Item' #. Name of a DocType +#. Option for the 'Based On' (Select) field in DocType 'BOM' #. Option for the 'Backflush Raw Materials Based On' (Select) field in DocType #. 'Manufacturing Settings' #. Label of the bom_section (Section Break) field in DocType 'Manufacturing @@ -6553,7 +6559,7 @@ msgstr "" #: erpnext/manufacturing/report/bom_stock_analysis/bom_stock_analysis.js:8 #: erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.py:109 #: erpnext/manufacturing/workspace/manufacturing/manufacturing.json -#: erpnext/selling/doctype/sales_order/sales_order.js:1440 +#: erpnext/selling/doctype/sales_order/sales_order.js:1438 #: erpnext/stock/doctype/material_request/material_request.js:351 #: erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json #: erpnext/stock/doctype/stock_entry/stock_entry.js:788 @@ -6570,7 +6576,7 @@ msgstr "" msgid "BOM 1" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1801 +#: erpnext/manufacturing/doctype/bom/bom.py:1802 msgid "BOM 1 {0} and BOM 2 {1} should not be same" msgstr "" @@ -6586,6 +6592,11 @@ msgstr "" msgid "BOM Comparison Tool" msgstr "" +#. Label of the bom_conf_tab (Tab Break) field in DocType 'BOM' +#: erpnext/manufacturing/doctype/bom/bom.json +msgid "BOM Configuration" +msgstr "" + #. Label of the bom_created (Check) field in DocType 'BOM Creator Item' #: erpnext/manufacturing/doctype/bom_creator_item/bom_creator_item.json msgid "BOM Created" @@ -6824,23 +6835,23 @@ msgstr "" msgid "BOM recursion: {0} cannot be child of {1}" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:789 +#: erpnext/manufacturing/doctype/bom/bom.py:790 msgid "BOM recursion: {1} cannot be parent or child of {0}" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1540 +#: erpnext/manufacturing/doctype/bom/bom.py:1541 msgid "BOM {0} does not belong to Item {1}" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1522 +#: erpnext/manufacturing/doctype/bom/bom.py:1523 msgid "BOM {0} must be active" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1525 +#: erpnext/manufacturing/doctype/bom/bom.py:1526 msgid "BOM {0} must be submitted" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:877 +#: erpnext/manufacturing/doctype/bom/bom.py:878 msgid "BOM {0} not found for the item {1}" msgstr "" @@ -6873,7 +6884,7 @@ msgstr "" #. Order Operation' #: erpnext/manufacturing/doctype/bom_operation/bom_operation.json #: erpnext/manufacturing/doctype/job_card/job_card.json -#: erpnext/manufacturing/doctype/work_order/work_order.js:381 +#: erpnext/manufacturing/doctype/work_order/work_order.js:386 #: erpnext/manufacturing/doctype/work_order_operation/work_order_operation.json msgid "Backflush Materials From WIP Warehouse" msgstr "" @@ -7443,10 +7454,10 @@ msgstr "" #. Label of the based_on_payment_terms (Check) field in DocType 'Process #. Statement Of Accounts' #: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json -#: erpnext/accounts/report/accounts_payable/accounts_payable.js:120 -#: erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js:97 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:142 -#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:115 +#: erpnext/accounts/report/accounts_payable/accounts_payable.js:131 +#: erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js:108 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:153 +#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:126 msgid "Based On Payment Terms" msgstr "" @@ -7570,7 +7581,7 @@ msgstr "" #: erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.py:115 #: erpnext/public/js/controllers/transaction.js:2950 #: erpnext/public/js/utils/barcode_scanner.js:281 -#: erpnext/public/js/utils/serial_no_batch_selector.js:438 +#: erpnext/public/js/utils/serial_no_batch_selector.js:449 #: erpnext/stock/doctype/delivery_note_item/delivery_note_item.json #: erpnext/stock/doctype/item_price/item_price.json #: erpnext/stock/doctype/packed_item/packed_item.json @@ -7621,7 +7632,7 @@ msgid "Batch No." msgstr "" #: erpnext/public/js/utils/serial_no_batch_selector.js:16 -#: erpnext/public/js/utils/serial_no_batch_selector.js:190 +#: erpnext/public/js/utils/serial_no_batch_selector.js:201 #: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.js:50 msgid "Batch Nos" msgstr "" @@ -7663,7 +7674,7 @@ msgstr "" #. Label of the batch_size (Float) field in DocType 'Work Order Operation' #: erpnext/manufacturing/doctype/bom_operation/bom_operation.json #: erpnext/manufacturing/doctype/operation/operation.json -#: erpnext/manufacturing/doctype/work_order/work_order.js:363 +#: erpnext/manufacturing/doctype/work_order/work_order.js:368 #: erpnext/manufacturing/doctype/work_order/work_order.json #: erpnext/manufacturing/doctype/work_order_operation/work_order_operation.json msgid "Batch Size" @@ -7680,7 +7691,7 @@ msgstr "" msgid "Batch and Serial No" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:921 +#: erpnext/manufacturing/doctype/work_order/work_order.py:937 msgid "Batch not created for item {} since it does not have a batch series." msgstr "" @@ -7692,12 +7703,12 @@ msgstr "" msgid "Batch {0} is not available in warehouse {1}" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:3519 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:3521 #: erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py:290 msgid "Batch {0} of Item {1} has expired." msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:3525 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:3527 msgid "Batch {0} of Item {1} is disabled." msgstr "" @@ -7740,7 +7751,7 @@ msgstr "" #. Label of the bill_date (Date) field in DocType 'Journal Entry' #. Label of the bill_date (Date) field in DocType 'Subcontracting Receipt' #: erpnext/accounts/doctype/journal_entry/journal_entry.json -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1253 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1261 #: erpnext/accounts/report/purchase_register/purchase_register.py:214 #: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.json msgid "Bill Date" @@ -7749,7 +7760,7 @@ msgstr "" #. Label of the bill_no (Data) field in DocType 'Journal Entry' #. Label of the bill_no (Data) field in DocType 'Subcontracting Receipt' #: erpnext/accounts/doctype/journal_entry/journal_entry.json -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1252 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1260 #: erpnext/accounts/report/purchase_register/purchase_register.py:213 #: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.json msgid "Bill No" @@ -7764,7 +7775,7 @@ msgstr "" #. Label of a Card Break in the Manufacturing Workspace #. Label of a Link in the Manufacturing Workspace #. Label of a Workspace Sidebar Item -#: erpnext/manufacturing/doctype/bom/bom.py:1372 +#: erpnext/manufacturing/doctype/bom/bom.py:1373 #: erpnext/manufacturing/workspace/manufacturing/manufacturing.json #: erpnext/stock/doctype/material_request/material_request.js:139 #: erpnext/stock/doctype/stock_entry/stock_entry.js:774 @@ -7868,7 +7879,7 @@ msgstr "" msgid "Billing Address Name" msgstr "" -#: erpnext/controllers/accounts_controller.py:570 +#: erpnext/controllers/accounts_controller.py:571 msgid "Billing Address does not belong to the {0}" msgstr "" @@ -8095,6 +8106,12 @@ msgstr "" msgid "Blanket Order Rate" msgstr "" +#. Label of the blanket_orders_section (Section Break) field in DocType +#. 'Selling Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "Blanket Orders" +msgstr "" + #: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js:109 #: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js:260 msgid "Block Invoice" @@ -8203,7 +8220,7 @@ msgstr "" msgid "Booked Fixed Asset" msgstr "" -#: erpnext/accounts/general_ledger.py:828 +#: erpnext/accounts/general_ledger.py:829 msgid "Books have been closed till the period ending on {0}" msgstr "" @@ -8694,9 +8711,9 @@ msgstr "" msgid "Cable Length (US)" msgstr "" -#: erpnext/accounts/report/accounts_payable/accounts_payable.js:62 +#: erpnext/accounts/report/accounts_payable/accounts_payable.js:73 #: erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js:28 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:91 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:102 #: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:28 msgid "Calculate Ageing With" msgstr "" @@ -8720,7 +8737,7 @@ msgstr "" #. Label of the editable_bundle_item_rates (Check) field in DocType 'Selling #. Settings' #: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "Calculate Product Bundle Price based on Child Items' Rates" +msgid "Calculate Product Bundle price based on child Item's rates" msgstr "" #. Description of the 'Hidden Line (Internal Use Only)' (Check) field in @@ -8921,7 +8938,7 @@ msgstr "" msgid "Can be approved by {0}" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:2559 +#: erpnext/manufacturing/doctype/work_order/work_order.py:2575 msgid "Can not close Work Order. Since {0} Job Cards are in Work In Progress state." msgstr "" @@ -8949,13 +8966,13 @@ msgstr "" msgid "Can not filter based on Voucher No, if grouped by Voucher" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1387 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1388 #: erpnext/accounts/doctype/payment_entry/payment_entry.py:2874 msgid "Can only make payment against unbilled {0}" msgstr "" #: erpnext/accounts/doctype/payment_entry/payment_entry.js:1517 -#: erpnext/controllers/accounts_controller.py:3188 +#: erpnext/controllers/accounts_controller.py:3191 #: erpnext/public/js/controllers/accounts.js:103 msgid "Can refer row only if the charge type is 'On Previous Row Amount' or 'Previous Row Total'" msgstr "" @@ -9036,7 +9053,7 @@ msgstr "" msgid "Cannot amend {0} {1}, please create a new one instead." msgstr "" -#: erpnext/accounts/doctype/tax_withholding_entry/tax_withholding_entry.py:1297 +#: erpnext/accounts/doctype/tax_withholding_entry/tax_withholding_entry.py:1298 msgid "Cannot apply TDS against multiple parties in one entry" msgstr "" @@ -9060,7 +9077,7 @@ msgstr "" msgid "Cannot cancel as processing of cancelled documents is pending." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1099 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1115 msgid "Cannot cancel because submitted Stock Entry {0} exists" msgstr "" @@ -9072,11 +9089,11 @@ msgstr "" msgid "Cannot cancel this Manufacturing Stock Entry as quantity of Finished Good produced cannot be less than quantity delivered in the linked Subcontracting Inward Order." msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:578 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:579 msgid "Cannot cancel this document as it is linked with the submitted Asset Value Adjustment {0}. Please cancel the Asset Value Adjustment to continue." msgstr "" -#: erpnext/controllers/buying_controller.py:1141 +#: erpnext/controllers/buying_controller.py:1148 msgid "Cannot cancel this document as it is linked with the submitted asset {asset_link}. Please cancel the asset to continue." msgstr "" @@ -9133,7 +9150,7 @@ msgstr "" msgid "Cannot create a pick list for Sales Order {0} because it has reserved stock. Please unreserve the stock in order to create a pick list." msgstr "" -#: erpnext/accounts/general_ledger.py:149 +#: erpnext/accounts/general_ledger.py:150 msgid "Cannot create accounting entries against disabled accounts: {0}" msgstr "" @@ -9141,7 +9158,7 @@ msgstr "" msgid "Cannot create return for consolidated invoice {0}." msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1210 +#: erpnext/manufacturing/doctype/bom/bom.py:1211 msgid "Cannot deactivate or cancel BOM as it is linked with other BOMs" msgstr "" @@ -9162,7 +9179,7 @@ msgstr "" msgid "Cannot delete Serial No {0}, as it is used in stock transactions" msgstr "" -#: erpnext/controllers/accounts_controller.py:3784 +#: erpnext/controllers/accounts_controller.py:3790 msgid "Cannot delete an item which has been ordered" msgstr "" @@ -9187,7 +9204,7 @@ msgstr "" msgid "Cannot disable {0} as it may lead to incorrect stock valuation." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:711 +#: erpnext/manufacturing/doctype/work_order/work_order.py:727 msgid "Cannot disassemble more than produced quantity." msgstr "" @@ -9216,7 +9233,7 @@ msgstr "" msgid "Cannot find Item with this Barcode" msgstr "" -#: erpnext/controllers/accounts_controller.py:3736 +#: erpnext/controllers/accounts_controller.py:3742 msgid "Cannot find a default warehouse for item {0}. Please set one in the Item Master or in Stock Settings." msgstr "" @@ -9224,15 +9241,15 @@ msgstr "" msgid "Cannot merge {0} '{1}' into '{2}' as both have existing accounting entries in different currencies for company '{3}'." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:561 +#: erpnext/manufacturing/doctype/work_order/work_order.py:577 msgid "Cannot produce more Item {0} than Sales Order quantity {1} {2}" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1456 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1472 msgid "Cannot produce more item for {0}" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1460 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1476 msgid "Cannot produce more than {0} items for {1}" msgstr "" @@ -9240,12 +9257,12 @@ msgstr "" msgid "Cannot receive from customer against negative outstanding" msgstr "" -#: erpnext/controllers/accounts_controller.py:3932 +#: erpnext/controllers/accounts_controller.py:3938 msgid "Cannot reduce quantity than ordered or purchased quantity" msgstr "" #: erpnext/accounts/doctype/payment_entry/payment_entry.js:1530 -#: erpnext/controllers/accounts_controller.py:3203 +#: erpnext/controllers/accounts_controller.py:3206 #: erpnext/public/js/controllers/accounts.js:120 msgid "Cannot refer row number greater than or equal to current row number for this Charge type" msgstr "" @@ -9265,9 +9282,9 @@ msgstr "" #: erpnext/accounts/doctype/payment_entry/payment_entry.js:1523 #: erpnext/accounts/doctype/payment_entry/payment_entry.js:1701 #: erpnext/accounts/doctype/payment_entry/payment_entry.py:1827 -#: erpnext/controllers/accounts_controller.py:3193 +#: erpnext/controllers/accounts_controller.py:3196 #: erpnext/public/js/controllers/accounts.js:112 -#: erpnext/public/js/controllers/taxes_and_totals.js:531 +#: erpnext/public/js/controllers/taxes_and_totals.js:550 msgid "Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row" msgstr "" @@ -9283,11 +9300,11 @@ msgstr "" msgid "Cannot set multiple Item Defaults for a company." msgstr "" -#: erpnext/controllers/accounts_controller.py:3898 +#: erpnext/controllers/accounts_controller.py:3904 msgid "Cannot set quantity less than delivered quantity" msgstr "" -#: erpnext/controllers/accounts_controller.py:3899 +#: erpnext/controllers/accounts_controller.py:3905 msgid "Cannot set quantity less than received quantity" msgstr "" @@ -9299,7 +9316,7 @@ msgstr "" msgid "Cannot start deletion. Another deletion {0} is already queued/running. Please wait for it to complete." msgstr "" -#: erpnext/controllers/accounts_controller.py:3926 +#: erpnext/controllers/accounts_controller.py:3932 msgid "Cannot update rate as item {0} is already ordered or purchased against this quotation" msgstr "" @@ -9332,7 +9349,7 @@ msgstr "" msgid "Capacity Planning" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1085 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1101 msgid "Capacity Planning Error, planned start time can not be same as end time" msgstr "" @@ -9463,15 +9480,15 @@ msgstr "" msgid "Cash Flow Statement" msgstr "" -#: erpnext/accounts/report/cash_flow/cash_flow.py:178 +#: erpnext/accounts/report/cash_flow/cash_flow.py:179 msgid "Cash Flow from Financing" msgstr "" -#: erpnext/accounts/report/cash_flow/cash_flow.py:171 +#: erpnext/accounts/report/cash_flow/cash_flow.py:172 msgid "Cash Flow from Investing" msgstr "" -#: erpnext/accounts/report/cash_flow/cash_flow.py:159 +#: erpnext/accounts/report/cash_flow/cash_flow.py:160 msgid "Cash Flow from Operations" msgstr "" @@ -9712,7 +9729,7 @@ msgid "Channel Partner" msgstr "" #: erpnext/accounts/doctype/payment_entry/payment_entry.py:2256 -#: erpnext/controllers/accounts_controller.py:3256 +#: erpnext/controllers/accounts_controller.py:3259 msgid "Charge of type 'Actual' in row {0} cannot be included in Item Rate or Paid Amount" msgstr "" @@ -9761,7 +9778,7 @@ msgstr "" #. Label of the section_break_28 (Section Break) field in DocType 'Company' #. Label of a Link in the Home Workspace #. Label of a Workspace Sidebar Item -#: erpnext/accounts/doctype/account/account.js:69 +#: erpnext/accounts/doctype/account/account.js:87 #: erpnext/accounts/doctype/account/account_tree.js:5 #: erpnext/accounts/doctype/cost_center/cost_center_tree.js:52 #: erpnext/accounts/workspace/invoicing/invoicing.json @@ -9823,6 +9840,13 @@ msgstr "" msgid "Check if material transfer entry is not required" msgstr "" +#. Description of the 'Not Applicable' (Check) field in DocType 'Item Tax +#. Template Detail' +#: erpnext/accounts/doctype/item_tax_template_detail/item_tax_template_detail.json +#, python-format +msgid "Check if this tax is not applicable to items (distinct from 0% rate)" +msgstr "" + #: erpnext/accounts/doctype/journal_entry_template/journal_entry_template.py:58 msgid "Check row {0} for account {1}: Party Type is only allowed for Receivable or Payable accounts" msgstr "" @@ -10009,10 +10033,6 @@ msgstr "" msgid "Clear Last Scanned Warehouse" msgstr "" -#: erpnext/selling/page/point_of_sale/pos_item_selector.js:264 -msgid "Clear Link" -msgstr "" - #. Label of the clear_notifications_status (Select) field in DocType #. 'Transaction Deletion Record' #: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.json @@ -10124,7 +10144,7 @@ msgstr "" msgid "Closed Documents" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:2482 +#: erpnext/manufacturing/doctype/work_order/work_order.py:2498 msgid "Closed Work Order can not be stopped or Re-opened" msgstr "" @@ -10303,7 +10323,7 @@ msgstr "" #: erpnext/accounts/doctype/pos_invoice/pos_invoice.json #: erpnext/accounts/doctype/sales_invoice/sales_invoice.json #: erpnext/selling/doctype/sales_order/sales_order.json -#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py:83 +#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py:49 #: erpnext/stock/doctype/delivery_note/delivery_note.json msgid "Commission" msgstr "" @@ -10321,8 +10341,8 @@ msgstr "" msgid "Commission Rate" msgstr "" -#: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py:67 -#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py:78 +#: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py:168 +#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py:47 #: erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.py:83 msgid "Commission Rate %" msgstr "" @@ -10747,7 +10767,7 @@ msgstr "" #: erpnext/selling/report/sales_order_analysis/sales_order_analysis.py:343 #: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.js:8 #: erpnext/selling/report/sales_partner_target_variance_based_on_item_group/sales_partner_target_variance_based_on_item_group.js:8 -#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.js:33 +#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.js:8 #: erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.js:33 #: erpnext/selling/report/sales_person_target_variance_based_on_item_group/sales_person_target_variance_based_on_item_group.js:8 #: erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.js:33 @@ -10901,11 +10921,11 @@ msgstr "" msgid "Company Address Name" msgstr "" -#: erpnext/controllers/accounts_controller.py:4364 +#: erpnext/controllers/accounts_controller.py:4370 msgid "Company Address is missing. You don't have permission to create an Address. Please contact your System Manager." msgstr "" -#: erpnext/controllers/accounts_controller.py:4352 +#: erpnext/controllers/accounts_controller.py:4358 msgid "Company Address is missing. You don't have permission to update it. Please contact your System Manager." msgstr "" @@ -11160,7 +11180,7 @@ msgstr "" msgid "Completed Qty" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1374 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1390 msgid "Completed Qty cannot be greater than 'Qty to Manufacture'" msgstr "" @@ -11227,6 +11247,11 @@ msgstr "" msgid "Component Name" msgstr "" +#. Label of the items (Table) field in DocType 'BOM' +#: erpnext/manufacturing/doctype/bom/bom.json +msgid "Components" +msgstr "" + #. Option for the 'Asset Type' (Select) field in DocType 'Asset' #: erpnext/assets/doctype/asset/asset.json msgid "Composite Asset" @@ -11311,7 +11336,7 @@ msgstr "" msgid "Consider Minimum Order Qty" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:1089 +#: erpnext/manufacturing/doctype/work_order/work_order.js:1096 msgid "Consider Process Loss" msgstr "" @@ -11442,6 +11467,12 @@ msgstr "" msgid "Consumables" msgstr "" +#. Label of the consume_components_section (Section Break) field in DocType +#. 'BOM' +#: erpnext/manufacturing/doctype/bom/bom.json +msgid "Consume Components" +msgstr "" + #. Option for the 'Status' (Select) field in DocType 'Serial No' #: erpnext/stock/doctype/serial_no/serial_no.json #: erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py:60 @@ -11502,7 +11533,7 @@ msgstr "" msgid "Consumed Qty" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1750 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1766 msgid "Consumed Qty cannot be greater than Reserved Qty for item {0}" msgstr "" @@ -11531,7 +11562,7 @@ msgstr "" msgid "Consumed Stock Total Value" msgstr "" -#: erpnext/stock/doctype/stock_entry_type/stock_entry_type.py:132 +#: erpnext/stock/doctype/stock_entry_type/stock_entry_type.py:136 msgid "Consumed quantity of item {0} exceeds transferred quantity." msgstr "" @@ -11659,7 +11690,7 @@ msgstr "" msgid "Contact Person" msgstr "" -#: erpnext/controllers/accounts_controller.py:582 +#: erpnext/controllers/accounts_controller.py:583 msgid "Contact Person does not belong to the {0}" msgstr "" @@ -11777,6 +11808,11 @@ msgstr "" msgid "Control Historical Stock Transactions" msgstr "" +#. Description of the 'Based On' (Select) field in DocType 'BOM' +#: erpnext/manufacturing/doctype/bom/bom.json +msgid "Controls how raw materials are consumed during the ‘Manufacture’ stock entry." +msgstr "" + #. Label of the conversion_factor (Float) field in DocType 'Loyalty Program' #. Label of the conversion_factor (Float) field in DocType 'Purchase Order Item #. Supplied' @@ -11848,15 +11884,15 @@ msgstr "" msgid "Conversion factor for item {0} has been reset to 1.0 as the uom {1} is same as stock uom {2}." msgstr "" -#: erpnext/controllers/accounts_controller.py:2971 +#: erpnext/controllers/accounts_controller.py:2974 msgid "Conversion rate cannot be 0" msgstr "" -#: erpnext/controllers/accounts_controller.py:2978 +#: erpnext/controllers/accounts_controller.py:2981 msgid "Conversion rate is 1.00, but document currency is different from company currency" msgstr "" -#: erpnext/controllers/accounts_controller.py:2974 +#: erpnext/controllers/accounts_controller.py:2977 msgid "Conversion rate must be 1.00 if document currency is same as company currency" msgstr "" @@ -11866,7 +11902,7 @@ msgstr "" msgid "Convert Item Description to Clean HTML in Transactions" msgstr "" -#: erpnext/accounts/doctype/account/account.js:106 +#: erpnext/accounts/doctype/account/account.js:124 #: erpnext/accounts/doctype/cost_center/cost_center.js:123 msgid "Convert to Group" msgstr "" @@ -11885,7 +11921,7 @@ msgctxt "Warehouse" msgid "Convert to Ledger" msgstr "" -#: erpnext/accounts/doctype/account/account.js:78 +#: erpnext/accounts/doctype/account/account.js:96 #: erpnext/accounts/doctype/cost_center/cost_center.js:121 msgid "Convert to Non-Group" msgstr "" @@ -11956,7 +11992,6 @@ msgstr "" msgid "Cost" msgstr "" -#. Label of the cost_allocation_section (Section Break) field in DocType 'BOM' #. Label of the cost_allocation (Currency) field in DocType 'BOM' #: erpnext/manufacturing/doctype/bom/bom.json msgid "Cost Allocation" @@ -11968,6 +12003,12 @@ msgstr "" msgid "Cost Allocation %" msgstr "" +#. Label of the cost_allocation__process_loss_section (Section Break) field in +#. DocType 'BOM' +#: erpnext/manufacturing/doctype/bom/bom.json +msgid "Cost Allocation / Process Loss" +msgstr "" + #. Label of the cost_center (Link) field in DocType 'Account Closing Balance' #. Label of the cost_center (Link) field in DocType 'Advance Taxes and Charges' #. Option for the 'Budget Against' (Select) field in DocType 'Budget' @@ -12084,7 +12125,7 @@ msgstr "" #: erpnext/accounts/report/accounts_payable/accounts_payable.js:28 #: erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js:47 #: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:30 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1239 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1246 #: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:47 #: erpnext/accounts/report/asset_depreciation_ledger/asset_depreciation_ledger.js:42 #: erpnext/accounts/report/asset_depreciation_ledger/asset_depreciation_ledger.py:204 @@ -12115,7 +12156,7 @@ msgstr "" #: erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json #: erpnext/buying/report/procurement_tracker/procurement_tracker.js:15 #: erpnext/buying/report/procurement_tracker/procurement_tracker.py:32 -#: erpnext/public/js/financial_statements.js:461 +#: erpnext/public/js/financial_statements.js:462 #: erpnext/selling/doctype/sales_order/sales_order.json #: erpnext/selling/doctype/sales_order_item/sales_order_item.json #: erpnext/stock/doctype/delivery_note/delivery_note.json @@ -12227,7 +12268,7 @@ msgstr "" msgid "Cost Per Unit" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:441 +#: erpnext/manufacturing/doctype/bom/bom.py:442 msgid "Cost allocation between finished goods and secondary items should equal 100%" msgstr "" @@ -12614,7 +12655,7 @@ msgstr "" msgid "Create Payment Request" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:811 +#: erpnext/manufacturing/doctype/work_order/work_order.js:818 msgid "Create Pick List" msgstr "" @@ -12641,7 +12682,7 @@ msgstr "" #. Title of an Onboarding Step #. Label of an action in the Onboarding Step 'Create Purchase Order' #: erpnext/buying/onboarding_step/create_purchase_order/create_purchase_order.json -#: erpnext/selling/doctype/sales_order/sales_order.js:1693 +#: erpnext/selling/doctype/sales_order/sales_order.js:1691 #: erpnext/utilities/activation.py:106 msgid "Create Purchase Order" msgstr "" @@ -12874,7 +12915,7 @@ msgstr "" msgid "Creating Accounts..." msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:1568 +#: erpnext/selling/doctype/sales_order/sales_order.js:1566 msgid "Creating Delivery Note ..." msgstr "" @@ -12898,7 +12939,7 @@ msgstr "" msgid "Creating Purchase Invoices ..." msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:1717 +#: erpnext/selling/doctype/sales_order/sales_order.js:1715 msgid "Creating Purchase Order ..." msgstr "" @@ -12917,7 +12958,7 @@ msgstr "" msgid "Creating Stock Entry" msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:1838 +#: erpnext/selling/doctype/sales_order/sales_order.js:1836 msgid "Creating Subcontracting Inward Order ..." msgstr "" @@ -13116,7 +13157,7 @@ msgstr "" #: erpnext/accounts/doctype/journal_entry_template/journal_entry_template.json #: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts_accounts_receivable.html:176 #: erpnext/accounts/report/accounts_receivable/accounts_receivable.html:147 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1262 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1270 #: erpnext/controllers/sales_and_purchase_return.py:453 #: erpnext/setup/setup_wizard/operations/install_fixtures.py:303 #: erpnext/stock/doctype/delivery_note/delivery_note.js:89 @@ -13152,7 +13193,7 @@ msgstr "" #: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json #: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py:375 #: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py:383 -#: erpnext/controllers/accounts_controller.py:2370 +#: erpnext/controllers/accounts_controller.py:2373 msgid "Credit To" msgstr "" @@ -13348,13 +13389,13 @@ msgstr "" msgid "Currency can not be changed after making entries using some other currency" msgstr "" -#: erpnext/accounts/doctype/financial_report_template/financial_report_engine.py:232 +#: erpnext/accounts/doctype/financial_report_template/financial_report_engine.py:236 msgid "Currency filters are currently unsupported in Custom Financial Report." msgstr "" #: erpnext/accounts/doctype/payment_entry/payment_entry.py:1604 #: erpnext/accounts/doctype/payment_entry/payment_entry.py:1672 -#: erpnext/accounts/utils.py:2532 +#: erpnext/accounts/utils.py:2533 msgid "Currency for {0} must be {1}" msgstr "" @@ -13362,7 +13403,7 @@ msgstr "" msgid "Currency of the Closing Account must be {0}" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:723 +#: erpnext/manufacturing/doctype/bom/bom.py:724 msgid "Currency of the price list {0} must be {1} or {2}" msgstr "" @@ -13531,6 +13572,11 @@ msgstr "" msgid "Custom Financial Statement" msgstr "" +#. Label of the custom_remark (Check) field in DocType 'Journal Entry' +#: erpnext/accounts/doctype/journal_entry/journal_entry.json +msgid "Custom Remark" +msgstr "" + #. Label of the custom_remarks (Check) field in DocType 'Payment Entry' #: erpnext/accounts/doctype/payment_entry/payment_entry.json msgid "Custom Remarks" @@ -13659,7 +13705,7 @@ msgstr "" #: erpnext/selling/doctype/customer/customer.json #: erpnext/selling/doctype/installation_note/installation_note.json #: erpnext/selling/doctype/party_specific_item/party_specific_item.json -#: erpnext/selling/doctype/sales_order/sales_order.js:1199 +#: erpnext/selling/doctype/sales_order/sales_order.js:1197 #: erpnext/selling/doctype/sales_order/sales_order.json #: erpnext/selling/doctype/sales_order/sales_order_calendar.js:19 #: erpnext/selling/doctype/sms_center/sms_center.json @@ -13675,9 +13721,9 @@ msgstr "" #: erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py:41 #: erpnext/selling/report/sales_order_analysis/sales_order_analysis.py:230 #: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.js:41 -#: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py:32 +#: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py:156 #: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.js:53 -#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py:32 +#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py:25 #: erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.js:40 #: erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.py:54 #: erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.js:53 @@ -13795,7 +13841,7 @@ msgstr "" #. Label of the customer_contact_display (Small Text) field in DocType #. 'Purchase Order' #. Label of the customer_contact (Small Text) field in DocType 'Delivery Stop' -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1233 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1240 #: erpnext/buying/doctype/purchase_order/purchase_order.json #: erpnext/stock/doctype/delivery_stop/delivery_stop.json msgid "Customer Contact" @@ -13828,8 +13874,8 @@ msgstr "" msgid "Customer Currency" msgstr "" -#. Label of the customer_defaults_section (Section Break) field in DocType -#. 'Selling Settings' +#. Label of the customer_defaults_tab (Tab Break) field in DocType 'Selling +#. Settings' #: erpnext/selling/doctype/selling_settings/selling_settings.json msgid "Customer Defaults" msgstr "" @@ -13899,9 +13945,9 @@ msgstr "" #: erpnext/accounts/doctype/promotional_scheme/promotional_scheme.json #: erpnext/accounts/doctype/sales_invoice/sales_invoice.json #: erpnext/accounts/doctype/tax_rule/tax_rule.json -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:104 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1290 -#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:85 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:115 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1298 +#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:96 #: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py:185 #: erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.js:56 #: erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py:163 @@ -13960,7 +14006,7 @@ msgstr "" msgid "Customer Items" msgstr "" -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1281 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1289 msgid "Customer LPO" msgstr "" @@ -14013,7 +14059,7 @@ msgstr "" #: erpnext/accounts/doctype/pos_invoice/pos_invoice.json #: erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.json #: erpnext/accounts/doctype/sales_invoice/sales_invoice.json -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1223 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1230 #: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py:156 #: erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.js:92 #: erpnext/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.py:35 @@ -14405,7 +14451,7 @@ msgstr "" msgid "Date of Joining" msgstr "" -#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:200 +#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:272 msgid "Date of Transaction" msgstr "" @@ -14594,7 +14640,7 @@ msgstr "" #: erpnext/accounts/doctype/journal_entry_template/journal_entry_template.json #: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts_accounts_receivable.html:178 #: erpnext/accounts/report/accounts_receivable/accounts_receivable.html:147 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1265 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1273 #: erpnext/controllers/sales_and_purchase_return.py:457 #: erpnext/setup/setup_wizard/operations/install_fixtures.py:304 #: erpnext/stock/doctype/purchase_receipt/purchase_receipt.js:45 @@ -14624,7 +14670,7 @@ msgstr "" #: erpnext/accounts/doctype/sales_invoice/sales_invoice.json #: erpnext/accounts/doctype/sales_invoice/sales_invoice.py:1011 #: erpnext/accounts/doctype/sales_invoice/sales_invoice.py:1022 -#: erpnext/controllers/accounts_controller.py:2370 +#: erpnext/controllers/accounts_controller.py:2373 msgid "Debit To" msgstr "" @@ -14632,7 +14678,7 @@ msgstr "" msgid "Debit To is required" msgstr "" -#: erpnext/accounts/general_ledger.py:535 +#: erpnext/accounts/general_ledger.py:536 msgid "Debit and Credit not equal for {0} #{1}. Difference is {2}." msgstr "" @@ -14798,15 +14844,15 @@ msgstr "" msgid "Default BOM ({0}) must be active for this item or its template" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:2250 +#: erpnext/manufacturing/doctype/work_order/work_order.py:2266 msgid "Default BOM for {0} not found" msgstr "" -#: erpnext/controllers/accounts_controller.py:3970 +#: erpnext/controllers/accounts_controller.py:3976 msgid "Default BOM not found for FG Item {0}" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:2247 +#: erpnext/manufacturing/doctype/work_order/work_order.py:2263 msgid "Default BOM not found for Item {0} and Project {1}" msgstr "" @@ -15422,7 +15468,7 @@ msgstr "" #. Label of the deliver_secondary_items (Check) field in DocType 'Selling #. Settings' #: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "Deliver Secondary Items" +msgid "Deliver secondary Items" msgstr "" #. Option for the 'Status' (Select) field in DocType 'Purchase Order' @@ -15534,7 +15580,7 @@ msgstr "" #: erpnext/public/js/utils.js:895 #: erpnext/selling/doctype/delivery_schedule_item/delivery_schedule_item.json #: erpnext/selling/doctype/sales_order/sales_order.js:632 -#: erpnext/selling/doctype/sales_order/sales_order.js:1515 +#: erpnext/selling/doctype/sales_order/sales_order.js:1513 #: erpnext/selling/doctype/sales_order/sales_order.json #: erpnext/selling/doctype/sales_order_item/sales_order_item.json #: erpnext/selling/report/sales_order_analysis/sales_order_analysis.py:321 @@ -15581,7 +15627,7 @@ msgstr "" #: erpnext/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.py:21 #: erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py:291 #: erpnext/accounts/report/sales_register/sales_register.py:245 -#: erpnext/selling/doctype/sales_order/sales_order.js:1050 +#: erpnext/selling/doctype/sales_order/sales_order.js:1048 #: erpnext/selling/doctype/sales_order/sales_order_list.js:81 #: erpnext/setup/doctype/authorization_rule/authorization_rule.json #: erpnext/stock/doctype/delivery_note/delivery_note.json @@ -15638,7 +15684,7 @@ msgstr "" msgid "Delivery Note {0} is not submitted" msgstr "" -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1285 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1293 #: erpnext/stock/doctype/delivery_trip/delivery_trip.js:75 msgid "Delivery Notes" msgstr "" @@ -15839,7 +15885,7 @@ msgstr "" #: erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts.py:105 #: erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts_with_account_number.py:176 #: erpnext/accounts/report/account_balance/account_balance.js:44 -#: erpnext/accounts/report/cash_flow/cash_flow.py:161 +#: erpnext/accounts/report/cash_flow/cash_flow.py:162 #: erpnext/assets/doctype/asset/asset.json msgid "Depreciation" msgstr "" @@ -16270,7 +16316,7 @@ msgstr "" msgid "Disable template to prevent use in reports" msgstr "" -#: erpnext/accounts/general_ledger.py:150 +#: erpnext/accounts/general_ledger.py:151 msgid "Disabled Account Selected" msgstr "" @@ -16278,11 +16324,11 @@ msgstr "" msgid "Disabled Warehouse {0} cannot be used for this transaction." msgstr "" -#: erpnext/controllers/accounts_controller.py:900 +#: erpnext/controllers/accounts_controller.py:901 msgid "Disabled pricing rules since this {} is an internal transfer" msgstr "" -#: erpnext/controllers/accounts_controller.py:914 +#: erpnext/controllers/accounts_controller.py:915 msgid "Disabled tax included prices since this {} is an internal transfer" msgstr "" @@ -16298,7 +16344,7 @@ msgstr "" #. Option for the 'Purpose' (Select) field in DocType 'Stock Entry' #. Option for the 'Purpose' (Select) field in DocType 'Stock Entry Type' -#: erpnext/manufacturing/doctype/work_order/work_order.js:1067 +#: erpnext/manufacturing/doctype/work_order/work_order.js:1074 #: erpnext/stock/doctype/stock_entry/stock_entry.js:370 #: erpnext/stock/doctype/stock_entry/stock_entry.js:413 #: erpnext/stock/doctype/stock_entry/stock_entry.json @@ -16314,7 +16360,7 @@ msgstr "" msgid "Disassemble Qty cannot be less than or equal to 0." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:458 +#: erpnext/manufacturing/doctype/work_order/work_order.js:463 msgid "Disassemble Qty cannot be less than or equal to 0." msgstr "" @@ -16875,6 +16921,11 @@ msgstr "" msgid "Do you want to submit the stock entry?" msgstr "" +#: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py:50 +#: erpnext/selling/report/sales_partner_commission_summary/test_sales_partner_commission_summary.py:22 +msgid "DocType can be one of them {0}" +msgstr "" + #: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:182 #: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:445 msgid "DocType {0} does not exist" @@ -16961,7 +17012,7 @@ msgstr "" #. Label of the dont_reserve_sales_order_qty_on_sales_return (Check) field in #. DocType 'Selling Settings' #: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "Don't Reserve Sales Order Qty on Sales Return" +msgid "Don't reserve Sales Order qty on sales return" msgstr "" #. Label of the doors (Int) field in DocType 'Vehicle' @@ -16980,7 +17031,7 @@ msgstr "" msgid "Double Declining Balance" msgstr "" -#: erpnext/public/js/utils/serial_no_batch_selector.js:235 +#: erpnext/public/js/utils/serial_no_batch_selector.js:246 msgid "Download CSV Template" msgstr "" @@ -17336,8 +17387,8 @@ msgstr "" #. Option for the 'Update frequency of Project' (Select) field in DocType #. 'Buying Settings' -#. Option for the 'Sales Update Frequency in Company and Project' (Select) -#. field in DocType 'Selling Settings' +#. Option for the 'How often should sales data be updated in Company/Project?' +#. (Select) field in DocType 'Selling Settings' #: erpnext/buying/doctype/buying_settings/buying_settings.json #: erpnext/selling/doctype/selling_settings/selling_settings.json msgid "Each Transaction" @@ -17830,12 +17881,6 @@ msgstr "" msgid "Enable Common Party Accounting" msgstr "" -#. Label of the enable_cutoff_date_on_bulk_delivery_note_creation (Check) field -#. in DocType 'Selling Settings' -#: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "Enable Cut-Off Date on Bulk Delivery Note Creation" -msgstr "" - #. Label of the enable_deferred_expense (Check) field in DocType 'Purchase #. Invoice Item' #. Label of the enable_deferred_expense (Check) field in DocType 'Item' @@ -17855,12 +17900,6 @@ msgstr "" msgid "Enable Deferred Revenue" msgstr "" -#. Label of the enable_discount_accounting (Check) field in DocType 'Selling -#. Settings' -#: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "Enable Discount Accounting for Selling" -msgstr "" - #. Label of the enable_discounts_and_margin (Check) field in DocType 'Accounts #. Settings' #: erpnext/accounts/doctype/accounts_settings/accounts_settings.json @@ -17970,6 +18009,18 @@ msgstr "" msgid "Enable cost center, projects and other custom accounting dimensions" msgstr "" +#. Label of the enable_cutoff_date_on_bulk_delivery_note_creation (Check) field +#. in DocType 'Selling Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "Enable cut-off date on creating bulk Delivery Notes" +msgstr "" + +#. Label of the enable_discount_accounting (Check) field in DocType 'Selling +#. Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "Enable discount accounting for selling" +msgstr "" + #. Description of the 'Consider Rejected Warehouses' (Check) field in DocType #. 'Pick List' #: erpnext/stock/doctype/pick_list/pick_list.json @@ -17987,6 +18038,18 @@ msgstr "" msgid "Enable this option to calculate daily depreciation by considering the total number of days in the entire depreciation period, (including leap years) while using daily pro-rata based depreciation" msgstr "" +#. Description of the 'Allow negative rates for Items' (Check) field in DocType +#. 'Selling Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "Enable this option to permit the use of negative rates for items in sales transactions. This setting is useful for applying substantial discounts, processing refunds or returns, and handling special promotional pricing." +msgstr "" + +#. Description of the 'Validate selling price for Item against purchase or +#. valuation rate' (Check) field in DocType 'Selling Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "Enable this to block transactions where the selling price is less than the purchase or valuation rate" +msgstr "" + #: erpnext/support/doctype/service_level_agreement/service_level_agreement.js:34 msgid "Enable to apply SLA on every {0}" msgstr "" @@ -18036,6 +18099,18 @@ msgstr "" msgid "Enabling this will change the way how cancelled transactions are handled." msgstr "" +#. Description of the 'Calculate Product Bundle price based on child Item's +#. rates' (Check) field in DocType 'Selling Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "" +"Enabling this will do the following:\n" +"
          \n" +"
        • Make the rate column of all Packed/Bundle Items tables editable.
        • \n" +"
        • Calculate the prices of all Product Bundles in the Items table, based on the prices of its child Items, specified in the Packed/Bundle Items table.
        • \n" +"
        \n" +"Note: If this is enabled, updating the rate of the Product Bundle in the Items table will not change its price. It will get reset to the price based on its Child Items on saving the doc." +msgstr "" + #. Label of the encashment_date (Date) field in DocType 'Employee' #: erpnext/setup/doctype/employee/employee.json msgid "Encashment Date" @@ -18127,11 +18202,11 @@ msgstr "" msgid "Enter First and Last name of Employee, based on Which Full Name will be updated. IN transactions, it will be Full Name which will be fetched." msgstr "" -#: erpnext/public/js/utils/serial_no_batch_selector.js:201 +#: erpnext/public/js/utils/serial_no_batch_selector.js:212 msgid "Enter Manually" msgstr "" -#: erpnext/public/js/utils/serial_no_batch_selector.js:279 +#: erpnext/public/js/utils/serial_no_batch_selector.js:290 msgid "Enter Serial Nos" msgstr "" @@ -18185,7 +18260,7 @@ msgstr "" msgid "Enter discount percentage." msgstr "" -#: erpnext/public/js/utils/serial_no_batch_selector.js:282 +#: erpnext/public/js/utils/serial_no_batch_selector.js:293 msgid "Enter each serial no in a new line" msgstr "" @@ -18216,7 +18291,7 @@ msgstr "" msgid "Enter the quantity of the Item that will be manufactured from this Bill of Materials." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:1229 +#: erpnext/manufacturing/doctype/work_order/work_order.js:1236 msgid "Enter the quantity to manufacture. Raw material Items will be fetched only when this is set." msgstr "" @@ -18246,14 +18321,16 @@ msgstr "" #. Option for the 'Root Type' (Select) field in DocType 'Account' #. Option for the 'Account Type' (Select) field in DocType 'Account' +#. Option for the 'Root Type' (Select) field in DocType 'Account Category' #. Option for the 'Root Type' (Select) field in DocType 'Ledger Merge' #: erpnext/accounts/doctype/account/account.json #: erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts.py:189 #: erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts_with_account_number.py:332 +#: erpnext/accounts/doctype/account_category/account_category.json #: erpnext/accounts/doctype/ledger_merge/ledger_merge.json #: erpnext/accounts/report/account_balance/account_balance.js:29 #: erpnext/accounts/report/account_balance/account_balance.js:45 -#: erpnext/accounts/report/balance_sheet/balance_sheet.py:254 +#: erpnext/accounts/report/balance_sheet/balance_sheet.py:255 #: erpnext/setup/setup_wizard/operations/install_fixtures.py:306 msgid "Equity" msgstr "" @@ -18436,8 +18513,8 @@ msgstr "" msgid "Exchange Gain/Loss" msgstr "" -#: erpnext/controllers/accounts_controller.py:1772 -#: erpnext/controllers/accounts_controller.py:1856 +#: erpnext/controllers/accounts_controller.py:1774 +#: erpnext/controllers/accounts_controller.py:1859 msgid "Exchange Gain/Loss amount has been booked through {0}" msgstr "" @@ -18722,18 +18799,20 @@ msgid "Expected Value After Useful Life" msgstr "" #. Option for the 'Root Type' (Select) field in DocType 'Account' +#. Option for the 'Root Type' (Select) field in DocType 'Account Category' #. Label of the expense (Float) field in DocType 'Cashier Closing' #. Option for the 'Root Type' (Select) field in DocType 'Ledger Merge' #. Option for the 'Type' (Select) field in DocType 'Process Deferred #. Accounting' #: erpnext/accounts/doctype/account/account.json +#: erpnext/accounts/doctype/account_category/account_category.json #: erpnext/accounts/doctype/cashier_closing/cashier_closing.json #: erpnext/accounts/doctype/ledger_merge/ledger_merge.json #: erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.json #: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py:601 #: erpnext/accounts/report/account_balance/account_balance.js:28 #: erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.js:89 -#: erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py:183 +#: erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py:184 #: erpnext/accounts/report/profitability_analysis/profitability_analysis.py:199 msgid "Expense" msgstr "" @@ -19078,7 +19157,7 @@ msgstr "" msgid "Fees" msgstr "" -#: erpnext/public/js/utils/serial_no_batch_selector.js:384 +#: erpnext/public/js/utils/serial_no_batch_selector.js:395 msgid "Fetch Based On" msgstr "" @@ -19141,10 +19220,6 @@ msgstr "" msgid "Fetched only {0} available serial numbers." msgstr "" -#: erpnext/edi/doctype/code_list/code_list_import.py:28 -msgid "Fetching Error" -msgstr "" - #: erpnext/manufacturing/doctype/master_production_schedule/master_production_schedule.js:198 msgid "Fetching Material Requests..." msgstr "" @@ -19354,11 +19429,11 @@ msgstr "" msgid "Financial Report Template" msgstr "" -#: erpnext/accounts/doctype/financial_report_template/financial_report_engine.py:248 +#: erpnext/accounts/doctype/financial_report_template/financial_report_engine.py:252 msgid "Financial Report Template {0} is disabled" msgstr "" -#: erpnext/accounts/doctype/financial_report_template/financial_report_engine.py:245 +#: erpnext/accounts/doctype/financial_report_template/financial_report_engine.py:249 msgid "Financial Report Template {0} not found" msgstr "" @@ -19394,9 +19469,9 @@ msgstr "" msgid "Financial reports will be generated using GL Entry doctypes (should be enabled if Period Closing Voucher is not posted for all years sequentially or missing) " msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:895 -#: erpnext/manufacturing/doctype/work_order/work_order.js:910 -#: erpnext/manufacturing/doctype/work_order/work_order.js:919 +#: erpnext/manufacturing/doctype/work_order/work_order.js:902 +#: erpnext/manufacturing/doctype/work_order/work_order.js:917 +#: erpnext/manufacturing/doctype/work_order/work_order.js:926 msgid "Finish" msgstr "" @@ -19412,7 +19487,7 @@ msgstr "" #: erpnext/manufacturing/doctype/production_plan_sub_assembly_item/production_plan_sub_assembly_item.json #: erpnext/manufacturing/report/bom_variance_report/bom_variance_report.py:43 #: erpnext/manufacturing/report/production_plan_summary/production_plan_summary.py:147 -#: erpnext/selling/doctype/sales_order/sales_order.js:832 +#: erpnext/selling/doctype/sales_order/sales_order.js:830 #: erpnext/selling/doctype/sales_order_item/sales_order_item.json #: erpnext/subcontracting/doctype/subcontracting_bom/subcontracting_bom.json msgid "Finished Good" @@ -19453,15 +19528,15 @@ msgstr "" msgid "Finished Good Item Quantity" msgstr "" -#: erpnext/controllers/accounts_controller.py:3956 +#: erpnext/controllers/accounts_controller.py:3962 msgid "Finished Good Item is not specified for service item {0}" msgstr "" -#: erpnext/controllers/accounts_controller.py:3973 +#: erpnext/controllers/accounts_controller.py:3979 msgid "Finished Good Item {0} Qty can not be zero" msgstr "" -#: erpnext/controllers/accounts_controller.py:3967 +#: erpnext/controllers/accounts_controller.py:3973 msgid "Finished Good Item {0} must be a sub-contracted item" msgstr "" @@ -19506,7 +19581,7 @@ msgstr "" msgid "Finished Good {0} must be a sub-contracted item." msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:1419 +#: erpnext/selling/doctype/sales_order/sales_order.js:1417 #: erpnext/setup/doctype/company/company.py:386 msgid "Finished Goods" msgstr "" @@ -19656,7 +19731,7 @@ msgstr "" msgid "Fiscal Year End Date should be one year after Fiscal Year Start Date" msgstr "" -#: erpnext/controllers/trends.py:53 +#: erpnext/controllers/trends.py:59 msgid "Fiscal Year {0} Does Not Exist" msgstr "" @@ -19718,7 +19793,7 @@ msgstr "" msgid "Fixed Asset Turnover Ratio" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:780 +#: erpnext/manufacturing/doctype/bom/bom.py:781 msgid "Fixed Asset item {0} cannot be used in BOMs." msgstr "" @@ -19894,7 +19969,7 @@ msgstr "" msgid "For Raw Materials" msgstr "" -#: erpnext/controllers/accounts_controller.py:1438 +#: erpnext/controllers/accounts_controller.py:1439 msgid "For Return Invoices with Stock effect, '0' qty Items are not allowed. Following rows are affected: {0}" msgstr "" @@ -19912,13 +19987,13 @@ msgstr "" #: erpnext/manufacturing/doctype/material_request_plan_item/material_request_plan_item.json #: erpnext/manufacturing/doctype/production_plan/production_plan.js:471 #: erpnext/manufacturing/doctype/production_plan/production_plan.json -#: erpnext/selling/doctype/sales_order/sales_order.js:1432 +#: erpnext/selling/doctype/sales_order/sales_order.js:1430 #: erpnext/stock/doctype/material_request/material_request.js:361 #: erpnext/templates/form_grid/material_request_grid.html:36 msgid "For Warehouse" msgstr "" -#: erpnext/public/js/utils/serial_no_batch_selector.js:125 +#: erpnext/public/js/utils/serial_no_batch_selector.js:136 msgid "For Work Order" msgstr "" @@ -19960,11 +20035,11 @@ msgstr "" msgid "For item {0}, rate must be a positive number. To Allow negative rates, enable {1} in {2}" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:367 +#: erpnext/manufacturing/doctype/bom/bom.py:368 msgid "For operation {0} at row {1}, please add raw materials or set a BOM against it." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:2629 +#: erpnext/manufacturing/doctype/work_order/work_order.py:2645 msgid "For operation {0}: Quantity ({1}) can not be greater than pending quantity({2})" msgstr "" @@ -20210,11 +20285,11 @@ msgstr "" msgid "From Date and To Date are mandatory" msgstr "" -#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:25 +#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:29 msgid "From Date and To Date are required" msgstr "" -#: erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py:29 +#: erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py:30 msgid "From Date and To Date lie in different Fiscal Year" msgstr "" @@ -20225,6 +20300,10 @@ msgstr "" msgid "From Date cannot be greater than To Date" msgstr "" +#: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py:60 +msgid "From Date cannot be greater than To Date." +msgstr "" + #: erpnext/crm/report/sales_pipeline_analytics/sales_pipeline_analytics.py:27 msgid "From Date is mandatory" msgstr "" @@ -20232,8 +20311,8 @@ msgstr "" #: erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py:53 #: erpnext/accounts/report/general_ledger/general_ledger.py:86 #: erpnext/accounts/report/pos_register/pos_register.py:115 -#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:28 -#: erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py:24 +#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:32 +#: erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py:25 #: erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py:34 #: erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.py:38 msgid "From Date must be before To Date" @@ -20456,7 +20535,7 @@ msgstr "" msgid "From date cannot be greater than To date" msgstr "" -#: erpnext/accounts/doctype/shipping_rule/shipping_rule.py:74 +#: erpnext/accounts/doctype/shipping_rule/shipping_rule.py:79 msgid "From value must be less than to value in row {0}" msgstr "" @@ -20590,14 +20669,14 @@ msgstr "" #: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts_accounts_receivable.html:188 #: erpnext/accounts/report/accounts_receivable/accounts_receivable.html:155 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1277 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1285 #: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py:177 msgid "Future Payment Amount" msgstr "" #: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts_accounts_receivable.html:187 #: erpnext/accounts/report/accounts_receivable/accounts_receivable.html:154 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1276 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1284 msgid "Future Payment Ref" msgstr "" @@ -20732,7 +20811,7 @@ msgstr "" #. Name of a report #. Label of a Link in the Financial Reports Workspace #. Label of a Workspace Sidebar Item -#: erpnext/accounts/doctype/account/account.js:92 +#: erpnext/accounts/doctype/account/account.js:110 #: erpnext/accounts/doctype/accounts_settings/accounts_settings.json #: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json #: erpnext/accounts/report/general_ledger/general_ledger.json @@ -20922,7 +21001,7 @@ msgstr "" #: erpnext/public/js/controllers/buying.js:327 #: erpnext/selling/doctype/quotation/quotation.js:183 #: erpnext/selling/doctype/sales_order/sales_order.js:211 -#: erpnext/selling/doctype/sales_order/sales_order.js:1216 +#: erpnext/selling/doctype/sales_order/sales_order.js:1214 #: erpnext/stock/doctype/delivery_note/delivery_note.js:187 #: erpnext/stock/doctype/delivery_note/delivery_note.js:239 #: erpnext/stock/doctype/material_request/material_request.js:141 @@ -21284,13 +21363,13 @@ msgstr "" #. Quotation' #. Label of the base_grand_total (Currency) field in DocType 'Quotation' #: erpnext/accounts/doctype/pos_invoice/pos_invoice.json -#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:169 +#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:246 #: erpnext/buying/doctype/supplier_quotation/supplier_quotation.json #: erpnext/selling/doctype/quotation/quotation.json msgid "Grand Total (Company Currency)" msgstr "" -#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:175 +#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:252 msgid "Grand Total (Transaction Currency)" msgstr "" @@ -21400,11 +21479,11 @@ msgstr "" msgid "Gross and Net Profit Report" msgstr "" -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:137 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:148 msgid "Group By Customer" msgstr "" -#: erpnext/accounts/report/accounts_payable/accounts_payable.js:115 +#: erpnext/accounts/report/accounts_payable/accounts_payable.js:126 msgid "Group By Supplier" msgstr "" @@ -21446,8 +21525,8 @@ msgstr "" msgid "Group by Sales Order" msgstr "" -#: erpnext/accounts/report/accounts_payable/accounts_payable.js:145 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:177 +#: erpnext/accounts/report/accounts_payable/accounts_payable.js:156 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:188 msgid "Group by Voucher" msgstr "" @@ -21491,25 +21570,46 @@ msgid "H - F" msgstr "" #. Name of a role +#: erpnext/accounts/doctype/account/account.json +#: erpnext/accounts/doctype/cost_center/cost_center.json +#: erpnext/accounts/doctype/mode_of_payment/mode_of_payment.json #: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.json #: erpnext/crm/doctype/contract/contract.json #: erpnext/crm/doctype/contract_template/contract_template.json +#: erpnext/projects/doctype/activity_type/activity_type.json +#: erpnext/projects/doctype/project/project.json +#: erpnext/projects/doctype/task/task.json +#: erpnext/projects/doctype/task_type/task_type.json +#: erpnext/projects/doctype/timesheet/timesheet.json #: erpnext/setup/doctype/branch/branch.json +#: erpnext/setup/doctype/company/company.json #: erpnext/setup/doctype/department/department.json -#: erpnext/setup/doctype/driver/driver.json +#: erpnext/setup/doctype/designation/designation.json #: erpnext/setup/doctype/employee/employee.json +#: erpnext/setup/doctype/employee_group/employee_group.json #: erpnext/setup/doctype/holiday_list/holiday_list.json +#: erpnext/setup/doctype/terms_and_conditions/terms_and_conditions.json #: erpnext/setup/setup_wizard/data/designation.txt:18 +#: erpnext/support/doctype/issue/issue.json msgid "HR Manager" msgstr "" #. Name of a role +#: erpnext/accounts/doctype/account/account.json +#: erpnext/accounts/doctype/cost_center/cost_center.json +#: erpnext/accounts/doctype/mode_of_payment/mode_of_payment.json +#: erpnext/projects/doctype/project/project.json +#: erpnext/projects/doctype/task/task.json #: erpnext/projects/doctype/timesheet/timesheet.json #: erpnext/setup/doctype/branch/branch.json +#: erpnext/setup/doctype/company/company.json #: erpnext/setup/doctype/department/department.json #: erpnext/setup/doctype/designation/designation.json -#: erpnext/setup/doctype/driver/driver.json #: erpnext/setup/doctype/employee/employee.json +#: erpnext/setup/doctype/employee_group/employee_group.json +#: erpnext/setup/doctype/holiday_list/holiday_list.json +#: erpnext/setup/doctype/terms_and_conditions/terms_and_conditions.json +#: erpnext/support/doctype/issue/issue.json msgid "HR User" msgstr "" @@ -21532,7 +21632,7 @@ msgstr "" msgid "Hand" msgstr "" -#: erpnext/accounts/report/accounts_payable/accounts_payable.js:150 +#: erpnext/accounts/report/accounts_payable/accounts_payable.js:161 msgid "Handle Employee Advances" msgstr "" @@ -21778,7 +21878,7 @@ msgstr "" #. Label of the hide_tax_id (Check) field in DocType 'Selling Settings' #: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "Hide Customer's Tax ID from Sales Transactions" +msgid "Hide Customer's Tax ID from sales transactions" msgstr "" #. Label of the hide_when_empty (Check) field in DocType 'Financial Report Row' @@ -21822,7 +21922,7 @@ msgid "History In Company" msgstr "" #: erpnext/buying/doctype/purchase_order/purchase_order.js:338 -#: erpnext/selling/doctype/sales_order/sales_order.js:997 +#: erpnext/selling/doctype/sales_order/sales_order.js:995 msgid "Hold" msgstr "" @@ -21920,10 +22020,9 @@ msgstr "" msgid "How frequently?" msgstr "" -#. Description of the 'Sales Update Frequency in Company and Project' (Select) -#. field in DocType 'Selling Settings' -#: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "How often should Project and Company be updated based on Sales Transactions?" +#. Description of the 'Quantity (Output Qty)' (Float) field in DocType 'BOM' +#: erpnext/manufacturing/doctype/bom/bom.json +msgid "How many units of the final product this BOM makes." msgstr "" #. Description of the 'Update frequency of Project' (Select) field in DocType @@ -21932,6 +22031,12 @@ msgstr "" msgid "How often should Project be updated of Total Purchase Cost ?" msgstr "" +#. Label of the sales_update_frequency (Select) field in DocType 'Selling +#. Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "How often should sales data be updated in Company/Project?" +msgstr "" + #. Description of the 'Data Source' (Select) field in DocType 'Financial Report #. Row' #: erpnext/accounts/doctype/financial_report_row/financial_report_row.json @@ -22148,7 +22253,7 @@ msgstr "" msgid "If enabled, a print of this document will be attached to each email" msgstr "" -#. Description of the 'Enable Discount Accounting for Selling' (Check) field in +#. Description of the 'Enable discount accounting for selling' (Check) field in #. DocType 'Selling Settings' #: erpnext/selling/doctype/selling_settings/selling_settings.json msgid "If enabled, additional ledger entries will be made for discounts in a separate Discount Account" @@ -22190,19 +22295,19 @@ msgstr "" msgid "If enabled, ledger entries will be posted for change amount in POS transactions" msgstr "" -#. Description of the 'Allow Delivery of Overproduced Qty' (Check) field in -#. DocType 'Selling Settings' +#. Description of the 'Allow delivery of overproduced quantity' (Check) field +#. in DocType 'Selling Settings' #: erpnext/selling/doctype/selling_settings/selling_settings.json msgid "If enabled, system will allow user to deliver the entire quantity of the finished goods produced against the Subcontracting Inward Order. If disabled, system will allow delivery of only the ordered quantity." msgstr "" -#. Description of the 'Set Incoming Rate as Zero for Expired Batch' (Check) +#. Description of the 'Set incoming rate as zero for expired Batch' (Check) #. field in DocType 'Selling Settings' #: erpnext/selling/doctype/selling_settings/selling_settings.json msgid "If enabled, system will set incoming rate as zero for stand-alone credit notes with expired batch item." msgstr "" -#. Description of the 'Deliver Secondary Items' (Check) field in DocType +#. Description of the 'Deliver secondary Items' (Check) field in DocType #. 'Selling Settings' #: erpnext/selling/doctype/selling_settings/selling_settings.json msgid "If enabled, the Secondary Items generated against a Finished Good will also be added in the Stock Entry when delivering that Finished Good." @@ -22306,6 +22411,12 @@ msgstr "" msgid "If multiple Pricing Rules continue to prevail, users are asked to set Priority manually to resolve conflict." msgstr "" +#. Description of the 'Use prices from Default Price List as fallback' (Check) +#. field in DocType 'Selling Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "If no Item Price is found for an item in the Price List set in the transaction, prices from the Default Price List will be fetched." +msgstr "" + #. Description of the 'Automatically Add Taxes from Taxes and Charges Template' #. (Check) field in DocType 'Accounts Settings' #: erpnext/accounts/doctype/accounts_settings/accounts_settings.json @@ -22340,7 +22451,7 @@ msgstr "" msgid "If set, the system does not use the user's Email or the standard outgoing Email account for sending request for quotations." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:1262 +#: erpnext/manufacturing/doctype/work_order/work_order.js:1269 msgid "If the BOM results in Scrap material, the Scrap Warehouse needs to be selected." msgstr "" @@ -22359,7 +22470,7 @@ msgstr "" msgid "If the reorder check is set at the Group warehouse level, the available quantity becomes the sum of the projected quantities of all its child warehouses." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:1281 +#: erpnext/manufacturing/doctype/work_order/work_order.js:1288 msgid "If the selected BOM has Operations mentioned in it, the system will fetch all Operations from BOM, these values can be changed." msgstr "" @@ -22369,7 +22480,7 @@ msgstr "" msgid "If there is no assigned timeslot, then communication will be handled by this group" msgstr "" -#: erpnext/edi/doctype/code_list/code_list_import.js:23 +#: erpnext/edi/doctype/code_list/code_list_import.js:24 msgid "If there is no title column, use the code column for the title." msgstr "" @@ -22526,7 +22637,7 @@ msgstr "" msgid "Ignore Exchange Rate Revaluation and Gain / Loss Journals" msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:1414 +#: erpnext/selling/doctype/sales_order/sales_order.js:1412 msgid "Ignore Existing Ordered Qty" msgstr "" @@ -22679,12 +22790,12 @@ msgstr "" msgid "Import Supplier Invoice" msgstr "" -#: erpnext/public/js/utils/serial_no_batch_selector.js:217 +#: erpnext/public/js/utils/serial_no_batch_selector.js:228 #: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.js:84 msgid "Import Using CSV file" msgstr "" -#: erpnext/edi/doctype/code_list/code_list_import.js:130 +#: erpnext/edi/doctype/code_list/code_list_import.js:131 msgid "Import completed. {0} common codes created." msgstr "" @@ -22696,7 +22807,11 @@ msgstr "" msgid "Imported {0} DocTypes" msgstr "" -#: erpnext/edi/doctype/common_code/common_code.py:109 +#: erpnext/edi/doctype/code_list/code_list_import.py:36 +msgid "Importing Code Lists from remote URLs is not allowed." +msgstr "" + +#: erpnext/edi/doctype/common_code/common_code.py:111 msgid "Importing Common Codes" msgstr "" @@ -22719,8 +22834,8 @@ msgstr "" msgid "In Mins" msgstr "" -#: erpnext/accounts/report/accounts_payable/accounts_payable.js:135 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:167 +#: erpnext/accounts/report/accounts_payable/accounts_payable.js:146 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:178 msgid "In Party Currency" msgstr "" @@ -22981,7 +23096,7 @@ msgstr "" #: erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json #: erpnext/buying/doctype/purchase_order_item/purchase_order_item.json #: erpnext/manufacturing/doctype/production_plan_item/production_plan_item.json -#: erpnext/selling/doctype/sales_order/sales_order.js:1410 +#: erpnext/selling/doctype/sales_order/sales_order.js:1408 #: erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json #: erpnext/subcontracting/doctype/subcontracting_inward_order_item/subcontracting_inward_order_item.json #: erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json @@ -23098,18 +23213,20 @@ msgid "Including items for sub assemblies" msgstr "" #. Option for the 'Root Type' (Select) field in DocType 'Account' +#. Option for the 'Root Type' (Select) field in DocType 'Account Category' #. Option for the 'Root Type' (Select) field in DocType 'Ledger Merge' #. Option for the 'Type' (Select) field in DocType 'Process Deferred #. Accounting' #: erpnext/accounts/doctype/account/account.json #: erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts.py:140 #: erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts_with_account_number.py:236 +#: erpnext/accounts/doctype/account_category/account_category.json #: erpnext/accounts/doctype/ledger_merge/ledger_merge.json #: erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.json #: erpnext/accounts/doctype/sales_invoice/sales_invoice.py:439 #: erpnext/accounts/report/account_balance/account_balance.js:27 #: erpnext/accounts/report/financial_statements.py:773 -#: erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py:181 +#: erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py:182 #: erpnext/accounts/report/profitability_analysis/profitability_analysis.py:192 msgid "Income" msgstr "" @@ -23252,7 +23369,7 @@ msgstr "" msgid "Incorrect Warehouse" msgstr "" -#: erpnext/accounts/general_ledger.py:63 +#: erpnext/accounts/general_ledger.py:64 msgid "Incorrect number of General Ledger Entries found. You might have selected a wrong Account in the transaction." msgstr "" @@ -23498,11 +23615,11 @@ msgstr "" msgid "Insufficient Capacity" msgstr "" -#: erpnext/controllers/accounts_controller.py:3850 -#: erpnext/controllers/accounts_controller.py:3874 -#: erpnext/controllers/accounts_controller.py:4394 +#: erpnext/controllers/accounts_controller.py:3856 +#: erpnext/controllers/accounts_controller.py:3880 #: erpnext/controllers/accounts_controller.py:4400 -#: erpnext/controllers/accounts_controller.py:4422 +#: erpnext/controllers/accounts_controller.py:4406 +#: erpnext/controllers/accounts_controller.py:4428 msgid "Insufficient Permissions" msgstr "" @@ -23609,7 +23726,7 @@ msgstr "" msgid "Inter Company Order Reference" msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:1153 +#: erpnext/selling/doctype/sales_order/sales_order.js:1151 msgid "Inter Company Purchase Order" msgstr "" @@ -23675,11 +23792,11 @@ msgstr "" msgid "Internal Customer for company {0} already exists" msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:1152 +#: erpnext/selling/doctype/sales_order/sales_order.js:1150 msgid "Internal Purchase Order" msgstr "" -#: erpnext/controllers/accounts_controller.py:800 +#: erpnext/controllers/accounts_controller.py:801 msgid "Internal Sale or Delivery Reference missing." msgstr "" @@ -23687,7 +23804,7 @@ msgstr "" msgid "Internal Sales Order" msgstr "" -#: erpnext/controllers/accounts_controller.py:802 +#: erpnext/controllers/accounts_controller.py:803 msgid "Internal Sales Reference Missing" msgstr "" @@ -23718,7 +23835,7 @@ msgstr "" msgid "Internal Transfer" msgstr "" -#: erpnext/controllers/accounts_controller.py:811 +#: erpnext/controllers/accounts_controller.py:812 msgid "Internal Transfer Reference Missing" msgstr "" @@ -23751,8 +23868,8 @@ msgstr "" #: erpnext/accounts/doctype/sales_invoice/sales_invoice.py:1027 #: erpnext/assets/doctype/asset_category/asset_category.py:69 #: erpnext/assets/doctype/asset_category/asset_category.py:97 -#: erpnext/controllers/accounts_controller.py:3217 -#: erpnext/controllers/accounts_controller.py:3225 +#: erpnext/controllers/accounts_controller.py:3220 +#: erpnext/controllers/accounts_controller.py:3228 msgid "Invalid Account" msgstr "" @@ -23773,7 +23890,7 @@ msgstr "" msgid "Invalid Attribute" msgstr "" -#: erpnext/controllers/accounts_controller.py:622 +#: erpnext/controllers/accounts_controller.py:623 msgid "Invalid Auto Repeat Date" msgstr "" @@ -23803,7 +23920,7 @@ msgstr "" #: erpnext/assets/doctype/asset/asset.py:361 #: erpnext/assets/doctype/asset/asset.py:368 -#: erpnext/controllers/accounts_controller.py:3240 +#: erpnext/controllers/accounts_controller.py:3243 msgid "Invalid Cost Center" msgstr "" @@ -23819,7 +23936,7 @@ msgstr "" msgid "Invalid Discount" msgstr "" -#: erpnext/controllers/taxes_and_totals.py:843 +#: erpnext/controllers/taxes_and_totals.py:857 msgid "Invalid Discount Amount" msgstr "" @@ -23859,7 +23976,7 @@ msgid "Invalid Net Purchase Amount" msgstr "" #: erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py:77 -#: erpnext/accounts/general_ledger.py:820 +#: erpnext/accounts/general_ledger.py:821 msgid "Invalid Opening Entry" msgstr "" @@ -23893,7 +24010,7 @@ msgstr "" msgid "Invalid Priority" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1275 +#: erpnext/manufacturing/doctype/bom/bom.py:1276 msgid "Invalid Process Loss Configuration" msgstr "" @@ -23901,12 +24018,12 @@ msgstr "" msgid "Invalid Purchase Invoice" msgstr "" -#: erpnext/controllers/accounts_controller.py:3894 -#: erpnext/controllers/accounts_controller.py:3908 +#: erpnext/controllers/accounts_controller.py:3900 +#: erpnext/controllers/accounts_controller.py:3914 msgid "Invalid Qty" msgstr "" -#: erpnext/controllers/accounts_controller.py:1456 +#: erpnext/controllers/accounts_controller.py:1457 msgid "Invalid Quantity" msgstr "" @@ -23940,6 +24057,10 @@ msgstr "" msgid "Invalid Source and Target Warehouse" msgstr "" +#: erpnext/edi/doctype/code_list/code_list_import.py:37 +msgid "Invalid Upload" +msgstr "" + #: erpnext/controllers/item_variant.py:145 msgid "Invalid Value" msgstr "" @@ -23991,8 +24112,8 @@ msgstr "" #: erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.py:109 #: erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.py:119 -#: erpnext/accounts/general_ledger.py:863 -#: erpnext/accounts/general_ledger.py:873 +#: erpnext/accounts/general_ledger.py:864 +#: erpnext/accounts/general_ledger.py:874 msgid "Invalid value {0} for {1} against account {2}" msgstr "" @@ -24024,7 +24145,7 @@ msgstr "" #. Label of a Workspace Sidebar Item #: erpnext/patches/v15_0/refactor_closing_stock_balance.py:43 #: erpnext/stock/doctype/inventory_dimension/inventory_dimension.json -#: erpnext/stock/doctype/inventory_dimension/inventory_dimension.py:175 +#: erpnext/stock/doctype/inventory_dimension/inventory_dimension.py:182 #: erpnext/workspace_sidebar/stock.json msgid "Inventory Dimension" msgstr "" @@ -24111,7 +24232,7 @@ msgstr "" msgid "Invoice Document Type Selection Error" msgstr "" -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1257 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1265 msgid "Invoice Grand Total" msgstr "" @@ -24214,7 +24335,7 @@ msgstr "" #: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts_accounts_receivable.html:171 #: erpnext/accounts/report/accounts_receivable/accounts_receivable.html:144 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1259 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1267 #: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py:164 #: erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py:194 msgid "Invoiced Amount" @@ -24416,7 +24537,7 @@ msgstr "" #. Label of the dn_required (Select) field in DocType 'Selling Settings' #: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "Is Delivery Note Required for Sales Invoice Creation?" +msgid "Is Delivery Note required to create Sales Invoice?" msgstr "" #. Label of the is_discounted (Check) field in DocType 'POS Invoice' @@ -24698,7 +24819,7 @@ msgstr "" #. Label of the so_required (Select) field in DocType 'Selling Settings' #: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "Is Sales Order Required for Sales Invoice & Delivery Note Creation?" +msgid "Is Sales Order required to create Sales Invoice/Delivery Note?" msgstr "" #. Label of the is_short_year (Check) field in DocType 'Fiscal Year' @@ -24940,7 +25061,6 @@ msgstr "" #. Label of the item_code (Link) field in DocType 'Asset Repair Consumed Item' #. Label of a Link in the Buying Workspace #. Label of the items (Table) field in DocType 'Blanket Order' -#. Label of the item (Link) field in DocType 'BOM' #. Label of a Link in the Manufacturing Workspace #. Option for the 'Restrict Items Based On' (Select) field in DocType 'Party #. Specific Item' @@ -24972,10 +25092,9 @@ msgstr "" #: erpnext/buying/report/supplier_quotation_comparison/supplier_quotation_comparison.js:33 #: erpnext/buying/report/supplier_quotation_comparison/supplier_quotation_comparison.py:204 #: erpnext/buying/workspace/buying/buying.json -#: erpnext/controllers/taxes_and_totals.py:1252 +#: erpnext/controllers/taxes_and_totals.py:1266 #: erpnext/manufacturing/doctype/blanket_order/blanket_order.json #: erpnext/manufacturing/doctype/bom/bom.js:1085 -#: erpnext/manufacturing/doctype/bom/bom.json #: erpnext/manufacturing/doctype/plant_floor/plant_floor.js:109 #: erpnext/manufacturing/doctype/workstation/workstation_job_card.html:25 #: erpnext/manufacturing/report/bom_stock_analysis/bom_stock_analysis.py:101 @@ -24993,7 +25112,7 @@ msgstr "" #: erpnext/public/js/stock_analytics.js:92 #: erpnext/selling/doctype/party_specific_item/party_specific_item.json #: erpnext/selling/doctype/product_bundle_item/product_bundle_item.json -#: erpnext/selling/doctype/sales_order/sales_order.js:1656 +#: erpnext/selling/doctype/sales_order/sales_order.js:1654 #: erpnext/selling/page/point_of_sale/pos_item_cart.js:50 #: erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.js:14 #: erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.js:36 @@ -25279,6 +25398,7 @@ msgstr "" #: erpnext/public/js/stock_reservation.js:112 #: erpnext/public/js/stock_reservation.js:318 erpnext/public/js/utils.js:579 #: erpnext/public/js/utils.js:736 +#: erpnext/public/js/utils/serial_no_batch_selector.js:96 #: erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.json #: erpnext/selling/doctype/delivery_schedule_item/delivery_schedule_item.json #: erpnext/selling/doctype/installation_note_item/installation_note_item.json @@ -25286,14 +25406,14 @@ msgstr "" #: erpnext/selling/doctype/quotation_item/quotation_item.json #: erpnext/selling/doctype/sales_order/sales_order.js:376 #: erpnext/selling/doctype/sales_order/sales_order.js:484 -#: erpnext/selling/doctype/sales_order/sales_order.js:1261 -#: erpnext/selling/doctype/sales_order/sales_order.js:1425 +#: erpnext/selling/doctype/sales_order/sales_order.js:1259 +#: erpnext/selling/doctype/sales_order/sales_order.js:1423 #: erpnext/selling/doctype/sales_order_item/sales_order_item.json #: erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py:29 #: erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py:27 #: erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py:19 #: erpnext/selling/report/sales_order_analysis/sales_order_analysis.py:241 -#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py:47 +#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py:33 #: erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py:87 #: erpnext/stock/doctype/bin/bin.json #: erpnext/stock/doctype/delivery_note_item/delivery_note_item.json @@ -25508,7 +25628,7 @@ msgstr "" #: erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.js:54 #: erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py:89 #: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.js:41 -#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py:54 +#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py:35 #: erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.js:41 #: erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py:94 #: erpnext/selling/workspace/selling/selling.json @@ -25760,7 +25880,7 @@ msgstr "" #: erpnext/public/js/controllers/transaction.js:2918 #: erpnext/public/js/utils.js:831 #: erpnext/selling/doctype/quotation_item/quotation_item.json -#: erpnext/selling/doctype/sales_order/sales_order.js:1268 +#: erpnext/selling/doctype/sales_order/sales_order.js:1266 #: erpnext/selling/doctype/sales_order_item/sales_order_item.json #: erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py:35 #: erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py:33 @@ -25839,16 +25959,13 @@ msgstr "" msgid "Item Price" msgstr "" -#: erpnext/stock/get_item_details.py:1118 +#: erpnext/stock/get_item_details.py:1123 msgid "Item Price Added for {0} in Price List {1}" msgstr "" #. Label of the item_price_settings_section (Section Break) field in DocType #. 'Accounts Settings' -#. Label of the item_price_settings_section (Section Break) field in DocType -#. 'Selling Settings' #: erpnext/accounts/doctype/accounts_settings/accounts_settings.json -#: erpnext/selling/doctype/selling_settings/selling_settings.json msgid "Item Price Settings" msgstr "" @@ -25861,7 +25978,7 @@ msgstr "" msgid "Item Price Stock" msgstr "" -#: erpnext/stock/get_item_details.py:1141 +#: erpnext/stock/get_item_details.py:1146 msgid "Item Price added for {0} in Price List {1}" msgstr "" @@ -25869,7 +25986,7 @@ msgstr "" msgid "Item Price appears multiple times based on Price List, Supplier/Customer, Currency, Item, Batch, UOM, Qty, and Dates." msgstr "" -#: erpnext/stock/get_item_details.py:1102 +#: erpnext/stock/get_item_details.py:1107 msgid "Item Price updated for {0} in Price List {1}" msgstr "" @@ -25974,11 +26091,11 @@ msgstr "" msgid "Item Tax Rate" msgstr "" -#: erpnext/accounts/doctype/item_tax_template/item_tax_template.py:61 +#: erpnext/accounts/doctype/item_tax_template/item_tax_template.py:68 msgid "Item Tax Row {0} must have account of type Tax or Income or Expense or Chargeable" msgstr "" -#: erpnext/accounts/doctype/item_tax_template/item_tax_template.py:48 +#: erpnext/accounts/doctype/item_tax_template/item_tax_template.py:55 msgid "Item Tax Row {0}: Account must belong to Company - {1}" msgstr "" @@ -26024,11 +26141,6 @@ msgstr "" msgid "Item To Manufacture" msgstr "" -#. Label of the uom (Link) field in DocType 'BOM' -#: erpnext/manufacturing/doctype/bom/bom.json -msgid "Item UOM" -msgstr "" - #. Name of a DocType #: erpnext/stock/doctype/item_variant/item_variant.json msgid "Item Variant" @@ -26135,7 +26247,7 @@ msgstr "" msgid "Item Wise Tax Details" msgstr "" -#: erpnext/controllers/taxes_and_totals.py:562 +#: erpnext/controllers/taxes_and_totals.py:573 msgid "Item Wise Tax Details do not match with Taxes and Charges at the following rows:" msgstr "" @@ -26155,7 +26267,7 @@ msgstr "" msgid "Item and Warranty Details" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:3498 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:3500 msgid "Item for row {0} does not match Material Request" msgstr "" @@ -26176,7 +26288,7 @@ msgid "Item must be added using 'Get Items from Purchase Receipts' button" msgstr "" #: erpnext/buying/report/subcontracted_item_to_be_received/subcontracted_item_to_be_received.py:42 -#: erpnext/selling/doctype/sales_order/sales_order.js:1663 +#: erpnext/selling/doctype/sales_order/sales_order.js:1661 msgid "Item name" msgstr "" @@ -26185,7 +26297,7 @@ msgstr "" msgid "Item operation" msgstr "" -#: erpnext/controllers/accounts_controller.py:3948 +#: erpnext/controllers/accounts_controller.py:3954 msgid "Item qty can not be updated as raw materials are already processed." msgstr "" @@ -26193,16 +26305,13 @@ msgstr "" msgid "Item rate has been updated to zero as Allow Zero Valuation Rate is checked for item {0}" msgstr "" +#. Label of the item (Link) field in DocType 'BOM' #. Label of the finished_good (Link) field in DocType 'Job Card' +#: erpnext/manufacturing/doctype/bom/bom.json #: erpnext/manufacturing/doctype/job_card/job_card.json msgid "Item to Manufacture" msgstr "" -#. Description of the 'Item' (Link) field in DocType 'BOM' -#: erpnext/manufacturing/doctype/bom/bom.json -msgid "Item to be manufactured or repacked" -msgstr "" - #: erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.js:27 msgid "Item valuation rate is recalculated considering landed cost voucher amount" msgstr "" @@ -26232,7 +26341,7 @@ msgstr "" msgid "Item {0} does not exist" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:708 +#: erpnext/manufacturing/doctype/bom/bom.py:709 msgid "Item {0} does not exist in the system or has expired" msgstr "" @@ -26296,11 +26405,11 @@ msgstr "" msgid "Item {0} must be a Fixed Asset Item" msgstr "" -#: erpnext/stock/get_item_details.py:349 +#: erpnext/stock/get_item_details.py:351 msgid "Item {0} must be a Non-Stock Item" msgstr "" -#: erpnext/stock/get_item_details.py:346 +#: erpnext/stock/get_item_details.py:348 msgid "Item {0} must be a Sub-contracted Item" msgstr "" @@ -26370,11 +26479,11 @@ msgstr "" msgid "Item-wise sales Register" msgstr "" -#: erpnext/stock/get_item_details.py:718 +#: erpnext/stock/get_item_details.py:720 msgid "Item/Item Code required to get Item Tax Template." msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:451 +#: erpnext/manufacturing/doctype/bom/bom.py:452 msgid "Item: {0} does not exist in the system" msgstr "" @@ -26395,7 +26504,7 @@ msgid "Items Filter" msgstr "" #: erpnext/manufacturing/doctype/production_plan/production_plan.py:1683 -#: erpnext/selling/doctype/sales_order/sales_order.js:1701 +#: erpnext/selling/doctype/sales_order/sales_order.js:1699 msgid "Items Required" msgstr "" @@ -26418,15 +26527,15 @@ msgstr "" msgid "Items and Pricing" msgstr "" -#: erpnext/controllers/accounts_controller.py:4208 +#: erpnext/controllers/accounts_controller.py:4214 msgid "Items cannot be updated as Subcontracting Inward Order(s) exist against this Subcontracted Sales Order." msgstr "" -#: erpnext/controllers/accounts_controller.py:4201 +#: erpnext/controllers/accounts_controller.py:4207 msgid "Items cannot be updated as Subcontracting Order is created against the Purchase Order {0}." msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:1461 +#: erpnext/selling/doctype/sales_order/sales_order.js:1459 msgid "Items for Raw Material Request" msgstr "" @@ -26511,7 +26620,7 @@ msgstr "" #: erpnext/manufacturing/doctype/job_card/job_card.json #: erpnext/manufacturing/doctype/job_card/job_card.py:997 #: erpnext/manufacturing/doctype/operation/operation.json -#: erpnext/manufacturing/doctype/work_order/work_order.js:410 +#: erpnext/manufacturing/doctype/work_order/work_order.js:415 #: erpnext/manufacturing/doctype/work_order/work_order.json #: erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.js:29 #: erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.py:86 @@ -26649,7 +26758,7 @@ msgstr "" msgid "Job Worker Warehouse" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:2684 +#: erpnext/manufacturing/doctype/work_order/work_order.py:2700 msgid "Job card {0} created" msgstr "" @@ -26734,7 +26843,7 @@ msgstr "" msgid "Journal Entry Type" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:556 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:557 msgid "Journal Entry for Asset scrapping cannot be cancelled. Please restore the Asset." msgstr "" @@ -26743,11 +26852,11 @@ msgstr "" msgid "Journal Entry for Scrap" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:349 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:350 msgid "Journal Entry type should be set as Depreciation Entry for asset depreciation" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:726 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:727 msgid "Journal Entry {0} does not have account {1} or already matched against other voucher" msgstr "" @@ -27363,14 +27472,16 @@ msgstr "" msgid "Lft" msgstr "" -#: erpnext/accounts/report/balance_sheet/balance_sheet.py:252 +#: erpnext/accounts/report/balance_sheet/balance_sheet.py:253 msgid "Liabilities" msgstr "" #. Option for the 'Root Type' (Select) field in DocType 'Account' #. Option for the 'Account Type' (Select) field in DocType 'Account' +#. Option for the 'Root Type' (Select) field in DocType 'Account Category' #. Option for the 'Root Type' (Select) field in DocType 'Ledger Merge' #: erpnext/accounts/doctype/account/account.json +#: erpnext/accounts/doctype/account_category/account_category.json #: erpnext/accounts/doctype/ledger_merge/ledger_merge.json #: erpnext/accounts/report/account_balance/account_balance.js:26 msgid "Liability" @@ -27868,12 +27979,6 @@ msgstr "" msgid "Maintain Same Rate Throughout Internal Transaction" msgstr "" -#. Label of the maintain_same_sales_rate (Check) field in DocType 'Selling -#. Settings' -#: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "Maintain Same Rate Throughout Sales Cycle" -msgstr "" - #. Label of the maintain_same_rate (Check) field in DocType 'Buying Settings' #: erpnext/buying/doctype/buying_settings/buying_settings.json msgid "Maintain Same Rate Throughout the Purchase Cycle" @@ -27884,6 +27989,12 @@ msgstr "" msgid "Maintain Stock" msgstr "" +#. Label of the maintain_same_sales_rate (Check) field in DocType 'Selling +#. Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "Maintain same rate throughout sales cycle" +msgstr "" + #. Group in Asset's connections #. Label of a Card Break in the Assets Workspace #. Option for the 'Status' (Select) field in DocType 'Workstation' @@ -27951,7 +28062,7 @@ msgstr "" #: erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.json #: erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js:81 #: erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.json -#: erpnext/selling/doctype/sales_order/sales_order.js:1130 +#: erpnext/selling/doctype/sales_order/sales_order.js:1128 #: erpnext/support/workspace/support/support.json #: erpnext/workspace_sidebar/crm.json erpnext/workspace_sidebar/support.json msgid "Maintenance Schedule" @@ -28058,7 +28169,7 @@ msgstr "" #: erpnext/crm/workspace/crm/crm.json #: erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.js:87 #: erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.json -#: erpnext/selling/doctype/sales_order/sales_order.js:1123 +#: erpnext/selling/doctype/sales_order/sales_order.js:1121 #: erpnext/support/doctype/warranty_claim/warranty_claim.js:47 #: erpnext/support/workspace/support/support.json #: erpnext/workspace_sidebar/crm.json erpnext/workspace_sidebar/support.json @@ -28082,8 +28193,8 @@ msgstr "" #. Label of the make (Data) field in DocType 'Vehicle' #: erpnext/accounts/doctype/journal_entry/journal_entry.js:123 #: erpnext/manufacturing/doctype/job_card/job_card.js:544 -#: erpnext/manufacturing/doctype/work_order/work_order.js:850 -#: erpnext/manufacturing/doctype/work_order/work_order.js:884 +#: erpnext/manufacturing/doctype/work_order/work_order.js:857 +#: erpnext/manufacturing/doctype/work_order/work_order.js:891 #: erpnext/setup/doctype/vehicle/vehicle.json msgid "Make" msgstr "" @@ -28170,7 +28281,7 @@ msgstr "" msgid "Make {0} Variants" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:172 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:173 msgid "Making Journal Entries against advance accounts: {0} is not recommended. These Journals won't be available for Reconciliation." msgstr "" @@ -28459,7 +28570,7 @@ msgstr "" msgid "Manufacturing Manager" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:2589 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:2587 msgid "Manufacturing Quantity is mandatory" msgstr "" @@ -28681,7 +28792,7 @@ msgstr "" msgid "Material" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:875 +#: erpnext/manufacturing/doctype/work_order/work_order.js:882 msgid "Material Consumption" msgstr "" @@ -28776,7 +28887,7 @@ msgstr "" #: erpnext/manufacturing/doctype/production_plan_material_request/production_plan_material_request.json #: erpnext/manufacturing/doctype/production_plan_sub_assembly_item/production_plan_sub_assembly_item.json #: erpnext/manufacturing/doctype/work_order/work_order.json -#: erpnext/selling/doctype/sales_order/sales_order.js:1094 +#: erpnext/selling/doctype/sales_order/sales_order.js:1092 #: erpnext/selling/doctype/sales_order_item/sales_order_item.json #: erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py:36 #: erpnext/stock/doctype/delivery_note_item/delivery_note_item.json @@ -28888,7 +28999,7 @@ msgstr "" msgid "Material Request {0} is cancelled or stopped" msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:1477 +#: erpnext/selling/doctype/sales_order/sales_order.js:1475 msgid "Material Request {0} submitted." msgstr "" @@ -28971,8 +29082,10 @@ msgstr "" msgid "Material Transferred" msgstr "" +#. Option for the 'Based On' (Select) field in DocType 'BOM' #. Option for the 'Backflush Raw Materials Based On' (Select) field in DocType #. 'Manufacturing Settings' +#: erpnext/manufacturing/doctype/bom/bom.json #: erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json msgid "Material Transferred for Manufacture" msgstr "" @@ -29077,9 +29190,9 @@ msgstr "" msgid "Max discount allowed for item: {0} is {1}%" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:1051 #: erpnext/manufacturing/doctype/work_order/work_order.js:1058 -#: erpnext/manufacturing/doctype/work_order/work_order.js:1081 +#: erpnext/manufacturing/doctype/work_order/work_order.js:1065 +#: erpnext/manufacturing/doctype/work_order/work_order.js:1088 #: erpnext/stock/doctype/pick_list/pick_list.js:200 #: erpnext/stock/doctype/stock_entry/stock_entry.js:382 msgid "Max: {0}" @@ -29107,11 +29220,11 @@ msgstr "" msgid "Maximum Producible Items" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:4104 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:4106 msgid "Maximum Samples - {0} can be retained for Batch {1} and Item {2}." msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:4095 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:4097 msgid "Maximum Samples - {0} have already been retained for Batch {1} and Item {2} in Batch {3}." msgstr "" @@ -29187,11 +29300,11 @@ msgstr "" msgid "Mention if non-standard receivable account applicable" msgstr "" -#: erpnext/accounts/doctype/account/account.js:151 +#: erpnext/accounts/doctype/account/account.js:169 msgid "Merge" msgstr "" -#: erpnext/accounts/doctype/account/account.js:45 +#: erpnext/accounts/doctype/account/account.js:55 msgid "Merge Account" msgstr "" @@ -29215,7 +29328,7 @@ msgstr "" msgid "Merge taxes from multiple documents" msgstr "" -#: erpnext/accounts/doctype/account/account.js:123 +#: erpnext/accounts/doctype/account/account.js:141 msgid "Merge with Existing Account" msgstr "" @@ -29529,7 +29642,7 @@ msgstr "" msgid "Miscellaneous Expenses" msgstr "" -#: erpnext/controllers/buying_controller.py:706 +#: erpnext/controllers/buying_controller.py:713 msgid "Mismatch" msgstr "" @@ -29599,12 +29712,12 @@ msgstr "" msgid "Missing email template for dispatch. Please set one in Delivery Settings." msgstr "" -#: erpnext/accounts/doctype/financial_report_template/financial_report_engine.py:229 +#: erpnext/accounts/doctype/financial_report_template/financial_report_engine.py:233 msgid "Missing required filter: {0}" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1218 -#: erpnext/manufacturing/doctype/work_order/work_order.py:1482 +#: erpnext/manufacturing/doctype/bom/bom.py:1219 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1498 msgid "Missing value" msgstr "" @@ -29790,6 +29903,12 @@ msgstr "" msgid "More/Less than 12 months." msgstr "" +#. Description of the 'Hide Customer's Tax ID from sales transactions' (Check) +#. field in DocType 'Selling Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "Most Customers have a unique Tax ID that is fetched into selling transactions. Enable this setting if you do not want Customer Tax IDs to appear in sales transactions." +msgstr "" + #: erpnext/setup/setup_wizard/data/industry_type.txt:32 msgid "Motion Picture & Video" msgstr "" @@ -29865,7 +29984,7 @@ msgstr "" msgid "Multiple company fields available: {0}. Please select manually." msgstr "" -#: erpnext/controllers/accounts_controller.py:1302 +#: erpnext/controllers/accounts_controller.py:1303 msgid "Multiple fiscal years exist for the date {0}. Please set company in Fiscal Year" msgstr "" @@ -29878,10 +29997,10 @@ msgid "Music" msgstr "" #. Label of the must_be_whole_number (Check) field in DocType 'UOM' -#: erpnext/manufacturing/doctype/work_order/work_order.py:1429 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1445 #: erpnext/setup/doctype/uom/uom.json #: erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py:267 -#: erpnext/utilities/transaction_base.py:568 +#: erpnext/utilities/transaction_base.py:571 msgid "Must be Whole Number" msgstr "" @@ -30094,40 +30213,40 @@ msgstr "" msgid "Net Asset value as on" msgstr "" -#: erpnext/accounts/report/cash_flow/cash_flow.py:177 +#: erpnext/accounts/report/cash_flow/cash_flow.py:178 msgid "Net Cash from Financing" msgstr "" -#: erpnext/accounts/report/cash_flow/cash_flow.py:170 +#: erpnext/accounts/report/cash_flow/cash_flow.py:171 msgid "Net Cash from Investing" msgstr "" -#: erpnext/accounts/report/cash_flow/cash_flow.py:158 +#: erpnext/accounts/report/cash_flow/cash_flow.py:159 msgid "Net Cash from Operations" msgstr "" -#: erpnext/accounts/report/cash_flow/cash_flow.py:163 +#: erpnext/accounts/report/cash_flow/cash_flow.py:164 msgid "Net Change in Accounts Payable" msgstr "" -#: erpnext/accounts/report/cash_flow/cash_flow.py:162 +#: erpnext/accounts/report/cash_flow/cash_flow.py:163 msgid "Net Change in Accounts Receivable" msgstr "" -#: erpnext/accounts/report/cash_flow/cash_flow.py:134 +#: erpnext/accounts/report/cash_flow/cash_flow.py:135 #: erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py:257 msgid "Net Change in Cash" msgstr "" -#: erpnext/accounts/report/cash_flow/cash_flow.py:179 +#: erpnext/accounts/report/cash_flow/cash_flow.py:180 msgid "Net Change in Equity" msgstr "" -#: erpnext/accounts/report/cash_flow/cash_flow.py:172 +#: erpnext/accounts/report/cash_flow/cash_flow.py:173 msgid "Net Change in Fixed Asset" msgstr "" -#: erpnext/accounts/report/cash_flow/cash_flow.py:164 +#: erpnext/accounts/report/cash_flow/cash_flow.py:165 msgid "Net Change in Inventory" msgstr "" @@ -30140,7 +30259,7 @@ msgstr "" #: erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py:214 #: erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py:215 -#: erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py:120 +#: erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py:121 msgid "Net Profit" msgstr "" @@ -30148,7 +30267,7 @@ msgstr "" msgid "Net Profit Ratio" msgstr "" -#: erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py:185 +#: erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py:186 msgid "Net Profit/Loss" msgstr "" @@ -30317,7 +30436,7 @@ msgstr "" msgid "Net Weight UOM" msgstr "" -#: erpnext/controllers/accounts_controller.py:1662 +#: erpnext/controllers/accounts_controller.py:1663 msgid "Net total calculation precision loss" msgstr "" @@ -30544,7 +30663,7 @@ msgstr "" msgid "No Account Data row found" msgstr "" -#: erpnext/setup/doctype/company/test_company.py:94 +#: erpnext/setup/doctype/company/test_company.py:93 msgid "No Account matched these filters: {}" msgstr "" @@ -30578,11 +30697,11 @@ msgstr "" msgid "No Impact on Accounting Ledger" msgstr "" -#: erpnext/stock/get_item_details.py:320 +#: erpnext/stock/get_item_details.py:322 msgid "No Item with Barcode {0}" msgstr "" -#: erpnext/stock/get_item_details.py:324 +#: erpnext/stock/get_item_details.py:326 msgid "No Item with Serial No {0}" msgstr "" @@ -30590,11 +30709,11 @@ msgstr "" msgid "No Items selected for transfer." msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:1242 +#: erpnext/selling/doctype/sales_order/sales_order.js:1240 msgid "No Items with Bill of Materials to Manufacture or all items already manufactured" msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:1395 +#: erpnext/selling/doctype/sales_order/sales_order.js:1393 msgid "No Items with Bill of Materials." msgstr "" @@ -30614,9 +30733,9 @@ msgstr "" msgid "No POS Profile found. Please create a New POS Profile first" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1573 -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1633 -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1647 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1574 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1634 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1648 #: erpnext/stock/doctype/item/item.py:1401 msgid "No Permission" msgstr "" @@ -30676,7 +30795,7 @@ msgid "No Work Orders were created" msgstr "" #: erpnext/stock/doctype/purchase_receipt/purchase_receipt.py:832 -#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:897 +#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:929 msgid "No accounting entries for the following warehouses" msgstr "" @@ -30712,7 +30831,7 @@ msgstr "" msgid "No description given" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:225 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:226 msgid "No difference found for stock account {0}" msgstr "" @@ -30724,6 +30843,10 @@ msgstr "" msgid "No employee was scheduled for call popup" msgstr "" +#: erpnext/edi/doctype/code_list/code_list_import.py:73 +msgid "No file uploaded or URL provided." +msgstr "" + #: erpnext/controllers/subcontracting_controller.py:1391 msgid "No item available for transfer." msgstr "" @@ -30971,7 +31094,7 @@ msgstr "" msgid "Non Profit" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1634 +#: erpnext/manufacturing/doctype/bom/bom.py:1635 msgid "Non stock items" msgstr "" @@ -30999,8 +31122,11 @@ msgstr "" msgid "Nos" msgstr "" +#. Label of the not_applicable (Check) field in DocType 'Item Tax Template +#. Detail' #. Option for the 'Delivery Status' (Select) field in DocType 'Sales Order' #. Option for the 'Based On' (Select) field in DocType 'Authorization Rule' +#: erpnext/accounts/doctype/item_tax_template_detail/item_tax_template_detail.json #: erpnext/selling/doctype/sales_order/sales_order.json #: erpnext/setup/doctype/authorization_rule/authorization_rule.json msgid "Not Applicable" @@ -31055,7 +31181,7 @@ msgstr "" msgid "Not Started" msgstr "" -#: erpnext/accounts/report/cash_flow/cash_flow.py:405 +#: erpnext/accounts/report/cash_flow/cash_flow.py:406 msgid "Not able to find the earliest Fiscal Year for the given company." msgstr "" @@ -31105,7 +31231,7 @@ msgstr "" msgid "Note: Email will not be sent to disabled users" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:792 +#: erpnext/manufacturing/doctype/bom/bom.py:793 msgid "Note: If you want to use the finished good {0} as a raw material, then enable the 'Do Not Explode' checkbox in the Items table against the same raw material." msgstr "" @@ -31113,7 +31239,7 @@ msgstr "" msgid "Note: Item {0} added multiple times" msgstr "" -#: erpnext/controllers/accounts_controller.py:708 +#: erpnext/controllers/accounts_controller.py:709 msgid "Note: Payment Entry will not be created since 'Cash or Bank Account' was not specified" msgstr "" @@ -31125,10 +31251,6 @@ msgstr "" msgid "Note: To merge the items, create a separate Stock Reconciliation for the old item {0}" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1030 -msgid "Note: {0}" -msgstr "" - #. Label of the notes (Small Text) field in DocType 'Asset Depreciation #. Schedule' #. Label of the notes (Text) field in DocType 'Contract Fulfilment Checklist' @@ -31369,7 +31491,7 @@ msgstr "" msgid "Offsetting Account" msgstr "" -#: erpnext/accounts/general_ledger.py:93 +#: erpnext/accounts/general_ledger.py:94 msgid "Offsetting for Accounting Dimension" msgstr "" @@ -31487,7 +31609,7 @@ msgstr "" msgid "Once set, this invoice will be on hold till the set date" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:762 +#: erpnext/manufacturing/doctype/work_order/work_order.js:769 msgid "Once the Work Order is Closed. It can't be resumed." msgstr "" @@ -31579,7 +31701,7 @@ msgstr "" msgid "Only one of Deposit or Withdrawal should be non-zero when applying an Excluded Fee." msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:329 +#: erpnext/manufacturing/doctype/bom/bom.py:330 msgid "Only one operation can have 'Is Final Finished Good' checked when 'Track Semi Finished Goods' is enabled." msgstr "" @@ -31816,7 +31938,7 @@ msgstr "" msgid "Opening Entry" msgstr "" -#: erpnext/accounts/general_ledger.py:819 +#: erpnext/accounts/general_ledger.py:820 msgid "Opening Entry can not be created after Period Closing Voucher is created." msgstr "" @@ -31937,7 +32059,7 @@ msgstr "" msgid "Operating Cost Per BOM Quantity" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1721 +#: erpnext/manufacturing/doctype/bom/bom.py:1722 msgid "Operating Cost as per Work Order / BOM" msgstr "" @@ -31985,7 +32107,7 @@ msgstr "" msgid "Operation ID" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:346 +#: erpnext/manufacturing/doctype/work_order/work_order.js:351 msgid "Operation Id" msgstr "" @@ -32013,7 +32135,7 @@ msgstr "" msgid "Operation Time" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1488 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1504 msgid "Operation Time must be greater than 0 for Operation {0}" msgstr "" @@ -32048,7 +32170,7 @@ msgstr "" #. Label of the operations (Table) field in DocType 'Work Order' #. Label of the operation (Section Break) field in DocType 'Email Digest' #: erpnext/manufacturing/doctype/bom/bom.json -#: erpnext/manufacturing/doctype/work_order/work_order.js:327 +#: erpnext/manufacturing/doctype/work_order/work_order.js:332 #: erpnext/manufacturing/doctype/work_order/work_order.json #: erpnext/setup/doctype/company/company.py:469 #: erpnext/setup/doctype/email_digest/email_digest.json @@ -32062,7 +32184,7 @@ msgstr "" msgid "Operations Routing" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1227 +#: erpnext/manufacturing/doctype/bom/bom.py:1228 msgid "Operations cannot be left blank" msgstr "" @@ -32223,7 +32345,7 @@ msgstr "" msgid "Optimize Route" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:1028 +#: erpnext/manufacturing/doctype/work_order/work_order.js:1035 msgid "Optional. Select a specific manufacture entry to reverse." msgstr "" @@ -32265,6 +32387,7 @@ msgstr "" #. Label of the order_date (Date) field in DocType 'Blanket Order' #: erpnext/manufacturing/doctype/blanket_order/blanket_order.json +#: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py:68 msgid "Order Date" msgstr "" @@ -32587,7 +32710,7 @@ msgstr "" #: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json #: erpnext/accounts/doctype/sales_invoice/sales_invoice.json #: erpnext/accounts/report/accounts_receivable/accounts_receivable.html:149 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1266 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1274 #: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py:167 #: erpnext/accounts/report/purchase_register/purchase_register.py:289 #: erpnext/accounts/report/sales_register/sales_register.py:319 @@ -32677,7 +32800,7 @@ msgstr "" msgid "Overbilling of {0} {1} ignored for item {2} because you have {3} role." msgstr "" -#: erpnext/controllers/accounts_controller.py:2178 +#: erpnext/controllers/accounts_controller.py:2181 msgid "Overbilling of {} ignored because you have {} role." msgstr "" @@ -32734,7 +32857,7 @@ msgstr "" msgid "Overlap in scoring between {0} and {1}" msgstr "" -#: erpnext/accounts/doctype/shipping_rule/shipping_rule.py:201 +#: erpnext/accounts/doctype/shipping_rule/shipping_rule.py:206 msgid "Overlapping conditions found between:" msgstr "" @@ -33223,7 +33346,7 @@ msgstr "" #: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json #: erpnext/accounts/doctype/sales_invoice/sales_invoice.json #: erpnext/accounts/report/accounts_receivable/accounts_receivable.html:146 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1260 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1268 #: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py:165 #: erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py:201 #: erpnext/accounts/report/pos_register/pos_register.py:209 @@ -33476,7 +33599,7 @@ msgstr "" msgid "Parsed file is not in valid MT940 format or contains no transactions." msgstr "" -#: erpnext/edi/doctype/code_list/code_list_import.py:45 +#: erpnext/edi/doctype/code_list/code_list_import.py:44 msgid "Parsing Error" msgstr "" @@ -33679,13 +33802,13 @@ msgstr "" #: erpnext/accounts/doctype/tax_category/tax_category_dashboard.py:11 #: erpnext/accounts/doctype/tax_withholding_entry/tax_withholding_entry.json #: erpnext/accounts/doctype/unreconcile_payment_entries/unreconcile_payment_entries.json -#: erpnext/accounts/report/accounts_payable/accounts_payable.js:94 -#: erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js:71 +#: erpnext/accounts/report/accounts_payable/accounts_payable.js:105 +#: erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js:82 #: erpnext/accounts/report/accounts_receivable/accounts_receivable.html:142 #: erpnext/accounts/report/accounts_receivable/accounts_receivable.html:159 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:54 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1197 -#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:71 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:65 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1204 +#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:82 #: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py:147 #: erpnext/accounts/report/general_and_payment_ledger_comparison/general_and_payment_ledger_comparison.js:49 #: erpnext/accounts/report/general_and_payment_ledger_comparison/general_and_payment_ledger_comparison.py:240 @@ -33711,7 +33834,7 @@ msgstr "" #. Name of a DocType #: erpnext/accounts/doctype/party_account/party_account.json -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1208 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1215 msgid "Party Account" msgstr "" @@ -33738,7 +33861,7 @@ msgstr "" msgid "Party Account No. (Bank Statement)" msgstr "" -#: erpnext/controllers/accounts_controller.py:2462 +#: erpnext/controllers/accounts_controller.py:2465 msgid "Party Account {0} currency ({1}) and document currency ({2}) should be same" msgstr "" @@ -33865,11 +33988,11 @@ msgstr "" #: erpnext/accounts/doctype/subscription/subscription.json #: erpnext/accounts/doctype/tax_withholding_entry/tax_withholding_entry.json #: erpnext/accounts/doctype/unreconcile_payment_entries/unreconcile_payment_entries.json -#: erpnext/accounts/report/accounts_payable/accounts_payable.js:81 -#: erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js:58 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:41 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1191 -#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:58 +#: erpnext/accounts/report/accounts_payable/accounts_payable.js:92 +#: erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js:69 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:52 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1198 +#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:69 #: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py:141 #: erpnext/accounts/report/general_and_payment_ledger_comparison/general_and_payment_ledger_comparison.js:42 #: erpnext/accounts/report/general_and_payment_ledger_comparison/general_and_payment_ledger_comparison.py:231 @@ -34010,8 +34133,8 @@ msgstr "" msgid "Payable" msgstr "" -#: erpnext/accounts/report/accounts_payable/accounts_payable.js:39 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1206 +#: erpnext/accounts/report/accounts_payable/accounts_payable.js:50 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1213 #: erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py:209 #: erpnext/accounts/report/purchase_register/purchase_register.py:194 #: erpnext/accounts/report/purchase_register/purchase_register.py:235 @@ -34046,7 +34169,7 @@ msgstr "" #: erpnext/accounts/doctype/sales_invoice/sales_invoice_list.js:42 #: erpnext/buying/doctype/purchase_order/purchase_order.js:421 #: erpnext/buying/doctype/purchase_order/purchase_order_dashboard.py:24 -#: erpnext/selling/doctype/sales_order/sales_order.js:1175 +#: erpnext/selling/doctype/sales_order/sales_order.js:1173 #: erpnext/selling/doctype/sales_order/sales_order_dashboard.py:31 msgid "Payment" msgstr "" @@ -34174,7 +34297,7 @@ msgstr "" msgid "Payment Entry is already created" msgstr "" -#: erpnext/controllers/accounts_controller.py:1613 +#: erpnext/controllers/accounts_controller.py:1614 msgid "Payment Entry {0} is linked against Order {1}, check if it should be pulled as advance in this invoice." msgstr "" @@ -34398,7 +34521,7 @@ msgstr "" #: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js:135 #: erpnext/accounts/doctype/sales_invoice/sales_invoice.js:139 #: erpnext/buying/doctype/purchase_order/purchase_order.js:429 -#: erpnext/selling/doctype/sales_order/sales_order.js:1168 +#: erpnext/selling/doctype/sales_order/sales_order.js:1166 #: erpnext/workspace_sidebar/invoicing.json #: erpnext/workspace_sidebar/payments.json msgid "Payment Request" @@ -34454,7 +34577,7 @@ msgstr "" #: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json #: erpnext/accounts/doctype/sales_invoice/sales_invoice.json #: erpnext/buying/doctype/purchase_order/purchase_order.json -#: erpnext/controllers/accounts_controller.py:2742 +#: erpnext/controllers/accounts_controller.py:2745 #: erpnext/selling/doctype/quotation/quotation.json #: erpnext/selling/doctype/sales_order/sales_order.json msgid "Payment Schedule" @@ -34487,7 +34610,7 @@ msgstr "" #: erpnext/accounts/doctype/payment_schedule/payment_schedule.json #: erpnext/accounts/doctype/payment_term/payment_term.json #: erpnext/accounts/doctype/payment_terms_template_detail/payment_terms_template_detail.json -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1256 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1264 #: erpnext/accounts/report/gross_profit/gross_profit.py:449 #: erpnext/accounts/workspace/invoicing/invoicing.json #: erpnext/public/js/controllers/transaction.js:498 @@ -34551,10 +34674,10 @@ msgstr "" #: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json #: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json #: erpnext/accounts/doctype/sales_invoice/sales_invoice.json -#: erpnext/accounts/report/accounts_payable/accounts_payable.js:75 -#: erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js:85 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:113 -#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:91 +#: erpnext/accounts/report/accounts_payable/accounts_payable.js:86 +#: erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js:96 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:124 +#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:102 #: erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.js:62 #: erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.js:61 #: erpnext/buying/doctype/purchase_order/purchase_order.json @@ -34599,7 +34722,7 @@ msgstr "" msgid "Payment Unlink Error" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:898 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:899 msgid "Payment against {0} {1} cannot be greater than Outstanding Amount {2}" msgstr "" @@ -34737,9 +34860,9 @@ msgstr "" #. Label of the pending_qty (Float) field in DocType 'Production Plan Item' #: erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.py:254 #: erpnext/manufacturing/doctype/production_plan_item/production_plan_item.json -#: erpnext/manufacturing/doctype/work_order/work_order.js:351 +#: erpnext/manufacturing/doctype/work_order/work_order.js:356 #: erpnext/manufacturing/report/production_plan_summary/production_plan_summary.py:182 -#: erpnext/selling/doctype/sales_order/sales_order.js:1670 +#: erpnext/selling/doctype/sales_order/sales_order.js:1668 #: erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py:45 msgid "Pending Qty" msgstr "" @@ -34873,7 +34996,7 @@ msgstr "" msgid "Period Based On" msgstr "" -#: erpnext/accounts/general_ledger.py:831 +#: erpnext/accounts/general_ledger.py:832 msgid "Period Closed" msgstr "" @@ -34999,7 +35122,7 @@ msgstr "" msgid "Periodic Accounting Entry" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:251 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:252 msgid "Periodic Accounting Entry is not allowed for company {0} with perpetual inventory enabled" msgstr "" @@ -35106,7 +35229,7 @@ msgstr "" #. Reservation Entry' #. Label of a Link in the Stock Workspace #. Label of a Workspace Sidebar Item -#: erpnext/selling/doctype/sales_order/sales_order.js:1030 +#: erpnext/selling/doctype/sales_order/sales_order.js:1028 #: erpnext/stock/doctype/delivery_note/delivery_note.js:199 #: erpnext/stock/doctype/material_request/material_request.js:156 #: erpnext/stock/doctype/pick_list/pick_list.json @@ -35496,7 +35619,7 @@ msgstr "" msgid "Please add a Temporary Opening account in Chart of Accounts" msgstr "" -#: erpnext/public/js/utils/serial_no_batch_selector.js:649 +#: erpnext/public/js/utils/serial_no_batch_selector.js:660 msgid "Please add atleast one Serial No / Batch No" msgstr "" @@ -35542,7 +35665,7 @@ msgstr "" msgid "Please capitalize this asset before submitting." msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:972 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:973 msgid "Please check Multi Currency option to allow accounts with other currency" msgstr "" @@ -35611,7 +35734,7 @@ msgstr "" msgid "Please create a new Accounting Dimension if required." msgstr "" -#: erpnext/controllers/accounts_controller.py:801 +#: erpnext/controllers/accounts_controller.py:802 msgid "Please create purchase from internal sale or delivery document itself" msgstr "" @@ -35741,7 +35864,7 @@ msgstr "" msgid "Please enter Receipt Document" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1036 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1037 msgid "Please enter Reference date" msgstr "" @@ -35753,7 +35876,7 @@ msgstr "" msgid "Please enter Serial No" msgstr "" -#: erpnext/public/js/utils/serial_no_batch_selector.js:308 +#: erpnext/public/js/utils/serial_no_batch_selector.js:319 msgid "Please enter Serial Nos" msgstr "" @@ -35770,7 +35893,7 @@ msgstr "" msgid "Please enter Write Off Account" msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:725 +#: erpnext/selling/doctype/sales_order/sales_order.js:723 msgid "Please enter a valid number of deliveries" msgstr "" @@ -35786,7 +35909,7 @@ msgstr "" msgid "Please enter company name first" msgstr "" -#: erpnext/controllers/accounts_controller.py:2968 +#: erpnext/controllers/accounts_controller.py:2971 msgid "Please enter default currency in Company Master" msgstr "" @@ -35818,7 +35941,7 @@ msgstr "" msgid "Please enter the company name to confirm" msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:721 +#: erpnext/selling/doctype/sales_order/sales_order.js:720 msgid "Please enter the first delivery date" msgstr "" @@ -35826,7 +35949,7 @@ msgstr "" msgid "Please enter the phone number first" msgstr "" -#: erpnext/controllers/buying_controller.py:1189 +#: erpnext/controllers/buying_controller.py:1196 msgid "Please enter the {schedule_date}." msgstr "" @@ -35890,8 +36013,8 @@ msgstr "" msgid "Please mention 'Weight UOM' along with Weight." msgstr "" -#: erpnext/accounts/general_ledger.py:665 -#: erpnext/accounts/general_ledger.py:672 +#: erpnext/accounts/general_ledger.py:666 +#: erpnext/accounts/general_ledger.py:673 msgid "Please mention '{0}' in Company: {1}" msgstr "" @@ -35928,7 +36051,7 @@ msgstr "" msgid "Please save first" msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:867 +#: erpnext/selling/doctype/sales_order/sales_order.js:865 msgid "Please save the Sales Order before adding a delivery schedule." msgstr "" @@ -35936,8 +36059,8 @@ msgstr "" msgid "Please select Template Type to download template" msgstr "" -#: erpnext/controllers/taxes_and_totals.py:849 -#: erpnext/public/js/controllers/taxes_and_totals.js:794 +#: erpnext/controllers/taxes_and_totals.py:863 +#: erpnext/public/js/controllers/taxes_and_totals.js:813 msgid "Please select Apply Discount On" msgstr "" @@ -35949,7 +36072,7 @@ msgstr "" msgid "Please select BOM for Item in Row {0}" msgstr "" -#: erpnext/controllers/buying_controller.py:640 +#: erpnext/controllers/buying_controller.py:647 msgid "Please select BOM in BOM field for Item {item_code}." msgstr "" @@ -35976,7 +36099,7 @@ msgstr "" msgid "Please select Company and Posting Date to getting entries" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.js:732 +#: erpnext/accounts/doctype/journal_entry/journal_entry.js:738 #: erpnext/manufacturing/doctype/plant_floor/plant_floor.js:28 msgid "Please select Company first" msgstr "" @@ -36017,7 +36140,7 @@ msgstr "" msgid "Please select Party Type first" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:257 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:258 msgid "Please select Periodic Accounting Entry Difference Account" msgstr "" @@ -36025,11 +36148,11 @@ msgstr "" msgid "Please select Posting Date before selecting Party" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.js:733 +#: erpnext/accounts/doctype/journal_entry/journal_entry.js:739 msgid "Please select Posting Date first" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1291 +#: erpnext/manufacturing/doctype/bom/bom.py:1292 msgid "Please select Price List" msgstr "" @@ -36049,7 +36172,7 @@ msgstr "" msgid "Please select Start Date and End Date for Item {0}" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:276 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:277 msgid "Please select Stock Asset Account" msgstr "" @@ -36057,11 +36180,11 @@ msgstr "" msgid "Please select Subcontracting Order instead of Purchase Order {0}" msgstr "" -#: erpnext/controllers/accounts_controller.py:2817 +#: erpnext/controllers/accounts_controller.py:2820 msgid "Please select Unrealized Profit / Loss account or add default Unrealized Profit / Loss account account for company {0}" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1546 +#: erpnext/manufacturing/doctype/bom/bom.py:1547 msgid "Please select a BOM" msgstr "" @@ -36072,7 +36195,7 @@ msgstr "" #: erpnext/accounts/doctype/payment_entry/payment_entry.js:268 #: erpnext/manufacturing/doctype/bom/bom.js:727 -#: erpnext/manufacturing/doctype/bom/bom.py:278 +#: erpnext/manufacturing/doctype/bom/bom.py:279 #: erpnext/public/js/controllers/accounts.js:277 #: erpnext/public/js/controllers/transaction.js:3373 msgid "Please select a Company first." @@ -36094,7 +36217,7 @@ msgstr "" msgid "Please select a Supplier" msgstr "" -#: erpnext/public/js/utils/serial_no_batch_selector.js:653 +#: erpnext/public/js/utils/serial_no_batch_selector.js:664 msgid "Please select a Warehouse" msgstr "" @@ -36102,6 +36225,10 @@ msgstr "" msgid "Please select a Work Order first." msgstr "" +#: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py:53 +msgid "Please select a company." +msgstr "" + #: erpnext/setup/doctype/holiday_list/holiday_list.py:89 msgid "Please select a country" msgstr "" @@ -36171,15 +36298,15 @@ msgstr "" msgid "Please select at least one schedule." msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:1312 +#: erpnext/selling/doctype/sales_order/sales_order.js:1310 msgid "Please select atleast one item to continue" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:394 +#: erpnext/manufacturing/doctype/work_order/work_order.js:399 msgid "Please select atleast one operation to create Job Card" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1712 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1713 msgid "Please select correct account" msgstr "" @@ -36233,13 +36360,15 @@ msgstr "" msgid "Please select the customer." msgstr "" -#: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py:21 -#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py:21 #: erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.py:43 #: erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py:54 msgid "Please select the document type first" msgstr "" +#: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py:47 +msgid "Please select the document type first." +msgstr "" + #: erpnext/stock/report/batch_item_expiry_status/batch_item_expiry_status.py:21 msgid "Please select the required filters" msgstr "" @@ -36269,7 +36398,7 @@ msgstr "" msgid "Please set 'Gain/Loss Account on Asset Disposal' in Company {0}" msgstr "" -#: erpnext/accounts/general_ledger.py:559 +#: erpnext/accounts/general_ledger.py:560 msgid "Please set '{0}' in Company: {1}" msgstr "" @@ -36337,7 +36466,7 @@ msgstr "" msgid "Please set Parent Row No for item {0}" msgstr "" -#: erpnext/controllers/buying_controller.py:352 +#: erpnext/controllers/buying_controller.py:356 msgid "Please set Purchase Expense Contra Account in Company {0}" msgstr "" @@ -36424,7 +36553,7 @@ msgstr "" msgid "Please set default Cash or Bank account in Mode of Payments {}" msgstr "" -#: erpnext/accounts/utils.py:2527 +#: erpnext/accounts/utils.py:2528 msgid "Please set default Exchange Gain/Loss Account in Company {}" msgstr "" @@ -36453,7 +36582,7 @@ msgstr "" msgid "Please set filter based on Item or Warehouse" msgstr "" -#: erpnext/controllers/accounts_controller.py:2378 +#: erpnext/controllers/accounts_controller.py:2381 msgid "Please set one of the following:" msgstr "" @@ -36473,7 +36602,7 @@ msgstr "" msgid "Please set the Default Cost Center in {0} company." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:679 +#: erpnext/manufacturing/doctype/work_order/work_order.js:686 msgid "Please set the Item Code first" msgstr "" @@ -36520,7 +36649,7 @@ msgstr "" msgid "Please set {0} in Company {1} to account for Exchange Gain / Loss" msgstr "" -#: erpnext/controllers/accounts_controller.py:590 +#: erpnext/controllers/accounts_controller.py:591 msgid "Please set {0} to {1}, the same account that was used in the original invoice {2}." msgstr "" @@ -36532,7 +36661,7 @@ msgstr "" msgid "Please share this email with your support team so that they can find and fix the issue." msgstr "" -#: erpnext/stock/get_item_details.py:331 +#: erpnext/stock/get_item_details.py:333 msgid "Please specify Company" msgstr "" @@ -36542,7 +36671,7 @@ msgstr "" msgid "Please specify Company to proceed" msgstr "" -#: erpnext/controllers/accounts_controller.py:3199 +#: erpnext/controllers/accounts_controller.py:3202 #: erpnext/public/js/controllers/accounts.js:117 msgid "Please specify a valid Row ID for row {0} in table {1}" msgstr "" @@ -36732,7 +36861,7 @@ msgstr "" #: erpnext/accounts/report/accounts_payable/accounts_payable.js:16 #: erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js:15 #: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:18 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1189 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1196 #: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:15 #: erpnext/accounts/report/bank_clearance_summary/bank_clearance_summary.py:38 #: erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.html:7 @@ -36756,8 +36885,7 @@ msgstr "" #: erpnext/manufacturing/report/job_card_summary/job_card_summary.py:134 #: erpnext/public/js/purchase_trends_filters.js:38 #: erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.py:25 -#: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py:51 -#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py:45 +#: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py:68 #: erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.py:67 #: erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py:85 #: erpnext/stock/doctype/landed_cost_purchase_receipt/landed_cost_purchase_receipt.json @@ -36788,7 +36916,7 @@ msgid "Posting Date Inheritance for Exchange Gain / Loss" msgstr "" #: erpnext/stock/doctype/purchase_receipt/purchase_receipt.py:269 -#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:142 +#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:144 msgid "Posting Date cannot be future date" msgstr "" @@ -36999,6 +37127,12 @@ msgstr "" msgid "Preventive Maintenance" msgstr "" +#. Description of the 'Don't reserve Sales Order qty on sales return' (Check) +#. field in DocType 'Selling Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "Prevents the automatic reservation of stock quantities from sales orders when processing sales returns." +msgstr "" + #. Label of the preview (Button) field in DocType 'Request for Quotation' #: erpnext/buying/doctype/request_for_quotation/request_for_quotation.js:267 #: erpnext/buying/doctype/request_for_quotation/request_for_quotation.json @@ -37011,7 +37145,7 @@ msgstr "" msgid "Preview Required Materials" msgstr "" -#: erpnext/accounts/report/balance_sheet/balance_sheet.py:181 +#: erpnext/accounts/report/balance_sheet/balance_sheet.py:182 #: erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py:142 msgid "Previous Financial Year is not closed" msgstr "" @@ -37135,7 +37269,7 @@ msgstr "" msgid "Price List Currency" msgstr "" -#: erpnext/stock/get_item_details.py:1315 +#: erpnext/stock/get_item_details.py:1320 msgid "Price List Currency not selected" msgstr "" @@ -37260,7 +37394,7 @@ msgstr "" msgid "Price is not set for the item." msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:604 +#: erpnext/manufacturing/doctype/bom/bom.py:605 msgid "Price not found for item {0} in price list {1}" msgstr "" @@ -37627,10 +37761,8 @@ msgstr "" msgid "Process Description" msgstr "" -#. Label of the process_loss_section (Section Break) field in DocType 'BOM' #. Label of the section_break_7qsm (Section Break) field in DocType 'Stock #. Entry' -#: erpnext/manufacturing/doctype/bom/bom.json #: erpnext/stock/doctype/stock_entry/stock_entry.json msgid "Process Loss" msgstr "" @@ -37641,7 +37773,7 @@ msgstr "" msgid "Process Loss %" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1271 +#: erpnext/manufacturing/doctype/bom/bom.py:1272 msgid "Process Loss Percentage cannot be greater than 100" msgstr "" @@ -37967,7 +38099,7 @@ msgstr "" #: erpnext/manufacturing/doctype/work_order/work_order.json #: erpnext/manufacturing/report/production_plan_summary/production_plan_summary.js:8 #: erpnext/manufacturing/workspace/manufacturing/manufacturing.json -#: erpnext/selling/doctype/sales_order/sales_order.js:1066 +#: erpnext/selling/doctype/sales_order/sales_order.js:1064 #: erpnext/stock/doctype/material_request_item/material_request_item.json #: erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.json #: erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.json @@ -38057,7 +38189,7 @@ msgstr "" msgid "Profit & Loss" msgstr "" -#: erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py:116 +#: erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py:117 msgid "Profit This Year" msgstr "" @@ -38094,8 +38226,8 @@ msgstr "" msgid "Profit and Loss Summary" msgstr "" -#: erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py:140 #: erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py:141 +#: erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py:142 msgid "Profit for the year" msgstr "" @@ -38248,7 +38380,7 @@ msgstr "" msgid "Project wise Stock Tracking " msgstr "" -#: erpnext/controllers/trends.py:429 +#: erpnext/controllers/trends.py:435 msgid "Project-wise data is not available for Quotation" msgstr "" @@ -38470,9 +38602,9 @@ msgstr "" msgid "Provisional Expense Account" msgstr "" -#: erpnext/accounts/report/balance_sheet/balance_sheet.py:158 #: erpnext/accounts/report/balance_sheet/balance_sheet.py:159 -#: erpnext/accounts/report/balance_sheet/balance_sheet.py:226 +#: erpnext/accounts/report/balance_sheet/balance_sheet.py:160 +#: erpnext/accounts/report/balance_sheet/balance_sheet.py:227 msgid "Provisional Profit / Loss (Credit)" msgstr "" @@ -38596,8 +38728,8 @@ msgstr "" msgid "Purchase Expense Contra Account" msgstr "" -#: erpnext/controllers/buying_controller.py:362 -#: erpnext/controllers/buying_controller.py:376 +#: erpnext/controllers/buying_controller.py:366 +#: erpnext/controllers/buying_controller.py:380 msgid "Purchase Expense for Item {0}" msgstr "" @@ -38725,12 +38857,12 @@ msgstr "" #: erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.js:48 #: erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.py:203 #: erpnext/buying/workspace/buying/buying.json -#: erpnext/controllers/buying_controller.py:922 +#: erpnext/controllers/buying_controller.py:929 #: erpnext/crm/doctype/contract/contract.json #: erpnext/manufacturing/doctype/blanket_order/blanket_order.js:54 #: erpnext/manufacturing/doctype/production_plan_sub_assembly_item/production_plan_sub_assembly_item.json #: erpnext/selling/doctype/sales_order/sales_order.js:189 -#: erpnext/selling/doctype/sales_order/sales_order.js:1113 +#: erpnext/selling/doctype/sales_order/sales_order.js:1111 #: erpnext/selling/doctype/sales_order_item/sales_order_item.json #: erpnext/setup/doctype/authorization_rule/authorization_rule.json #: erpnext/stock/doctype/delivery_note_item/delivery_note_item.json @@ -38800,7 +38932,7 @@ msgstr "" msgid "Purchase Order Item Supplied" msgstr "" -#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:1012 +#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:1044 msgid "Purchase Order Item reference is missing in Subcontracting Receipt {0}" msgstr "" @@ -38831,7 +38963,7 @@ msgstr "" msgid "Purchase Order Trends" msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:1614 +#: erpnext/selling/doctype/sales_order/sales_order.js:1612 msgid "Purchase Order already created for all Sales Order items" msgstr "" @@ -38877,7 +39009,7 @@ msgstr "" msgid "Purchase Orders to Receive" msgstr "" -#: erpnext/controllers/accounts_controller.py:2010 +#: erpnext/controllers/accounts_controller.py:2013 msgid "Purchase Orders {0} are un-linked" msgstr "" @@ -38988,7 +39120,7 @@ msgstr "" msgid "Purchase Receipt doesn't have any Item for which Retain Sample is enabled." msgstr "" -#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:1088 +#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:1120 msgid "Purchase Receipt {0} created." msgstr "" @@ -39179,8 +39311,8 @@ msgstr "" #: erpnext/assets/doctype/asset_capitalization_service_item/asset_capitalization_service_item.json #: erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.py:240 #: erpnext/buying/report/requested_items_to_order_and_receive/requested_items_to_order_and_receive.py:224 -#: erpnext/controllers/trends.py:276 erpnext/controllers/trends.py:288 -#: erpnext/controllers/trends.py:293 +#: erpnext/controllers/trends.py:282 erpnext/controllers/trends.py:294 +#: erpnext/controllers/trends.py:299 #: erpnext/crm/doctype/opportunity_item/opportunity_item.json #: erpnext/manufacturing/doctype/bom/bom.js:1105 #: erpnext/manufacturing/doctype/bom_creator_item/bom_creator_item.json @@ -39205,8 +39337,8 @@ msgstr "" #: erpnext/selling/doctype/sales_order/sales_order.js:502 #: erpnext/selling/doctype/sales_order/sales_order.js:592 #: erpnext/selling/doctype/sales_order/sales_order.js:639 -#: erpnext/selling/doctype/sales_order/sales_order.js:1288 -#: erpnext/selling/doctype/sales_order/sales_order.js:1450 +#: erpnext/selling/doctype/sales_order/sales_order.js:1286 +#: erpnext/selling/doctype/sales_order/sales_order.js:1448 #: erpnext/selling/report/sales_order_analysis/sales_order_analysis.py:255 #: erpnext/stock/doctype/landed_cost_item/landed_cost_item.json #: erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.json @@ -39316,7 +39448,7 @@ msgstr "" msgid "Qty To Manufacture" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1425 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1441 msgid "Qty To Manufacture ({0}) cannot be a fraction for the UOM {2}. To allow this, disable '{1}' in the UOM {2}." msgstr "" @@ -39371,8 +39503,8 @@ msgstr "" msgid "Qty for which recursion isn't applicable." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:1056 -#: erpnext/manufacturing/doctype/work_order/work_order.js:1079 +#: erpnext/manufacturing/doctype/work_order/work_order.js:1063 +#: erpnext/manufacturing/doctype/work_order/work_order.js:1086 msgid "Qty for {0}" msgstr "" @@ -39423,7 +39555,7 @@ msgstr "" msgid "Qty to Disassemble" msgstr "" -#: erpnext/public/js/utils/serial_no_batch_selector.js:373 +#: erpnext/public/js/utils/serial_no_batch_selector.js:384 msgid "Qty to Fetch" msgstr "" @@ -39561,7 +39693,6 @@ msgstr "" #. Label of the quality_inspection (Link) field in DocType 'Sales Invoice Item' #. Label of the quality_inspection_section_break (Section Break) field in #. DocType 'BOM' -#. Label of the quality_inspection_tab (Tab Break) field in DocType 'BOM' #. Label of the quality_inspection (Link) field in DocType 'Job Card' #. Label of the quality_inspection_section (Section Break) field in DocType #. 'Job Card' @@ -39773,7 +39904,6 @@ msgstr "" #. Label of the qty (Float) field in DocType 'Request for Quotation Item' #. Label of the qty (Float) field in DocType 'Supplier Quotation Item' #. Label of the qty (Float) field in DocType 'Blanket Order Item' -#. Label of the quantity (Float) field in DocType 'BOM' #. Label of the qty (Float) field in DocType 'BOM Creator' #. Label of the section_break_4rxf (Section Break) field in DocType 'Production #. Plan Sub Assembly Item' @@ -39812,7 +39942,6 @@ msgstr "" #: erpnext/buying/report/supplier_quotation_comparison/supplier_quotation_comparison.py:213 #: erpnext/manufacturing/doctype/blanket_order_item/blanket_order_item.json #: erpnext/manufacturing/doctype/bom/bom.js:493 -#: erpnext/manufacturing/doctype/bom/bom.json #: erpnext/manufacturing/doctype/bom_creator/bom_creator.js:76 #: erpnext/manufacturing/doctype/bom_creator/bom_creator.json #: erpnext/manufacturing/doctype/plant_floor/plant_floor.js:194 @@ -39820,13 +39949,13 @@ msgstr "" #: erpnext/manufacturing/doctype/production_plan_sub_assembly_item/production_plan_sub_assembly_item.json #: erpnext/public/js/controllers/buying.js:615 #: erpnext/public/js/stock_analytics.js:50 -#: erpnext/public/js/utils/serial_no_batch_selector.js:486 +#: erpnext/public/js/utils/serial_no_batch_selector.js:497 #: erpnext/selling/doctype/quotation_item/quotation_item.json #: erpnext/selling/doctype/sales_order_item/sales_order_item.json #: erpnext/selling/page/point_of_sale/pos_item_cart.js:51 #: erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py:42 #: erpnext/selling/report/sales_analytics/sales_analytics.js:44 -#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py:67 +#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py:39 #: erpnext/stock/dashboard/item_dashboard.js:248 #: erpnext/stock/doctype/delivery_note_item/delivery_note_item.json #: erpnext/stock/doctype/material_request/material_request.js:368 @@ -39866,6 +39995,11 @@ msgstr "" msgid "Quantity (A - B)" msgstr "" +#. Label of the quantity (Float) field in DocType 'BOM' +#: erpnext/manufacturing/doctype/bom/bom.json +msgid "Quantity (Output Qty)" +msgstr "" + #. Label of the quantity_difference (Read Only) field in DocType 'Stock #. Reconciliation Item' #: erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.json @@ -39948,36 +40082,31 @@ msgstr "" msgid "Quantity must be less than or equal to {0}" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:1109 +#: erpnext/manufacturing/doctype/work_order/work_order.js:1116 #: erpnext/stock/doctype/pick_list/pick_list.js:206 msgid "Quantity must not be more than {0}" msgstr "" -#. Description of the 'Quantity' (Float) field in DocType 'BOM' -#: erpnext/manufacturing/doctype/bom/bom.json -msgid "Quantity of item obtained after manufacturing / repacking from given quantities of raw materials" -msgstr "" - -#: erpnext/manufacturing/doctype/bom/bom.py:772 +#: erpnext/manufacturing/doctype/bom/bom.py:773 msgid "Quantity required for Item {0} in row {1}" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:716 +#: erpnext/manufacturing/doctype/bom/bom.py:717 #: erpnext/manufacturing/doctype/job_card/job_card.js:393 #: erpnext/manufacturing/doctype/job_card/job_card.js:463 #: erpnext/manufacturing/doctype/workstation/workstation.js:303 msgid "Quantity should be greater than 0" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:356 +#: erpnext/manufacturing/doctype/work_order/work_order.js:361 msgid "Quantity to Manufacture" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:2622 +#: erpnext/manufacturing/doctype/work_order/work_order.py:2638 msgid "Quantity to Manufacture can not be zero for the operation {0}" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1417 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1433 msgid "Quantity to Manufacture must be greater than 0." msgstr "" @@ -40067,7 +40196,7 @@ msgstr "" #: erpnext/crm/report/lead_details/lead_details.js:37 #: erpnext/manufacturing/doctype/blanket_order/blanket_order.js:38 #: erpnext/selling/doctype/quotation/quotation.json -#: erpnext/selling/doctype/sales_order/sales_order.js:1191 +#: erpnext/selling/doctype/sales_order/sales_order.js:1189 #: erpnext/selling/doctype/sales_order_item/sales_order_item.json #: erpnext/selling/workspace/selling/selling.json #: erpnext/setup/doctype/authorization_rule/authorization_rule.json @@ -40255,7 +40384,7 @@ msgstr "" #: erpnext/selling/doctype/quotation_item/quotation_item.json #: erpnext/selling/doctype/sales_order_item/sales_order_item.json #: erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py:45 -#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py:68 +#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py:41 #: erpnext/stock/dashboard/item_dashboard.js:255 #: erpnext/stock/doctype/delivery_note_item/delivery_note_item.json #: erpnext/stock/doctype/item_price/item_price.json @@ -40432,7 +40561,7 @@ msgstr "" msgid "Rate at which this tax is applied" msgstr "" -#: erpnext/controllers/accounts_controller.py:4074 +#: erpnext/controllers/accounts_controller.py:4080 msgid "Rate of '{}' items cannot be changed" msgstr "" @@ -40569,12 +40698,10 @@ msgstr "" msgid "Raw Material Warehouse" msgstr "" -#. Label of the materials_section (Section Break) field in DocType 'BOM' #. Label of the section_break_8 (Section Break) field in DocType 'Job Card' #. Label of the mr_items (Table) field in DocType 'Production Plan' #: erpnext/manufacturing/doctype/bom/bom.js:446 #: erpnext/manufacturing/doctype/bom/bom.js:1078 -#: erpnext/manufacturing/doctype/bom/bom.json #: erpnext/manufacturing/doctype/job_card/job_card.json #: erpnext/manufacturing/doctype/production_plan/production_plan.json #: erpnext/manufacturing/doctype/workstation/workstation.js:462 @@ -40637,7 +40764,7 @@ msgstr "" msgid "Raw Materials Supplied Cost" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:764 +#: erpnext/manufacturing/doctype/bom/bom.py:765 msgid "Raw Materials cannot be blank." msgstr "" @@ -40659,8 +40786,8 @@ msgstr "" #: erpnext/buying/doctype/purchase_order/purchase_order.js:369 #: erpnext/manufacturing/doctype/production_plan/production_plan.js:124 -#: erpnext/manufacturing/doctype/work_order/work_order.js:778 -#: erpnext/selling/doctype/sales_order/sales_order.js:976 +#: erpnext/manufacturing/doctype/work_order/work_order.js:785 +#: erpnext/selling/doctype/sales_order/sales_order.js:974 #: erpnext/selling/doctype/sales_order/sales_order_list.js:70 #: erpnext/stock/doctype/material_request/material_request.js:243 #: erpnext/subcontracting/doctype/subcontracting_inward_order/subcontracting_inward_order.js:116 @@ -40759,7 +40886,7 @@ msgid "Reason for Failure" msgstr "" #: erpnext/buying/doctype/purchase_order/purchase_order.js:679 -#: erpnext/selling/doctype/sales_order/sales_order.js:1785 +#: erpnext/selling/doctype/sales_order/sales_order.js:1783 msgid "Reason for Hold" msgstr "" @@ -40768,7 +40895,7 @@ msgstr "" msgid "Reason for Leaving" msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:1800 +#: erpnext/selling/doctype/sales_order/sales_order.js:1798 msgid "Reason for hold:" msgstr "" @@ -40839,8 +40966,8 @@ msgstr "" msgid "Receivable / Payable Account" msgstr "" -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:68 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1204 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:79 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1211 #: erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py:241 #: erpnext/accounts/report/sales_register/sales_register.py:217 #: erpnext/accounts/report/sales_register/sales_register.py:271 @@ -41202,7 +41329,7 @@ msgstr "" msgid "Ref Date" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1034 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1035 msgid "Reference #{0} dated {1}" msgstr "" @@ -41240,7 +41367,7 @@ msgstr "" msgid "Reference No" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:648 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:649 msgid "Reference No & Reference Date is required for {0}" msgstr "" @@ -41248,11 +41375,11 @@ msgstr "" msgid "Reference No and Reference Date is mandatory for Bank transaction" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:653 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:654 msgid "Reference No is mandatory if you entered Reference Date" msgstr "" -#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:193 +#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:265 msgid "Reference No." msgstr "" @@ -41397,7 +41524,7 @@ msgstr "" msgid "Regular" msgstr "" -#: erpnext/stock/doctype/inventory_dimension/inventory_dimension.py:202 +#: erpnext/stock/doctype/inventory_dimension/inventory_dimension.py:209 msgid "Rejected " msgstr "" @@ -41457,7 +41584,7 @@ msgstr "" msgid "Rejected Warehouse" msgstr "" -#: erpnext/public/js/utils/serial_no_batch_selector.js:657 +#: erpnext/public/js/utils/serial_no_batch_selector.js:668 msgid "Rejected Warehouse and Accepted Warehouse cannot be same." msgstr "" @@ -41502,12 +41629,13 @@ msgstr "" #: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts_accounts_receivable.html:189 #: erpnext/accounts/report/accounts_receivable/accounts_receivable.html:156 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1278 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1286 #: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py:178 msgid "Remaining Balance" msgstr "" #. Label of the remark (Small Text) field in DocType 'Journal Entry' +#: erpnext/accounts/doctype/journal_entry/journal_entry.js:651 #: erpnext/accounts/doctype/journal_entry/journal_entry.json #: erpnext/selling/page/point_of_sale/pos_payment.js:489 msgid "Remark" @@ -41555,7 +41683,7 @@ msgstr "" #: erpnext/accounts/report/accounts_receivable/accounts_receivable.html:159 #: erpnext/accounts/report/accounts_receivable/accounts_receivable.html:204 #: erpnext/accounts/report/accounts_receivable/accounts_receivable.html:275 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1310 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1318 #: erpnext/accounts/report/general_ledger/general_ledger.html:90 #: erpnext/accounts/report/general_ledger/general_ledger.html:116 #: erpnext/accounts/report/general_ledger/general_ledger.py:794 @@ -42026,7 +42154,7 @@ msgstr "" msgid "Request for Quotation Supplier" msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:1100 +#: erpnext/selling/doctype/sales_order/sales_order.js:1098 msgid "Request for Raw Materials" msgstr "" @@ -42231,7 +42359,7 @@ msgstr "" msgid "Reservation Based On" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:936 +#: erpnext/manufacturing/doctype/work_order/work_order.js:943 #: erpnext/selling/doctype/sales_order/sales_order.js:107 #: erpnext/stock/doctype/pick_list/pick_list.js:150 #: erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js:180 @@ -42353,7 +42481,7 @@ msgstr "" #. Label of the reserved_stock (Float) field in DocType 'Bin' #. Name of a report #: erpnext/manufacturing/doctype/plant_floor/stock_summary_template.html:24 -#: erpnext/manufacturing/doctype/work_order/work_order.js:952 +#: erpnext/manufacturing/doctype/work_order/work_order.js:959 #: erpnext/public/js/stock_reservation.js:236 #: erpnext/selling/doctype/sales_order/sales_order.js:135 #: erpnext/selling/doctype/sales_order/sales_order.js:465 @@ -42380,7 +42508,7 @@ msgstr "" msgid "Reserved Stock for Sub-assembly" msgstr "" -#: erpnext/controllers/buying_controller.py:649 +#: erpnext/controllers/buying_controller.py:656 msgid "Reserved Warehouse is mandatory for the Item {item_code} in Raw Materials supplied." msgstr "" @@ -42630,7 +42758,7 @@ msgstr "" #: erpnext/accounts/doctype/process_period_closing_voucher/process_period_closing_voucher.js:43 #: erpnext/buying/doctype/purchase_order/purchase_order.js:344 #: erpnext/manufacturing/doctype/workstation/workstation_job_card.html:63 -#: erpnext/selling/doctype/sales_order/sales_order.js:962 +#: erpnext/selling/doctype/sales_order/sales_order.js:960 msgid "Resume" msgstr "" @@ -42735,7 +42863,7 @@ msgstr "" msgid "Return Against Subcontracting Receipt" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:297 +#: erpnext/manufacturing/doctype/work_order/work_order.js:302 msgid "Return Components" msgstr "" @@ -42865,10 +42993,10 @@ msgstr "" msgid "Returns" msgstr "" -#: erpnext/accounts/report/accounts_payable/accounts_payable.js:140 -#: erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js:102 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:172 -#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:130 +#: erpnext/accounts/report/accounts_payable/accounts_payable.js:151 +#: erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js:113 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:183 +#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:141 msgid "Revaluation Journals" msgstr "" @@ -43037,11 +43165,8 @@ msgstr "" #. Settings' #. Label of the role_to_override_stop_action (Link) field in DocType 'Buying #. Settings' -#. Label of the role_to_override_stop_action (Link) field in DocType 'Selling -#. Settings' #: erpnext/accounts/doctype/accounts_settings/accounts_settings.json #: erpnext/buying/doctype/buying_settings/buying_settings.json -#: erpnext/selling/doctype/selling_settings/selling_settings.json msgid "Role Allowed to Override Stop Action" msgstr "" @@ -43056,6 +43181,12 @@ msgstr "" msgid "Role allowed to bypass period restrictions." msgstr "" +#. Label of the role_to_override_stop_action (Link) field in DocType 'Selling +#. Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "Role allowed to override stop action" +msgstr "" + #. Label of the role_to_notify_on_depreciation_failure (Link) field in DocType #. 'Accounts Settings' #: erpnext/accounts/doctype/accounts_settings/accounts_settings.json @@ -43078,9 +43209,11 @@ msgid "Root Company" msgstr "" #. Label of the root_type (Select) field in DocType 'Account' +#. Label of the root_type (Select) field in DocType 'Account Category' #. Label of the root_type (Select) field in DocType 'Ledger Merge' #: erpnext/accounts/doctype/account/account.json #: erpnext/accounts/doctype/account/account_tree.js:147 +#: erpnext/accounts/doctype/account_category/account_category.json #: erpnext/accounts/doctype/ledger_merge/ledger_merge.json #: erpnext/accounts/report/account_balance/account_balance.js:22 msgid "Root Type" @@ -43296,7 +43429,7 @@ msgstr "" msgid "Row # {0}: Returned Item {1} does not exist in {2} {3}" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:275 +#: erpnext/manufacturing/doctype/work_order/work_order.py:279 msgid "Row #1: Sequence ID must be 1 for Operation {0}." msgstr "" @@ -43323,15 +43456,15 @@ msgid "Row #{0}: Acceptance Criteria Formula is required." msgstr "" #: erpnext/controllers/subcontracting_controller.py:125 -#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:571 +#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:603 msgid "Row #{0}: Accepted Warehouse and Rejected Warehouse cannot be same" msgstr "" -#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:564 +#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:596 msgid "Row #{0}: Accepted Warehouse is mandatory for the accepted Item {1}" msgstr "" -#: erpnext/controllers/accounts_controller.py:1290 +#: erpnext/controllers/accounts_controller.py:1291 msgid "Row #{0}: Account {1} does not belong to company {2}" msgstr "" @@ -43396,27 +43529,27 @@ msgstr "" msgid "Row #{0}: Cannot create entry with different taxable AND withholding document links." msgstr "" -#: erpnext/controllers/accounts_controller.py:3777 +#: erpnext/controllers/accounts_controller.py:3783 msgid "Row #{0}: Cannot delete item {1} which has already been billed." msgstr "" -#: erpnext/controllers/accounts_controller.py:3751 +#: erpnext/controllers/accounts_controller.py:3757 msgid "Row #{0}: Cannot delete item {1} which has already been delivered" msgstr "" -#: erpnext/controllers/accounts_controller.py:3770 +#: erpnext/controllers/accounts_controller.py:3776 msgid "Row #{0}: Cannot delete item {1} which has already been received" msgstr "" -#: erpnext/controllers/accounts_controller.py:3757 +#: erpnext/controllers/accounts_controller.py:3763 msgid "Row #{0}: Cannot delete item {1} which has work order assigned to it." msgstr "" -#: erpnext/controllers/accounts_controller.py:3763 +#: erpnext/controllers/accounts_controller.py:3769 msgid "Row #{0}: Cannot delete item {1} which is already ordered against this Sales Order." msgstr "" -#: erpnext/controllers/accounts_controller.py:4084 +#: erpnext/controllers/accounts_controller.py:4090 msgid "Row #{0}: Cannot set Rate if the billed amount is greater than the amount for Item {1}." msgstr "" @@ -43470,11 +43603,11 @@ msgstr "" msgid "Row #{0}: Customer Provided Item {1} cannot be added multiple times in the Subcontracting Inward process." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:352 +#: erpnext/manufacturing/doctype/work_order/work_order.py:356 msgid "Row #{0}: Customer Provided Item {1} cannot be added multiple times." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:377 +#: erpnext/manufacturing/doctype/work_order/work_order.py:381 msgid "Row #{0}: Customer Provided Item {1} does not exist in the Required Items table linked to the Subcontracting Inward Order." msgstr "" @@ -43482,7 +43615,7 @@ msgstr "" msgid "Row #{0}: Customer Provided Item {1} exceeds quantity available through Subcontracting Inward Order" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:365 +#: erpnext/manufacturing/doctype/work_order/work_order.py:369 msgid "Row #{0}: Customer Provided Item {1} has insufficient quantity in the Subcontracting Inward Order. Available quantity is {2}." msgstr "" @@ -43542,7 +43675,7 @@ msgstr "" msgid "Row #{0}: Finished Good must be {1}" msgstr "" -#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:552 +#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:584 msgid "Row #{0}: Finished Good reference is mandatory for Secondary Item {1}." msgstr "" @@ -43551,11 +43684,11 @@ msgstr "" msgid "Row #{0}: For Customer Provided Item {1}, Source Warehouse must be {2}" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:696 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:697 msgid "Row #{0}: For {1}, you can select reference document only if account gets credited" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:706 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:707 msgid "Row #{0}: For {1}, you can select reference document only if account gets debited" msgstr "" @@ -43681,11 +43814,11 @@ msgstr "" msgid "Row #{0}: Please set reorder quantity" msgstr "" -#: erpnext/controllers/accounts_controller.py:613 +#: erpnext/controllers/accounts_controller.py:614 msgid "Row #{0}: Please update deferred revenue/expense account in item row or default account in company master" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:345 +#: erpnext/manufacturing/doctype/bom/bom.py:346 #, python-format msgid "Row #{0}: Process Loss Percentage should be less than 100% for {1} Item {2}" msgstr "" @@ -43719,7 +43852,7 @@ msgstr "" msgid "Row #{0}: Quantity cannot be a non-positive number. Please increase the quantity or remove the Item {1}" msgstr "" -#: erpnext/controllers/accounts_controller.py:1453 +#: erpnext/controllers/accounts_controller.py:1454 msgid "Row #{0}: Quantity for Item {1} cannot be zero." msgstr "" @@ -43727,7 +43860,7 @@ msgstr "" msgid "Row #{0}: Quantity of Item {1} cannot be more than {2} {3} against Subcontracting Inward Order {4}" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:338 +#: erpnext/manufacturing/doctype/bom/bom.py:339 msgid "Row #{0}: Quantity should be greater than 0 for {1} Item {2}" msgstr "" @@ -43735,8 +43868,8 @@ msgstr "" msgid "Row #{0}: Quantity to reserve for the Item {1} should be greater than 0." msgstr "" -#: erpnext/controllers/accounts_controller.py:868 -#: erpnext/controllers/accounts_controller.py:880 +#: erpnext/controllers/accounts_controller.py:869 +#: erpnext/controllers/accounts_controller.py:881 #: erpnext/utilities/transaction_base.py:114 #: erpnext/utilities/transaction_base.py:120 msgid "Row #{0}: Rate must be same as {1}: {2} ({3} / {4})" @@ -43750,7 +43883,7 @@ msgstr "" msgid "Row #{0}: Reference Document Type must be one of Sales Order, Sales Invoice, Journal Entry or Dunning" msgstr "" -#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:545 +#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:577 msgid "Row #{0}: Rejected Qty cannot be set for Secondary Item {1}." msgstr "" @@ -43774,7 +43907,7 @@ msgstr "" msgid "Row #{0}: Returned quantity cannot be greater than available quantity to return for Item {1}" msgstr "" -#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:540 +#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:572 msgid "Row #{0}: Secondary Item Qty cannot be zero" msgstr "" @@ -43786,7 +43919,7 @@ msgid "" "\t\t\t\t\tthis validation." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:281 +#: erpnext/manufacturing/doctype/work_order/work_order.py:285 msgid "Row #{0}: Sequence ID must be {1} or {2} for Operation {3}." msgstr "" @@ -43806,15 +43939,15 @@ msgstr "" msgid "Row #{0}: Serial No(s) {1} are not a part of the linked Subcontracting Inward Order. Please select valid Serial No(s)." msgstr "" -#: erpnext/controllers/accounts_controller.py:641 +#: erpnext/controllers/accounts_controller.py:642 msgid "Row #{0}: Service End Date cannot be before Invoice Posting Date" msgstr "" -#: erpnext/controllers/accounts_controller.py:635 +#: erpnext/controllers/accounts_controller.py:636 msgid "Row #{0}: Service Start Date cannot be greater than Service End Date" msgstr "" -#: erpnext/controllers/accounts_controller.py:629 +#: erpnext/controllers/accounts_controller.py:630 msgid "Row #{0}: Service Start and End Date is required for deferred accounting" msgstr "" @@ -43830,11 +43963,11 @@ msgstr "" msgid "Row #{0}: Source Warehouse must be same as Customer Warehouse {1} from the linked Subcontracting Inward Order" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:386 +#: erpnext/manufacturing/doctype/work_order/work_order.py:390 msgid "Row #{0}: Source Warehouse {1} for item {2} cannot be a customer warehouse." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:341 +#: erpnext/manufacturing/doctype/work_order/work_order.py:345 msgid "Row #{0}: Source Warehouse {1} for item {2} must be same as Source Warehouse {3} in the Work Order." msgstr "" @@ -43854,7 +43987,7 @@ msgstr "" msgid "Row #{0}: Status is mandatory" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:458 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:459 msgid "Row #{0}: Status must be {1} for Invoice Discounting {2}" msgstr "" @@ -43951,7 +44084,7 @@ msgstr "" msgid "Row #{0}: {1} of {2} should be {3}. Please update the {1} or select a different account." msgstr "" -#: erpnext/controllers/accounts_controller.py:3891 +#: erpnext/controllers/accounts_controller.py:3897 msgid "Row #{0}:Quantity for Item {1} cannot be zero." msgstr "" @@ -43959,35 +44092,35 @@ msgstr "" msgid "Row #{1}: Warehouse is mandatory for stock Item {0}" msgstr "" -#: erpnext/controllers/buying_controller.py:311 +#: erpnext/controllers/buying_controller.py:315 msgid "Row #{idx}: Cannot select Supplier Warehouse while suppling raw materials to subcontractor." msgstr "" -#: erpnext/controllers/buying_controller.py:580 +#: erpnext/controllers/buying_controller.py:587 msgid "Row #{idx}: Item rate has been updated as per valuation rate since its an internal stock transfer." msgstr "" -#: erpnext/controllers/buying_controller.py:1064 +#: erpnext/controllers/buying_controller.py:1071 msgid "Row #{idx}: Please enter a location for the asset item {item_code}." msgstr "" -#: erpnext/controllers/buying_controller.py:703 +#: erpnext/controllers/buying_controller.py:710 msgid "Row #{idx}: Received Qty must be equal to Accepted + Rejected Qty for Item {item_code}." msgstr "" -#: erpnext/controllers/buying_controller.py:716 +#: erpnext/controllers/buying_controller.py:723 msgid "Row #{idx}: {field_label} can not be negative for item {item_code}." msgstr "" -#: erpnext/controllers/buying_controller.py:669 +#: erpnext/controllers/buying_controller.py:676 msgid "Row #{idx}: {field_label} is mandatory." msgstr "" -#: erpnext/controllers/buying_controller.py:302 +#: erpnext/controllers/buying_controller.py:306 msgid "Row #{idx}: {from_warehouse_field} and {to_warehouse_field} cannot be same." msgstr "" -#: erpnext/controllers/buying_controller.py:1181 +#: erpnext/controllers/buying_controller.py:1188 msgid "Row #{idx}: {schedule_date} cannot be before {transaction_date}." msgstr "" @@ -44072,11 +44205,11 @@ msgstr "" msgid "Row {0}# Item {1} not found in 'Raw Materials Supplied' table in {2} {3}" msgstr "" -#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:273 +#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:276 msgid "Row {0}: Accepted Qty and Rejected Qty can't be zero at the same time." msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:611 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:612 msgid "Row {0}: Account {1} and Party Type {2} have different account types" msgstr "" @@ -44084,11 +44217,11 @@ msgstr "" msgid "Row {0}: Activity Type is mandatory." msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:677 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:678 msgid "Row {0}: Advance against Customer must be credit" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:679 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:680 msgid "Row {0}: Advance against Supplier must be debit" msgstr "" @@ -44108,11 +44241,11 @@ msgstr "" msgid "Row {0}: Bill of Materials not found for the Item {1}" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:930 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:931 msgid "Row {0}: Both Debit and Credit values cannot be zero" msgstr "" -#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:587 +#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:619 msgid "" "Row {0}: Consumed Qty {1} {2} must be less than or equal to Available Qty For Consumption\n" "\t\t\t\t\t{3} {4} in Consumed Items Table." @@ -44122,7 +44255,7 @@ msgstr "" msgid "Row {0}: Conversion Factor is mandatory" msgstr "" -#: erpnext/controllers/accounts_controller.py:3237 +#: erpnext/controllers/accounts_controller.py:3240 msgid "Row {0}: Cost Center {1} does not belong to Company {2}" msgstr "" @@ -44130,15 +44263,15 @@ msgstr "" msgid "Row {0}: Cost center is required for an item {1}" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:776 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:777 msgid "Row {0}: Credit entry can not be linked with a {1}" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:578 +#: erpnext/manufacturing/doctype/bom/bom.py:579 msgid "Row {0}: Currency of the BOM #{1} should be equal to the selected currency {2}" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:771 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:772 msgid "Row {0}: Debit entry can not be linked with a {1}" msgstr "" @@ -44150,7 +44283,7 @@ msgstr "" msgid "Row {0}: Delivery Warehouse cannot be same as Customer Warehouse for Item {1}." msgstr "" -#: erpnext/controllers/accounts_controller.py:2730 +#: erpnext/controllers/accounts_controller.py:2733 msgid "Row {0}: Due Date in the Payment Terms table cannot be before Posting Date" msgstr "" @@ -44158,8 +44291,8 @@ msgstr "" msgid "Row {0}: Either Delivery Note Item or Packed Item reference is mandatory." msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1021 -#: erpnext/controllers/taxes_and_totals.py:1381 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1022 +#: erpnext/controllers/taxes_and_totals.py:1395 msgid "Row {0}: Exchange Rate is mandatory" msgstr "" @@ -44212,11 +44345,11 @@ msgstr "" msgid "Row {0}: Hours value must be greater than zero." msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:796 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:797 msgid "Row {0}: Invalid reference {1}" msgstr "" -#: erpnext/controllers/taxes_and_totals.py:129 +#: erpnext/controllers/taxes_and_totals.py:134 msgid "Row {0}: Item Tax template updated as per validity and rate applied" msgstr "" @@ -44240,7 +44373,7 @@ msgstr "" msgid "Row {0}: Item {1}'s quantity cannot be higher than the available quantity." msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1244 +#: erpnext/manufacturing/doctype/bom/bom.py:1245 msgid "Row {0}: Operation time should be greater than 0 for operation {1}" msgstr "" @@ -44252,11 +44385,11 @@ msgstr "" msgid "Row {0}: Packing Slip is already created for Item {1}." msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:822 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:823 msgid "Row {0}: Party / Account does not match with {1} / {2} in {3} {4}" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:600 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:601 msgid "Row {0}: Party Type and Party is required for Receivable / Payable account {1}" msgstr "" @@ -44264,11 +44397,11 @@ msgstr "" msgid "Row {0}: Payment Term is mandatory" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:670 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:671 msgid "Row {0}: Payment against Sales/Purchase Order should always be marked as advance" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:663 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:664 msgid "Row {0}: Please check 'Is Advance' against Account {1} if this is an advance entry." msgstr "" @@ -44356,7 +44489,7 @@ msgstr "" msgid "Row {0}: The item {1}, quantity must be positive number" msgstr "" -#: erpnext/controllers/accounts_controller.py:3214 +#: erpnext/controllers/accounts_controller.py:3217 msgid "Row {0}: The {3} Account {1} does not belong to the company {2}" msgstr "" @@ -44364,7 +44497,7 @@ msgstr "" msgid "Row {0}: To set {1} periodicity, difference between from and to date must be greater than or equal to {2}" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:3593 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:3595 msgid "Row {0}: Transferred quantity cannot be greater than the requested quantity." msgstr "" @@ -44380,12 +44513,12 @@ msgstr "" msgid "Row {0}: Warehouse {1} is linked to company {2}. Please select a warehouse belonging to company {3}." msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1238 -#: erpnext/manufacturing/doctype/work_order/work_order.py:415 +#: erpnext/manufacturing/doctype/bom/bom.py:1239 +#: erpnext/manufacturing/doctype/work_order/work_order.py:419 msgid "Row {0}: Workstation or Workstation Type is mandatory for an operation {1}" msgstr "" -#: erpnext/controllers/accounts_controller.py:1172 +#: erpnext/controllers/accounts_controller.py:1173 msgid "Row {0}: user has not applied the rule {1} on the item {2}" msgstr "" @@ -44397,11 +44530,11 @@ msgstr "" msgid "Row {0}: {1} must be greater than 0" msgstr "" -#: erpnext/controllers/accounts_controller.py:778 +#: erpnext/controllers/accounts_controller.py:779 msgid "Row {0}: {1} {2} cannot be same as {3} (Party Account) {4}" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:836 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:837 msgid "Row {0}: {1} {2} does not match with {3}" msgstr "" @@ -44413,11 +44546,11 @@ msgstr "" msgid "Row {0}: {2} Item {1} does not exist in {2} {3}" msgstr "" -#: erpnext/utilities/transaction_base.py:563 +#: erpnext/utilities/transaction_base.py:566 msgid "Row {1}: Quantity ({0}) cannot be a fraction. To allow this, disable '{2}' in UOM {3}." msgstr "" -#: erpnext/controllers/buying_controller.py:1046 +#: erpnext/controllers/buying_controller.py:1053 msgid "Row {idx}: Asset Naming Series is mandatory for the auto creation of assets for item {item_code}." msgstr "" @@ -44443,7 +44576,7 @@ msgstr "" msgid "Rows with Same Account heads will be merged on Ledger" msgstr "" -#: erpnext/controllers/accounts_controller.py:2741 +#: erpnext/controllers/accounts_controller.py:2744 msgid "Rows with duplicate due dates in other rows were found: {0}" msgstr "" @@ -44451,7 +44584,7 @@ msgstr "" msgid "Rows: {0} have 'Payment Entry' as reference_type. This should not be set manually." msgstr "" -#: erpnext/controllers/accounts_controller.py:280 +#: erpnext/controllers/accounts_controller.py:281 msgid "Rows: {0} in {1} section are Invalid. Reference Name should point to a valid Payment Entry or Journal Entry." msgstr "" @@ -44733,7 +44866,7 @@ msgstr "" #: erpnext/projects/doctype/timesheet/timesheet.json #: erpnext/projects/doctype/timesheet_detail/timesheet_detail.json #: erpnext/selling/doctype/quotation/quotation_list.js:22 -#: erpnext/selling/doctype/sales_order/sales_order.js:1079 +#: erpnext/selling/doctype/sales_order/sales_order.js:1077 #: erpnext/selling/doctype/sales_order/sales_order_list.js:75 #: erpnext/selling/workspace/selling/selling.json #: erpnext/setup/doctype/authorization_rule/authorization_rule.json @@ -44980,7 +45113,7 @@ msgstr "" #: erpnext/manufacturing/doctype/work_order/work_order.json #: erpnext/selling/doctype/delivery_schedule_item/delivery_schedule_item.json #: erpnext/selling/doctype/sales_order/sales_order.js:344 -#: erpnext/selling/doctype/sales_order/sales_order.js:1295 +#: erpnext/selling/doctype/sales_order/sales_order.js:1293 #: erpnext/selling/doctype/sales_order_item/sales_order_item.json #: erpnext/stock/doctype/material_request_item/material_request_item.json #: erpnext/stock/doctype/pick_list_item/pick_list_item.json @@ -45040,12 +45173,12 @@ msgstr "" msgid "Sales Order {0} is not submitted" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:479 +#: erpnext/manufacturing/doctype/work_order/work_order.py:495 msgid "Sales Order {0} is not valid" msgstr "" #: erpnext/controllers/selling_controller.py:476 -#: erpnext/manufacturing/doctype/work_order/work_order.py:484 +#: erpnext/manufacturing/doctype/work_order/work_order.py:500 msgid "Sales Order {0} is {1}" msgstr "" @@ -45100,18 +45233,18 @@ msgstr "" #: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json #: erpnext/accounts/doctype/promotional_scheme/promotional_scheme.json #: erpnext/accounts/doctype/sales_invoice/sales_invoice.json -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:119 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1299 -#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:103 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:130 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1307 +#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:114 #: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py:194 #: erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.js:74 #: erpnext/selling/doctype/customer/customer.json #: erpnext/selling/doctype/sales_order/sales_order.json #: erpnext/selling/doctype/sms_center/sms_center.json #: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.js:16 -#: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py:60 -#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.js:8 -#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py:71 +#: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py:166 +#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.js:16 +#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py:45 #: erpnext/selling/workspace/selling/selling.json #: erpnext/setup/doctype/sales_partner/sales_partner.json #: erpnext/stock/doctype/delivery_note/delivery_note.json @@ -45207,9 +45340,9 @@ msgstr "" #: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json #: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts_accounts_receivable.html:158 #: erpnext/accounts/report/accounts_receivable/accounts_receivable.html:137 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:125 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1296 -#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:109 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:136 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1304 +#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:120 #: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py:191 #: erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.js:80 #: erpnext/accounts/report/gross_profit/gross_profit.js:50 @@ -45403,12 +45536,6 @@ msgstr "" msgid "Sales Team" msgstr "" -#. Label of the sales_update_frequency (Select) field in DocType 'Selling -#. Settings' -#: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "Sales Update Frequency in Company and Project" -msgstr "" - #: erpnext/selling/report/sales_order_trends/sales_order_trends.py:56 msgid "Sales Value" msgstr "" @@ -45483,7 +45610,7 @@ msgstr "" msgid "Sample Size" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:4086 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:4088 msgid "Sample quantity {0} cannot be more than received quantity {1}" msgstr "" @@ -45537,7 +45664,7 @@ msgstr "" msgid "Scan Barcode" msgstr "" -#: erpnext/public/js/utils/serial_no_batch_selector.js:160 +#: erpnext/public/js/utils/serial_no_batch_selector.js:171 msgid "Scan Batch No" msgstr "" @@ -45553,7 +45680,7 @@ msgstr "" msgid "Scan Mode" msgstr "" -#: erpnext/public/js/utils/serial_no_batch_selector.js:145 +#: erpnext/public/js/utils/serial_no_batch_selector.js:156 msgid "Scan Serial No" msgstr "" @@ -45770,7 +45897,6 @@ msgid "Secondary Item Name" msgstr "" #. Label of the secondary_items (Table) field in DocType 'BOM' -#. Label of the secondary_items_tab (Tab Break) field in DocType 'BOM' #. Label of the secondary_items (Table) field in DocType 'Job Card' #. Label of the secondary_items_section (Tab Break) field in DocType 'Job Card' #. Label of the secondary_items (Table) field in DocType 'Subcontracting Inward @@ -45817,11 +45943,6 @@ msgstr "" msgid "Secretary" msgstr "" -#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:112 -#: erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py:90 -msgid "Section Code" -msgstr "" - #: erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts.py:177 #: erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts_with_account_number.py:301 msgid "Secured Loans" @@ -45860,11 +45981,11 @@ msgstr "" msgid "Select Attribute Values" msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:1278 +#: erpnext/selling/doctype/sales_order/sales_order.js:1276 msgid "Select BOM" msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:1255 +#: erpnext/selling/doctype/sales_order/sales_order.js:1253 msgid "Select BOM and Qty for Production" msgstr "" @@ -45886,7 +46007,7 @@ msgstr "" msgid "Select Brand..." msgstr "" -#: erpnext/edi/doctype/code_list/code_list_import.js:109 +#: erpnext/edi/doctype/code_list/code_list_import.js:110 msgid "Select Columns and Filters" msgstr "" @@ -45939,7 +46060,7 @@ msgid "Select Employees" msgstr "" #: erpnext/buying/doctype/purchase_order/purchase_order.js:198 -#: erpnext/selling/doctype/sales_order/sales_order.js:826 +#: erpnext/selling/doctype/sales_order/sales_order.js:824 msgid "Select Finished Good" msgstr "" @@ -45949,13 +46070,13 @@ msgstr "" #. Forecast' #: erpnext/manufacturing/doctype/master_production_schedule/master_production_schedule.json #: erpnext/manufacturing/doctype/sales_forecast/sales_forecast.json -#: erpnext/selling/doctype/sales_order/sales_order.js:1621 -#: erpnext/selling/doctype/sales_order/sales_order.js:1649 +#: erpnext/selling/doctype/sales_order/sales_order.js:1619 +#: erpnext/selling/doctype/sales_order/sales_order.js:1647 #: erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js:493 msgid "Select Items" msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:1507 +#: erpnext/selling/doctype/sales_order/sales_order.js:1505 msgid "Select Items based on Delivery Date" msgstr "" @@ -45966,7 +46087,7 @@ msgstr "" #. Label of the select_items_to_manufacture_section (Section Break) field in #. DocType 'Production Plan' #: erpnext/manufacturing/doctype/production_plan/production_plan.json -#: erpnext/selling/doctype/sales_order/sales_order.js:1307 +#: erpnext/selling/doctype/sales_order/sales_order.js:1305 msgid "Select Items to Manufacture" msgstr "" @@ -45997,7 +46118,7 @@ msgstr "" msgid "Select Possible Supplier" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:1115 +#: erpnext/manufacturing/doctype/work_order/work_order.js:1122 #: erpnext/stock/doctype/pick_list/pick_list.js:216 msgid "Select Quantity" msgstr "" @@ -46110,7 +46231,7 @@ msgstr "" msgid "Select company name first." msgstr "" -#: erpnext/controllers/accounts_controller.py:2989 +#: erpnext/controllers/accounts_controller.py:2992 msgid "Select finance book for the item {0} at row {1}" msgstr "" @@ -46131,7 +46252,7 @@ msgstr "" msgid "Select the Default Workstation where the Operation will be performed. This will be fetched in BOMs and Work Orders." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:1217 +#: erpnext/manufacturing/doctype/work_order/work_order.js:1224 msgid "Select the Item to be manufactured." msgstr "" @@ -46486,7 +46607,7 @@ msgstr "" #: erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.js:74 #: erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.py:114 #: erpnext/public/js/controllers/transaction.js:2944 -#: erpnext/public/js/utils/serial_no_batch_selector.js:421 +#: erpnext/public/js/utils/serial_no_batch_selector.js:432 #: erpnext/selling/doctype/installation_note_item/installation_note_item.json #: erpnext/stock/doctype/delivery_note_item/delivery_note_item.json #: erpnext/stock/doctype/packed_item/packed_item.json @@ -46542,7 +46663,7 @@ msgstr "" msgid "Serial No Ledger" msgstr "" -#: erpnext/public/js/utils/serial_no_batch_selector.js:259 +#: erpnext/public/js/utils/serial_no_batch_selector.js:270 msgid "Serial No Range" msgstr "" @@ -46611,7 +46732,7 @@ msgstr "" msgid "Serial No is mandatory for Item {0}" msgstr "" -#: erpnext/public/js/utils/serial_no_batch_selector.js:590 +#: erpnext/public/js/utils/serial_no_batch_selector.js:601 msgid "Serial No {0} already exists" msgstr "" @@ -46670,14 +46791,14 @@ msgstr "" #: erpnext/public/js/utils/barcode_scanner.js:292 #: erpnext/public/js/utils/serial_no_batch_selector.js:16 -#: erpnext/public/js/utils/serial_no_batch_selector.js:190 +#: erpnext/public/js/utils/serial_no_batch_selector.js:201 #: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.js:50 #: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:170 msgid "Serial Nos" msgstr "" #: erpnext/public/js/utils/serial_no_batch_selector.js:20 -#: erpnext/public/js/utils/serial_no_batch_selector.js:194 +#: erpnext/public/js/utils/serial_no_batch_selector.js:205 msgid "Serial Nos / Batch Nos" msgstr "" @@ -47208,12 +47329,6 @@ msgstr "" msgid "Set Grand Total to Default Payment Method" msgstr "" -#. Label of the set_zero_rate_for_expired_batch (Check) field in DocType -#. 'Selling Settings' -#: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "Set Incoming Rate as Zero for Expired Batch" -msgstr "" - #. Description of the 'Territory Targets' (Section Break) field in DocType #. 'Territory' #: erpnext/setup/doctype/territory/territory.json @@ -47298,7 +47413,7 @@ msgstr "" msgid "Set Source Warehouse" msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:1627 +#: erpnext/selling/doctype/sales_order/sales_order.js:1625 msgid "Set Supplier" msgstr "" @@ -47378,6 +47493,12 @@ msgstr "" msgid "Set fieldname from which you want to fetch the data from the parent form." msgstr "" +#. Label of the set_zero_rate_for_expired_batch (Check) field in DocType +#. 'Selling Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "Set incoming rate as zero for expired Batch" +msgstr "" + #: erpnext/manufacturing/doctype/bom/bom.js:1021 msgid "Set quantity of process loss item:" msgstr "" @@ -47394,7 +47515,7 @@ msgstr "" msgid "Set targets Item Group-wise for this Sales Person." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:1274 +#: erpnext/manufacturing/doctype/work_order/work_order.js:1281 msgid "Set the Planned Start Date (an Estimated Date at which you want the Production to begin)" msgstr "" @@ -47489,8 +47610,8 @@ msgstr "" msgid "Setting up company" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1217 -#: erpnext/manufacturing/doctype/work_order/work_order.py:1481 +#: erpnext/manufacturing/doctype/bom/bom.py:1218 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1497 msgid "Setting {0} is required" msgstr "" @@ -47740,11 +47861,11 @@ msgstr "" msgid "Shipping Address Template" msgstr "" -#: erpnext/controllers/accounts_controller.py:572 +#: erpnext/controllers/accounts_controller.py:573 msgid "Shipping Address does not belong to the {0}" msgstr "" -#: erpnext/accounts/doctype/shipping_rule/shipping_rule.py:129 +#: erpnext/accounts/doctype/shipping_rule/shipping_rule.py:134 msgid "Shipping Address does not have country, which is required for this Shipping Rule" msgstr "" @@ -47837,15 +47958,15 @@ msgstr "" msgid "Shipping Zipcode" msgstr "" -#: erpnext/accounts/doctype/shipping_rule/shipping_rule.py:133 +#: erpnext/accounts/doctype/shipping_rule/shipping_rule.py:138 msgid "Shipping rule not applicable for country {0} in Shipping Address" msgstr "" -#: erpnext/accounts/doctype/shipping_rule/shipping_rule.py:152 +#: erpnext/accounts/doctype/shipping_rule/shipping_rule.py:157 msgid "Shipping rule only applicable for Buying" msgstr "" -#: erpnext/accounts/doctype/shipping_rule/shipping_rule.py:147 +#: erpnext/accounts/doctype/shipping_rule/shipping_rule.py:152 msgid "Shipping rule only applicable for Selling" msgstr "" @@ -47945,14 +48066,14 @@ msgstr "" #. Label of the show_future_payments (Check) field in DocType 'Process #. Statement Of Accounts' #: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json -#: erpnext/accounts/report/accounts_payable/accounts_payable.js:130 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:147 -#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:120 +#: erpnext/accounts/report/accounts_payable/accounts_payable.js:141 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:158 +#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:131 msgid "Show Future Payments" msgstr "" -#: erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js:107 -#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:125 +#: erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js:118 +#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:136 msgid "Show GL Balance" msgstr "" @@ -47992,7 +48113,7 @@ msgstr "" msgid "Show Ledger View" msgstr "" -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:152 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:163 msgid "Show Linked Delivery Notes" msgstr "" @@ -48038,8 +48159,8 @@ msgstr "" #. Label of the show_remarks (Check) field in DocType 'Process Statement Of #. Accounts' #: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json -#: erpnext/accounts/report/accounts_payable/accounts_payable.js:125 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:162 +#: erpnext/accounts/report/accounts_payable/accounts_payable.js:136 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:173 #: erpnext/accounts/report/general_ledger/general_ledger.js:213 msgid "Show Remarks" msgstr "" @@ -48049,7 +48170,7 @@ msgstr "" msgid "Show Return Entries" msgstr "" -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:157 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:168 msgid "Show Sales Person" msgstr "" @@ -48209,7 +48330,7 @@ msgstr "" msgid "Since there is a process loss of {0} units for the finished good {1}, you should reduce the quantity by {0} units for the finished good {1} in the Items Table." msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:322 +#: erpnext/manufacturing/doctype/bom/bom.py:323 msgid "Since you have enabled 'Track Semi Finished Goods', at least one operation must have 'Is Final Finished Good' checked. For that set the FG / Semi FG Item as {0} against an operation." msgstr "" @@ -48243,7 +48364,7 @@ msgstr "" #. Label of the skip_material_transfer (Check) field in DocType 'Work Order #. Operation' -#: erpnext/manufacturing/doctype/work_order/work_order.js:375 +#: erpnext/manufacturing/doctype/work_order/work_order.js:380 #: erpnext/manufacturing/doctype/work_order_operation/work_order_operation.json #: erpnext/manufacturing/doctype/workstation/workstation.js:454 msgid "Skip Material Transfer" @@ -48310,7 +48431,7 @@ msgstr "" msgid "Solvency Ratios" msgstr "" -#: erpnext/controllers/accounts_controller.py:4344 +#: erpnext/controllers/accounts_controller.py:4350 msgid "Some required Company details are missing. You don't have permission to update them. Please contact your System Manager." msgstr "" @@ -48374,7 +48495,7 @@ msgstr "" msgid "Source Location" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:1025 +#: erpnext/manufacturing/doctype/work_order/work_order.js:1032 msgid "Source Manufacture Entry" msgstr "" @@ -48445,7 +48566,7 @@ msgstr "" msgid "Source Warehouse is mandatory for the Item {0}." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:300 +#: erpnext/manufacturing/doctype/work_order/work_order.py:304 msgid "Source Warehouse {0} must be same as Customer Warehouse {1} in the Subcontracting Inward Order." msgstr "" @@ -48610,7 +48731,7 @@ msgstr "" #: erpnext/setup/setup_wizard/operations/defaults_setup.py:70 #: erpnext/setup/setup_wizard/operations/install_fixtures.py:485 -#: erpnext/tests/utils.py:316 +#: erpnext/tests/utils.py:275 msgid "Standard Buying" msgstr "" @@ -48624,8 +48745,8 @@ msgstr "" #: erpnext/setup/setup_wizard/operations/defaults_setup.py:70 #: erpnext/setup/setup_wizard/operations/install_fixtures.py:493 -#: erpnext/stock/doctype/item/item.py:267 erpnext/tests/utils.py:324 -#: erpnext/tests/utils.py:2522 +#: erpnext/stock/doctype/item/item.py:267 erpnext/tests/utils.py:283 +#: erpnext/tests/utils.py:2504 msgid "Standard Selling" msgstr "" @@ -48989,7 +49110,7 @@ msgstr "" msgid "Stock Entry {0} has created" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1315 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1316 msgid "Stock Entry {0} is not submitted" msgstr "" @@ -49221,9 +49342,9 @@ msgstr "" #: erpnext/manufacturing/doctype/production_plan/production_plan.js:289 #: erpnext/manufacturing/doctype/production_plan/production_plan.js:297 #: erpnext/manufacturing/doctype/production_plan/production_plan.js:303 -#: erpnext/manufacturing/doctype/work_order/work_order.js:938 -#: erpnext/manufacturing/doctype/work_order/work_order.js:947 +#: erpnext/manufacturing/doctype/work_order/work_order.js:945 #: erpnext/manufacturing/doctype/work_order/work_order.js:954 +#: erpnext/manufacturing/doctype/work_order/work_order.js:961 #: erpnext/manufacturing/doctype/work_order/work_order_dashboard.py:14 #: erpnext/public/js/stock_reservation.js:12 #: erpnext/selling/doctype/sales_order/sales_order.js:109 @@ -49261,7 +49382,7 @@ msgstr "" #: erpnext/controllers/subcontracting_inward_controller.py:1018 #: erpnext/manufacturing/doctype/production_plan/production_plan.py:2245 -#: erpnext/manufacturing/doctype/work_order/work_order.py:2130 +#: erpnext/manufacturing/doctype/work_order/work_order.py:2146 #: erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py:1777 msgid "Stock Reservation Entries Created" msgstr "" @@ -49633,14 +49754,14 @@ msgstr "" msgid "Stop Reason" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1089 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1105 msgid "Stopped Work Order cannot be cancelled, Unstop it first to cancel" msgstr "" #: erpnext/setup/doctype/company/company.py:384 #: erpnext/setup/setup_wizard/operations/defaults_setup.py:33 #: erpnext/setup/setup_wizard/operations/install_fixtures.py:537 -#: erpnext/stock/doctype/item/item.py:304 erpnext/tests/utils.py:289 +#: erpnext/stock/doctype/item/item.py:304 erpnext/tests/utils.py:248 msgid "Stores" msgstr "" @@ -49884,7 +50005,7 @@ msgstr "" #. Label of a Link in the Subcontracting Workspace #. Label of a Workspace Sidebar Item #: erpnext/manufacturing/doctype/work_order/work_order.json -#: erpnext/selling/doctype/sales_order/sales_order.js:1013 +#: erpnext/selling/doctype/sales_order/sales_order.js:1011 #: erpnext/stock/doctype/stock_entry/stock_entry.json #: erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.json #: erpnext/subcontracting/doctype/subcontracting_inward_order/subcontracting_inward_order.json @@ -49921,12 +50042,6 @@ msgstr "" msgid "Subcontracting Inward Order Service Item" msgstr "" -#. Label of the section_break_zwh6 (Section Break) field in DocType 'Selling -#. Settings' -#: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "Subcontracting Inward Settings" -msgstr "" - #. Label of a Link in the Manufacturing Workspace #. Label of the subcontracting_order (Link) field in DocType 'Stock Entry' #. Option for the 'Voucher Type' (Select) field in DocType 'Stock Reservation @@ -50066,7 +50181,7 @@ msgid "Subdivision" msgstr "" #: erpnext/buying/doctype/purchase_order/purchase_order.py:920 -#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:1084 +#: erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py:1116 msgid "Submit Action Failed" msgstr "" @@ -50428,7 +50543,7 @@ msgstr "" #: erpnext/selling/doctype/customer/customer.js:253 #: erpnext/selling/doctype/party_specific_item/party_specific_item.json #: erpnext/selling/doctype/sales_order/sales_order.js:197 -#: erpnext/selling/doctype/sales_order/sales_order.js:1685 +#: erpnext/selling/doctype/sales_order/sales_order.js:1683 #: erpnext/selling/doctype/sales_order_item/sales_order_item.json #: erpnext/selling/doctype/sms_center/sms_center.json #: erpnext/setup/workspace/home/home.json @@ -50524,9 +50639,9 @@ msgstr "" #: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json #: erpnext/accounts/doctype/supplier_group_item/supplier_group_item.json #: erpnext/accounts/doctype/tax_rule/tax_rule.json -#: erpnext/accounts/report/accounts_payable/accounts_payable.js:108 -#: erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js:91 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1303 +#: erpnext/accounts/report/accounts_payable/accounts_payable.js:119 +#: erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js:102 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1311 #: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py:198 #: erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py:178 #: erpnext/accounts/report/purchase_register/purchase_register.js:27 @@ -50572,7 +50687,7 @@ msgstr "" #. Label of the bill_date (Date) field in DocType 'Purchase Invoice' #: erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.json #: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json -#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:145 +#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:232 msgid "Supplier Invoice Date" msgstr "" @@ -50583,7 +50698,7 @@ msgstr "" #: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json #: erpnext/accounts/report/general_ledger/general_ledger.html:110 #: erpnext/accounts/report/general_ledger/general_ledger.py:789 -#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:139 +#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:226 msgid "Supplier Invoice No" msgstr "" @@ -50630,7 +50745,7 @@ msgstr "" #. Label of the supplier_name (Data) field in DocType 'Purchase Receipt' #. Label of the supplier_name (Data) field in DocType 'Stock Entry' #: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1220 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1227 #: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py:156 #: erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py:196 #: erpnext/accounts/report/purchase_register/purchase_register.py:177 @@ -50755,7 +50870,7 @@ msgstr "" msgid "Supplier Reference" msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:1709 +#: erpnext/selling/doctype/sales_order/sales_order.js:1707 msgid "Supplier Required" msgstr "" @@ -50849,7 +50964,7 @@ msgstr "" msgid "Supplier delivers to Customer" msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:1708 +#: erpnext/selling/doctype/sales_order/sales_order.js:1706 msgid "Supplier is required for all selected Items" msgstr "" @@ -51000,7 +51115,7 @@ msgstr "" msgid "System will fetch all the entries if limit value is zero." msgstr "" -#: erpnext/controllers/accounts_controller.py:2223 +#: erpnext/controllers/accounts_controller.py:2226 msgid "System will not check over billing since amount for Item {0} in {1} is zero" msgstr "" @@ -51172,7 +51287,7 @@ msgstr "" msgid "Target Warehouse Address Link" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:245 +#: erpnext/manufacturing/doctype/work_order/work_order.py:249 msgid "Target Warehouse Reservation Error" msgstr "" @@ -51180,7 +51295,7 @@ msgstr "" msgid "Target Warehouse for Finished Good must be same as Finished Good Warehouse {1} in Work Order {2} linked to the Subcontracting Inward Order." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:777 +#: erpnext/manufacturing/doctype/work_order/work_order.py:793 msgid "Target Warehouse is required before Submit" msgstr "" @@ -51188,7 +51303,7 @@ msgstr "" msgid "Target Warehouse is set for some items but the customer is not an internal customer." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:316 +#: erpnext/manufacturing/doctype/work_order/work_order.py:320 msgid "Target Warehouse {0} must be same as Delivery Warehouse {1} in the Subcontracting Inward Order Item." msgstr "" @@ -51286,8 +51401,8 @@ msgstr "" #. Label of the amount (Currency) field in DocType 'Item Wise Tax Detail' #: erpnext/accounts/doctype/item_wise_tax_detail/item_wise_tax_detail.json -#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:163 -#: erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py:115 +#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:244 +#: erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py:91 msgid "Tax Amount" msgstr "" @@ -51392,7 +51507,7 @@ msgstr "" msgid "Tax Category" msgstr "" -#: erpnext/controllers/buying_controller.py:258 +#: erpnext/controllers/buying_controller.py:262 msgid "Tax Category has been changed to \"Total\" because all the Items are non-stock items" msgstr "" @@ -51426,8 +51541,8 @@ msgstr "" #: erpnext/accounts/report/purchase_register/purchase_register.py:192 #: erpnext/accounts/report/sales_register/sales_register.py:215 #: erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.js:67 -#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:118 -#: erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py:75 +#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:205 +#: erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py:57 #: erpnext/selling/doctype/sales_order/sales_order.json #: erpnext/stock/doctype/delivery_note/delivery_note.json msgid "Tax Id" @@ -51465,8 +51580,8 @@ msgstr "" msgid "Tax Rate" msgstr "" -#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:151 -#: erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py:103 +#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:237 +#: erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py:84 msgid "Tax Rate %" msgstr "" @@ -51555,6 +51670,8 @@ msgstr "" #: erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json #: erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.json #: erpnext/accounts/doctype/tax_withholding_entry/tax_withholding_entry.json +#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:199 +#: erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py:72 #: erpnext/accounts/workspace/invoicing/invoicing.json #: erpnext/buying/doctype/supplier/supplier.json #: erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.json @@ -51664,8 +51781,8 @@ msgstr "" #. Label of the taxable_amount (Currency) field in DocType 'Item Wise Tax #. Detail' #: erpnext/accounts/doctype/item_wise_tax_detail/item_wise_tax_detail.json -#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:157 -#: erpnext/controllers/taxes_and_totals.py:1252 +#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:239 +#: erpnext/controllers/taxes_and_totals.py:1266 msgid "Taxable Amount" msgstr "" @@ -51875,7 +51992,7 @@ msgstr "" msgid "Template Item" msgstr "" -#: erpnext/stock/get_item_details.py:340 +#: erpnext/stock/get_item_details.py:342 msgid "Template Item Selected" msgstr "" @@ -52097,9 +52214,9 @@ msgstr "" #: erpnext/accounts/doctype/promotional_scheme/promotional_scheme.json #: erpnext/accounts/doctype/sales_invoice/sales_invoice.json #: erpnext/accounts/doctype/territory_item/territory_item.json -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:131 -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1287 -#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:97 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:142 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1295 +#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:108 #: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py:182 #: erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.js:68 #: erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py:169 @@ -52128,9 +52245,9 @@ msgstr "" #: erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py:87 #: erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py:42 #: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.js:47 -#: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py:45 +#: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py:160 #: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.js:59 -#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py:39 +#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py:29 #: erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.js:46 #: erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.py:61 #: erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.js:59 @@ -52250,7 +52367,7 @@ msgstr "" msgid "The Pick List having Stock Reservation Entries cannot be updated. If you need to make changes, we recommend canceling the existing Stock Reservation Entries before updating the Pick List." msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:2820 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:2822 msgid "The Process Loss Qty has reset as per job cards Process Loss Qty" msgstr "" @@ -52308,7 +52425,7 @@ msgstr "" msgid "The current POS opening entry is outdated. Please close it and create a new one." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:1222 +#: erpnext/manufacturing/doctype/work_order/work_order.js:1229 msgid "The default BOM for that item will be fetched by the system. You can also change the BOM." msgstr "" @@ -52341,6 +52458,11 @@ msgstr "" msgid "The fields From Shareholder and To Shareholder cannot be blank" msgstr "" +#. Description of the 'Item to Manufacture' (Link) field in DocType 'BOM' +#: erpnext/manufacturing/doctype/bom/bom.json +msgid "The final item that will be produced using this BOM." +msgstr "" + #: erpnext/accounts/notification/notification_for_new_fiscal_year/notification_for_new_fiscal_year.html:40 msgid "The fiscal year has been automatically created in a Disabled state to maintain consistency with the previous fiscal year's status." msgstr "" @@ -52365,7 +52487,7 @@ msgstr "" msgid "The following batches are expired, please restock them:
        {0}" msgstr "" -#: erpnext/controllers/accounts_controller.py:423 +#: erpnext/controllers/accounts_controller.py:424 msgid "The following cancelled repost entries exist for {0}:

        {1}

        Kindly delete these entries before continuing." msgstr "" @@ -52395,6 +52517,12 @@ msgstr "" msgid "The following {0} were created: {1}" msgstr "" +#. Description of the 'How often should sales data be updated in +#. Company/Project?' (Select) field in DocType 'Selling Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "The frequency at which project progress and company transaction details will be updated. Set it to daily or monthly if you post a lot of transactions." +msgstr "" + #. Description of the 'Gross Weight' (Float) field in DocType 'Packing Slip' #: erpnext/stock/doctype/packing_slip/packing_slip.json msgid "The gross weight of the package. Usually net weight + packaging material weight. (for print)" @@ -52404,7 +52532,7 @@ msgstr "" msgid "The holiday on {0} is not between From Date and To Date" msgstr "" -#: erpnext/controllers/buying_controller.py:1248 +#: erpnext/controllers/buying_controller.py:1255 msgid "The item {item} is not marked as {type_of} item. You can enable it as {type_of} item from its Item master." msgstr "" @@ -52412,7 +52540,7 @@ msgstr "" msgid "The items {0} and {1} are present in the following {2} :" msgstr "" -#: erpnext/controllers/buying_controller.py:1241 +#: erpnext/controllers/buying_controller.py:1248 msgid "The items {items} are not marked as {type_of} item. You can enable them as {type_of} item from their Item masters." msgstr "" @@ -52458,7 +52586,7 @@ msgstr "" msgid "The original invoice should be consolidated before or along with the return invoice." msgstr "" -#: erpnext/controllers/accounts_controller.py:202 +#: erpnext/controllers/accounts_controller.py:203 msgid "The outstanding amount {0} in {1} is lesser than {2}. Updating the outstanding to this invoice." msgstr "" @@ -52581,11 +52709,15 @@ msgstr "" msgid "The total Issue / Transfer quantity {0} in Material Request {1} cannot be greater than requested quantity {2} for Item {3}" msgstr "" +#: erpnext/edi/doctype/code_list/code_list_import.py:43 +msgid "The uploaded file could not be parsed as a genericode XML document." +msgstr "" + #: erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py:154 msgid "The uploaded file does not appear to be in valid MT940 format." msgstr "" -#: erpnext/edi/doctype/code_list/code_list_import.py:54 +#: erpnext/edi/doctype/code_list/code_list_import.py:40 msgid "The uploaded file does not match the selected Code List." msgstr "" @@ -52613,15 +52745,15 @@ msgstr "" msgid "The value {0} is already assigned to an existing Item {1}." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:1250 +#: erpnext/manufacturing/doctype/work_order/work_order.js:1257 msgid "The warehouse where you store finished Items before they are shipped." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:1243 +#: erpnext/manufacturing/doctype/work_order/work_order.js:1250 msgid "The warehouse where you store your raw materials. Each required item can have a separate source warehouse. Group warehouse also can be selected as source warehouse. On submission of the Work Order, the raw materials will be reserved in these warehouses for production usage." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:1255 +#: erpnext/manufacturing/doctype/work_order/work_order.js:1262 msgid "The warehouse where your Items will be transferred when you begin production. Group Warehouse can also be selected as a Work in Progress warehouse." msgstr "" @@ -52693,7 +52825,7 @@ msgstr "" msgid "There can only be 1 Account per Company in {0} {1}" msgstr "" -#: erpnext/accounts/doctype/shipping_rule/shipping_rule.py:81 +#: erpnext/accounts/doctype/shipping_rule/shipping_rule.py:86 msgid "There can only be one Shipping Rule Condition with 0 or blank value for \"To Value\"" msgstr "" @@ -52772,6 +52904,12 @@ msgstr "" msgid "This action will unlink this account from any external service integrating ERPNext with your bank accounts. It cannot be undone. Are you certain ?" msgstr "" +#. Description of the 'Allow Sales Order creation for expired Quotation' +#. (Check) field in DocType 'Selling Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "This allows creation of sales orders from quotations that have passed their expiration date, providing flexibility in processing orders despite outdated quotes." +msgstr "" + #: erpnext/assets/doctype/asset/asset.py:431 msgid "This asset category is marked as non-depreciable. Please disable depreciation calculation or choose a different category." msgstr "" @@ -52827,7 +52965,7 @@ msgstr "" msgid "This is a preview of the email to be sent. A PDF of the document will automatically be attached with the email." msgstr "" -#: erpnext/accounts/doctype/account/account.js:35 +#: erpnext/accounts/doctype/account/account.js:45 msgid "This is a root account and cannot be edited." msgstr "" @@ -52875,7 +53013,7 @@ msgstr "" msgid "This is done to handle accounting for cases when Purchase Receipt is created after Purchase Invoice" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:1236 +#: erpnext/manufacturing/doctype/work_order/work_order.js:1243 msgid "This is enabled by default. If you want to plan materials for sub-assemblies of the Item you're manufacturing leave this enabled. If you plan and manufacture the sub-assemblies separately, you can disable this checkbox." msgstr "" @@ -53201,7 +53339,7 @@ msgstr "" msgid "To Currency" msgstr "" -#: erpnext/controllers/accounts_controller.py:622 +#: erpnext/controllers/accounts_controller.py:623 #: erpnext/setup/doctype/holiday_list/holiday_list.py:121 msgid "To Date cannot be before From Date" msgstr "" @@ -53475,7 +53613,7 @@ msgid "To include sub-assembly costs and secondary items in Finished Goods on a msgstr "" #: erpnext/accounts/doctype/payment_entry/payment_entry.py:2247 -#: erpnext/controllers/accounts_controller.py:3247 +#: erpnext/controllers/accounts_controller.py:3250 msgid "To include tax in row {0} in Item rate, taxes in rows {1} must also be included" msgstr "" @@ -53508,7 +53646,7 @@ msgstr "" msgid "To use a different finance book, please uncheck 'Include Default FB Assets'" msgstr "" -#: erpnext/accounts/doctype/financial_report_template/financial_report_engine.py:705 +#: erpnext/accounts/doctype/financial_report_template/financial_report_engine.py:709 #: erpnext/accounts/report/financial_statements.py:621 #: erpnext/accounts/report/general_ledger/general_ledger.py:310 #: erpnext/accounts/report/trial_balance/trial_balance.py:310 @@ -53586,8 +53724,8 @@ msgstr "" msgid "Total (Company Currency)" msgstr "" -#: erpnext/accounts/report/balance_sheet/balance_sheet.py:126 #: erpnext/accounts/report/balance_sheet/balance_sheet.py:127 +#: erpnext/accounts/report/balance_sheet/balance_sheet.py:128 msgid "Total (Credit)" msgstr "" @@ -53679,7 +53817,7 @@ msgstr "" msgid "Total Applicable Charges in Purchase Receipt Items table must be same as Total Taxes and Charges" msgstr "" -#: erpnext/accounts/report/balance_sheet/balance_sheet.py:216 +#: erpnext/accounts/report/balance_sheet/balance_sheet.py:217 msgid "Total Asset" msgstr "" @@ -53753,7 +53891,7 @@ msgstr "" #: erpnext/accounts/doctype/pos_invoice/pos_invoice.json #: erpnext/accounts/doctype/sales_invoice/sales_invoice.json #: erpnext/selling/doctype/sales_order/sales_order.json -#: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py:73 +#: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py:170 #: erpnext/stock/doctype/delivery_note/delivery_note.json msgid "Total Commission" msgstr "" @@ -53812,7 +53950,7 @@ msgstr "" msgid "Total Credit" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:342 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:343 msgid "Total Credit/ Debit Amount should be same as linked Journal Entry" msgstr "" @@ -53821,7 +53959,7 @@ msgstr "" msgid "Total Debit" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:936 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:937 msgid "Total Debit must be equal to Total Credit. The difference is {0}" msgstr "" @@ -53833,7 +53971,7 @@ msgstr "" msgid "Total Demand (Past Data)" msgstr "" -#: erpnext/accounts/report/balance_sheet/balance_sheet.py:223 +#: erpnext/accounts/report/balance_sheet/balance_sheet.py:224 msgid "Total Equity" msgstr "" @@ -53842,11 +53980,11 @@ msgstr "" msgid "Total Estimated Distance" msgstr "" -#: erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py:122 +#: erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py:123 msgid "Total Expense" msgstr "" -#: erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py:118 +#: erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py:119 msgid "Total Expense This Year" msgstr "" @@ -53884,11 +54022,11 @@ msgstr "" msgid "Total Holidays" msgstr "" -#: erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py:121 +#: erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py:122 msgid "Total Income" msgstr "" -#: erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py:117 +#: erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py:118 msgid "Total Income This Year" msgstr "" @@ -53930,7 +54068,7 @@ msgstr "" msgid "Total Ledgers" msgstr "" -#: erpnext/accounts/report/balance_sheet/balance_sheet.py:219 +#: erpnext/accounts/report/balance_sheet/balance_sheet.py:220 msgid "Total Liability" msgstr "" @@ -54035,7 +54173,7 @@ msgstr "" msgid "Total Paid Amount" msgstr "" -#: erpnext/controllers/accounts_controller.py:2795 +#: erpnext/controllers/accounts_controller.py:2798 msgid "Total Payment Amount in Payment Schedule must be equal to Grand / Rounded Total" msgstr "" @@ -54173,7 +54311,7 @@ msgstr "" msgid "Total Tax" msgstr "" -#: erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py:109 +#: erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py:86 msgid "Total Taxable Amount" msgstr "" @@ -54373,11 +54511,11 @@ msgstr "" msgid "Total {0} for all items is zero, may be you should change 'Distribute Charges Based On'" msgstr "" -#: erpnext/controllers/trends.py:23 erpnext/controllers/trends.py:30 +#: erpnext/controllers/trends.py:25 erpnext/controllers/trends.py:32 msgid "Total(Amt)" msgstr "" -#: erpnext/controllers/trends.py:23 erpnext/controllers/trends.py:30 +#: erpnext/controllers/trends.py:25 erpnext/controllers/trends.py:32 msgid "Total(Qty)" msgstr "" @@ -54573,7 +54711,7 @@ msgstr "" #. Label of the transaction_type (Data) field in DocType 'Bank Transaction' #: erpnext/accounts/doctype/bank_transaction/bank_transaction.json #: erpnext/accounts/report/calculated_discount_mismatch/calculated_discount_mismatch.py:38 -#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:187 +#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:259 msgid "Transaction Type" msgstr "" @@ -55022,7 +55160,7 @@ msgstr "" #: erpnext/selling/doctype/delivery_schedule_item/delivery_schedule_item.json #: erpnext/selling/doctype/product_bundle_item/product_bundle_item.json #: erpnext/selling/doctype/quotation_item/quotation_item.json -#: erpnext/selling/doctype/sales_order/sales_order.js:1678 +#: erpnext/selling/doctype/sales_order/sales_order.js:1676 #: erpnext/selling/doctype/sales_order_item/sales_order_item.json #: erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py:43 #: erpnext/selling/report/sales_analytics/sales_analytics.py:138 @@ -55112,7 +55250,7 @@ msgstr "" msgid "UOM Name" msgstr "" -#: erpnext/stock/doctype/stock_entry/stock_entry.py:4008 +#: erpnext/stock/doctype/stock_entry/stock_entry.py:4010 msgid "UOM conversion factor required for UOM: {0} in Item: {1}" msgstr "" @@ -55189,7 +55327,7 @@ msgstr "" msgid "Unable to find score starting at {0}. You need to have standing scores covering 0 to 100" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1047 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1063 msgid "Unable to find the time slot in the next {0} days for the operation {1}. Please increase the 'Capacity Planning For (Days)' in the {2}." msgstr "" @@ -55218,8 +55356,8 @@ msgstr "" msgid "Unblock Invoice" msgstr "" -#: erpnext/accounts/report/balance_sheet/balance_sheet.py:83 #: erpnext/accounts/report/balance_sheet/balance_sheet.py:84 +#: erpnext/accounts/report/balance_sheet/balance_sheet.py:85 #: erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py:90 #: erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py:91 msgid "Unclosed Fiscal Years Profit / Loss (Credit)" @@ -55275,7 +55413,12 @@ msgstr "" msgid "Unit" msgstr "" -#: erpnext/controllers/accounts_controller.py:4074 +#. Label of the uom (Link) field in DocType 'BOM' +#: erpnext/manufacturing/doctype/bom/bom.json +msgid "Unit Of Measure" +msgstr "" + +#: erpnext/controllers/accounts_controller.py:4080 msgid "Unit Price" msgstr "" @@ -55426,7 +55569,7 @@ msgstr "" msgid "Unreconciled Entries" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:945 +#: erpnext/manufacturing/doctype/work_order/work_order.js:952 #: erpnext/selling/doctype/sales_order/sales_order.js:122 #: erpnext/stock/doctype/pick_list/pick_list.js:158 #: erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js:193 @@ -55510,11 +55653,11 @@ msgstr "" msgid "Upcoming Calendar Events " msgstr "" -#: erpnext/accounts/doctype/account/account.js:52 +#: erpnext/accounts/doctype/account/account.js:62 msgid "Update Account Name / Number" msgstr "" -#: erpnext/accounts/doctype/account/account.js:158 +#: erpnext/accounts/doctype/account/account.js:176 msgid "Update Account Number / Name" msgstr "" @@ -55637,7 +55780,7 @@ msgstr "" #: erpnext/public/js/utils.js:946 #: erpnext/selling/doctype/quotation/quotation.js:135 #: erpnext/selling/doctype/sales_order/sales_order.js:90 -#: erpnext/selling/doctype/sales_order/sales_order.js:948 +#: erpnext/selling/doctype/sales_order/sales_order.js:946 msgid "Update Items" msgstr "" @@ -55647,7 +55790,7 @@ msgstr "" #. Invoice' #: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json #: erpnext/accounts/doctype/sales_invoice/sales_invoice.json -#: erpnext/controllers/accounts_controller.py:195 +#: erpnext/controllers/accounts_controller.py:196 msgid "Update Outstanding for Self" msgstr "" @@ -55724,7 +55867,7 @@ msgstr "" msgid "Updated via 'Time Log' (In Minutes)" msgstr "" -#: erpnext/accounts/doctype/account_category/account_category.py:54 +#: erpnext/accounts/doctype/account_category/account_category.py:55 msgid "Updated {0} Financial Report Row(s) with new category name" msgstr "" @@ -55736,7 +55879,7 @@ msgstr "" msgid "Updating Variants..." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:1198 +#: erpnext/manufacturing/doctype/work_order/work_order.js:1205 msgid "Updating Work Order status" msgstr "" @@ -55869,12 +56012,6 @@ msgstr "" msgid "Use Posting Datetime for Naming Documents" msgstr "" -#. Label of the fallback_to_default_price_list (Check) field in DocType -#. 'Selling Settings' -#: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "Use Prices from Default Price List as Fallback" -msgstr "" - #. Label of the use_serial_batch_fields (Check) field in DocType 'Stock #. Settings' #: erpnext/stock/doctype/stock_settings/stock_settings.json @@ -55937,6 +56074,12 @@ msgstr "" msgid "Use for Shopping Cart" msgstr "" +#. Label of the fallback_to_default_price_list (Check) field in DocType +#. 'Selling Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "Use prices from Default Price List as fallback" +msgstr "" + #. Label of the used (Int) field in DocType 'Coupon Code' #: erpnext/accounts/doctype/coupon_code/coupon_code.json msgid "Used" @@ -55964,7 +56107,6 @@ msgstr "" #. Label of the user_remark (Small Text) field in DocType 'Journal Entry' #. Label of the user_remark (Small Text) field in DocType 'Journal Entry #. Account' -#: erpnext/accounts/doctype/journal_entry/journal_entry.js:651 #: erpnext/accounts/doctype/journal_entry/journal_entry.json #: erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json msgid "User Remark" @@ -56185,17 +56327,17 @@ msgstr "" msgid "Validate Pricing Rule" msgstr "" -#. Label of the validate_selling_price (Check) field in DocType 'Selling -#. Settings' -#: erpnext/selling/doctype/selling_settings/selling_settings.json -msgid "Validate Selling Price for Item Against Purchase Rate or Valuation Rate" -msgstr "" - #. Label of the validate_stock_on_save (Check) field in DocType 'POS Profile' #: erpnext/accounts/doctype/pos_profile/pos_profile.json msgid "Validate Stock on Save" msgstr "" +#. Label of the validate_selling_price (Check) field in DocType 'Selling +#. Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "Validate selling price for Item against purchase or valuation rate" +msgstr "" + #. Label of the validity_details_section (Section Break) field in DocType #. 'Lower Deduction Certificate' #: erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.json @@ -56324,7 +56466,7 @@ msgid "Valuation rate for the item as per Sales Invoice (Only for Internal Trans msgstr "" #: erpnext/accounts/doctype/payment_entry/payment_entry.py:2271 -#: erpnext/controllers/accounts_controller.py:3271 +#: erpnext/controllers/accounts_controller.py:3274 msgid "Valuation type charges can not be marked as Inclusive" msgstr "" @@ -56826,7 +56968,7 @@ msgstr "" #: erpnext/accounts/doctype/repost_accounting_ledger_items/repost_accounting_ledger_items.json #: erpnext/accounts/doctype/repost_payment_ledger_items/repost_payment_ledger_items.json #: erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.json -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1242 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1250 #: erpnext/accounts/report/general_and_payment_ledger_comparison/general_and_payment_ledger_comparison.js:56 #: erpnext/accounts/report/general_and_payment_ledger_comparison/general_and_payment_ledger_comparison.py:221 #: erpnext/accounts/report/general_ledger/general_ledger.js:49 @@ -56899,7 +57041,7 @@ msgstr "" #: erpnext/accounts/doctype/repost_payment_ledger/repost_payment_ledger.json #: erpnext/accounts/doctype/repost_payment_ledger_items/repost_payment_ledger_items.json #: erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.json -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1240 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1248 #: erpnext/accounts/report/general_and_payment_ledger_comparison/general_and_payment_ledger_comparison.py:212 #: erpnext/accounts/report/general_ledger/general_ledger.py:736 #: erpnext/accounts/report/invalid_ledger_entries/invalid_ledger_entries.py:31 @@ -57132,7 +57274,7 @@ msgstr "" msgid "Warehouse {0} does not exist" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:242 +#: erpnext/manufacturing/doctype/work_order/work_order.py:246 msgid "Warehouse {0} is not allowed for Sales Order {1}, it should be {2}" msgstr "" @@ -57185,8 +57327,8 @@ msgstr "" #. Expense' (Select) field in DocType 'Budget' #. Option for the 'Action If Same Rate is Not Maintained' (Select) field in #. DocType 'Buying Settings' -#. Option for the 'Action if Same Rate is Not Maintained Throughout Sales -#. Cycle' (Select) field in DocType 'Selling Settings' +#. Option for the 'Action if same rate is not maintained throughout sales +#. cycle' (Select) field in DocType 'Selling Settings' #. Option for the 'Action If Quality Inspection Is Not Submitted' (Select) #. field in DocType 'Stock Settings' #. Option for the 'Action If Quality Inspection Is Rejected' (Select) field in @@ -57233,6 +57375,12 @@ msgstr "" msgid "Warn for new Request for Quotations" msgstr "" +#. Description of the 'Maintain same rate throughout sales cycle' (Check) field +#. in DocType 'Selling Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "Warn or stop if Item rate is changed in Delivery Notes and Sales Invoices generated from a Sales Order." +msgstr "" + #: erpnext/projects/doctype/timesheet_detail/timesheet_detail.py:134 msgid "Warning - Row {0}: Billing Hours are more than Actual Hours" msgstr "" @@ -57249,7 +57397,7 @@ msgstr "" msgid "Warning: Account changed for warehouse" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1321 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1322 msgid "Warning: Another {0} # {1} exists against stock entry {2}" msgstr "" @@ -57257,7 +57405,7 @@ msgstr "" msgid "Warning: Material Requested Qty is less than Minimum Order Qty" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1466 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1482 msgid "Warning: Quantity exceeds maximum producible quantity based on quantity of raw materials received through the Subcontracting Inward Order {0}." msgstr "" @@ -57351,7 +57499,7 @@ msgstr "" msgid "Wavelength In Megametres" msgstr "" -#: erpnext/controllers/accounts_controller.py:190 +#: erpnext/controllers/accounts_controller.py:191 msgid "We can see {0} is made against {1}. If you want {1}'s outstanding to be updated, uncheck the '{2}' checkbox." msgstr "" @@ -57528,6 +57676,12 @@ msgstr "" msgid "When creating an Item, entering a value for this field will automatically create an Item Price at the backend." msgstr "" +#. Description of the 'Enable cut-off date on creating bulk Delivery Notes' +#. (Check) field in DocType 'Selling Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "When enabled, it adds a cutoff date filter to Delivery Notes created in bulk from Sales Orders. This allows you to process orders only with a transaction date up to the specified cutoff date, which is useful for period-end processing and batch fulfillment." +msgstr "" + #: erpnext/stock/doctype/stock_entry/stock_entry.py:304 msgid "When there are multiple finished goods ({0}) in a Repack stock entry, the basic rate for all finished goods must be set manually. To set rate manually, enable the checkbox 'Set Basic Rate Manually' in the respective finished good row." msgstr "" @@ -57606,7 +57760,7 @@ msgstr "" msgid "Withholding Date" msgstr "" -#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:206 +#: erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py:278 msgid "Withholding Document" msgstr "" @@ -57680,7 +57834,7 @@ msgstr "" #: erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.js:29 #: erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.py:104 #: erpnext/manufacturing/workspace/manufacturing/manufacturing.json -#: erpnext/selling/doctype/sales_order/sales_order.js:1058 +#: erpnext/selling/doctype/sales_order/sales_order.js:1056 #: erpnext/stock/doctype/material_request/material_request.js:216 #: erpnext/stock/doctype/material_request/material_request.json #: erpnext/stock/doctype/material_request/material_request.py:871 @@ -57762,16 +57916,16 @@ msgstr "" msgid "Work Order cannot be created for following reason:
        {0}" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:1410 +#: erpnext/manufacturing/doctype/work_order/work_order.py:1426 msgid "Work Order cannot be raised against a Item Template" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:2486 -#: erpnext/manufacturing/doctype/work_order/work_order.py:2566 +#: erpnext/manufacturing/doctype/work_order/work_order.py:2502 +#: erpnext/manufacturing/doctype/work_order/work_order.py:2582 msgid "Work Order has been {0}" msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:1241 +#: erpnext/selling/doctype/sales_order/sales_order.js:1239 msgid "Work Order not created" msgstr "" @@ -57792,7 +57946,7 @@ msgstr "" msgid "Work Orders" msgstr "" -#: erpnext/selling/doctype/sales_order/sales_order.js:1334 +#: erpnext/selling/doctype/sales_order/sales_order.js:1332 msgid "Work Orders Created: {0}" msgstr "" @@ -57813,7 +57967,7 @@ msgstr "" msgid "Work-in-Progress Warehouse" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:775 +#: erpnext/manufacturing/doctype/work_order/work_order.py:791 msgid "Work-in-Progress Warehouse is required before Submit" msgstr "" @@ -57861,7 +58015,7 @@ msgstr "" #: erpnext/manufacturing/doctype/bom_operation/bom_operation.json #: erpnext/manufacturing/doctype/bom_website_operation/bom_website_operation.json #: erpnext/manufacturing/doctype/job_card/job_card.json -#: erpnext/manufacturing/doctype/work_order/work_order.js:339 +#: erpnext/manufacturing/doctype/work_order/work_order.js:344 #: erpnext/manufacturing/doctype/work_order_operation/work_order_operation.json #: erpnext/manufacturing/doctype/workstation/workstation.json #: erpnext/manufacturing/report/bom_operations_time/bom_operations_time.js:35 @@ -58105,15 +58259,15 @@ msgstr "" msgid "Year start date or end date is overlapping with {0}. To avoid please set company" msgstr "" -#: erpnext/edi/doctype/code_list/code_list_import.js:29 +#: erpnext/edi/doctype/code_list/code_list_import.js:30 msgid "You are importing data for the code list:" msgstr "" -#: erpnext/controllers/accounts_controller.py:3871 +#: erpnext/controllers/accounts_controller.py:3877 msgid "You are not allowed to update as per the conditions set in {} Workflow." msgstr "" -#: erpnext/accounts/general_ledger.py:810 +#: erpnext/accounts/general_ledger.py:811 msgid "You are not authorized to add or update entries before {0}" msgstr "" @@ -58145,7 +58299,7 @@ msgstr "" msgid "You can change the parent account to a Balance Sheet account or select a different account." msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:712 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:713 msgid "You can not enter current voucher in 'Against Journal Entry' column" msgstr "" @@ -58170,7 +58324,7 @@ msgstr "" msgid "You can set it as a machine name or operation type. For example, stiching machine 12" msgstr "" -#: erpnext/controllers/accounts_controller.py:211 +#: erpnext/controllers/accounts_controller.py:212 msgid "You can use {0} to reconcile against {1} later." msgstr "" @@ -58194,15 +58348,15 @@ msgstr "" msgid "You cannot create a {0} within the closed Accounting Period {1}" msgstr "" -#: erpnext/accounts/general_ledger.py:182 +#: erpnext/accounts/general_ledger.py:183 msgid "You cannot create or cancel any accounting entries with in the closed Accounting Period {0}" msgstr "" -#: erpnext/accounts/general_ledger.py:830 +#: erpnext/accounts/general_ledger.py:831 msgid "You cannot create/amend any accounting entries till this date." msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:945 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:946 msgid "You cannot credit and debit same account at the same time" msgstr "" @@ -58250,7 +58404,7 @@ msgstr "" msgid "You do not have permission to edit this document" msgstr "" -#: erpnext/controllers/accounts_controller.py:3847 +#: erpnext/controllers/accounts_controller.py:3853 msgid "You do not have permissions to {} items in a {}." msgstr "" @@ -58262,15 +58416,15 @@ msgstr "" msgid "You don't have enough points to redeem." msgstr "" -#: erpnext/controllers/accounts_controller.py:4419 +#: erpnext/controllers/accounts_controller.py:4425 msgid "You don't have permission to create a Company Address. Please contact your System Manager." msgstr "" -#: erpnext/controllers/accounts_controller.py:4399 +#: erpnext/controllers/accounts_controller.py:4405 msgid "You don't have permission to update Company details. Please contact your System Manager." msgstr "" -#: erpnext/controllers/accounts_controller.py:4393 +#: erpnext/controllers/accounts_controller.py:4399 msgid "You don't have permission to update this document. Please contact your System Manager." msgstr "" @@ -58314,7 +58468,7 @@ msgstr "" msgid "You need to cancel POS Closing Entry {} to be able to cancel this document." msgstr "" -#: erpnext/controllers/accounts_controller.py:3222 +#: erpnext/controllers/accounts_controller.py:3225 msgid "You selected the account group {1} as {2} Account in row {0}. Please select a single account." msgstr "" @@ -58369,6 +58523,12 @@ msgstr "" msgid "Zero quantity" msgstr "" +#. Label of the section_break_zero_qty (Section Break) field in DocType +#. 'Selling Settings' +#: erpnext/selling/doctype/selling_settings/selling_settings.json +msgid "Zero-Quantity Line Items" +msgstr "" + #. Label of the zip_file (Attach) field in DocType 'Import Supplier Invoice' #: erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.json msgid "Zip File" @@ -58386,15 +58546,15 @@ msgstr "" msgid "after" msgstr "" -#: erpnext/edi/doctype/code_list/code_list_import.js:57 +#: erpnext/edi/doctype/code_list/code_list_import.js:58 msgid "as Code" msgstr "" -#: erpnext/edi/doctype/code_list/code_list_import.js:73 +#: erpnext/edi/doctype/code_list/code_list_import.js:74 msgid "as Description" msgstr "" -#: erpnext/edi/doctype/code_list/code_list_import.js:48 +#: erpnext/edi/doctype/code_list/code_list_import.js:49 msgid "as Title" msgstr "" @@ -58414,7 +58574,7 @@ msgstr "" msgid "based_on" msgstr "" -#: erpnext/edi/doctype/code_list/code_list_import.js:90 +#: erpnext/edi/doctype/code_list/code_list_import.js:91 msgid "by {}" msgstr "" @@ -58429,7 +58589,7 @@ msgstr "" #. Label of the description (Small Text) field in DocType 'Production Plan Sub #. Assembly Item' -#: erpnext/edi/doctype/code_list/code_list_import.js:80 +#: erpnext/edi/doctype/code_list/code_list_import.js:81 #: erpnext/manufacturing/doctype/production_plan_sub_assembly_item/production_plan_sub_assembly_item.json msgid "description" msgstr "" @@ -58449,11 +58609,6 @@ msgstr "" msgid "doc_type" msgstr "" -#: erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py:25 -#: erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py:25 -msgid "doctype" -msgstr "" - #. Description of the 'Coupon Name' (Data) field in DocType 'Coupon Code' #: erpnext/accounts/doctype/coupon_code/coupon_code.json msgid "e.g. \"Summer Holiday 2019 Offer 20\"" @@ -58685,7 +58840,7 @@ msgstr "" msgid "you must select Capital Work in Progress Account in accounts table" msgstr "" -#: erpnext/controllers/accounts_controller.py:1282 +#: erpnext/controllers/accounts_controller.py:1283 msgid "{0} '{1}' is disabled" msgstr "" @@ -58693,7 +58848,7 @@ msgstr "" msgid "{0} '{1}' not in Fiscal Year {2}" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.py:661 +#: erpnext/manufacturing/doctype/work_order/work_order.py:677 msgid "{0} ({1}) cannot be greater than planned quantity ({2}) in Work Order {3}" msgstr "" @@ -58701,7 +58856,7 @@ msgstr "" msgid "{0} {1} has submitted Assets. Remove Item {2} from table to continue." msgstr "" -#: erpnext/controllers/accounts_controller.py:2377 +#: erpnext/controllers/accounts_controller.py:2380 msgid "{0} Account not found against Customer {1}." msgstr "" @@ -58729,11 +58884,11 @@ msgstr "" msgid "{0} Number {1} is already used in {2} {3}" msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:1679 +#: erpnext/manufacturing/doctype/bom/bom.py:1680 msgid "{0} Operating Cost for operation {1}" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:573 +#: erpnext/manufacturing/doctype/work_order/work_order.js:578 msgid "{0} Operations: {1}" msgstr "" @@ -58761,19 +58916,19 @@ msgstr "" msgid "{0} account not found while submitting purchase receipt" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1065 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1066 msgid "{0} against Bill {1} dated {2}" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1074 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1075 msgid "{0} against Purchase Order {1}" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1041 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1042 msgid "{0} against Sales Invoice {1}" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1048 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1049 msgid "{0} against Sales Order {1}" msgstr "" @@ -58790,7 +58945,7 @@ msgstr "" msgid "{0} asset cannot be transferred" msgstr "" -#: erpnext/controllers/trends.py:60 +#: erpnext/controllers/trends.py:66 msgid "{0} can be either {1} or {2}." msgstr "" @@ -58837,11 +58992,11 @@ msgstr "" msgid "{0} does not belong to Company {1}" msgstr "" -#: erpnext/controllers/accounts_controller.py:349 +#: erpnext/controllers/accounts_controller.py:350 msgid "{0} does not belong to the Company {1}." msgstr "" -#: erpnext/accounts/doctype/item_tax_template/item_tax_template.py:67 +#: erpnext/accounts/doctype/item_tax_template/item_tax_template.py:74 msgid "{0} entered twice in Item Tax" msgstr "" @@ -58871,7 +59026,7 @@ msgstr "" msgid "{0} hours" msgstr "" -#: erpnext/controllers/accounts_controller.py:2735 +#: erpnext/controllers/accounts_controller.py:2738 msgid "{0} in row {1}" msgstr "" @@ -58893,7 +59048,7 @@ msgstr "" msgid "{0} is already running for {1}" msgstr "" -#: erpnext/controllers/accounts_controller.py:172 +#: erpnext/controllers/accounts_controller.py:173 msgid "{0} is blocked so this transaction cannot proceed" msgstr "" @@ -58906,15 +59061,15 @@ msgid "{0} is mandatory for Item {1}" msgstr "" #: erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.py:100 -#: erpnext/accounts/general_ledger.py:854 +#: erpnext/accounts/general_ledger.py:855 msgid "{0} is mandatory for account {1}" msgstr "" -#: erpnext/public/js/controllers/taxes_and_totals.js:129 +#: erpnext/public/js/controllers/taxes_and_totals.js:131 msgid "{0} is mandatory. Maybe Currency Exchange record is not created for {1} to {2}" msgstr "" -#: erpnext/controllers/accounts_controller.py:3179 +#: erpnext/controllers/accounts_controller.py:3182 msgid "{0} is mandatory. Maybe Currency Exchange record is not created for {1} to {2}." msgstr "" @@ -58966,27 +59121,27 @@ msgstr "" msgid "{0} is open. Close the POS or cancel the existing POS Opening Entry to create a new POS Opening Entry." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:538 +#: erpnext/manufacturing/doctype/work_order/work_order.js:543 msgid "{0} items disassembled" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:502 +#: erpnext/manufacturing/doctype/work_order/work_order.js:507 msgid "{0} items in progress" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:526 +#: erpnext/manufacturing/doctype/work_order/work_order.js:531 msgid "{0} items lost during process." msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:483 +#: erpnext/manufacturing/doctype/work_order/work_order.js:488 msgid "{0} items produced" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:506 +#: erpnext/manufacturing/doctype/work_order/work_order.js:511 msgid "{0} items returned" msgstr "" -#: erpnext/manufacturing/doctype/work_order/work_order.js:509 +#: erpnext/manufacturing/doctype/work_order/work_order.js:514 msgid "{0} items to return" msgstr "" @@ -58998,7 +59153,7 @@ msgstr "" msgid "{0} not allowed to transact with {1}. Please change the Company or add the Company in the 'Allowed To Transact With'-Section in the Customer record." msgstr "" -#: erpnext/manufacturing/doctype/bom/bom.py:611 +#: erpnext/manufacturing/doctype/bom/bom.py:612 msgid "{0} not found for item {1}" msgstr "" @@ -59055,7 +59210,7 @@ msgstr "" msgid "{0} variants created." msgstr "" -#: erpnext/accounts/doctype/financial_report_template/financial_report_engine.py:238 +#: erpnext/accounts/doctype/financial_report_template/financial_report_engine.py:242 msgid "{0} view is currently unsupported in Custom Financial Report." msgstr "" @@ -59071,7 +59226,7 @@ msgstr "" msgid "{0} {1}" msgstr "" -#: erpnext/public/js/utils/serial_no_batch_selector.js:254 +#: erpnext/public/js/utils/serial_no_batch_selector.js:265 msgid "{0} {1} Manually" msgstr "" @@ -59119,7 +59274,7 @@ msgstr "" msgid "{0} {1} is allocated twice in this Bank Transaction" msgstr "" -#: erpnext/edi/doctype/common_code/common_code.py:52 +#: erpnext/edi/doctype/common_code/common_code.py:54 msgid "{0} {1} is already linked to Common Code {2}." msgstr "" @@ -59140,7 +59295,7 @@ msgstr "" msgid "{0} {1} is cancelled so the action cannot be completed" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:860 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:861 msgid "{0} {1} is closed" msgstr "" @@ -59152,7 +59307,7 @@ msgstr "" msgid "{0} {1} is frozen" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:857 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:858 msgid "{0} {1} is fully billed" msgstr "" @@ -59168,8 +59323,8 @@ msgstr "" msgid "{0} {1} is not in any active Fiscal Year" msgstr "" -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:854 -#: erpnext/accounts/doctype/journal_entry/journal_entry.py:893 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:855 +#: erpnext/accounts/doctype/journal_entry/journal_entry.py:894 msgid "{0} {1} is not submitted" msgstr "" @@ -59189,7 +59344,7 @@ msgstr "" msgid "{0} {1} status is {2}" msgstr "" -#: erpnext/public/js/utils/serial_no_batch_selector.js:230 +#: erpnext/public/js/utils/serial_no_batch_selector.js:241 msgid "{0} {1} via CSV File" msgstr "" @@ -59286,11 +59441,11 @@ msgstr "" msgid "{0}: Virtual DocType (no database table)" msgstr "" -#: erpnext/controllers/accounts_controller.py:539 +#: erpnext/controllers/accounts_controller.py:540 msgid "{0}: {1} does not belong to the Company: {2}" msgstr "" -#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1392 +#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1400 msgid "{0}: {1} does not exist" msgstr "" @@ -59306,15 +59461,15 @@ msgstr "" msgid "{0}: {1} must be less than {2}" msgstr "" -#: erpnext/controllers/buying_controller.py:1023 +#: erpnext/controllers/buying_controller.py:1030 msgid "{count} Assets created for {item_code}" msgstr "" -#: erpnext/controllers/buying_controller.py:921 +#: erpnext/controllers/buying_controller.py:928 msgid "{doctype} {name} is cancelled or closed." msgstr "" -#: erpnext/controllers/buying_controller.py:632 +#: erpnext/controllers/buying_controller.py:639 msgid "{field_label} is mandatory for sub-contracted {doctype}." msgstr "" @@ -59322,7 +59477,7 @@ msgstr "" msgid "{item_name}'s Sample Size ({sample_size}) cannot be greater than the Accepted Quantity ({accepted_quantity})" msgstr "" -#: erpnext/controllers/buying_controller.py:729 +#: erpnext/controllers/buying_controller.py:736 msgid "{ref_doctype} {ref_name} is {status}." msgstr "" @@ -59334,7 +59489,7 @@ msgstr "" msgid "{} can't be cancelled since the Loyalty Points earned has been redeemed. First cancel the {} No {}" msgstr "" -#: erpnext/controllers/buying_controller.py:286 +#: erpnext/controllers/buying_controller.py:290 msgid "{} has submitted assets linked to it. You need to cancel the assets to create purchase return." msgstr "" From ac9aa7f1545d513067c532e65e4ffdcebda12da5 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 05:50:37 +0000 Subject: [PATCH 27/56] refactor: quality inspection item query (backport #54511) (#54540) * refactor: quality inspection item query (#54511) (cherry picked from commit be2a4b7b2a0f0154bcd89796398d62db73d61c8c) # Conflicts: # erpnext/stock/doctype/quality_inspection/quality_inspection.py * chore: resolve conflicts --------- Co-authored-by: Mihir Kandoi --- .../quality_inspection/quality_inspection.js | 22 +--- .../quality_inspection/quality_inspection.py | 101 +++++++++--------- 2 files changed, 58 insertions(+), 65 deletions(-) diff --git a/erpnext/stock/doctype/quality_inspection/quality_inspection.js b/erpnext/stock/doctype/quality_inspection/quality_inspection.js index 8d5764d5697..e991f63a0f3 100644 --- a/erpnext/stock/doctype/quality_inspection/quality_inspection.js +++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.js @@ -48,26 +48,14 @@ frappe.ui.form.on("Quality Inspection", { // item code based on GRN/DN frm.set_query("item_code", function (doc) { - let doctype = doc.reference_type; - - if (doc.reference_type !== "Job Card") { - doctype = - doc.reference_type == "Stock Entry" ? "Stock Entry Detail" : doc.reference_type + " Item"; - } - if (doc.reference_type && doc.reference_name) { - let filters = { - from: doctype, - parent_doctype: doc.reference_type, - inspection_type: doc.inspection_type, - }; - - if (doc.reference_type == doctype) filters["reference_name"] = doc.reference_name; - else filters["parent"] = doc.reference_name; - return { query: "erpnext.stock.doctype.quality_inspection.quality_inspection.item_query", - filters: filters, + filters: { + reference_doctype: doc.reference_type, + reference_name: doc.reference_name, + inspection_type: doc.inspection_type, + }, }; } }); diff --git a/erpnext/stock/doctype/quality_inspection/quality_inspection.py b/erpnext/stock/doctype/quality_inspection/quality_inspection.py index 52ac45ec6fb..586bc4dbef1 100644 --- a/erpnext/stock/doctype/quality_inspection/quality_inspection.py +++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.py @@ -365,58 +365,63 @@ class QualityInspection(Document): @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs def item_query(doctype, txt, searchfield, start, page_len, filters): - from frappe.desk.reportview import get_match_cond + reference_doctype = filters.get("reference_doctype") - from_doctype = cstr(filters.get("from")) - parent_doctype = cstr(filters.get("parent_doctype")) - if not from_doctype or not frappe.db.exists("DocType", from_doctype): + if not reference_doctype: return [] - - mcond = get_match_cond(parent_doctype or from_doctype) - cond, qi_condition = "", "and (quality_inspection is null or quality_inspection = '')" - - if filters.get("parent"): - if ( - from_doctype in ["Purchase Invoice Item", "Purchase Receipt Item"] - and filters.get("inspection_type") != "In Process" - ): - cond = """and item_code in (select name from `tabItem` where - inspection_required_before_purchase = 1)""" - elif ( - from_doctype in ["Sales Invoice Item", "Delivery Note Item"] - and filters.get("inspection_type") != "In Process" - ): - cond = """and item_code in (select name from `tabItem` where - inspection_required_before_delivery = 1)""" - elif from_doctype == "Stock Entry Detail": - cond = """and s_warehouse is null""" - - if from_doctype in ["Supplier Quotation Item"]: - qi_condition = "" - - return frappe.db.sql( - f""" - SELECT distinct item_code, item_name - FROM `tab{from_doctype}` - WHERE parent=%(parent)s and docstatus < 2 and item_code like %(txt)s - {qi_condition} {cond} {mcond} - ORDER BY item_code limit {cint(page_len)} offset {cint(start)} - """, - {"parent": filters.get("parent"), "txt": "%%%s%%" % txt}, + elif reference_doctype == "Job Card": + production_item, item_name = frappe.get_value( + "Job Card", filters.get("reference_name"), ["production_item", "item_name"] ) + return ((production_item, item_name),) + else: + my_filters = [ + ["items.parent", "=", filters.get("reference_name")], + "and", + ["items.item_code", "like", f"%{txt}%"], + "and", + ["docstatus", "<", 2], + "and", + ["items.quality_inspection", "is", "not set"], + ] - elif filters.get("reference_name"): - return frappe.db.sql( - f""" - SELECT production_item - FROM `tab{from_doctype}` - WHERE name = %(reference_name)s and docstatus < 2 and production_item like %(txt)s - {qi_condition} {cond} {mcond} - ORDER BY production_item - limit {cint(page_len)} offset {cint(start)} - """, - {"reference_name": filters.get("reference_name"), "txt": "%%%s%%" % txt}, - ) + if reference_doctype == "Stock Entry": + my_filters.extend( + [ + "and", + ["items.t_warehouse", "is", "not set"], + ] + ) + elif filters.get("inspection_type") != "In Process": + my_filters.extend( + [ + "and", + [ + "items.item_code", + "in", + frappe.get_list( + "Item", + filters={ + "inspection_required_before_purchase" + if filters.get("inspection_type") == "Incoming" + else "inspection_required_before_delivery": 1 + }, + pluck="name", + ), + ], + ] + ) + + return frappe.get_query( + reference_doctype, + fields=["items.item_code, items.item_name"], + filters=my_filters, + offset=start, + limit=page_len, + order_by="items.item_code", + ignore_permissions=False, + distinct=True, + ).run() @frappe.whitelist() From cc85370d54c474d98ef592b41faffce2b53cd44e Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 07:20:16 +0000 Subject: [PATCH 28/56] fix(stock): remove validation for transfer_qty field (backport #54542) (#54545) fix(stock): remove validation for transfer_qty field (#54542) (cherry picked from commit 60a6b38c314261cbaa8092c8fa62337b50c317a6) Co-authored-by: Pandiyan P --- .../stock/doctype/stock_entry_detail/stock_entry_detail.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json index f28f5e25a66..b446aa1e51e 100644 --- a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json +++ b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json @@ -278,8 +278,7 @@ "oldfieldname": "transfer_qty", "oldfieldtype": "Currency", "print_hide": 1, - "read_only": 1, - "reqd": 1 + "read_only": 1 }, { "default": "0", @@ -680,7 +679,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2026-03-02 14:05:23.116017", + "modified": "2026-04-27 11:40:38.294196", "modified_by": "Administrator", "module": "Stock", "name": "Stock Entry Detail", From d56df96f73d0457713bc47a9e927e0d8368f6b93 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 15:10:44 +0530 Subject: [PATCH 29/56] fix: make inv dimen reqd only in delivery note (backport #54546) (#54552) fix: make inv dimen reqd only in delivery note (#54546) (cherry picked from commit 0aadd1e3a50689218286560f6e2c05f0082afaef) Co-authored-by: Mihir Kandoi --- erpnext/patches.txt | 1 + .../patches/v16_0/packed_item_inv_dimen.py | 27 +++++++++++++++++++ .../inventory_dimension.py | 5 +++- .../doctype/packed_item/packed_item.json | 7 ++--- 4 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 erpnext/patches/v16_0/packed_item_inv_dimen.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 4cffef36951..1eb86cef190 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -478,3 +478,4 @@ erpnext.patches.v16_0.uom_category erpnext.patches.v16_0.merge_repost_settings_to_accounts_settings erpnext.patches.v16_0.set_root_type_in_account_categories erpnext.patches.v16_0.scr_inv_dimension +erpnext.patches.v16_0.packed_item_inv_dimen \ No newline at end of file diff --git a/erpnext/patches/v16_0/packed_item_inv_dimen.py b/erpnext/patches/v16_0/packed_item_inv_dimen.py new file mode 100644 index 00000000000..38dd2007045 --- /dev/null +++ b/erpnext/patches/v16_0/packed_item_inv_dimen.py @@ -0,0 +1,27 @@ +import frappe + +from erpnext.stock.doctype.inventory_dimension.inventory_dimension import get_inventory_dimensions + + +def execute(): + for dimension in get_inventory_dimensions(): + if frappe.db.exists( + "Custom Field", + { + "fieldname": dimension.source_fieldname, + "dt": "Packed Item", + "reqd": 1, + }, + ): + frappe.set_value( + "Custom Field", + { + "fieldname": dimension.source_fieldname, + "dt": "Packed Item", + "reqd": 1, + }, + { + "reqd": 0, + "mandatory_depends_on": "eval:doc.parent_detail_docname && ['Delivery Note', 'Sales Invoice', 'POS Invoice'].includes(parent.doctype)", + }, + ) diff --git a/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py b/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py index 86ce5c3eb85..7495b1dde43 100644 --- a/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py +++ b/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py @@ -173,6 +173,8 @@ class InventoryDimension(Document): mandatory_depends_on = "eval:doc.s_warehouse" elif doctype == "Subcontracting Receipt Supplied Item": mandatory_depends_on = "eval:doc.reference_name" + elif doctype == "Packed Item": + mandatory_depends_on = "eval:doc.parent_detail_docname && ['Delivery Note', 'Sales Invoice', 'POS Invoice'].includes(parent.doctype)" dimension_fields = [ dict( @@ -193,7 +195,8 @@ class InventoryDimension(Document): reqd=1 if self.reqd and not self.mandatory_depends_on - and doctype not in ["Stock Entry Detail", "Subcontracting Receipt Supplied Item"] + and doctype + not in ["Stock Entry Detail", "Subcontracting Receipt Supplied Item", "Packed Item"] else 0, mandatory_depends_on=mandatory_depends_on, ), diff --git a/erpnext/stock/doctype/packed_item/packed_item.json b/erpnext/stock/doctype/packed_item/packed_item.json index 1614bfe2ab7..f7ff0a921be 100644 --- a/erpnext/stock/doctype/packed_item/packed_item.json +++ b/erpnext/stock/doctype/packed_item/packed_item.json @@ -8,6 +8,7 @@ "parent_item", "item_code", "item_name", + "delivered_by_supplier", "column_break_5", "description", "section_break_6", @@ -23,7 +24,6 @@ "use_serial_batch_fields", "column_break_11", "serial_and_batch_bundle", - "delivered_by_supplier", "section_break_bgys", "serial_no", "column_break_qlha", @@ -119,6 +119,7 @@ "read_only": 1 }, { + "depends_on": "eval:parent.doctype !== \"Sales Order\"", "fieldname": "section_break_9", "fieldtype": "Section Break" }, @@ -285,7 +286,7 @@ "label": "Use Serial No / Batch Fields" }, { - "depends_on": "eval:doc.use_serial_batch_fields === 1", + "depends_on": "eval:doc.use_serial_batch_fields === 1 && parent.doctype !== \"Sales Order\"", "fieldname": "section_break_bgys", "fieldtype": "Section Break" }, @@ -314,7 +315,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2026-03-16 18:10:47.511381", + "modified": "2026-04-27 13:00:22.949296", "modified_by": "Administrator", "module": "Stock", "name": "Packed Item", From 0df38a841e2353a50c21f7565758477f2c7a3452 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Mon, 27 Apr 2026 15:38:47 +0530 Subject: [PATCH 30/56] fix: correct display depends on condition (#54556) --- erpnext/stock/doctype/packed_item/packed_item.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/doctype/packed_item/packed_item.json b/erpnext/stock/doctype/packed_item/packed_item.json index f7ff0a921be..f77661c4245 100644 --- a/erpnext/stock/doctype/packed_item/packed_item.json +++ b/erpnext/stock/doctype/packed_item/packed_item.json @@ -119,7 +119,7 @@ "read_only": 1 }, { - "depends_on": "eval:parent.doctype !== \"Sales Order\"", + "depends_on": "eval:!['Sales Order', 'Quotation'].includes(parent.doctype)", "fieldname": "section_break_9", "fieldtype": "Section Break" }, @@ -286,7 +286,7 @@ "label": "Use Serial No / Batch Fields" }, { - "depends_on": "eval:doc.use_serial_batch_fields === 1 && parent.doctype !== \"Sales Order\"", + "depends_on": "eval:doc.use_serial_batch_fields === 1 && !['Sales Order', 'Quotation'].includes(parent.doctype)", "fieldname": "section_break_bgys", "fieldtype": "Section Break" }, @@ -315,7 +315,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2026-04-27 13:00:22.949296", + "modified": "2026-04-27 14:12:53.236906", "modified_by": "Administrator", "module": "Stock", "name": "Packed Item", From d9a9a5bcde08ae084c3fe0c1b29d37200e85aad0 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 15:23:05 +0000 Subject: [PATCH 31/56] fix: debit credit not equal in purchase transactions for multi currency (backport #54456) (#54564) fix: debit credit not equal in purchase transactions for multi currency (#54456) (cherry picked from commit 601581d6f818b678c284d47f9b6328ef0873b7dd) Co-authored-by: Mihir Kandoi --- erpnext/controllers/buying_controller.py | 12 +++++++++++- .../doctype/purchase_receipt/purchase_receipt.py | 9 ++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 5627dffea95..0f74ea12348 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -461,7 +461,17 @@ class BuyingController(SubcontractingController): get_conversion_factor(item.item_code, item.uom).get("conversion_factor") or 1.0 ) - net_rate = item.qty * item.base_net_rate + net_rate = ( + flt( + (item.base_net_amount / item.received_qty) * item.qty, + item.precision("base_net_amount"), + ) + if item.received_qty + and frappe.get_single_value( + "Buying Settings", "bill_for_rejected_quantity_in_purchase_invoice" + ) + else item.base_net_amount + ) if item.sales_incoming_rate: # for internal transfer net_rate = item.qty * item.sales_incoming_rate diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index b0b4d9470d4..ac738fe66d8 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -560,7 +560,14 @@ class PurchaseReceipt(BuyingController): else flt(item.net_amount, item.precision("net_amount")) ) - outgoing_amount = item.qty * item.base_net_rate + outgoing_amount = ( + flt((item.base_net_amount / item.received_qty) * item.qty, item.precision("base_net_amount")) + if item.received_qty + and frappe.get_single_value( + "Buying Settings", "bill_for_rejected_quantity_in_purchase_invoice" + ) + else item.base_net_amount + ) if self.is_internal_transfer() and item.valuation_rate: outgoing_amount = abs(get_stock_value_difference(self.name, item.name, item.from_warehouse)) credit_amount = outgoing_amount From f7fa394aea779e32f595e1450d22b8a29aea4dab Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 05:33:55 +0000 Subject: [PATCH 32/56] fix: negative quantity check in validate_item_qty (backport #54559) (#54572) fix: negative quantity check in validate_item_qty (#54559) Fix negative quantity check in validate_item_qty When saving a Blanket Order with a blank qty field in the items table, the following error is raised: TypeError: '<' not supported between instances of 'NoneType' and 'int' Root cause: The validate_item_qty method compares d.qty < 0 directly. When the qty field is left empty, its value is None, and Python cannot compare None with an integer. Fix Wrap d.qty with flt(), which safely converts None (and any non-numeric value) to 0.0 before the comparison. # Before if d.qty < 0: # After if flt(d.qty) < 0: (cherry picked from commit 63edd5ddc6b6894102fd6d40ea735113022f995c) Co-authored-by: Vinay Mishra <39999379+vinaymishraofficial@users.noreply.github.com> --- erpnext/manufacturing/doctype/blanket_order/blanket_order.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/blanket_order/blanket_order.py b/erpnext/manufacturing/doctype/blanket_order/blanket_order.py index 69e9d8ee14c..21f7fe5bb3e 100644 --- a/erpnext/manufacturing/doctype/blanket_order/blanket_order.py +++ b/erpnext/manufacturing/doctype/blanket_order/blanket_order.py @@ -120,7 +120,7 @@ class BlanketOrder(Document): def validate_item_qty(self): for d in self.items: - if d.qty < 0: + if flt(d.qty) < 0: frappe.throw(_("Row {0}: Quantity cannot be negative.").format(d.idx)) From f14751d5382a137902e5a6c66de892f89cf1c94b Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 05:38:29 +0000 Subject: [PATCH 33/56] fix(manufacturing): remove conversion factor for stock qty (backport #54525) (#54573) fix(manufacturing): remove conversion factor for stock qty (#54525) (cherry picked from commit 6f9089dd5be99a25393317745bf451a9f72b3047) Co-authored-by: Sudharsanan Ashok <135326972+Sudharsanan11@users.noreply.github.com> --- .../doctype/production_plan/production_plan.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index 36364f6740b..fa4c812d5b8 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -382,9 +382,9 @@ class ProductionPlan(Document): items = items_query.run(as_dict=True) for item in items: - item.pending_qty = ( - flt(item.qty) - max(item.work_order_qty, item.delivered_qty, 0) - ) * item.conversion_factor + item.pending_qty = flt(item.qty) - max( + item.work_order_qty, flt(item.delivered_qty) * item.conversion_factor, 0 + ) pi = frappe.qb.DocType("Packed Item") From 15b6633fc3ba07cbaa7d577e06cafff39ba89aca Mon Sep 17 00:00:00 2001 From: Jatin3128 <140256508+Jatin3128@users.noreply.github.com> Date: Tue, 28 Apr 2026 13:09:50 +0530 Subject: [PATCH 34/56] feat: add setting to hide Subscription references across doctypes (#54576) --- .../accounts_settings/accounts_settings.json | 1 + .../accounts_settings/accounts_settings.py | 11 +++++ .../doctype/journal_entry/journal_entry.json | 7 +-- .../doctype/payment_entry/payment_entry.json | 16 +++---- .../payment_request/payment_request.json | 4 +- .../doctype/pos_invoice/pos_invoice.json | 15 ++++--- .../purchase_invoice/purchase_invoice.json | 11 ++++- .../doctype/sales_invoice/sales_invoice.json | 43 +++++++++++++------ .../purchase_order/purchase_order.json | 14 +++--- .../supplier_quotation.json | 14 +++--- erpnext/hooks.py | 2 + .../selling/doctype/quotation/quotation.json | 12 +++--- .../doctype/sales_order/sales_order.json | 26 +++++------ .../doctype/delivery_note/delivery_note.json | 12 +++--- 14 files changed, 111 insertions(+), 77 deletions(-) diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json index 0807f07d8d9..7d0b80c8283 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json @@ -16,6 +16,7 @@ "invoicing_features_section", "check_supplier_invoice_uniqueness", "automatically_fetch_payment_terms", + "enable_subscription", "column_break_17", "enable_common_party_accounting", "allow_multi_currency_invoices_against_single_party_account", diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py index 693d0918d20..fa36f1de183 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py @@ -77,6 +77,7 @@ class AccountsSettings(Document): enable_immutable_ledger: DF.Check enable_loyalty_point_program: DF.Check enable_party_matching: DF.Check + enable_subscription: DF.Check exchange_gain_loss_posting_date: DF.Literal["Invoice", "Payment", "Reconciliation Date"] fetch_payment_schedule_in_payment_request: DF.Check fetch_valuation_rate_for_internal_transaction: DF.Check @@ -142,6 +143,10 @@ class AccountsSettings(Document): toggle_loyalty_point_program_section(not self.enable_loyalty_point_program) clear_cache = True + if old_doc.enable_subscription != self.enable_subscription: + toggle_subscription_sections(not self.enable_subscription) + clear_cache = True + if clear_cache: frappe.clear_cache() @@ -234,6 +239,12 @@ def toggle_loyalty_point_program_section(hide): create_property_setter_for_hiding_field(doctype, "loyalty_points_redemption", hide) +def toggle_subscription_sections(hide): + subscription_doctypes = frappe.get_hooks("subscription_doctypes") + for doctype in subscription_doctypes: + create_property_setter_for_hiding_field(doctype, "subscription_section", hide) + + def create_property_setter_for_hiding_field(doctype, field_name, hide): make_property_setter( doctype, diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.json b/erpnext/accounts/doctype/journal_entry/journal_entry.json index 0eaefb5f618..00831ce7711 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.json +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.json @@ -39,7 +39,7 @@ "clearance_date", "column_break_oizh", "user_remark", - "subscription_section", + "auto_repeat_section", "auto_repeat", "tax_withholding_tab", "section_tax_withholding_entry", @@ -477,11 +477,6 @@ "options": "Stock Entry", "read_only": 1 }, - { - "fieldname": "subscription_section", - "fieldtype": "Section Break", - "label": "Subscription" - }, { "allow_on_submit": 1, "fieldname": "auto_repeat", diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json index afa508781d8..5500e1b3e07 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.json +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json @@ -89,6 +89,7 @@ "remarks", "base_in_words", "is_opening", + "title", "column_break_16", "letter_head", "print_heading", @@ -96,10 +97,9 @@ "bank_account_no", "payment_order", "in_words", - "subscription_section", - "auto_repeat", "amended_from", - "title" + "auto_repeat_section", + "auto_repeat" ], "fields": [ { @@ -503,11 +503,6 @@ "print_hide": 1, "read_only": 1 }, - { - "fieldname": "subscription_section", - "fieldtype": "Section Break", - "label": "Subscription Section" - }, { "allow_on_submit": 1, "fieldname": "auto_repeat", @@ -781,6 +776,11 @@ "fieldname": "override_tax_withholding_entries", "fieldtype": "Check", "label": "Edit Tax Withholding Entries" + }, + { + "fieldname": "auto_repeat_section", + "fieldtype": "Section Break", + "label": "Auto Repeat" } ], "grid_page_length": 50, diff --git a/erpnext/accounts/doctype/payment_request/payment_request.json b/erpnext/accounts/doctype/payment_request/payment_request.json index 8fcf1f2f41f..17d8b74aa14 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.json +++ b/erpnext/accounts/doctype/payment_request/payment_request.json @@ -183,7 +183,7 @@ "depends_on": "eval:doc.is_a_subscription", "fieldname": "subscription_section", "fieldtype": "Section Break", - "label": "Subscription Section" + "label": "Subscription" }, { "fieldname": "subscription_plans", @@ -478,7 +478,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2026-01-13 12:53:00.963274", + "modified": "2026-02-27 19:11:03.308896", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Request", diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json index ff57c811c58..c8fc266b012 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json @@ -187,7 +187,7 @@ "subscription_section", "from_date", "to_date", - "column_break_140", + "auto_repeat_section", "auto_repeat", "update_auto_repeat_reference", "against_income_account" @@ -1462,7 +1462,7 @@ { "fieldname": "subscription_section", "fieldtype": "Section Break", - "label": "Subscription Section" + "label": "Subscription" }, { "allow_on_submit": 1, @@ -1480,10 +1480,6 @@ "no_copy": 1, "print_hide": 1 }, - { - "fieldname": "column_break_140", - "fieldtype": "Column Break" - }, { "allow_on_submit": 1, "fieldname": "auto_repeat", @@ -1619,12 +1615,17 @@ { "fieldname": "column_break_bhao", "fieldtype": "Column Break" + }, + { + "fieldname": "auto_repeat_section", + "fieldtype": "Section Break", + "label": "Auto Repeat" } ], "icon": "fa fa-file-text", "is_submittable": 1, "links": [], - "modified": "2026-02-10 14:23:07.181782", + "modified": "2026-03-02 07:32:47.667810", "modified_by": "Administrator", "module": "Accounts", "name": "POS Invoice", diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index adb7dad6726..f7f8d8b8ffc 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -180,11 +180,12 @@ "unrealized_profit_loss_account", "subscription_section", "subscription", - "auto_repeat", - "update_auto_repeat_reference", "column_break_114", "from_date", "to_date", + "automation_section", + "auto_repeat", + "update_auto_repeat_reference", "printing_settings", "letter_head", "group_same_items", @@ -1675,6 +1676,12 @@ "fieldname": "totals_section", "fieldtype": "Section Break", "label": "Totals" + }, + { + "collapsible": 1, + "fieldname": "automation_section", + "fieldtype": "Section Break", + "label": "Automation" } ], "grid_page_length": 50, diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index 50734582dad..267b161bee5 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -91,9 +91,9 @@ "column_break_xjag", "base_rounding_adjustment", "base_rounded_total", - "section_break_vacb", + "section_break_pxwz", "total_advance", - "column_break_rdks", + "column_break_iaso", "outstanding_amount", "section_tax_withholding_entry", "tax_withholding_group", @@ -199,6 +199,7 @@ "unrealized_profit_loss_account", "against_income_account", "commission_section", + "column_break_rdiw", "sales_partner", "amount_eligible_for_commission", "column_break10", @@ -214,12 +215,14 @@ "language", "subscription_section", "subscription", - "from_date", - "auto_repeat", "column_break_140", + "from_date", "to_date", + "automation_section", + "auto_repeat", "update_auto_repeat_reference", "utm_analytics_section", + "column_break_rdke", "utm_source", "utm_medium", "column_break_ixxw", @@ -2304,14 +2307,6 @@ "options": "fa fa-group", "print_hide": 1 }, - { - "fieldname": "section_break_vacb", - "fieldtype": "Section Break" - }, - { - "fieldname": "column_break_rdks", - "fieldtype": "Column Break" - }, { "fieldname": "column_break_ixxw", "fieldtype": "Column Break" @@ -2321,6 +2316,28 @@ "fieldname": "utm_analytics_section", "fieldtype": "Section Break", "label": "UTM Analytics" + }, + { + "collapsible": 1, + "fieldname": "automation_section", + "fieldtype": "Section Break", + "label": "Automation" + }, + { + "fieldname": "section_break_pxwz", + "fieldtype": "Section Break" + }, + { + "fieldname": "column_break_rdke", + "fieldtype": "Column Break" + }, + { + "fieldname": "column_break_rdiw", + "fieldtype": "Column Break" + }, + { + "fieldname": "column_break_iaso", + "fieldtype": "Column Break" } ], "grid_page_length": 50, @@ -2334,7 +2351,7 @@ "link_fieldname": "consolidated_invoice" } ], - "modified": "2026-03-09 17:15:30.931929", + "modified": "2026-04-28 12:39:53.267755", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json index 260dc52ceac..6d59d0b9884 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.json +++ b/erpnext/buying/doctype/purchase_order/purchase_order.json @@ -147,7 +147,7 @@ "column_break_86", "select_print_heading", "language", - "subscription_section", + "auto_repeat_section", "from_date", "to_date", "column_break_97", @@ -1013,12 +1013,6 @@ "label": "Print Language", "print_hide": 1 }, - { - "collapsible": 1, - "fieldname": "subscription_section", - "fieldtype": "Section Break", - "label": "Auto Repeat" - }, { "allow_on_submit": 1, "fieldname": "from_date", @@ -1309,6 +1303,12 @@ "fieldtype": "Time", "label": "Time", "mandatory_depends_on": "is_internal_supplier" + }, + { + "collapsible": 1, + "fieldname": "auto_repeat_section", + "fieldtype": "Section Break", + "label": "Auto Repeat" } ], "grid_page_length": 50, diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json index 1328d8aebdc..bb1c048301e 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json @@ -111,7 +111,7 @@ "column_break_85", "select_print_heading", "language", - "subscription_section", + "auto_repeat_section", "auto_repeat", "update_auto_repeat_reference", "more_info", @@ -736,11 +736,6 @@ "print_hide": 1, "read_only": 1 }, - { - "fieldname": "subscription_section", - "fieldtype": "Section Break", - "label": "Auto Repeat" - }, { "fieldname": "auto_repeat", "fieldtype": "Link", @@ -940,6 +935,11 @@ "no_copy": 1, "options": "Item Wise Tax Detail", "print_hide": 1 + }, + { + "fieldname": "auto_repeat_section", + "fieldtype": "Section Break", + "label": "Auto Repeat" } ], "grid_page_length": 50, @@ -948,7 +948,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2026-01-29 21:23:13.778468", + "modified": "2026-02-27 18:05:50.121391", "modified_by": "Administrator", "module": "Buying", "name": "Supplier Quotation", diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 2fd4be3a510..a32c033c9ec 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -581,6 +581,8 @@ accounting_dimension_doctypes = [ "Advance Taxes and Charges", ] +subscription_doctypes = ["Sales Invoice", "Purchase Invoice", "Payment Request", "POS Invoice"] + get_matching_queries = ( "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_matching_queries" ) diff --git a/erpnext/selling/doctype/quotation/quotation.json b/erpnext/selling/doctype/quotation/quotation.json index f5e867964e5..71d977638e8 100644 --- a/erpnext/selling/doctype/quotation/quotation.json +++ b/erpnext/selling/doctype/quotation/quotation.json @@ -109,7 +109,7 @@ "tc_name", "terms", "more_info_tab", - "subscription_section", + "auto_repeat_section", "auto_repeat", "update_auto_repeat_reference", "print_settings", @@ -832,11 +832,6 @@ "print_hide": 1, "read_only": 1 }, - { - "fieldname": "subscription_section", - "fieldtype": "Section Break", - "label": "Auto Repeat" - }, { "fieldname": "auto_repeat", "fieldtype": "Link", @@ -1122,6 +1117,11 @@ "fieldname": "utm_analytics_section", "fieldtype": "Section Break", "label": "UTM Analytics" + }, + { + "fieldname": "auto_repeat_section", + "fieldtype": "Section Break", + "label": "Auto Repeat" } ], "icon": "fa fa-shopping-cart", diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json index 87816741728..3109fd0e36e 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.json +++ b/erpnext/selling/doctype/sales_order/sales_order.json @@ -151,7 +151,7 @@ "loyalty_points", "column_break_116", "loyalty_amount", - "subscription_section", + "auto_repeat_section", "from_date", "to_date", "column_break_108", @@ -1372,18 +1372,6 @@ "options": "Sales Team", "print_hide": 1 }, - { - "allow_on_submit": 1, - "collapsible": 1, - "fieldname": "subscription_section", - "fieldtype": "Section Break", - "hide_days": 1, - "hide_seconds": 1, - "label": "Auto Repeat", - "no_copy": 1, - "print_hide": 1, - "read_only": 1 - }, { "allow_on_submit": 1, "fieldname": "from_date", @@ -1742,6 +1730,18 @@ "hidden": 1, "label": "Ignore Default Payment Terms Template", "read_only": 1 + }, + { + "allow_on_submit": 1, + "collapsible": 1, + "fieldname": "auto_repeat_section", + "fieldtype": "Section Break", + "hide_days": 1, + "hide_seconds": 1, + "label": "Auto Repeat", + "no_copy": 1, + "print_hide": 1, + "read_only": 1 } ], "grid_page_length": 50, diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.json b/erpnext/stock/doctype/delivery_note/delivery_note.json index 479786a122a..e8871227c60 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.json +++ b/erpnext/stock/doctype/delivery_note/delivery_note.json @@ -147,7 +147,7 @@ "total_commission", "section_break1", "sales_team", - "subscription_section", + "auto_repeat_section", "auto_repeat", "printing_details", "letter_head", @@ -1115,11 +1115,6 @@ "oldfieldname": "instructions", "oldfieldtype": "Text" }, - { - "fieldname": "subscription_section", - "fieldtype": "Section Break", - "label": "Subscription Section" - }, { "fieldname": "auto_repeat", "fieldtype": "Link", @@ -1446,6 +1441,11 @@ { "fieldname": "column_break_neoj", "fieldtype": "Column Break" + }, + { + "fieldname": "auto_repeat_section", + "fieldtype": "Section Break", + "label": "Auto Repeat" } ], "icon": "fa fa-truck", From 134e4b744632979d3b5d4caa1d0d2a4fc07feb87 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 09:44:16 +0000 Subject: [PATCH 35/56] fix: update status of quotation in patch (backport #54577) (#54580) fix: update status of quotation in patch (#54577) (cherry picked from commit 2088a01c198ca498dea05c1db183d7055351759f) Co-authored-by: Mihir Kandoi --- .../set_ordered_qty_in_quotation_item.py | 19 +++++++++++++++---- .../selling/doctype/quotation/quotation.js | 3 +-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/erpnext/patches/v16_0/set_ordered_qty_in_quotation_item.py b/erpnext/patches/v16_0/set_ordered_qty_in_quotation_item.py index 93a6323eb6f..314bc6dfe9e 100644 --- a/erpnext/patches/v16_0/set_ordered_qty_in_quotation_item.py +++ b/erpnext/patches/v16_0/set_ordered_qty_in_quotation_item.py @@ -10,7 +10,18 @@ def execute(): ) if data: frappe.db.auto_commit_on_many_writes = 1 - frappe.db.bulk_update( - "Quotation Item", {d.quotation_item: {"ordered_qty": d.ordered_qty} for d in data} - ) - frappe.db.auto_commit_on_many_writes = 0 + try: + frappe.db.bulk_update( + "Quotation Item", {d.quotation_item: {"ordered_qty": d.ordered_qty} for d in data} + ) + quotations = frappe.get_all( + "Quotation Item", + filters={"name": ["in", [d.quotation_item for d in data]]}, + pluck="parent", + distinct=True, + ) + for quotation in quotations: + doc = frappe.get_doc("Quotation", quotation) + doc.set_status(update=True, update_modified=False) + finally: + frappe.db.auto_commit_on_many_writes = 0 diff --git a/erpnext/selling/doctype/quotation/quotation.js b/erpnext/selling/doctype/quotation/quotation.js index bb82310d9c5..a692aa3e3ca 100644 --- a/erpnext/selling/doctype/quotation/quotation.js +++ b/erpnext/selling/doctype/quotation/quotation.js @@ -132,6 +132,7 @@ erpnext.selling.QuotationController = class QuotationController extends erpnext. frappe.datetime.get_diff(doc.valid_till, frappe.datetime.get_today()) >= 0) ) { this.frm.add_custom_button(__("Sales Order"), () => this.make_sales_order(), __("Create")); + cur_frm.page.set_inner_btn_group_as_primary(__("Create")); this.frm.add_custom_button(__("Update Items"), () => { erpnext.utils.update_child_items({ frm: this.frm, @@ -146,8 +147,6 @@ erpnext.selling.QuotationController = class QuotationController extends erpnext. this.frm.trigger("set_as_lost_dialog"); }); } - - cur_frm.page.set_inner_btn_group_as_primary(__("Create")); } if (this.frm.doc.docstatus === 0 && frappe.model.can_read("Opportunity")) { From 386a373c9b6c5265134c6139e1a989972692ef9f Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 15:41:36 +0530 Subject: [PATCH 36/56] chore(sidebar): moved `Inactive Customers` from CRM to Selling Workspace Sidebar (backport #54578) (#54581) Co-authored-by: diptanilsaha --- erpnext/workspace_sidebar/crm.json | 13 +------------ erpnext/workspace_sidebar/selling.json | 13 ++++++++++++- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/erpnext/workspace_sidebar/crm.json b/erpnext/workspace_sidebar/crm.json index 6e8bde422f2..625bf09af40 100644 --- a/erpnext/workspace_sidebar/crm.json +++ b/erpnext/workspace_sidebar/crm.json @@ -143,17 +143,6 @@ "show_arrow": 0, "type": "Link" }, - { - "child": 1, - "collapsible": 1, - "indent": 0, - "keep_closed": 0, - "label": "Inactive Customers", - "link_to": "Inactive Customers", - "link_type": "Report", - "show_arrow": 0, - "type": "Link" - }, { "child": 1, "collapsible": 1, @@ -485,7 +474,7 @@ "type": "Link" } ], - "modified": "2026-01-10 00:06:13.192366", + "modified": "2026-04-28 14:11:15.910719", "modified_by": "Administrator", "module": "CRM", "name": "CRM", diff --git a/erpnext/workspace_sidebar/selling.json b/erpnext/workspace_sidebar/selling.json index e844e37f54d..2a97a2daa5e 100644 --- a/erpnext/workspace_sidebar/selling.json +++ b/erpnext/workspace_sidebar/selling.json @@ -498,6 +498,17 @@ "show_arrow": 0, "type": "Link" }, + { + "child": 1, + "collapsible": 1, + "indent": 0, + "keep_closed": 0, + "label": "Inactive Customers", + "link_to": "Inactive Customers", + "link_type": "Report", + "show_arrow": 0, + "type": "Link" + }, { "child": 1, "collapsible": 1, @@ -687,7 +698,7 @@ "type": "Link" } ], - "modified": "2026-02-20 16:44:44.931581", + "modified": "2026-04-28 14:38:37.179705", "modified_by": "Administrator", "module": "Selling", "module_onboarding": "Selling Onboarding", From 45dc2c40fd7c09813155a4586d7094c567577d2e Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 24 Apr 2026 14:52:33 +0530 Subject: [PATCH 37/56] fix: hide feature flag controlled fields on install (cherry picked from commit 889fdf2f11690ac59b62f2f5309881724a7dce61) --- erpnext/setup/install.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/erpnext/setup/install.py b/erpnext/setup/install.py index a45279e994c..be75e44759f 100644 --- a/erpnext/setup/install.py +++ b/erpnext/setup/install.py @@ -38,6 +38,7 @@ def after_install(): update_pegged_currencies() set_default_print_formats() create_letter_head() + toggle_hidden_fields() frappe.db.commit() @@ -364,6 +365,21 @@ def create_letter_head(): doc.insert(ignore_permissions=True) +def toggle_hidden_fields(): + from erpnext.accounts.doctype.accounts_settings.accounts_settings import ( + toggle_accounting_dimension_sections, + toggle_loyalty_point_program_section, + toggle_sales_discount_section, + toggle_subscription_sections, + ) + + acc_settings = frappe.get_doc("Accounts Settings") + toggle_accounting_dimension_sections(not acc_settings.enable_accounting_dimensions) + toggle_sales_discount_section(not acc_settings.enable_discounts_and_margin) + toggle_subscription_sections(not acc_settings.enable_subscription) + toggle_loyalty_point_program_section(not acc_settings.enable_loyalty_point_program) + + DEFAULT_ROLE_PROFILES = { _("Inventory"): [ "Stock User", From 5289aa0ab32640d79c3fd76fca966aa0ee8515fb Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 10:48:41 +0000 Subject: [PATCH 38/56] fix(payment_entry): escape arguments on invoice and order fetching sql queries (backport #54582) (#54586) Co-authored-by: diptanilsaha fix(payment_entry): escape arguments on invoice and order fetching sql queries (#54582) --- .../doctype/payment_entry/payment_entry.py | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index d60f77120b2..a582d31044b 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -2306,22 +2306,20 @@ def get_outstanding_reference_documents(args, validate=False): # Get positive outstanding sales /purchase invoices condition = "" if args.get("voucher_type") and args.get("voucher_no"): - condition = " and voucher_type={} and voucher_no={}".format( - frappe.db.escape(args["voucher_type"]), frappe.db.escape(args["voucher_no"]) - ) + condition = f" and voucher_type={frappe.db.escape(args['voucher_type'])} and voucher_no={frappe.db.escape(args['voucher_no'])}" common_filter.append(ple.voucher_type == args["voucher_type"]) common_filter.append(ple.voucher_no == args["voucher_no"]) # Add cost center condition if args.get("cost_center"): - condition += " and cost_center='%s'" % args.get("cost_center") + condition += f" and cost_center={frappe.db.escape(args.get('cost_center'))}" accounting_dimensions_filter.append(ple.cost_center == args.get("cost_center")) # dynamic dimension filters active_dimensions = get_dimensions()[0] for dim in active_dimensions: if args.get(dim.fieldname): - condition += f" and {dim.fieldname}='{args.get(dim.fieldname)}'" + condition += f" and {dim.fieldname}={frappe.db.escape(args.get(dim.fieldname))}" accounting_dimensions_filter.append(ple[dim.fieldname] == args.get(dim.fieldname)) date_fields_dict = { @@ -2331,17 +2329,15 @@ def get_outstanding_reference_documents(args, validate=False): for fieldname, date_fields in date_fields_dict.items(): if args.get(date_fields[0]) and args.get(date_fields[1]): - condition += " and {} between '{}' and '{}'".format( - fieldname, args.get(date_fields[0]), args.get(date_fields[1]) - ) + condition += f" and {fieldname} between {frappe.db.escape(args.get(date_fields[0]))} and {frappe.db.escape(args.get(date_fields[1]))}" posting_and_due_date.append(ple[fieldname][args.get(date_fields[0]) : args.get(date_fields[1])]) elif args.get(date_fields[0]): # if only from date is supplied - condition += f" and {fieldname} >= '{args.get(date_fields[0])}'" + condition += f" and {fieldname} >= {frappe.db.escape(args.get(date_fields[0]))}" posting_and_due_date.append(ple[fieldname].gte(args.get(date_fields[0]))) elif args.get(date_fields[1]): # if only to date is supplied - condition += f" and {fieldname} <= '{args.get(date_fields[1])}'" + condition += f" and {fieldname} <= {frappe.db.escape(args.get(date_fields[1]))}" posting_and_due_date.append(ple[fieldname].lte(args.get(date_fields[1]))) if args.get("company"): @@ -2561,7 +2557,7 @@ def get_orders_to_be_billed( active_dimensions = get_dimensions(True)[0] for dim in active_dimensions: if filters.get(dim.fieldname): - condition += f" and {dim.fieldname}='{filters.get(dim.fieldname)}'" + condition += f" and {dim.fieldname}={frappe.db.escape(filters.get(dim.fieldname))}" if party_account_currency == company_currency: grand_total_field = "base_grand_total" From 9f04fcc190eac3491d655d101706acbffdbe006c Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 11:35:16 +0000 Subject: [PATCH 39/56] fix(`get_stock_balance`): validate inventory dimension fieldnames (backport #54587) (#54589) Co-authored-by: diptanilsaha fix(`get_stock_balance`): validate inventory dimension fieldnames (#54587) --- erpnext/stock/utils.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py index b4f25e22e04..0e95ba06ab1 100644 --- a/erpnext/stock/utils.py +++ b/erpnext/stock/utils.py @@ -10,6 +10,7 @@ from frappe.query_builder.functions import IfNull, Sum from frappe.utils import cstr, flt, get_link_to_form, get_time, getdate, nowdate, nowtime import erpnext +from erpnext.stock.doctype.inventory_dimension.inventory_dimension import get_inventory_dimensions from erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle import get_available_serial_nos from erpnext.stock.doctype.warehouse.warehouse import get_child_warehouses from erpnext.stock.serial_batch_bundle import BatchNoValuation, SerialNoValuation @@ -122,11 +123,19 @@ def get_stock_balance( } extra_cond = "" + if inventory_dimensions_dict: + inventory_dimensions_fieldname = [d.get("fieldname") for d in get_inventory_dimensions()] + for field, value in inventory_dimensions_dict.items(): - column = frappe.utils.sanitize_column(field) + if field not in inventory_dimensions_fieldname: + frappe.throw( + _("{0} is not a valid {1} fieldname.").format( + frappe.bold(field), frappe.bold("Inventory Dimension") + ) + ) args[field] = value - extra_cond += f" and {column} = %({field})s" + extra_cond += f" and {field} = %({field})s" last_entry = get_previous_sle(args, extra_cond=extra_cond) From fba78711cc7b331725103266aee84faf18bc80e3 Mon Sep 17 00:00:00 2001 From: Abdeali Chharchhoda Date: Thu, 23 Apr 2026 15:43:20 +0530 Subject: [PATCH 40/56] fix: ensure fiscal year is checked before validating date filters in financial statements (cherry picked from commit 5a915cb45e872b45919b6311b9b29037abd5d239) --- erpnext/public/js/financial_statements.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/public/js/financial_statements.js b/erpnext/public/js/financial_statements.js index cdfb8f8a2ca..3d752b9931f 100644 --- a/erpnext/public/js/financial_statements.js +++ b/erpnext/public/js/financial_statements.js @@ -298,7 +298,7 @@ erpnext.financial_statements = { let fiscal_year = erpnext.utils.get_fiscal_year(frappe.datetime.get_today()); var filters = report.get_values(); - if (!filters.period_start_date || !filters.period_end_date) { + if (fiscal_year && (!filters.period_start_date || !filters.period_end_date)) { frappe.model.with_doc("Fiscal Year", fiscal_year, function (r) { var fy = frappe.model.get_doc("Fiscal Year", fiscal_year); frappe.query_report.set_filter_value({ From 6570796fba30acfe0ac610efe6b1163da84c9caf Mon Sep 17 00:00:00 2001 From: Abdeali Chharchhoda Date: Thu, 23 Apr 2026 15:54:42 +0530 Subject: [PATCH 41/56] fix: update fiscal year filter to use mandatory_depends_on instead of reqd (cherry picked from commit 79d6a51e1eb83b341ee92d52c8b2f0e1e2532b48) --- erpnext/public/js/financial_statements.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/public/js/financial_statements.js b/erpnext/public/js/financial_statements.js index 3d752b9931f..9c7929939d1 100644 --- a/erpnext/public/js/financial_statements.js +++ b/erpnext/public/js/financial_statements.js @@ -422,16 +422,16 @@ function get_filters() { label: __("Start Year"), fieldtype: "Link", options: "Fiscal Year", - reqd: 1, depends_on: "eval:doc.filter_based_on == 'Fiscal Year'", + mandatory_depends_on: "eval:doc.filter_based_on == 'Fiscal Year'", }, { fieldname: "to_fiscal_year", label: __("End Year"), fieldtype: "Link", options: "Fiscal Year", - reqd: 1, depends_on: "eval:doc.filter_based_on == 'Fiscal Year'", + mandatory_depends_on: "eval:doc.filter_based_on == 'Fiscal Year'", }, { fieldname: "periodicity", From e6f0bb66e29ee8d9cb8dc7815d005fbe54abe558 Mon Sep 17 00:00:00 2001 From: Abdeali Chharchhoda Date: Thu, 23 Apr 2026 16:29:38 +0530 Subject: [PATCH 42/56] fix: add filter labels and required filters for financial report validation (cherry picked from commit 4274c2aba390348a9786fa99a9f53be7b64416d1) --- .../financial_report_engine.py | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py b/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py index 46369b07cd9..ea2a8d232b8 100644 --- a/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py +++ b/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py @@ -207,6 +207,21 @@ class FormattingRule: # ============================================================================ +FILTER_LABELS = { + "report_template": _("Report Template"), + "filter_based_on": _("Filter Based On"), + "period_start_date": _("Start Date"), + "period_end_date": _("End Date"), + "from_fiscal_year": _("Start Year"), + "to_fiscal_year": _("End Year"), +} + +REQUIRED_FILTERS_BY_BASIS = { + "Date Range": ("period_start_date", "period_end_date"), + "Fiscal Year": ("from_fiscal_year", "to_fiscal_year"), +} + + class FinancialReportEngine: def execute(self, filters: dict[str, Any]) -> tuple[list[dict], list[dict]]: """Execute the complete report generation""" @@ -226,14 +241,24 @@ class FinancialReportEngine: return context.get_result() def _validate_filters(self, filters: dict[str, Any]) -> None: - required_filters = ["report_template", "period_start_date", "period_end_date"] + required_filters = ["report_template", "filter_based_on"] + required_filters.extend(REQUIRED_FILTERS_BY_BASIS.get(filters.get("filter_based_on"), ())) for filter_key in required_filters: if not filters.get(filter_key): - frappe.throw(_("Missing required filter: {0}").format(filter_key)) + frappe.throw( + title=_("Missing Required Filter"), + msg=_("Missing required filter: {0}").format( + frappe.bold(FILTER_LABELS.get(filter_key, filter_key)) + ), + ) if filters.get("presentation_currency"): - frappe.msgprint(_("Currency filters are currently unsupported in Custom Financial Report.")) + frappe.msgprint( + title=_("Unsupported Feature"), + msg=_("Currency filters are currently unsupported in Custom Financial Report."), + indicator="orange", + ) # Margin view is dependent on first row being an income account. Hence not supported. # Way to implement this would be using calculated rows with formulas. From 7b60ec8457fc965ef6371c62aa694b275be27070 Mon Sep 17 00:00:00 2001 From: Abdeali Chharchhoda Date: Thu, 23 Apr 2026 17:05:33 +0530 Subject: [PATCH 43/56] fix: update account identification to avoid using name_field in financial statements (cherry picked from commit 1fd6c3ba1a847720b18bb884164dd200b1fbfa26) --- erpnext/public/js/financial_statements.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/public/js/financial_statements.js b/erpnext/public/js/financial_statements.js index 9c7929939d1..95a4dcc0d17 100644 --- a/erpnext/public/js/financial_statements.js +++ b/erpnext/public/js/financial_statements.js @@ -64,7 +64,7 @@ erpnext.financial_statements = { const isPeriodColumn = periodKeys.includes(baseName); return { - isAccount: baseName === erpnext.financial_statements.name_field, + isAccount: baseName === "account", // DO NOT USE `name_field` ! This can be overridden in some reports! isPeriod: isPeriodColumn, segmentIndex: valueMatch && valueMatch[1] ? parseInt(valueMatch[1]) : null, fieldname: baseName, From 859b24dd951d71a7808c98aca1e5a9090762a46a Mon Sep 17 00:00:00 2001 From: Abdeali Chharchhoda Date: Thu, 23 Apr 2026 17:13:01 +0530 Subject: [PATCH 44/56] chore: minor fix (cherry picked from commit 3854d2cbf6dfef8aecdc1ddb3876e49d35b32c57) --- .../financial_report_engine.py | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py b/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py index ea2a8d232b8..4ea86e2c1f4 100644 --- a/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py +++ b/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py @@ -207,21 +207,6 @@ class FormattingRule: # ============================================================================ -FILTER_LABELS = { - "report_template": _("Report Template"), - "filter_based_on": _("Filter Based On"), - "period_start_date": _("Start Date"), - "period_end_date": _("End Date"), - "from_fiscal_year": _("Start Year"), - "to_fiscal_year": _("End Year"), -} - -REQUIRED_FILTERS_BY_BASIS = { - "Date Range": ("period_start_date", "period_end_date"), - "Fiscal Year": ("from_fiscal_year", "to_fiscal_year"), -} - - class FinancialReportEngine: def execute(self, filters: dict[str, Any]) -> tuple[list[dict], list[dict]]: """Execute the complete report generation""" @@ -241,15 +226,29 @@ class FinancialReportEngine: return context.get_result() def _validate_filters(self, filters: dict[str, Any]) -> None: + filter_labels = { + "report_template": _("Report Template"), + "filter_based_on": _("Filter Based On"), + "period_start_date": _("Start Date"), + "period_end_date": _("End Date"), + "from_fiscal_year": _("Start Year"), + "to_fiscal_year": _("End Year"), + } + + required_filters_by_basis = { + "Date Range": ("period_start_date", "period_end_date"), + "Fiscal Year": ("from_fiscal_year", "to_fiscal_year"), + } + required_filters = ["report_template", "filter_based_on"] - required_filters.extend(REQUIRED_FILTERS_BY_BASIS.get(filters.get("filter_based_on"), ())) + required_filters.extend(required_filters_by_basis.get(filters.get("filter_based_on"), ())) for filter_key in required_filters: if not filters.get(filter_key): frappe.throw( title=_("Missing Required Filter"), msg=_("Missing required filter: {0}").format( - frappe.bold(FILTER_LABELS.get(filter_key, filter_key)) + frappe.bold(filter_labels.get(filter_key, filter_key)) ), ) From 446c111653e097154529c7dee70a2d2cc461cb6b Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Wed, 22 Apr 2026 16:09:42 +0530 Subject: [PATCH 45/56] fix: always exclude pcv entries except for closing account head (cherry picked from commit 0349e7a0b8a146400880a4c35f4cf42f9d5f9709) --- .../financial_report_engine.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py b/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py index 46369b07cd9..8dedffa941b 100644 --- a/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py +++ b/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py @@ -684,11 +684,18 @@ class FinancialQueryBuilder: account_data.unaccumulate_values() def _apply_standard_filters(self, query, table, doctype: str = "GL Entry"): - if self.filters.get("ignore_closing_entries"): - if doctype == "GL Entry": - query = query.where(table.voucher_type != "Period Closing Voucher") - else: - query = query.where(table.is_period_closing_voucher_entry == 0) + # Exclude PCV-generated entries except those posted to a closing-account-head + # so BS retained earnings survive while P&L reversal entries are filtered out + pcv = frappe.qb.DocType("Period Closing Voucher") + closing_heads = frappe.qb.from_(pcv).select(pcv.closing_account_head).where(pcv.docstatus == 1) + + if doctype == "GL Entry": + is_pcv = table.voucher_type == "Period Closing Voucher" + else: + # Account Closing Balance + is_pcv = table.is_period_closing_voucher_entry == 1 + + query = query.where(~is_pcv | table.account.isin(closing_heads)) if self.filters.get("project"): projects = self.filters.get("project") From fa901946ce16ed3dcf19703486e7ad441b8b11d1 Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Tue, 28 Apr 2026 16:30:02 +0530 Subject: [PATCH 46/56] test: pcv is excluded from PL accounts (cherry picked from commit 84aa54c540c6c72610835f89fcc87b6a8051a346) --- .../test_financial_report_engine.py | 208 ++++++++++++++++++ 1 file changed, 208 insertions(+) diff --git a/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py b/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py index ef6f2785184..5b297b332f4 100644 --- a/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py +++ b/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py @@ -10,6 +10,7 @@ from erpnext.accounts.doctype.financial_report_template.financial_report_engine DependencyResolver, FilterExpressionParser, FinancialQueryBuilder, + FinancialReportEngine, FormulaCalculator, PeriodValue, ) @@ -2025,3 +2026,210 @@ class TestFinancialQueryBuilder(FinancialReportTemplateTestCase): finally: jv.cancel() + + def test_pl_pcv_exclusion_and_growth_view_year_over_year(self): + """ + Sequence: + 1. Expense JV 2000 in FY 2024, PCV for FY 2024 + → assert FY 2024 movement = 2000 via FinancialQueryBuilder + 2. Expense JV 3000 in FY 2025, PCV for FY 2025 + 3. Run FinancialReportEngine with selected_view="Growth" + → assert col_2024 = 2000 (raw), col_2025 = 50.0 (% growth) + """ + company = "_Test Company" + expense_account = "Administrative Expenses - _TC" + bank_account = "_Test Bank - _TC" + + template = None + pcv_2024 = None + pcv_2025 = None + jv_2024 = None + jv_2025 = None + original_pcv_setting = frappe.db.get_single_value( + "Accounts Settings", "use_legacy_controller_for_pcv" + ) + + try: + closing_account = frappe.db.get_value( + "Account", + { + "company": company, + "root_type": "Liability", + "is_group": 0, + "account_type": ["not in", ["Payable", "Receivable"]], + }, + "name", + ) + + frappe.db.set_single_value("Accounts Settings", "use_legacy_controller_for_pcv", 1) + + accounts = [ + frappe._dict( + { + "name": expense_account, + "account_name": "Administrative Expenses", + "account_number": "5001", + } + ), + ] + + # --- Step 1: FY 2024 expense + PCV, assert PCV reversal excluded --- + jv_2024 = make_journal_entry( + account1=expense_account, + account2=bank_account, + amount=2000, + posting_date="2024-06-15", + company=company, + submit=True, + ) + fy_2024 = get_fiscal_year("2024-06-15", company=company) + pcv_2024 = frappe.get_doc( + { + "doctype": "Period Closing Voucher", + "transaction_date": "2024-12-31", + "period_start_date": fy_2024[1], + "period_end_date": fy_2024[2], + "company": company, + "fiscal_year": fy_2024[0], + "cost_center": "_Test Cost Center - _TC", + "closing_account_head": closing_account, + "remarks": "Test PCV FY 2024", + } + ) + pcv_2024.insert() + pcv_2024.submit() + pcv_2024.reload() + + builder_2024 = FinancialQueryBuilder( + { + "company": company, + "from_fiscal_year": "2024", + "to_fiscal_year": "2024", + "period_start_date": "2024-01-01", + "period_end_date": "2024-12-31", + "filter_based_on": "Date Range", + "periodicity": "Yearly", + }, + [{"key": "2024", "from_date": "2024-01-01", "to_date": "2024-12-31"}], + ) + data_2024 = builder_2024.fetch_account_balances(accounts) + expense_2024 = data_2024.get(expense_account) + self.assertIsNotNone(expense_2024, "Expense account must appear in FY 2024 results") + year_2024 = expense_2024.get_period("2024") + self.assertEqual( + year_2024.movement, + 2000.0, + "FY 2024 expense movement must equal real expense (PCV reversal excluded)", + ) + + # --- Step 2: FY 2025 expense + PCV --- + jv_2025 = make_journal_entry( + account1=expense_account, + account2=bank_account, + amount=3000, + posting_date="2025-06-15", + company=company, + submit=True, + ) + fy_2025 = get_fiscal_year("2025-06-15", company=company) + pcv_2025 = frappe.get_doc( + { + "doctype": "Period Closing Voucher", + "transaction_date": "2025-12-31", + "period_start_date": fy_2025[1], + "period_end_date": fy_2025[2], + "company": company, + "fiscal_year": fy_2025[0], + "cost_center": "_Test Cost Center - _TC", + "closing_account_head": closing_account, + "remarks": "Test PCV FY 2025", + } + ) + pcv_2025.insert() + pcv_2025.submit() + pcv_2025.reload() + + # --- Step 3: full pipeline with Growth view across both years --- + template_name = f"Test Growth Template {frappe.generate_hash()[:8]}" + template = frappe.get_doc( + { + "doctype": "Financial Report Template", + "template_name": template_name, + "report_type": "Profit and Loss Statement", + "rows": [ + { + "reference_code": "EXP_ADMIN", + "display_name": "Administrative Expenses", + "indentation_level": 0, + "data_source": "Account Data", + "balance_type": "Closing Balance", + "calculation_formula": f'["name", "=", "{expense_account}"]', + }, + ], + } + ) + template.insert() + + filters = frappe._dict( + { + "company": company, + "report_template": template_name, + "from_fiscal_year": fy_2024[0], + "to_fiscal_year": fy_2025[0], + "period_start_date": "2024-01-01", + "period_end_date": "2025-12-31", + "filter_based_on": "Date Range", + "periodicity": "Yearly", + "accumulated_values": 0, + "selected_view": "Growth", + } + ) + + _columns, formatted_data, _msg, _chart = FinancialReportEngine().execute(filters) + + expense_row = next( + (row for row in formatted_data if row.get("account_name") == "Administrative Expenses"), + None, + ) + self.assertIsNotNone(expense_row, "Administrative Expenses row must appear in growth view") + + period_keys = expense_row.get("_segment_info", {}).get("period_keys", []) + self.assertEqual(len(period_keys), 2, "Yearly view must yield exactly two periods") + first_period_key, second_period_key = period_keys + + # First column: raw absolute value (FY 2024 expense) + self.assertEqual( + flt(expense_row[first_period_key]), + 2000.0, + "First column in growth view must keep raw FY 2024 expense value", + ) + # Second column: ((3000 - 2000) / 2000) * 100 = 50.0 + self.assertEqual( + flt(expense_row[second_period_key]), + 50.0, + "Second column must be % growth FY 2024 → FY 2025", + ) + + finally: + frappe.db.set_single_value( + "Accounts Settings", "use_legacy_controller_for_pcv", original_pcv_setting or 0 + ) + + if pcv_2025: + pcv_2025.reload() + if pcv_2025.docstatus == 1: + pcv_2025.cancel() + + if jv_2025 and jv_2025.docstatus == 1: + jv_2025.cancel() + + if pcv_2024: + pcv_2024.reload() + if pcv_2024.docstatus == 1: + pcv_2024.cancel() + + if jv_2024 and jv_2024.docstatus == 1: + jv_2024.cancel() + + if template and frappe.db.exists("Financial Report Template", template.name): + frappe.delete_doc("Financial Report Template", template.name, force=1) From 6bd6e62c8c5219b570556243a1d1965d39b432ff Mon Sep 17 00:00:00 2001 From: vorasmit Date: Fri, 17 Apr 2026 22:27:48 +0530 Subject: [PATCH 47/56] fix: filter opening entries in first year in custom financial statement (cherry picked from commit 3c8a0664849a0972dae7d92aea0bf9181566b4b8) --- .../financial_report_engine.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py b/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py index 46369b07cd9..14a12dde9dd 100644 --- a/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py +++ b/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py @@ -468,6 +468,7 @@ class FinancialQueryBuilder: self.periods = periods self.company = filters.get("company") self.account_meta = {} # {name: {account_name, account_number}} + self.ignore_opening_entries = False def fetch_account_balances(self, accounts: list[dict]) -> dict[str, AccountData]: """ @@ -505,6 +506,8 @@ class FinancialQueryBuilder: """ Return opening balances for *all accounts* defaulting to zero. """ + self.ignore_opening_entries = False + if frappe.get_single_value("Accounts Settings", "ignore_account_closing_balance"): return self._get_opening_balances_from_gl(accounts) @@ -526,6 +529,8 @@ class FinancialQueryBuilder: closing_data = self._get_closing_balances(accounts, closing_voucher.name) if sum(closing_data.values()) != 0.0: + # opening in current period + self.ignore_opening_entries = True return self._rebase_closing_balances(closing_data, closing_voucher.period_end_date) return self._get_opening_balances_from_gl(accounts) @@ -620,7 +625,10 @@ class FinancialQueryBuilder: .groupby(gl_table.account) ) - if not frappe.get_single_value("Accounts Settings", "ignore_is_opening_check_for_reporting"): + ignore_is_opening = frappe.get_single_value( + "Accounts Settings", "ignore_is_opening_check_for_reporting" + ) + if self.ignore_opening_entries and not ignore_is_opening: query = query.where(gl_table.is_opening == "No") # Add period-specific columns From d51ce66cb2989551d2dfba0e7d07df018b95dd7f Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Wed, 22 Apr 2026 13:27:36 +0530 Subject: [PATCH 48/56] fix: summing of values could be zero even if values exist (cherry picked from commit 7ae91cac01556ef2fffcf5f02a2788a2d88c564f) --- .../financial_report_template/financial_report_engine.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py b/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py index 14a12dde9dd..eb94ab7f4b8 100644 --- a/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py +++ b/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py @@ -527,11 +527,9 @@ class FinancialQueryBuilder: if last_closing_voucher: closing_voucher = last_closing_voucher[0] closing_data = self._get_closing_balances(accounts, closing_voucher.name) + self.ignore_opening_entries = True # Else it will double count - if sum(closing_data.values()) != 0.0: - # opening in current period - self.ignore_opening_entries = True - return self._rebase_closing_balances(closing_data, closing_voucher.period_end_date) + return self._rebase_closing_balances(closing_data, closing_voucher.period_end_date) return self._get_opening_balances_from_gl(accounts) From 46759210772387437ab5d1df6d02adadbbd0214c Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Fri, 24 Apr 2026 19:32:00 +0530 Subject: [PATCH 49/56] chore: comment (cherry picked from commit c94b8c41f37f17691bd2c4f53c0612abce8f5fb0) --- .../financial_report_template/financial_report_engine.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py b/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py index eb94ab7f4b8..c24156d6c2c 100644 --- a/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py +++ b/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py @@ -627,6 +627,8 @@ class FinancialQueryBuilder: "Accounts Settings", "ignore_is_opening_check_for_reporting" ) if self.ignore_opening_entries and not ignore_is_opening: + # This filter here applies to all accounts (BS & PL) + # However, in legacy query, this filter only applies to BS accounts query = query.where(gl_table.is_opening == "No") # Add period-specific columns From 7f32c3aca7824e1c411c76f559985555e45d8d49 Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Tue, 28 Apr 2026 16:02:32 +0530 Subject: [PATCH 50/56] test: opening entries after period closing (cherry picked from commit 5fc3ca1d4b0b32bed1330c1b57fd833c5b26ecb9) --- .../test_financial_report_engine.py | 135 ++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py b/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py index ef6f2785184..00e8ceb60d9 100644 --- a/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py +++ b/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py @@ -1952,6 +1952,141 @@ class TestFinancialQueryBuilder(FinancialReportTemplateTestCase): jv_2023.cancel() + def test_opening_entries_roll_into_opening_after_period_closing(self): + """ + Sequence: + 1. is_opening JV of 3000 in current year (FY 2024) + 2. is_opening JV of 5000 in next year (FY 2025) + 3. Period Closing Voucher for previous year (FY 2023) + + Expected (BS report for FY 2024): + opening of FY 2024 = 3000 + 5000 = 8000 + (all is_opening entries roll into opening irrespective of fiscal year, + on top of the PCV carry-forward — here PCV closing for cash is 0). + """ + company = "_Test Company" + cash_account = "_Test Cash - _TC" + # Opening JVs cannot post against P&L accounts; use a Balance Sheet offset. + opening_offset_account = "Temporary Opening - _TC" + + pcv = None + jv_current_year = None + jv_next_year = None + original_pcv_setting = frappe.db.get_single_value( + "Accounts Settings", "use_legacy_controller_for_pcv" + ) + + try: + # Step 1: opening JV in current year (FY 2024) — must be posted before PCV + # exists, else `validate_against_pcv` rejects it. + jv_current_year = make_journal_entry( + account1=cash_account, + account2=opening_offset_account, + amount=3000, + posting_date="2024-06-15", + company=company, + save=False, + ) + jv_current_year.is_opening = "Yes" + jv_current_year.insert() + jv_current_year.submit() + + # Step 2: opening JV in next year (FY 2025) + jv_next_year = make_journal_entry( + account1=cash_account, + account2=opening_offset_account, + amount=5000, + posting_date="2025-06-15", + company=company, + save=False, + ) + jv_next_year.is_opening = "Yes" + jv_next_year.insert() + jv_next_year.submit() + + # Step 3: book Period Closing Voucher for previous year (FY 2023) + closing_account = frappe.db.get_value( + "Account", + { + "company": company, + "root_type": "Liability", + "is_group": 0, + "account_type": ["not in", ["Payable", "Receivable"]], + }, + "name", + ) + fy_2023 = get_fiscal_year("2023-06-15", company=company) + + frappe.db.set_single_value("Accounts Settings", "use_legacy_controller_for_pcv", 1) + + pcv = frappe.get_doc( + { + "doctype": "Period Closing Voucher", + "transaction_date": "2023-12-31", + "period_start_date": fy_2023[1], + "period_end_date": fy_2023[2], + "company": company, + "fiscal_year": fy_2023[0], + "cost_center": "_Test Cost Center - _TC", + "closing_account_head": closing_account, + "remarks": "Test Period Closing", + } + ) + pcv.insert() + pcv.submit() + pcv.reload() + + # Run BS report for FY 2024 + filters = { + "company": company, + "from_fiscal_year": "2024", + "to_fiscal_year": "2024", + "period_start_date": "2024-01-01", + "period_end_date": "2024-12-31", + "filter_based_on": "Date Range", + "periodicity": "Yearly", + "ignore_closing_entries": True, + } + + periods = [{"key": "2024", "from_date": "2024-01-01", "to_date": "2024-12-31"}] + + query_builder = FinancialQueryBuilder(filters, periods) + accounts = [ + frappe._dict({"name": cash_account, "account_name": "Cash", "account_number": "1001"}), + ] + + balances_data = query_builder.fetch_account_balances(accounts) + cash_data = balances_data.get(cash_account) + self.assertIsNotNone(cash_data, "Cash account should exist in results") + + year_2024 = cash_data.get_period("2024") + self.assertIsNotNone(year_2024, "FY 2024 period should exist") + + # All is_opening JVs (current + next year) roll into FY 2024 opening = 8000 + self.assertEqual( + year_2024.opening, + 8000.0, + "FY 2024 opening must combine is_opening JVs from current and next year", + ) + self.assertEqual(year_2024.movement, 0.0, "Opening JVs must not be counted as period movement") + self.assertEqual(year_2024.closing, 8000.0, "Closing = opening when no non-opening movement") + + finally: + frappe.db.set_single_value( + "Accounts Settings", "use_legacy_controller_for_pcv", original_pcv_setting or 0 + ) + + if pcv: + pcv.reload() + if pcv.docstatus == 1: + pcv.cancel() + + if jv_next_year and jv_next_year.docstatus == 1: + jv_next_year.cancel() + + if jv_current_year and jv_current_year.docstatus == 1: + jv_current_year.cancel() + def test_account_with_gl_entries_but_no_prior_closing_balance(self): company = "_Test Company" cash_account = "_Test Cash - _TC" From 64a724baea14b90e33f1c3ef3ac89c4aa3490041 Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Tue, 28 Apr 2026 16:45:26 +0530 Subject: [PATCH 51/56] test: include both accounts to test sum = 0 (cherry picked from commit 590f2ffe284ba46860de3106f4b7c5fb16241b72) --- .../test_financial_report_engine.py | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py b/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py index 00e8ceb60d9..91be22ba08b 100644 --- a/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py +++ b/erpnext/accounts/doctype/financial_report_template/test_financial_report_engine.py @@ -2053,23 +2053,41 @@ class TestFinancialQueryBuilder(FinancialReportTemplateTestCase): query_builder = FinancialQueryBuilder(filters, periods) accounts = [ frappe._dict({"name": cash_account, "account_name": "Cash", "account_number": "1001"}), + frappe._dict( + { + "name": opening_offset_account, + "account_name": "Temporary Opening", + "account_number": "1900", + } + ), ] balances_data = query_builder.fetch_account_balances(accounts) cash_data = balances_data.get(cash_account) + offset_data = balances_data.get(opening_offset_account) self.assertIsNotNone(cash_data, "Cash account should exist in results") + self.assertIsNotNone(offset_data, "Offset account should exist in results") - year_2024 = cash_data.get_period("2024") - self.assertIsNotNone(year_2024, "FY 2024 period should exist") + year_2024_cash = cash_data.get_period("2024") + year_2024_offset = offset_data.get_period("2024") + self.assertIsNotNone(year_2024_cash, "FY 2024 period should exist for cash") + self.assertIsNotNone(year_2024_offset, "FY 2024 period should exist for offset") - # All is_opening JVs (current + next year) roll into FY 2024 opening = 8000 + # All is_opening JVs (current + next year) roll into FY 2024 opening self.assertEqual( - year_2024.opening, + year_2024_cash.opening, 8000.0, - "FY 2024 opening must combine is_opening JVs from current and next year", + "FY 2024 cash opening must combine is_opening JVs from current and next year", ) - self.assertEqual(year_2024.movement, 0.0, "Opening JVs must not be counted as period movement") - self.assertEqual(year_2024.closing, 8000.0, "Closing = opening when no non-opening movement") + self.assertEqual( + year_2024_offset.opening, + -8000.0, + "FY 2024 offset opening must combine is_opening JVs from current and next year", + ) + self.assertEqual( + year_2024_cash.movement, 0.0, "Opening JVs must not be counted as period movement" + ) + self.assertEqual(year_2024_cash.closing, 8000.0, "Closing = opening when no non-opening movement") finally: frappe.db.set_single_value( From deef1696d6a73b7a59f0229f991d5f6a788a7994 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 15:41:59 +0000 Subject: [PATCH 52/56] refactor(`sms_center`): replaced raw SQL queries with `Query Builder` (backport #54600) (#54603) Co-authored-by: diptanilsaha --- .../selling/doctype/sms_center/sms_center.py | 143 ++++++++++++------ 1 file changed, 94 insertions(+), 49 deletions(-) diff --git a/erpnext/selling/doctype/sms_center/sms_center.py b/erpnext/selling/doctype/sms_center/sms_center.py index 99f035141c5..b35b608f4b4 100644 --- a/erpnext/selling/doctype/sms_center/sms_center.py +++ b/erpnext/selling/doctype/sms_center/sms_center.py @@ -6,6 +6,7 @@ import frappe from frappe import _, msgprint from frappe.core.doctype.sms_settings.sms_settings import send_sms from frappe.model.document import Document +from frappe.query_builder import functions as fn from frappe.utils import cstr @@ -41,73 +42,117 @@ class SMSCenter(Document): @frappe.whitelist() def create_receiver_list(self): - rec, where_clause = "", "" - if self.send_to == "All Customer Contact": - where_clause = " and dl.link_doctype = 'Customer'" - if self.customer: - where_clause += ( - " and dl.link_name = '%s'" % self.customer.replace("'", "'") - or " and ifnull(dl.link_name, '') != ''" - ) - if self.send_to == "All Supplier Contact": - where_clause = " and dl.link_doctype = 'Supplier'" - if self.supplier: - where_clause += ( - " and dl.link_name = '%s'" % self.supplier.replace("'", "'") - or " and ifnull(dl.link_name, '') != ''" - ) - if self.send_to == "All Sales Partner Contact": - where_clause = " and dl.link_doctype = 'Sales Partner'" - if self.sales_partner: - where_clause += ( - "and dl.link_name = '%s'" % self.sales_partner.replace("'", "'") - or " and ifnull(dl.link_name, '') != ''" - ) + query = None + + if self.send_to == "": + return + if self.send_to in [ "All Contact", "All Customer Contact", "All Supplier Contact", "All Sales Partner Contact", ]: - rec = frappe.db.sql( - """select CONCAT(ifnull(c.first_name,''), ' ', ifnull(c.last_name,'')), - c.mobile_no from `tabContact` c, `tabDynamic Link` dl where ifnull(c.mobile_no,'')!='' and - c.docstatus != 2 and dl.parent = c.name%s""" - % where_clause - ) + query = self.get_contact_query_for_all_contacts() elif self.send_to == "All Lead (Open)": - rec = frappe.db.sql( - """select lead_name, mobile_no from `tabLead` where - ifnull(mobile_no,'')!='' and docstatus != 2 and status='Open'""" - ) + query = self.get_contact_query_for_all_open_leads() elif self.send_to == "All Employee (Active)": - where_clause = ( - self.department and " and department = '%s'" % self.department.replace("'", "'") or "" - ) - where_clause += self.branch and " and branch = '%s'" % self.branch.replace("'", "'") or "" - - rec = frappe.db.sql( - """select employee_name, cell_number from - `tabEmployee` where status = 'Active' and docstatus < 2 and - ifnull(cell_number,'')!='' %s""" - % where_clause - ) + query = self.get_contact_query_for_all_active_employee() elif self.send_to == "All Sales Person": - rec = frappe.db.sql( - """select sales_person_name, - tabEmployee.cell_number from `tabSales Person` left join tabEmployee - on `tabSales Person`.employee = tabEmployee.name - where ifnull(tabEmployee.cell_number,'')!=''""" - ) + query = self.get_contact_query_for_all_sales_person() + + rec = query.run(as_list=1) rec_list = "" for d in rec: rec_list += d[0] + " - " + d[1] + "\n" self.receiver_list = rec_list + def get_contact_query_for_all_contacts(self): + Contact = frappe.qb.DocType("Contact") + DynamicLink = frappe.qb.DocType("Dynamic Link") + query = ( + frappe.qb.from_(Contact) + .join(DynamicLink) + .on(DynamicLink.parent == Contact.name) + .select( + fn.Concat(fn.IfNull(Contact.first_name, ""), " ", fn.IfNull(Contact.last_name, "")), + Contact.mobile_no, + ) + .where((fn.IfNull(Contact.mobile_no, "") != "") & (Contact.docstatus != 2)) + ) + + if self.send_to == "All Customer Contact": + query = query.where(DynamicLink.link_doctype == "Customer") + query = ( + query.where(DynamicLink.link_name == self.customer) + if self.customer + else query.where(fn.IfNull(DynamicLink.link_name, "") != "") + ) + + elif self.send_to == "All Supplier Contact": + query = query.where(DynamicLink.link_doctype == "Supplier") + query = ( + query.where(DynamicLink.link_name == self.supplier) + if self.supplier + else query.where(fn.IfNull(DynamicLink.link_name, "") != "") + ) + + elif self.send_to == "All Sales Partner Contact": + query = query.where(DynamicLink.link_doctype == "Sales Partner") + query = ( + query.where(DynamicLink.link_name == self.sales_partner) + if self.sales_partner + else query.where(fn.IfNull(DynamicLink.link_name, "") != "") + ) + return query + + def get_contact_query_for_all_open_leads(self): + Lead = frappe.qb.DocType("Lead") + query = ( + frappe.qb.from_(Lead) + .select(Lead.lead_name, Lead.mobile) + .where((fn.IfNull(Lead.mobile_no, "") != "") & (Lead.docstatus != 2) & (Lead.status == "Open")) + ) + return query + + def get_contact_query_for_all_active_employee(self): + Employee = frappe.qb.DocType("Employee") + query = ( + frappe.qb.from_(Employee) + .select(Employee.employee_name, Employee.cell_number) + .where( + (Employee.status == "Active") + & (Employee.docstatus != 2) + & (fn.IfNull(Employee.cell_number, "") != "") + ) + ) + + if self.department: + query = query.where(Employee.department == self.department) + + if self.branch: + query = query.where(Employee.branch == self.branch) + + return query + + def get_contact_query_for_all_sales_person(self): + SalesPerson = frappe.qb.DocType("Sales Person") + Employee = frappe.qb.DocType("Employee") + + query = ( + frappe.qb.from_(SalesPerson) + .left_join(Employee) + .on(SalesPerson.employee == Employee.name) + .select(SalesPerson.sales_person_name, Employee.cell_number) + .where(fn.IfNull(Employee.cell_number, "") != "") + ) + + return query + def get_receiver_nos(self): receiver_nos = [] if self.receiver_list: From 0d498baa100098b2481ad664fdc543a5dddb0d4e Mon Sep 17 00:00:00 2001 From: Trusted Computer <75872475+trustedcomputer@users.noreply.github.com> Date: Tue, 28 Apr 2026 08:42:41 -0700 Subject: [PATCH 53/56] refactor: bring back titles on sales transactions and make them optional and visible on purchase transactions (backport #52633) (#54601) * refactor: bring back titles on sales transactions and make them optional and visible on purchase transactions * fix: update timestamp in json to UTC --- .../doctype/pos_invoice/pos_invoice.json | 16 +++++++++++++++- .../doctype/pos_invoice/pos_invoice.py | 1 + .../purchase_invoice/purchase_invoice.json | 16 +++++++++++++++- .../purchase_invoice/purchase_invoice.py | 1 + .../doctype/sales_invoice/sales_invoice.json | 16 +++++++++++++++- .../doctype/sales_invoice/sales_invoice.py | 1 + .../purchase_order/purchase_order.json | 16 +++++++++++++++- .../doctype/purchase_order/purchase_order.py | 1 + .../request_for_quotation.json | 19 +++++++++++++++++-- .../request_for_quotation.py | 1 + .../supplier_quotation.json | 14 +++++++++----- erpnext/patches.txt | 3 ++- erpnext/patches/v16_0/correct_po_titles.py | 15 +++++++++++++++ .../selling/doctype/quotation/quotation.json | 16 +++++++++++++++- .../selling/doctype/quotation/quotation.py | 1 + .../doctype/sales_order/sales_order.json | 16 +++++++++++++++- .../doctype/sales_order/sales_order.py | 1 + .../doctype/delivery_note/delivery_note.json | 17 +++++++++++++++-- .../doctype/delivery_note/delivery_note.py | 1 + .../purchase_receipt/purchase_receipt.json | 16 +++++++++++++++- .../purchase_receipt/purchase_receipt.py | 1 + 21 files changed, 172 insertions(+), 17 deletions(-) create mode 100644 erpnext/patches/v16_0/correct_po_titles.py diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json index c8fc266b012..248b577d57d 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json @@ -26,6 +26,8 @@ "due_date", "amended_from", "return_against", + "section_break_abck", + "title", "accounting_dimensions_section", "project", "dimension_col_break", @@ -1620,12 +1622,24 @@ "fieldname": "auto_repeat_section", "fieldtype": "Section Break", "label": "Auto Repeat" + }, + { + "fieldname": "section_break_abck", + "fieldtype": "Section Break" + }, + { + "allow_on_submit": 1, + "fieldname": "title", + "fieldtype": "Data", + "label": "Title", + "no_copy": 1, + "print_hide": 1 } ], "icon": "fa fa-file-text", "is_submittable": 1, "links": [], - "modified": "2026-03-02 07:32:47.667810", + "modified": "2026-04-28 06:06:14.283612", "modified_by": "Administrator", "module": "Accounts", "name": "POS Invoice", diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index 503c19c7ff8..a5437409bcd 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -172,6 +172,7 @@ class POSInvoice(SalesInvoice): terms: DF.TextEditor | None territory: DF.Link | None timesheets: DF.Table[SalesInvoiceTimesheet] + title: DF.Data | None to_date: DF.Date | None total: DF.Currency total_advance: DF.Currency diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index f7f8d8b8ffc..4f8fe3a79ca 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -27,6 +27,8 @@ "update_billed_amount_in_purchase_receipt", "apply_tds", "amended_from", + "section_break_hzux", + "title", "supplier_invoice_details", "bill_no", "column_break_15", @@ -1682,6 +1684,18 @@ "fieldname": "automation_section", "fieldtype": "Section Break", "label": "Automation" + }, + { + "fieldname": "section_break_hzux", + "fieldtype": "Section Break" + }, + { + "allow_on_submit": 1, + "fieldname": "title", + "fieldtype": "Data", + "label": "Title", + "no_copy": 1, + "print_hide": 1 } ], "grid_page_length": 50, @@ -1689,7 +1703,7 @@ "idx": 204, "is_submittable": 1, "links": [], - "modified": "2026-03-25 11:45:38.696888", + "modified": "2026-04-28 07:15:31.062404", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice", diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index c790f86633a..a7ef9f1414d 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -203,6 +203,7 @@ class PurchaseInvoice(BuyingController): taxes_and_charges_deducted: DF.Currency tc_name: DF.Link | None terms: DF.TextEditor | None + title: DF.Data | None to_date: DF.Date | None total: DF.Currency total_advance: DF.Currency diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index 267b161bee5..9baa366c27f 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -33,6 +33,8 @@ "is_created_using_pos", "pos_closing_entry", "has_subcontracted", + "section_break_qllv", + "title", "accounting_dimensions_section", "cost_center", "dimension_col_break", @@ -2338,6 +2340,18 @@ { "fieldname": "column_break_iaso", "fieldtype": "Column Break" + }, + { + "fieldname": "section_break_qllv", + "fieldtype": "Section Break" + }, + { + "allow_on_submit": 1, + "fieldname": "title", + "fieldtype": "Data", + "label": "Title", + "no_copy": 1, + "print_hide": 1 } ], "grid_page_length": 50, @@ -2351,7 +2365,7 @@ "link_fieldname": "consolidated_invoice" } ], - "modified": "2026-04-28 12:39:53.267755", + "modified": "2026-04-28 13:08:19.849783", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 0477c172587..ef64a3ef79b 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -225,6 +225,7 @@ class SalesInvoice(SellingController): terms: DF.TextEditor | None territory: DF.Link | None timesheets: DF.Table[SalesInvoiceTimesheet] + title: DF.Data | None to_date: DF.Date | None total: DF.Currency total_advance: DF.Currency diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json index 6d59d0b9884..ee1f13e4b3f 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.json +++ b/erpnext/buying/doctype/purchase_order/purchase_order.json @@ -23,6 +23,8 @@ "is_subcontracted", "has_unit_price_items", "supplier_warehouse", + "section_break_ahub", + "title", "accounting_dimensions_section", "cost_center", "dimension_col_break", @@ -1309,6 +1311,18 @@ "fieldname": "auto_repeat_section", "fieldtype": "Section Break", "label": "Auto Repeat" + }, + { + "fieldname": "section_break_ahub", + "fieldtype": "Section Break" + }, + { + "allow_on_submit": 1, + "fieldname": "title", + "fieldtype": "Data", + "label": "Title", + "no_copy": 1, + "print_hide": 1 } ], "grid_page_length": 50, @@ -1316,7 +1330,7 @@ "idx": 105, "is_submittable": 1, "links": [], - "modified": "2026-03-25 11:46:18.748951", + "modified": "2026-04-28 06:11:46.904768", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order", diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 2cb285c14f3..48ed761829e 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -159,6 +159,7 @@ class PurchaseOrder(BuyingController): taxes_and_charges_deducted: DF.Currency tc_name: DF.Link | None terms: DF.TextEditor | None + title: DF.Data | None to_date: DF.Date | None total: DF.Currency total_net_weight: DF.Float diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.json b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.json index de8b4d28547..988ffcb9eb3 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.json +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.json @@ -16,6 +16,8 @@ "status", "has_unit_price_items", "amended_from", + "section_break_mhyw", + "title", "suppliers_section", "suppliers", "items_section", @@ -371,6 +373,18 @@ "fieldtype": "Text Editor", "label": "Shipping Address Details", "read_only": 1 + }, + { + "fieldname": "section_break_mhyw", + "fieldtype": "Section Break" + }, + { + "allow_on_submit": 1, + "fieldname": "title", + "fieldtype": "Data", + "label": "Title", + "no_copy": 1, + "print_hide": 1 } ], "grid_page_length": 50, @@ -378,7 +392,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2026-03-19 15:27:56.730649", + "modified": "2026-04-28 06:18:05.661710", "modified_by": "Administrator", "module": "Buying", "name": "Request for Quotation", @@ -448,5 +462,6 @@ "show_name_in_global_search": 1, "sort_field": "creation", "sort_order": "DESC", - "states": [] + "states": [], + "title_field": "company" } diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py index 03254c30f6e..c99d0f00606 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py @@ -63,6 +63,7 @@ class RequestforQuotation(BuyingController): suppliers: DF.Table[RequestforQuotationSupplier] tc_name: DF.Link | None terms: DF.TextEditor | None + title: DF.Data | None transaction_date: DF.Date use_html: DF.Check vendor: DF.Link | None diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json index bb1c048301e..ec0b33611b3 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json @@ -9,7 +9,6 @@ "engine": "InnoDB", "field_order": [ "supplier_section", - "title", "naming_series", "supplier", "supplier_name", @@ -21,6 +20,8 @@ "quotation_number", "has_unit_price_items", "amended_from", + "section_break_kumc", + "title", "accounting_dimensions_section", "cost_center", "dimension_col_break", @@ -127,10 +128,9 @@ "options": "fa fa-user" }, { - "default": "{supplier_name}", + "allow_on_submit": 1, "fieldname": "title", "fieldtype": "Data", - "hidden": 1, "label": "Title", "no_copy": 1, "print_hide": 1, @@ -940,6 +940,10 @@ "fieldname": "auto_repeat_section", "fieldtype": "Section Break", "label": "Auto Repeat" + }, + { + "fieldname": "section_break_kumc", + "fieldtype": "Section Break" } ], "grid_page_length": 50, @@ -948,7 +952,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2026-02-27 18:05:50.121391", + "modified": "2026-04-28 06:23:52.813948", "modified_by": "Administrator", "module": "Buying", "name": "Supplier Quotation", @@ -1016,5 +1020,5 @@ "sort_order": "DESC", "states": [], "timeline_field": "supplier", - "title_field": "title" + "title_field": "supplier_name" } diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 1eb86cef190..f9fd4a5cb66 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -478,4 +478,5 @@ erpnext.patches.v16_0.uom_category erpnext.patches.v16_0.merge_repost_settings_to_accounts_settings erpnext.patches.v16_0.set_root_type_in_account_categories erpnext.patches.v16_0.scr_inv_dimension -erpnext.patches.v16_0.packed_item_inv_dimen \ No newline at end of file +erpnext.patches.v16_0.packed_item_inv_dimen +erpnext.patches.v16_0.correct_po_titles \ No newline at end of file diff --git a/erpnext/patches/v16_0/correct_po_titles.py b/erpnext/patches/v16_0/correct_po_titles.py new file mode 100644 index 00000000000..04334e52ca7 --- /dev/null +++ b/erpnext/patches/v16_0/correct_po_titles.py @@ -0,0 +1,15 @@ +import frappe + + +def execute(): + """ + This patch corrects the titles of purchase orders that were set to + the text string "{supplier_name}" instead of the actual supplier name. + """ + + purchase_order = frappe.qb.DocType("Purchase Order") + ( + frappe.qb.update(purchase_order) + .set(purchase_order.title, purchase_order.supplier_name) + .where(purchase_order.title == "{supplier_name}") + ).run() diff --git a/erpnext/selling/doctype/quotation/quotation.json b/erpnext/selling/doctype/quotation/quotation.json index 71d977638e8..c22bd3b3e68 100644 --- a/erpnext/selling/doctype/quotation/quotation.json +++ b/erpnext/selling/doctype/quotation/quotation.json @@ -22,6 +22,8 @@ "company", "has_unit_price_items", "amended_from", + "section_break_jdzz", + "title", "currency_and_price_list", "currency", "conversion_rate", @@ -1122,13 +1124,25 @@ "fieldname": "auto_repeat_section", "fieldtype": "Section Break", "label": "Auto Repeat" + }, + { + "fieldname": "section_break_jdzz", + "fieldtype": "Section Break" + }, + { + "allow_on_submit": 1, + "fieldname": "title", + "fieldtype": "Data", + "label": "Title", + "no_copy": 1, + "print_hide": 1 } ], "icon": "fa fa-shopping-cart", "idx": 82, "is_submittable": 1, "links": [], - "modified": "2026-03-09 17:15:31.941114", + "modified": "2026-04-28 06:28:13.103302", "modified_by": "Administrator", "module": "Selling", "name": "Quotation", diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index 3eb82af1b01..dcdf4adcd35 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -112,6 +112,7 @@ class Quotation(SellingController): tc_name: DF.Link | None terms: DF.TextEditor | None territory: DF.Link | None + title: DF.Data | None total: DF.Currency total_net_weight: DF.Float total_qty: DF.Float diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json index 3109fd0e36e..a8506dfb03f 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.json +++ b/erpnext/selling/doctype/sales_order/sales_order.json @@ -26,6 +26,8 @@ "has_unit_price_items", "is_subcontracted", "amended_from", + "section_break_zstt", + "title", "accounting_dimensions_section", "cost_center", "dimension_col_break", @@ -1742,6 +1744,18 @@ "no_copy": 1, "print_hide": 1, "read_only": 1 + }, + { + "fieldname": "section_break_zstt", + "fieldtype": "Section Break" + }, + { + "allow_on_submit": 1, + "fieldname": "title", + "fieldtype": "Data", + "label": "Title", + "no_copy": 1, + "print_hide": 1 } ], "grid_page_length": 50, @@ -1749,7 +1763,7 @@ "idx": 105, "is_submittable": 1, "links": [], - "modified": "2026-03-04 18:04:05.873483", + "modified": "2026-04-28 06:30:35.902868", "modified_by": "Administrator", "module": "Selling", "name": "Sales Order", diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 619f5cfcf19..e63ac802e35 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -181,6 +181,7 @@ class SalesOrder(SellingController): tc_name: DF.Link | None terms: DF.TextEditor | None territory: DF.Link | None + title: DF.Data | None to_date: DF.Date | None total: DF.Currency total_commission: DF.Currency diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.json b/erpnext/stock/doctype/delivery_note/delivery_note.json index e8871227c60..0b620fd189c 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.json +++ b/erpnext/stock/doctype/delivery_note/delivery_note.json @@ -22,6 +22,8 @@ "is_return", "issue_credit_note", "return_against", + "section_break_zxcd", + "title", "accounting_dimensions_section", "cost_center", "column_break_18", @@ -76,7 +78,6 @@ "base_totals_section", "base_grand_total", "base_in_words", - "column_break_ydwe", "base_rounding_adjustment", "base_rounded_total", "section_break_49", @@ -1446,13 +1447,25 @@ "fieldname": "auto_repeat_section", "fieldtype": "Section Break", "label": "Auto Repeat" + }, + { + "fieldname": "section_break_zxcd", + "fieldtype": "Section Break" + }, + { + "allow_on_submit": 1, + "fieldname": "title", + "fieldtype": "Data", + "label": "Title", + "no_copy": 1, + "print_hide": 1 } ], "icon": "fa fa-truck", "idx": 146, "is_submittable": 1, "links": [], - "modified": "2026-03-09 17:15:27.932956", + "modified": "2026-04-28 06:37:33.600775", "modified_by": "Administrator", "module": "Stock", "name": "Delivery Note", diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index e0154bf13cc..f0e44ed368d 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -145,6 +145,7 @@ class DeliveryNote(SellingController): tc_name: DF.Link | None terms: DF.TextEditor | None territory: DF.Link | None + title: DF.Data | None total: DF.Currency total_commission: DF.Currency total_net_weight: DF.Float diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json index 82745b34bbf..5238eca245a 100755 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json @@ -25,6 +25,8 @@ "apply_putaway_rule", "is_return", "return_against", + "section_break_yxar", + "title", "accounting_dimensions_section", "cost_center", "dimension_col_break", @@ -1285,6 +1287,18 @@ { "fieldname": "column_break_ugyv", "fieldtype": "Column Break" + }, + { + "fieldname": "section_break_yxar", + "fieldtype": "Section Break" + }, + { + "allow_on_submit": 1, + "fieldname": "title", + "fieldtype": "Data", + "label": "Title", + "no_copy": 1, + "print_hide": 1 } ], "grid_page_length": 50, @@ -1292,7 +1306,7 @@ "idx": 261, "is_submittable": 1, "links": [], - "modified": "2026-04-06 14:11:29.630333", + "modified": "2026-04-28 06:47:12.170270", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt", diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index ac738fe66d8..d28cce17c00 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -148,6 +148,7 @@ class PurchaseReceipt(BuyingController): taxes_and_charges_deducted: DF.Currency tc_name: DF.Link | None terms: DF.TextEditor | None + title: DF.Data | None total: DF.Currency total_net_weight: DF.Float total_qty: DF.Float From 11117710d3f7cf35d85461bbb214c1ba8730f0d2 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 22:23:13 +0530 Subject: [PATCH 54/56] =?UTF-8?q?fix:=20duplicate=20entries=20being=20show?= =?UTF-8?q?n=20in=20batch=20exists=20in=20future=20transact=E2=80=A6=20(ba?= =?UTF-8?q?ckport=20#54604)=20(#54606)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: duplicate entries being shown in batch exists in future transact… (#54604) fix: duplicate entries being shown in batch exists in future transactions msg (cherry picked from commit 54f20de7e3f261b311338475740e8c082b69beb3) Co-authored-by: Mihir Kandoi --- .../doctype/serial_and_batch_bundle/serial_and_batch_bundle.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index 67a85a03705..bd8b0af1db2 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -931,6 +931,7 @@ class SerialandBatchBundle(Document): parent.voucher_type, parent.voucher_no, ) + .distinct() .where( (child.parent != self.name) & (parent.item_code == self.item_code) From 8f8bf13b41ee49bbbac688e5e3338defd94009ad Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 01:25:31 +0530 Subject: [PATCH 55/56] fix: filter overdue purchase order items by company (backport #54099) (#54611) Co-authored-by: Ravibharathi <131471282+ravibharathi656@users.noreply.github.com> fix: filter overdue purchase order items by company (#54099) --- .../doctype/email_digest/email_digest.py | 57 +++++++++------ .../email_digest/templates/default.html | 58 +++++++-------- .../doctype/email_digest/test_email_digest.py | 73 ++++++++++++++++++- 3 files changed, 133 insertions(+), 55 deletions(-) diff --git a/erpnext/setup/doctype/email_digest/email_digest.py b/erpnext/setup/doctype/email_digest/email_digest.py index 7f087768fe7..4e323097970 100644 --- a/erpnext/setup/doctype/email_digest/email_digest.py +++ b/erpnext/setup/doctype/email_digest/email_digest.py @@ -158,10 +158,7 @@ class EmailDigest(Document): context.quote = {"text": quote[0], "author": quote[1]} if self.get("purchase_orders_items_overdue"): - ( - context.purchase_order_list, - context.purchase_orders_items_overdue_list, - ) = self.get_purchase_orders_items_overdue_list() + context.purchase_orders_items_overdue_map = self.get_purchase_orders_items_overdue_list() if not context: return None @@ -860,30 +857,42 @@ class EmailDigest(Document): return fmt_money(value, currency=self.currency) def get_purchase_orders_items_overdue_list(self): - fields_po = "distinct `tabPurchase Order Item`.parent as po" - fields_poi = ( - "`tabPurchase Order Item`.parent, `tabPurchase Order Item`.schedule_date, item_code," - "received_qty, qty - received_qty as missing_qty, rate, amount" + po = frappe.qb.DocType("Purchase Order") + poi = frappe.qb.DocType("Purchase Order Item") + + query = ( + frappe.qb.from_(poi) + .select( + poi.parent, + poi.schedule_date, + poi.item_code, + poi.received_qty, + (poi.qty - poi.received_qty).as_("missing_qty"), + poi.rate, + poi.amount, + po.currency, + ) + .inner_join(po) + .on(po.name == poi.parent) + .where(po.status != "Closed") + .where(poi.docstatus == 1) + .where(poi.schedule_date < today()) + .where(poi.received_qty < poi.qty) + .where(po.company == self.company) + .orderby(poi.parent, order=frappe.qb.desc) + .orderby(poi.idx) ) - sql_po = f"""select {fields_po} from `tabPurchase Order Item` - left join `tabPurchase Order` on `tabPurchase Order`.name = `tabPurchase Order Item`.parent - where status<>'Closed' and `tabPurchase Order Item`.docstatus=1 and CURRENT_DATE > `tabPurchase Order Item`.schedule_date - and received_qty < qty order by `tabPurchase Order Item`.parent DESC, - `tabPurchase Order Item`.schedule_date DESC""" + items_by_parent = frappe._dict() - sql_poi = f"""select {fields_poi} from `tabPurchase Order Item` - left join `tabPurchase Order` on `tabPurchase Order`.name = `tabPurchase Order Item`.parent - where status<>'Closed' and `tabPurchase Order Item`.docstatus=1 and CURRENT_DATE > `tabPurchase Order Item`.schedule_date - and received_qty < qty order by `tabPurchase Order Item`.idx""" - purchase_order_list = frappe.db.sql(sql_po, as_dict=True) - purchase_order_items_overdue_list = frappe.db.sql(sql_poi, as_dict=True) + for row in query.run(as_dict=True): + row.link = get_url_to_form("Purchase Order", row.parent) + row.rate = fmt_money(row.rate, 2, row.currency) + row.amount = fmt_money(row.amount, 2, row.currency) - for t in purchase_order_items_overdue_list: - t.link = get_url_to_form("Purchase Order", t.parent) - t.rate = fmt_money(t.rate, 2, t.currency) - t.amount = fmt_money(t.amount, 2, t.currency) - return purchase_order_list, purchase_order_items_overdue_list + items_by_parent.setdefault(row.parent, []).append(row) + + return items_by_parent def send(): diff --git a/erpnext/setup/doctype/email_digest/templates/default.html b/erpnext/setup/doctype/email_digest/templates/default.html index 666301a643e..722a2470772 100644 --- a/erpnext/setup/doctype/email_digest/templates/default.html +++ b/erpnext/setup/doctype/email_digest/templates/default.html @@ -182,7 +182,7 @@ {% endif %} -{% if purchase_orders_items_overdue_list %} +{% if purchase_orders_items_overdue_map %}

        {{ _("Purchase Order Items not received on time") }}

        @@ -206,43 +206,41 @@
        - {% for po in purchase_order_list %} + {% for po, po_items in purchase_orders_items_overdue_map.items() %}
        diff --git a/erpnext/setup/doctype/email_digest/test_email_digest.py b/erpnext/setup/doctype/email_digest/test_email_digest.py index 7ea0da03382..3b45cb7da01 100644 --- a/erpnext/setup/doctype/email_digest/test_email_digest.py +++ b/erpnext/setup/doctype/email_digest/test_email_digest.py @@ -2,8 +2,79 @@ # See license.txt import unittest +import frappe +from frappe.utils import add_days, today + +from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order from erpnext.tests.utils import ERPNextTestSuite class TestEmailDigest(ERPNextTestSuite): - pass + def test_purchase_orders_items_overdue_list_is_filtered_by_company(self): + digest = create_email_digest( + company="_Test Company", + frequency="Daily", + purchase_orders_items_overdue=1, + name="Test Email Digest PO Company Filter", + ) + backdate = add_days(today(), -1) + + po1 = create_purchase_order(transaction_date=backdate, do_not_save=True) + po1.schedule_date = backdate + po1.items[0].schedule_date = backdate + po1.insert() + po1.submit() + + po2 = create_purchase_order( + company="_Test Company 1", + warehouse="Stores - _TC1", + transaction_date=backdate, + do_not_save=True, + ) + po2.schedule_date = backdate + po2.items[0].schedule_date = backdate + po2.insert() + po2.submit() + + overdue_items = digest.get_purchase_orders_items_overdue_list() + + self.assertIn(po1.name, overdue_items) + self.assertNotIn(po2.name, overdue_items) + + +def create_email_digest(**args): + args = frappe._dict(args) + doc = frappe.new_doc("Email Digest") + doc.name = args.name or "Test Email Digest" + doc.company = args.company or "_Test Company" + doc.frequency = args.frequency or "Daily" + doc.enabled = args.enabled or 0 + doc.bank_balance = args.bank_balance or 0 + doc.credit_balance = args.credit_balance or 0 + doc.invoiced_amount = args.invoiced_amount or 0 + doc.payables = args.payables or 0 + doc.sales_orders_to_bill = args.sales_orders_to_bill or 0 + doc.purchase_orders_to_bill = args.purchase_orders_to_bill or 0 + doc.sales_order = args.sales_order or 0 + doc.purchase_order = args.purchase_order or 0 + doc.sales_orders_to_deliver = args.sales_orders_to_deliver or 0 + doc.purchase_orders_to_receive = args.purchase_orders_to_receive or 0 + doc.sales_invoice = args.sales_invoice or 0 + doc.purchase_invoice = args.purchase_invoice or 0 + doc.new_quotations = args.new_quotations or 0 + doc.pending_quotations = args.pending_quotations or 0 + doc.issue = args.issue or 0 + doc.project = args.project or 0 + doc.purchase_orders_items_overdue = args.purchase_orders_items_overdue or 0 + doc.calendar_events = args.calendar_events or 0 + doc.todo_list = args.todo_list or 0 + doc.notifications = args.notifications or 0 + doc.add_quote = args.add_quote or 0 + + for recipient in args.recipients or ["Administrator"]: + doc.append("recipients", {"recipient": recipient}) + + if not args.do_not_save: + doc.insert() + + return doc From 5de4b013eada0e9a4a14896a00a395a0f122519a Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 20:41:42 +0000 Subject: [PATCH 56/56] fix: avoid double reduction of pe reference outstanding (backport #54193) (#54613) * fix: avoid double reduction of pe reference outstanding (#54193) Co-authored-by: diptanilsaha (cherry picked from commit d1a80d40c4f8e7459a76640ecadf1cf9173509cf) # Conflicts: # erpnext/accounts/utils.py * chore: remove type hints for function parameters --------- Co-authored-by: Ravibharathi <131471282+ravibharathi656@users.noreply.github.com> Co-authored-by: diptanilsaha --- .../payment_entry/test_payment_entry.py | 24 +++++++++++++++++++ erpnext/accounts/utils.py | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py index f6a23ddf450..759a6f0cfa2 100644 --- a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py @@ -195,6 +195,30 @@ class TestPaymentEntry(ERPNextTestSuite): outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount")) self.assertEqual(outstanding_amount, 100) + def test_reference_outstanding_amount_on_advance_pull(self): + from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice + + so = make_sales_order(qty=1, rate=1000) + pe = get_payment_entry("Sales Order", so.name, bank_account="_Test Cash - _TC") + pe.paid_amount = pe.received_amount = 500 + pe.references[0].allocated_amount = 500 + pe.insert() + pe.submit() + + so.reload() + self.assertEqual(so.advance_paid, 500) + + si = make_sales_invoice(so.name) + si.allocate_advances_automatically = 1 + si.save() + self.assertEqual(si.get("advances")[0].allocated_amount, 500) + self.assertEqual(si.get("advances")[0].reference_name, pe.name) + si.submit() + + pe.load_from_db() + self.assertEqual(pe.references[0].reference_name, si.name) + self.assertEqual(pe.references[0].outstanding_amount, si.outstanding_amount) + def test_payment_entry_against_pi(self): pi = make_purchase_invoice( supplier="_Test Supplier USD", diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index fe68c4018aa..c1e8a831b2c 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -546,7 +546,7 @@ def reconcile_against_document( skip_ref_details_update_for_pe=skip_ref_details_update_for_pe, dimensions_dict=dimensions_dict, ) - if referenced_row.get("outstanding_amount"): + if referenced_row.get("outstanding_amount") and entry.get("outstanding_amount") is None: referenced_row.outstanding_amount -= flt(entry.allocated_amount) reposting_rows.append(referenced_row)
        - {{ po.po }} + {{ po | e }}
        - {% for t in purchase_orders_items_overdue_list %} - {% if t.parent == po.po %} -
        - - - - - - - -
        - {{ _(t.item_code) }} - - - {{ t.missing_qty }} - - - - {{ t.rate }} - - - - {{ t.amount }} - -
        -
        - {% endif %} + {% for row in po_items %} +
        + + + + + + + +
        + {{ _(row.item_code) | e }} + + + {{ row.missing_qty | e }} + + + + {{ row.rate | e }} + + + + {{ row.amount | e }} + +
        +
        {% endfor %}