Materialize ERPNext Bank / Bank Account / GL Account from e-taxes load
load_company_bank_accounts now makes every non-closed e-taxes bank record usable inside ERPNext, not just a read-only E-Taxes Bank Account cache row: - Bank (global, one per unique bankName) — idempotent insert. - GL Account under parent "223 Bank hesablaşma hesabları", named "<CUR> <IBAN>", account_type=Bank, account_currency from e-taxes. Parent discovered by account_number=223 with a name-prefix fallback. - Bank Account linking Bank + GL Account + Company, is_company_account=1, iban + bank_account_no = the AZ IBAN. Closed accounts (status=C) are left at cache-row only; no native records are created for them. After the loop, unused AZ CoA placeholder accounts (names like "AZN AZXXXXXXXXXXXXXXXXXXXXXXXXXX" under the bank group) are deleted so the chart isn't cluttered with unmatched templates. Per-record failures go to the "E-Taxes Bank Native Materialize" error log and don't abort the overall load.
This commit is contained in:
parent
f622a4ce2a
commit
bb13e293c9
|
|
@ -471,6 +471,23 @@ def load_company_bank_accounts(company):
|
||||||
created += c
|
created += c
|
||||||
updated += u
|
updated += u
|
||||||
|
|
||||||
|
# Phase 2: also materialise ERPNext-native Bank / GL Account / Bank Account
|
||||||
|
# for non-closed accounts so users can actually post transactions against them.
|
||||||
|
# Status "C" = closed — skip entirely (cache row above still written).
|
||||||
|
if (acc.get("status") or "").upper() != "C":
|
||||||
|
try:
|
||||||
|
_materialize_native_bank(company, acc)
|
||||||
|
except Exception as e:
|
||||||
|
frappe.log_error(
|
||||||
|
f"{acc.get('number')}: {e}\n{frappe.get_traceback()}",
|
||||||
|
"E-Taxes Bank Native Materialize",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Clean up unused AZ CoA bank placeholders (entries named "<CUR> AZXX…" under
|
||||||
|
# parent 223). On a fresh setup they've never been referenced, so deletion
|
||||||
|
# is safe. Per-row failures logged but don't abort.
|
||||||
|
_delete_bank_placeholders(company)
|
||||||
|
|
||||||
frappe.db.commit()
|
frappe.db.commit()
|
||||||
return _summarize(created, updated, len(accounts), "Bank accounts loaded")
|
return _summarize(created, updated, len(accounts), "Bank accounts loaded")
|
||||||
|
|
||||||
|
|
@ -482,6 +499,120 @@ def load_company_bank_accounts(company):
|
||||||
return {"success": False, "message": f"Error: {e}"}
|
return {"success": False, "message": f"Error: {e}"}
|
||||||
|
|
||||||
|
|
||||||
|
def _find_bank_parent_account(company):
|
||||||
|
"""Resolve the 'Bank hesablaşma hesabları' (account_number=223) group under this
|
||||||
|
company. Falls back to any Asset group containing bank-typed children."""
|
||||||
|
parent = frappe.db.get_value(
|
||||||
|
"Account",
|
||||||
|
{"company": company, "account_number": "223", "is_group": 1},
|
||||||
|
"name",
|
||||||
|
)
|
||||||
|
if parent:
|
||||||
|
return parent
|
||||||
|
parent = frappe.db.get_value(
|
||||||
|
"Account",
|
||||||
|
{"company": company, "account_name": ("like", "Bank hesablaşma%"), "is_group": 1},
|
||||||
|
"name",
|
||||||
|
)
|
||||||
|
return parent
|
||||||
|
|
||||||
|
|
||||||
|
def _materialize_native_bank(company, acc):
|
||||||
|
"""Create Bank (global) + GL Account (per-company) + Bank Account (linking) for
|
||||||
|
a single e-taxes bank record. Idempotent — safe to call repeatedly.
|
||||||
|
"""
|
||||||
|
bank_name = (acc.get("bankName") or "").strip()
|
||||||
|
iban = (acc.get("number") or "").strip()
|
||||||
|
currency = (acc.get("currency") or "").strip() or "AZN"
|
||||||
|
etx_account_type = (acc.get("type") or "").strip()
|
||||||
|
|
||||||
|
if not bank_name or not iban:
|
||||||
|
return # can't build records without these
|
||||||
|
|
||||||
|
# 1. Bank (global, unique on bank_name)
|
||||||
|
if not frappe.db.exists("Bank", bank_name):
|
||||||
|
bank_doc = frappe.get_doc({"doctype": "Bank", "bank_name": bank_name})
|
||||||
|
bank_doc.flags.ignore_permissions = True
|
||||||
|
bank_doc.flags.ignore_if_duplicate = True
|
||||||
|
bank_doc.insert(ignore_permissions=True, ignore_if_duplicate=True)
|
||||||
|
|
||||||
|
# 2. GL Account under parent 223 (Bank hesablaşma hesabları)
|
||||||
|
parent = _find_bank_parent_account(company)
|
||||||
|
if not parent:
|
||||||
|
frappe.log_error(
|
||||||
|
f"No bank parent account found for company '{company}'; skipping native GL account for {iban}",
|
||||||
|
"E-Taxes Bank Native Materialize",
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
account_name = f"{currency} {iban}"
|
||||||
|
existing_gl = frappe.db.get_value(
|
||||||
|
"Account",
|
||||||
|
{"company": company, "account_name": account_name},
|
||||||
|
"name",
|
||||||
|
)
|
||||||
|
if existing_gl:
|
||||||
|
gl_name = existing_gl
|
||||||
|
else:
|
||||||
|
gl_doc = frappe.get_doc({
|
||||||
|
"doctype": "Account",
|
||||||
|
"account_name": account_name,
|
||||||
|
"parent_account": parent,
|
||||||
|
"company": company,
|
||||||
|
"account_type": "Bank",
|
||||||
|
"account_currency": currency,
|
||||||
|
"is_group": 0,
|
||||||
|
})
|
||||||
|
gl_doc.insert(ignore_permissions=True)
|
||||||
|
gl_name = gl_doc.name
|
||||||
|
|
||||||
|
# 3. Bank Account (links Bank + GL + Company)
|
||||||
|
ba_exists = frappe.db.exists(
|
||||||
|
"Bank Account",
|
||||||
|
{"bank": bank_name, "account_name": account_name, "company": company},
|
||||||
|
)
|
||||||
|
if not ba_exists:
|
||||||
|
ba_doc = frappe.get_doc({
|
||||||
|
"doctype": "Bank Account",
|
||||||
|
"account_name": account_name,
|
||||||
|
"bank": bank_name,
|
||||||
|
"account": gl_name,
|
||||||
|
"company": company,
|
||||||
|
"is_company_account": 1,
|
||||||
|
"bank_account_no": iban,
|
||||||
|
"iban": iban,
|
||||||
|
"account_type": etx_account_type or None,
|
||||||
|
})
|
||||||
|
ba_doc.insert(ignore_permissions=True)
|
||||||
|
|
||||||
|
|
||||||
|
def _delete_bank_placeholders(company):
|
||||||
|
"""AZ CoA seeds placeholders like 'AZN AZXXXXXXXXXXXXXXXXXXXXXXXXXX' under the
|
||||||
|
bank group. Remove any that remain after real accounts have been materialised.
|
||||||
|
"""
|
||||||
|
parent = _find_bank_parent_account(company)
|
||||||
|
if not parent:
|
||||||
|
return
|
||||||
|
placeholders = frappe.get_all(
|
||||||
|
"Account",
|
||||||
|
filters={
|
||||||
|
"company": company,
|
||||||
|
"parent_account": parent,
|
||||||
|
"account_name": ("like", "% AZXX%"),
|
||||||
|
"is_group": 0,
|
||||||
|
},
|
||||||
|
pluck="name",
|
||||||
|
)
|
||||||
|
for p in placeholders:
|
||||||
|
try:
|
||||||
|
frappe.delete_doc("Account", p, ignore_permissions=True, delete_permanently=True)
|
||||||
|
except Exception as e:
|
||||||
|
frappe.log_error(
|
||||||
|
f"Placeholder delete failed: {p}: {e}",
|
||||||
|
"E-Taxes Bank Native Materialize",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# ======= OBLIGATION PACTS (sub-contractor obl-pact-list) =======
|
# ======= OBLIGATION PACTS (sub-contractor obl-pact-list) =======
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue