Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: incorrect gl if tax on multi currency payment entry (backport #32217) #32283

Merged
merged 2 commits into from
Sep 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 28 additions & 7 deletions erpnext/accounts/doctype/payment_entry/payment_entry.js
Original file line number Diff line number Diff line change
Expand Up @@ -1091,7 +1091,7 @@ frappe.ui.form.on('Payment Entry', {

$.each(tax_fields, function(i, fieldname) { tax[fieldname] = 0.0; });

frm.doc.paid_amount_after_tax = frm.doc.paid_amount;
frm.doc.paid_amount_after_tax = frm.doc.base_paid_amount;
});
},

Expand Down Expand Up @@ -1182,7 +1182,7 @@ frappe.ui.form.on('Payment Entry', {
}

cumulated_tax_fraction += tax.tax_fraction_for_current_item;
frm.doc.paid_amount_after_tax = flt(frm.doc.paid_amount/(1+cumulated_tax_fraction))
frm.doc.paid_amount_after_tax = flt(frm.doc.base_paid_amount/(1+cumulated_tax_fraction))
});
},

Expand Down Expand Up @@ -1214,6 +1214,7 @@ frappe.ui.form.on('Payment Entry', {
frm.doc.total_taxes_and_charges = 0.0;
frm.doc.base_total_taxes_and_charges = 0.0;

let company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
let actual_tax_dict = {};

// maintain actual tax rate based on idx
Expand All @@ -1234,8 +1235,8 @@ frappe.ui.form.on('Payment Entry', {
}
}

tax.tax_amount = current_tax_amount;
tax.base_tax_amount = tax.tax_amount * frm.doc.source_exchange_rate;
// tax accounts are only in company currency
tax.base_tax_amount = current_tax_amount;
current_tax_amount *= (tax.add_deduct_tax == "Deduct") ? -1.0 : 1.0;

if(i==0) {
Expand All @@ -1244,9 +1245,29 @@ frappe.ui.form.on('Payment Entry', {
tax.total = flt(frm.doc["taxes"][i-1].total + current_tax_amount, precision("total", tax));
}

tax.base_total = tax.total * frm.doc.source_exchange_rate;
frm.doc.total_taxes_and_charges += current_tax_amount;
frm.doc.base_total_taxes_and_charges += current_tax_amount * frm.doc.source_exchange_rate;
// tac accounts are only in company currency
tax.base_total = tax.total

// calculate total taxes and base total taxes
if(frm.doc.payment_type == "Pay") {
// tax accounts only have company currency
if(tax.currency != frm.doc.paid_to_account_currency) {
//total_taxes_and_charges has the target currency. so using target conversion rate
frm.doc.total_taxes_and_charges += flt(current_tax_amount / frm.doc.target_exchange_rate);

} else {
frm.doc.total_taxes_and_charges += current_tax_amount;
}
} else if(frm.doc.payment_type == "Receive") {
if(tax.currency != frm.doc.paid_from_account_currency) {
//total_taxes_and_charges has the target currency. so using source conversion rate
frm.doc.total_taxes_and_charges += flt(current_tax_amount / frm.doc.source_exchange_rate);
} else {
frm.doc.total_taxes_and_charges += current_tax_amount;
}
}

frm.doc.base_total_taxes_and_charges += tax.base_tax_amount;

frm.refresh_field('taxes');
frm.refresh_field('total_taxes_and_charges');
Expand Down
31 changes: 22 additions & 9 deletions erpnext/accounts/doctype/payment_entry/payment_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -940,6 +940,13 @@ def add_tax_gl_entries(self, gl_entries):
)

if not d.included_in_paid_amount:
if get_account_currency(payment_account) != self.company_currency:
if self.payment_type == "Receive":
exchange_rate = self.target_exchange_rate
elif self.payment_type in ["Pay", "Internal Transfer"]:
exchange_rate = self.source_exchange_rate
base_tax_amount = flt((tax_amount / exchange_rate), self.precision("paid_amount"))

gl_entries.append(
self.get_gl_dict(
{
Expand Down Expand Up @@ -1033,7 +1040,7 @@ def initialize_taxes(self):
for fieldname in tax_fields:
tax.set(fieldname, 0.0)

self.paid_amount_after_tax = self.paid_amount
self.paid_amount_after_tax = self.base_paid_amount

def determine_exclusive_rate(self):
if not any(cint(tax.included_in_paid_amount) for tax in self.get("taxes")):
Expand All @@ -1052,7 +1059,7 @@ def determine_exclusive_rate(self):

cumulated_tax_fraction += tax.tax_fraction_for_current_item

self.paid_amount_after_tax = flt(self.paid_amount / (1 + cumulated_tax_fraction))
self.paid_amount_after_tax = flt(self.base_paid_amount / (1 + cumulated_tax_fraction))

def calculate_taxes(self):
self.total_taxes_and_charges = 0.0
Expand All @@ -1075,7 +1082,7 @@ def calculate_taxes(self):
current_tax_amount += actual_tax_dict[tax.idx]

tax.tax_amount = current_tax_amount
tax.base_tax_amount = tax.tax_amount * self.source_exchange_rate
tax.base_tax_amount = current_tax_amount

if tax.add_deduct_tax == "Deduct":
current_tax_amount *= -1.0
Expand All @@ -1089,14 +1096,20 @@ def calculate_taxes(self):
self.get("taxes")[i - 1].total + current_tax_amount, self.precision("total", tax)
)

tax.base_total = tax.total * self.source_exchange_rate
tax.base_total = tax.total

if self.payment_type == "Pay":
self.base_total_taxes_and_charges += flt(current_tax_amount / self.source_exchange_rate)
self.total_taxes_and_charges += flt(current_tax_amount / self.target_exchange_rate)
else:
self.base_total_taxes_and_charges += flt(current_tax_amount / self.target_exchange_rate)
self.total_taxes_and_charges += flt(current_tax_amount / self.source_exchange_rate)
if tax.currency != self.paid_to_account_currency:
self.total_taxes_and_charges += flt(current_tax_amount / self.target_exchange_rate)
else:
self.total_taxes_and_charges += current_tax_amount
elif self.payment_type == "Receive":
if tax.currency != self.paid_from_account_currency:
self.total_taxes_and_charges += flt(current_tax_amount / self.source_exchange_rate)
else:
self.total_taxes_and_charges += current_tax_amount

self.base_total_taxes_and_charges += tax.base_tax_amount

if self.get("taxes"):
self.paid_amount_after_tax = self.get("taxes")[-1].base_total
Expand Down
41 changes: 41 additions & 0 deletions erpnext/accounts/doctype/payment_entry/test_payment_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import unittest

import frappe
from frappe import qb
from frappe.tests.utils import FrappeTestCase
from frappe.utils import flt, nowdate

Expand Down Expand Up @@ -722,6 +723,46 @@ def test_multi_currency_payment_entry_with_taxes(self):
flt(payment_entry.total_taxes_and_charges, 2), flt(10 / payment_entry.target_exchange_rate, 2)
)

def test_gl_of_multi_currency_payment_with_taxes(self):
payment_entry = create_payment_entry(
party="_Test Supplier USD", paid_to="_Test Payable USD - _TC", save=True
)
payment_entry.append(
"taxes",
{
"account_head": "_Test Account Service Tax - _TC",
"charge_type": "Actual",
"tax_amount": 100,
"add_deduct_tax": "Add",
"description": "Test",
},
)
payment_entry.target_exchange_rate = 80
payment_entry.received_amount = 12.5
payment_entry = payment_entry.submit()
gle = qb.DocType("GL Entry")
gl_entries = (
qb.from_(gle)
.select(
gle.account,
gle.debit,
gle.credit,
gle.debit_in_account_currency,
gle.credit_in_account_currency,
)
.orderby(gle.account)
.where(gle.voucher_no == payment_entry.name)
.run()
)

expected_gl_entries = (
("_Test Account Service Tax - _TC", 100.0, 0.0, 100.0, 0.0),
("_Test Bank - _TC", 0.0, 1100.0, 0.0, 1100.0),
("_Test Payable USD - _TC", 1000.0, 0.0, 12.5, 0),
)

self.assertEqual(gl_entries, expected_gl_entries)

def test_payment_entry_against_onhold_purchase_invoice(self):
pi = make_purchase_invoice()

Expand Down