mirror of
https://github.com/frappe/erpnext.git
synced 2026-03-20 10:45:29 +00:00
fix: Wrong bank_ac_no filter + simplify convoluted logic
This commit is contained in:
@@ -45,45 +45,41 @@ class AutoMatchbyAccountIBAN:
|
|||||||
if not (self.bank_party_account_number or self.bank_party_iban):
|
if not (self.bank_party_account_number or self.bank_party_iban):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
result = self.match_account_in_party()
|
return self.match_account_in_party()
|
||||||
return result
|
|
||||||
|
|
||||||
def match_account_in_party(self) -> tuple | None:
|
def match_account_in_party(self) -> tuple | None:
|
||||||
"""Check if there is a IBAN/Account No. match in Customer/Supplier/Employee"""
|
"""
|
||||||
result = None
|
Returns (Party Type, Party) if a matching account is found in Bank Account or Employee:
|
||||||
parties = get_parties_in_order(self.deposit)
|
1. Get party from a matching (iban/account no) Bank Account
|
||||||
or_filters = self.get_or_filters()
|
2. If not found, get party from Employee with matching bank account details (iban/account no)
|
||||||
|
"""
|
||||||
|
if not (self.bank_party_account_number or self.bank_party_iban):
|
||||||
|
# Nothing to match
|
||||||
|
return None
|
||||||
|
|
||||||
for party in parties:
|
# Search for a matching Bank Account that has party set
|
||||||
party_result = frappe.db.get_all(
|
party_result = frappe.db.get_all(
|
||||||
"Bank Account", or_filters=or_filters, pluck="party", limit_page_length=1
|
"Bank Account",
|
||||||
)
|
or_filters=self.get_or_filters(),
|
||||||
|
filters={"party_type": ("is", "set"), "party": ("is", "set")},
|
||||||
|
fields=["party", "party_type"],
|
||||||
|
limit_page_length=1,
|
||||||
|
)
|
||||||
|
if result := party_result[0] if party_result else None:
|
||||||
|
return (result["party_type"], result["party"])
|
||||||
|
|
||||||
if party == "Employee" and not party_result:
|
# If no party is found, search in Employee (since it has bank account details)
|
||||||
# Search in Bank Accounts first for Employee, and then Employee record
|
if employee_result := frappe.db.get_all(
|
||||||
if "bank_account_no" in or_filters:
|
"Employee", or_filters=self.get_or_filters("Employee"), pluck="name", limit_page_length=1
|
||||||
or_filters["bank_ac_no"] = or_filters.pop("bank_account_no")
|
):
|
||||||
|
return ("Employee", employee_result[0])
|
||||||
|
|
||||||
party_result = frappe.db.get_all(
|
def get_or_filters(self, party: str | None = None) -> dict:
|
||||||
party, or_filters=or_filters, pluck="name", limit_page_length=1
|
"""Return OR filters for Bank Account and IBAN"""
|
||||||
)
|
|
||||||
|
|
||||||
if "bank_ac_no" in or_filters:
|
|
||||||
or_filters["bank_account_no"] = or_filters.pop("bank_ac_no")
|
|
||||||
|
|
||||||
if party_result:
|
|
||||||
result = (
|
|
||||||
party,
|
|
||||||
party_result[0],
|
|
||||||
)
|
|
||||||
break
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
def get_or_filters(self) -> dict:
|
|
||||||
or_filters = {}
|
or_filters = {}
|
||||||
if self.bank_party_account_number:
|
if self.bank_party_account_number:
|
||||||
or_filters["bank_account_no"] = self.bank_party_account_number
|
bank_ac_field = "bank_ac_no" if party == "Employee" else "bank_account_no"
|
||||||
|
or_filters[bank_ac_field] = self.bank_party_account_number
|
||||||
|
|
||||||
if self.bank_party_iban:
|
if self.bank_party_iban:
|
||||||
or_filters["iban"] = self.bank_party_iban
|
or_filters["iban"] = self.bank_party_iban
|
||||||
@@ -103,8 +99,7 @@ class AutoMatchbyPartyNameDescription:
|
|||||||
if not (self.bank_party_name or self.description):
|
if not (self.bank_party_name or self.description):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
result = self.match_party_name_desc_in_party()
|
return self.match_party_name_desc_in_party()
|
||||||
return result
|
|
||||||
|
|
||||||
def match_party_name_desc_in_party(self) -> tuple | None:
|
def match_party_name_desc_in_party(self) -> tuple | None:
|
||||||
"""Fuzzy search party name and/or description against parties in the system"""
|
"""Fuzzy search party name and/or description against parties in the system"""
|
||||||
@@ -113,7 +108,7 @@ class AutoMatchbyPartyNameDescription:
|
|||||||
|
|
||||||
for party in parties:
|
for party in parties:
|
||||||
filters = {"status": "Active"} if party == "Employee" else {"disabled": 0}
|
filters = {"status": "Active"} if party == "Employee" else {"disabled": 0}
|
||||||
field = party.lower() + "_name"
|
field = f"{party.lower()}_name"
|
||||||
names = frappe.get_all(party, filters=filters, fields=[f"{field} as party_name", "name"])
|
names = frappe.get_all(party, filters=filters, fields=[f"{field} as party_name", "name"])
|
||||||
|
|
||||||
for field in ["bank_party_name", "description"]:
|
for field in ["bank_party_name", "description"]:
|
||||||
@@ -140,13 +135,7 @@ class AutoMatchbyPartyNameDescription:
|
|||||||
)
|
)
|
||||||
party_name, skip = self.process_fuzzy_result(result)
|
party_name, skip = self.process_fuzzy_result(result)
|
||||||
|
|
||||||
if not party_name:
|
return ((party, party_name), skip) if party_name else (None, skip)
|
||||||
return None, skip
|
|
||||||
|
|
||||||
return (
|
|
||||||
party,
|
|
||||||
party_name,
|
|
||||||
), skip
|
|
||||||
|
|
||||||
def process_fuzzy_result(self, result: list | None):
|
def process_fuzzy_result(self, result: list | None):
|
||||||
"""
|
"""
|
||||||
@@ -164,8 +153,8 @@ class AutoMatchbyPartyNameDescription:
|
|||||||
if len(result) == 1:
|
if len(result) == 1:
|
||||||
return (first_result[PARTY_ID] if first_result[SCORE] > CUTOFF else None), True
|
return (first_result[PARTY_ID] if first_result[SCORE] > CUTOFF else None), True
|
||||||
|
|
||||||
second_result = result[1]
|
|
||||||
if first_result[SCORE] > CUTOFF:
|
if first_result[SCORE] > CUTOFF:
|
||||||
|
second_result = result[1]
|
||||||
# If multiple matches with the same score, return None but discontinue matching
|
# If multiple matches with the same score, return None but discontinue matching
|
||||||
# Matches were found but were too close to distinguish between
|
# Matches were found but were too close to distinguish between
|
||||||
if first_result[SCORE] == second_result[SCORE]:
|
if first_result[SCORE] == second_result[SCORE]:
|
||||||
@@ -177,8 +166,8 @@ class AutoMatchbyPartyNameDescription:
|
|||||||
|
|
||||||
|
|
||||||
def get_parties_in_order(deposit: float) -> list:
|
def get_parties_in_order(deposit: float) -> list:
|
||||||
parties = ["Supplier", "Employee", "Customer"] # most -> least likely to receive
|
return (
|
||||||
if flt(deposit) > 0:
|
["Customer", "Supplier", "Employee"] # most -> least likely to pay us
|
||||||
parties = ["Customer", "Supplier", "Employee"] # most -> least likely to pay
|
if flt(deposit) > 0
|
||||||
|
else ["Supplier", "Employee", "Customer"] # most -> least likely to receive from us
|
||||||
return parties
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user