diff --git a/erpnext/accounts/doctype/bank_account/bank_account.json b/erpnext/accounts/doctype/bank_account/bank_account.json index 962551b2417..4946dc168ba 100644 --- a/erpnext/accounts/doctype/bank_account/bank_account.json +++ b/erpnext/accounts/doctype/bank_account/bank_account.json @@ -132,7 +132,8 @@ "fieldtype": "Data", "in_list_view": 1, "label": "IBAN", - "length": 30 + "length": 34, + "options": "IBAN" }, { "fieldname": "column_break_12", @@ -208,6 +209,7 @@ "label": "Disabled" } ], + "grid_page_length": 50, "links": [ { "group": "Transactions", @@ -250,7 +252,7 @@ "link_fieldname": "default_bank_account" } ], - "modified": "2024-10-30 09:41:14.113414", + "modified": "2025-08-29 12:32:01.081687", "modified_by": "Administrator", "module": "Accounts", "name": "Bank Account", @@ -282,6 +284,7 @@ "write": 1 } ], + "row_format": "Dynamic", "search_fields": "bank,account", "sort_field": "modified", "sort_order": "DESC", diff --git a/erpnext/accounts/doctype/bank_account/bank_account.py b/erpnext/accounts/doctype/bank_account/bank_account.py index 5a728eb415b..5a874701a39 100644 --- a/erpnext/accounts/doctype/bank_account/bank_account.py +++ b/erpnext/accounts/doctype/bank_account/bank_account.py @@ -9,7 +9,8 @@ from frappe.contacts.address_and_contact import ( load_address_and_contact, ) from frappe.model.document import Document -from frappe.utils import comma_and, get_link_to_form +from frappe.utils import comma_and, get_link_to_form, validate_iban +from frappe.utils.deprecations import deprecated class BankAccount(Document): @@ -52,7 +53,6 @@ class BankAccount(Document): def validate(self): self.validate_company() - self.validate_iban() self.validate_account() self.update_default_bank_account() @@ -72,34 +72,10 @@ class BankAccount(Document): if self.is_company_account and not self.company: frappe.throw(_("Company is manadatory for company account")) + @deprecated def validate_iban(self): - """ - Algorithm: https://en.wikipedia.org/wiki/International_Bank_Account_Number#Validating_the_IBAN - """ - # IBAN field is optional - if not self.iban: - return - - def encode_char(c): - # Position in the alphabet (A=1, B=2, ...) plus nine - return str(9 + ord(c) - 64) - - # remove whitespaces, upper case to get the right number from ord() - iban = "".join(self.iban.split(" ")).upper() - - # Move country code and checksum from the start to the end - flipped = iban[4:] + iban[:4] - - # Encode characters as numbers - encoded = [encode_char(c) if ord(c) >= 65 and ord(c) <= 90 else c for c in flipped] - - try: - to_check = int("".join(encoded)) - except ValueError: - frappe.throw(_("IBAN is not valid")) - - if to_check % 97 != 1: - frappe.throw(_("IBAN is not valid")) + """Kept for backward compatibility, will be removed in v16.""" + validate_iban(self.iban, throw=True) def update_default_bank_account(self): if self.is_default and not self.disabled: diff --git a/erpnext/accounts/doctype/bank_account/test_bank_account.py b/erpnext/accounts/doctype/bank_account/test_bank_account.py index 0ec388d9e5c..d285b89d10c 100644 --- a/erpnext/accounts/doctype/bank_account/test_bank_account.py +++ b/erpnext/accounts/doctype/bank_account/test_bank_account.py @@ -3,45 +3,8 @@ import unittest -import frappe -from frappe import ValidationError - # test_records = frappe.get_test_records('Bank Account') class TestBankAccount(unittest.TestCase): - def test_validate_iban(self): - valid_ibans = [ - "GB82 WEST 1234 5698 7654 32", - "DE91 1000 0000 0123 4567 89", - "FR76 3000 6000 0112 3456 7890 189", - ] - - invalid_ibans = [ - # wrong checksum (3rd place) - "GB72 WEST 1234 5698 7654 32", - "DE81 1000 0000 0123 4567 89", - "FR66 3000 6000 0112 3456 7890 189", - ] - - bank_account = frappe.get_doc({"doctype": "Bank Account"}) - - try: - bank_account.validate_iban() - except AttributeError: - msg = "BankAccount.validate_iban() failed for empty IBAN" - self.fail(msg=msg) - - for iban in valid_ibans: - bank_account.iban = iban - try: - bank_account.validate_iban() - except ValidationError: - msg = f"BankAccount.validate_iban() failed for valid IBAN {iban}" - self.fail(msg=msg) - - for not_iban in invalid_ibans: - bank_account.iban = not_iban - msg = f"BankAccount.validate_iban() accepted invalid IBAN {not_iban}" - with self.assertRaises(ValidationError, msg=msg): - bank_account.validate_iban() + pass diff --git a/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.json b/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.json index dc5413e973c..c255ce7ba8f 100644 --- a/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.json +++ b/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.json @@ -146,6 +146,7 @@ "fieldname": "iban", "fieldtype": "Data", "label": "IBAN", + "options": "IBAN", "read_only": 1 }, { @@ -216,7 +217,7 @@ ], "is_submittable": 1, "links": [], - "modified": "2025-09-25 23:44:12.473583", + "modified": "2025-09-26 00:38:17.584694", "modified_by": "Administrator", "module": "Accounts", "name": "Bank Guarantee", diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.json b/erpnext/accounts/doctype/bank_transaction/bank_transaction.json index 37fbd261898..02ff1dbf3e9 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.json +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.json @@ -223,7 +223,8 @@ { "fieldname": "bank_party_iban", "fieldtype": "Data", - "label": "Party IBAN (Bank Statement)" + "label": "Party IBAN (Bank Statement)", + "options": "IBAN" }, { "fieldname": "bank_party_account_number", @@ -238,7 +239,7 @@ "grid_page_length": 50, "is_submittable": 1, "links": [], - "modified": "2025-09-26 17:06:29.207673", + "modified": "2025-10-14 11:53:45.908169", "modified_by": "Administrator", "module": "Accounts", "name": "Bank Transaction", diff --git a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json index 5d31c627381..b333e103b59 100644 --- a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json +++ b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json @@ -272,7 +272,8 @@ "label": "Advance Voucher Type", "no_copy": 1, "options": "DocType", - "read_only": 1 + "read_only": 1, + "search_index": 1 }, { "fieldname": "advance_voucher_no", @@ -280,13 +281,14 @@ "label": "Advance Voucher No", "no_copy": 1, "options": "advance_voucher_type", - "read_only": 1 + "read_only": 1, + "search_index": 1 } ], "idx": 1, "istable": 1, "links": [], - "modified": "2025-09-29 13:01:48.916517", + "modified": "2025-10-20 17:46:47.344089", "modified_by": "Administrator", "module": "Accounts", "name": "Journal Entry Account", diff --git a/erpnext/accounts/doctype/payment_request/payment_request.json b/erpnext/accounts/doctype/payment_request/payment_request.json index 5a19a080484..6853e9ca1fb 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.json +++ b/erpnext/accounts/doctype/payment_request/payment_request.json @@ -226,7 +226,8 @@ "fetch_from": "bank_account.iban", "fieldname": "iban", "fieldtype": "Read Only", - "label": "IBAN" + "label": "IBAN", + "options": "IBAN" }, { "fetch_from": "bank_account.branch_code", @@ -443,11 +444,12 @@ "label": "Phone Number" } ], + "grid_page_length": 50, "in_create": 1, "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2024-12-27 21:29:10.361894", + "modified": "2025-08-29 11:52:48.555415", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Request", @@ -482,8 +484,9 @@ "write": 1 } ], + "row_format": "Dynamic", "show_preview_popup": 1, "sort_field": "modified", "sort_order": "DESC", "states": [] -} \ No newline at end of file +} diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 0f4d7cf496c..5cbba410f86 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -644,9 +644,8 @@ class PurchaseOrder(BuyingController): if not self.is_against_so(): return for item in removed_items: - prev_ordered_qty = ( + prev_ordered_qty = flt( frappe.get_cached_value("Sales Order Item", item.get("sales_order_item"), "ordered_qty") - or 0.0 ) frappe.db.set_value( diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 96864bb5a60..b134e79a137 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -3073,9 +3073,7 @@ def set_balance_in_account_currency( _("Account: {0} with currency: {1} can not be selected").format(gl_dict.account, account_currency) ) - gl_dict["account_currency"] = ( - company_currency if account_currency == company_currency else account_currency - ) + gl_dict["account_currency"] = account_currency # set debit/credit in account currency if not provided if flt(gl_dict.debit) and not flt(gl_dict.debit_in_account_currency): diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 1726756cc26..035dfc6e264 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -1552,7 +1552,9 @@ def get_stock_ledger_preview(doc, filters): if doc.get("update_stock") or doc.doctype in ("Purchase Receipt", "Delivery Note"): doc.docstatus = 1 + doc.make_bundle_using_old_serial_batch_fields() doc.update_stock_ledger() + columns = get_sl_columns(filters) sl_entries = get_sl_entries_for_preview(doc.doctype, doc.name, fields) diff --git a/erpnext/public/js/controllers/buying.js b/erpnext/public/js/controllers/buying.js index 8c0be8042ac..e0e68c37451 100644 --- a/erpnext/public/js/controllers/buying.js +++ b/erpnext/public/js/controllers/buying.js @@ -17,7 +17,17 @@ erpnext.buying = { this.setup_queries(doc, cdt, cdn); super.onload(); - this.frm.set_query('shipping_rule', function() { + if (["Purchase Order", "Purchase Receipt", "Purchase Invoice"].includes(this.frm.doctype)) { + this.frm.set_query("supplier", function () { + return { + filters: { + is_transporter: 0, + }, + }; + }); + } + + this.frm.set_query("shipping_rule", function () { return { filters: { "shipping_rule_type": "Buying" diff --git a/erpnext/selling/page/point_of_sale/pos_payment.js b/erpnext/selling/page/point_of_sale/pos_payment.js index 92e9ad060df..165066a151a 100644 --- a/erpnext/selling/page/point_of_sale/pos_payment.js +++ b/erpnext/selling/page/point_of_sale/pos_payment.js @@ -394,6 +394,10 @@ erpnext.PointOfSale.Payment = class { const payments = doc.payments; const currency = doc.currency; + if (!this.$payment_modes.is(":visible")) { + return; + } + this.$payment_modes.html( `${payments .map((p, i) => { @@ -612,6 +616,10 @@ erpnext.PointOfSale.Payment = class { const currency = doc.currency; const label = __("Change Amount"); + if (!this.$totals.is(":visible")) { + return; + } + this.$totals.html( `