bug fix
This commit is contained in:
parent
5b47d06eec
commit
68c3d7d8a9
|
|
@ -1,6 +1,18 @@
|
||||||
import json
|
import json
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
|
from frappe.utils import cint, flt
|
||||||
|
|
||||||
|
|
||||||
|
def _extract_messages(message_log):
|
||||||
|
"""Extract plain text from frappe.local.message_log entries."""
|
||||||
|
parts = []
|
||||||
|
for m in message_log:
|
||||||
|
if isinstance(m, dict):
|
||||||
|
parts.append(m.get("message") or m.get("msg") or "")
|
||||||
|
else:
|
||||||
|
parts.append(str(m))
|
||||||
|
return " | ".join(p for p in parts if p)
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
|
|
@ -291,6 +303,8 @@ def _create_and_reconcile_doc(txn, paid_from, paid_to, document_type, multi_curr
|
||||||
return {"success": True, "doc_name": doc_name, "reconciled": False, "error": str(re)}
|
return {"success": True, "doc_name": doc_name, "reconciled": False, "error": str(re)}
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
frappe.db.rollback()
|
||||||
|
frappe.local.message_log = []
|
||||||
frappe.log_error(
|
frappe.log_error(
|
||||||
f"_create_and_reconcile_doc failed for {bank_transaction_name}: {e}\n{frappe.get_traceback()}",
|
f"_create_and_reconcile_doc failed for {bank_transaction_name}: {e}\n{frappe.get_traceback()}",
|
||||||
"Kapital Bank Mapping",
|
"Kapital Bank Mapping",
|
||||||
|
|
@ -320,11 +334,22 @@ def _create_payment_entry_for_brt(txn, paid_from, paid_to, bank_txn):
|
||||||
if party_type and party:
|
if party_type and party:
|
||||||
pe.party_type = party_type
|
pe.party_type = party_type
|
||||||
pe.party = party
|
pe.party = party
|
||||||
|
|
||||||
|
frappe.local.message_log = []
|
||||||
pe.insert(ignore_permissions=True)
|
pe.insert(ignore_permissions=True)
|
||||||
pe.submit()
|
pe.submit()
|
||||||
|
|
||||||
|
if frappe.local.message_log:
|
||||||
|
msgs = _extract_messages(frappe.local.message_log)
|
||||||
|
frappe.local.message_log = []
|
||||||
|
frappe.db.rollback()
|
||||||
|
return {"success": False, "error": msgs}
|
||||||
|
|
||||||
return {"success": True, "doc_name": pe.name}
|
return {"success": True, "doc_name": pe.name}
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
frappe.db.rollback()
|
||||||
|
frappe.local.message_log = []
|
||||||
frappe.log_error(
|
frappe.log_error(
|
||||||
f"_create_payment_entry_for_brt failed: {e}\n{frappe.get_traceback()}",
|
f"_create_payment_entry_for_brt failed: {e}\n{frappe.get_traceback()}",
|
||||||
"Kapital Bank Mapping",
|
"Kapital Bank Mapping",
|
||||||
|
|
@ -335,6 +360,9 @@ def _create_payment_entry_for_brt(txn, paid_from, paid_to, bank_txn):
|
||||||
def _create_journal_entry_for_brt(txn, paid_from, paid_to, bank_txn, multi_currency=False):
|
def _create_journal_entry_for_brt(txn, paid_from, paid_to, bank_txn, multi_currency=False):
|
||||||
"""Create and submit a Journal Entry for a BRT transaction."""
|
"""Create and submit a Journal Entry for a BRT transaction."""
|
||||||
try:
|
try:
|
||||||
|
import erpnext
|
||||||
|
from erpnext.setup.utils import get_exchange_rate
|
||||||
|
|
||||||
amount = abs(float(txn.get("amount") or 0))
|
amount = abs(float(txn.get("amount") or 0))
|
||||||
party_type = (txn.get("party_type") or "").strip()
|
party_type = (txn.get("party_type") or "").strip()
|
||||||
party = (txn.get("party") or "").strip()
|
party = (txn.get("party") or "").strip()
|
||||||
|
|
@ -342,9 +370,47 @@ def _create_journal_entry_for_brt(txn, paid_from, paid_to, bank_txn, multi_curre
|
||||||
posting_date = bank_txn.date or txn.get("date")
|
posting_date = bank_txn.date or txn.get("date")
|
||||||
ref_no = bank_txn.reference_number or txn.get("reference_number") or ""
|
ref_no = bank_txn.reference_number or txn.get("reference_number") or ""
|
||||||
|
|
||||||
# Determine account types to assign party to the right row
|
company_currency = erpnext.get_company_currency(bank_txn.company)
|
||||||
paid_from_type = frappe.db.get_value("Account", paid_from, "account_type") or ""
|
|
||||||
paid_to_type = frappe.db.get_value("Account", paid_to, "account_type") or ""
|
# Get account currencies and types
|
||||||
|
from_account = frappe.get_cached_value("Account", paid_from, ["account_type", "account_currency"], as_dict=True) or {}
|
||||||
|
to_account = frappe.get_cached_value("Account", paid_to, ["account_type", "account_currency"], as_dict=True) or {}
|
||||||
|
paid_from_type = from_account.get("account_type") or ""
|
||||||
|
paid_to_type = to_account.get("account_type") or ""
|
||||||
|
from_currency = from_account.get("account_currency") or company_currency
|
||||||
|
to_currency = to_account.get("account_currency") or company_currency
|
||||||
|
|
||||||
|
# Auto-enable multi_currency if any account is in a foreign currency
|
||||||
|
is_multi = from_currency != company_currency or to_currency != company_currency
|
||||||
|
|
||||||
|
# Frappe rounds debit_in_account_currency to field precision BEFORE multiplying
|
||||||
|
# by exchange_rate to get debit (company currency).
|
||||||
|
# Strategy: keep the original amount on the company-currency row, then compute
|
||||||
|
# an exact exchange rate for the foreign row so that:
|
||||||
|
# flt(foreign_amount * exact_rate, P) == flt(amount, P)
|
||||||
|
# This mirrors what Frappe UI does when the user types the AZN amount first.
|
||||||
|
currency_precision = cint(frappe.db.get_single_value("System Settings", "currency_precision") or 2)
|
||||||
|
|
||||||
|
if from_currency == company_currency and to_currency != company_currency:
|
||||||
|
to_rate = get_exchange_rate(to_currency, company_currency, posting_date)
|
||||||
|
to_amount = flt(amount / to_rate, currency_precision)
|
||||||
|
exact_to_rate = (amount / to_amount) if to_amount else to_rate
|
||||||
|
from_rate = 1
|
||||||
|
from_amount = amount
|
||||||
|
to_rate = exact_to_rate
|
||||||
|
elif to_currency == company_currency and from_currency != company_currency:
|
||||||
|
from_rate = get_exchange_rate(from_currency, company_currency, posting_date)
|
||||||
|
from_amount = flt(amount / from_rate, currency_precision)
|
||||||
|
exact_from_rate = (amount / from_amount) if from_amount else from_rate
|
||||||
|
to_rate = 1
|
||||||
|
to_amount = amount
|
||||||
|
from_rate = exact_from_rate
|
||||||
|
else:
|
||||||
|
# Both same currency OR both foreign (rare)
|
||||||
|
from_rate = 1 if from_currency == company_currency else get_exchange_rate(from_currency, company_currency, posting_date)
|
||||||
|
to_rate = 1 if to_currency == company_currency else get_exchange_rate(to_currency, company_currency, posting_date)
|
||||||
|
from_amount = flt(amount / from_rate, currency_precision)
|
||||||
|
to_amount = flt(amount / to_rate, currency_precision)
|
||||||
|
|
||||||
je = frappe.new_doc("Journal Entry")
|
je = frappe.new_doc("Journal Entry")
|
||||||
je.voucher_type = "Bank Entry"
|
je.voucher_type = "Bank Entry"
|
||||||
|
|
@ -353,28 +419,38 @@ def _create_journal_entry_for_brt(txn, paid_from, paid_to, bank_txn, multi_curre
|
||||||
je.cheque_no = ref_no
|
je.cheque_no = ref_no
|
||||||
je.cheque_date = posting_date
|
je.cheque_date = posting_date
|
||||||
je.user_remark = bank_txn.description or txn.get("purpose") or ""
|
je.user_remark = bank_txn.description or txn.get("purpose") or ""
|
||||||
if multi_currency:
|
if is_multi:
|
||||||
je.multi_currency = 1
|
je.multi_currency = 1
|
||||||
|
|
||||||
# Pay: paid_from credit, paid_to debit
|
# Pay: paid_from credit, paid_to debit
|
||||||
# Receive: paid_from debit, paid_to credit
|
# Receive: paid_from debit, paid_to credit
|
||||||
|
# Only set *_in_account_currency + exchange_rate; Frappe computes debit/credit itself.
|
||||||
if is_pay:
|
if is_pay:
|
||||||
from_credit, from_debit = amount, 0
|
from_row = {
|
||||||
to_credit, to_debit = 0, amount
|
"account": paid_from,
|
||||||
|
"exchange_rate": from_rate,
|
||||||
|
"credit_in_account_currency": from_amount,
|
||||||
|
"debit_in_account_currency": 0,
|
||||||
|
}
|
||||||
|
to_row = {
|
||||||
|
"account": paid_to,
|
||||||
|
"exchange_rate": to_rate,
|
||||||
|
"debit_in_account_currency": to_amount,
|
||||||
|
"credit_in_account_currency": 0,
|
||||||
|
}
|
||||||
else:
|
else:
|
||||||
from_credit, from_debit = 0, amount
|
from_row = {
|
||||||
to_credit, to_debit = amount, 0
|
"account": paid_from,
|
||||||
|
"exchange_rate": from_rate,
|
||||||
from_row = {
|
"debit_in_account_currency": from_amount,
|
||||||
"account": paid_from,
|
"credit_in_account_currency": 0,
|
||||||
"credit_in_account_currency": from_credit,
|
}
|
||||||
"debit_in_account_currency": from_debit,
|
to_row = {
|
||||||
}
|
"account": paid_to,
|
||||||
to_row = {
|
"exchange_rate": to_rate,
|
||||||
"account": paid_to,
|
"credit_in_account_currency": to_amount,
|
||||||
"credit_in_account_currency": to_credit,
|
"debit_in_account_currency": 0,
|
||||||
"debit_in_account_currency": to_debit,
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if party_type and party:
|
if party_type and party:
|
||||||
if paid_from_type in ("Receivable", "Payable"):
|
if paid_from_type in ("Receivable", "Payable"):
|
||||||
|
|
@ -386,11 +462,22 @@ def _create_journal_entry_for_brt(txn, paid_from, paid_to, bank_txn, multi_curre
|
||||||
|
|
||||||
je.append("accounts", from_row)
|
je.append("accounts", from_row)
|
||||||
je.append("accounts", to_row)
|
je.append("accounts", to_row)
|
||||||
|
|
||||||
|
frappe.local.message_log = []
|
||||||
je.insert(ignore_permissions=True)
|
je.insert(ignore_permissions=True)
|
||||||
je.submit()
|
je.submit()
|
||||||
|
|
||||||
|
if frappe.local.message_log:
|
||||||
|
msgs = _extract_messages(frappe.local.message_log)
|
||||||
|
frappe.local.message_log = []
|
||||||
|
frappe.db.rollback()
|
||||||
|
return {"success": False, "error": msgs}
|
||||||
|
|
||||||
return {"success": True, "doc_name": je.name}
|
return {"success": True, "doc_name": je.name}
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
frappe.db.rollback()
|
||||||
|
frappe.local.message_log = []
|
||||||
frappe.log_error(
|
frappe.log_error(
|
||||||
f"_create_journal_entry_for_brt failed: {e}\n{frappe.get_traceback()}",
|
f"_create_journal_entry_for_brt failed: {e}\n{frappe.get_traceback()}",
|
||||||
"Kapital Bank Mapping",
|
"Kapital Bank Mapping",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue