Skip to content

Commit

Permalink
fix: set correct unallocated amount in Payment Entry (#43958)
Browse files Browse the repository at this point in the history
* fix: set correct unallocated amount in Payment Entry

* fix: add checkbox and other logic fix

* fix: patch to set is_exchange_gain_loss in Payment Entry deductions

* fix: consider deductions except exch. gain/loss

* fix: set exchange gain loss in payment entry

* fix: separate function to set exchange gain loss

* fix: failing test cases

* fix: add cash disc. row first

* fix: review changes

* fix: changes as per review

* fix: failing test cases

* fix: review

* fix: wait for request to complete before updating exchange gain loss

* fix: review

---------

Co-authored-by: vishakhdesai <vishakhdesai@gmail.com>
Co-authored-by: ruthra kumar <ruthra@erpnext.com>
(cherry picked from commit 7cc111f)

# Conflicts:
#	erpnext/accounts/doctype/payment_entry_deduction/payment_entry_deduction.json
#	erpnext/patches.txt
  • Loading branch information
sagarvora authored and mergify[bot] committed Dec 2, 2024
1 parent f5ddc9a commit ae93f7f
Show file tree
Hide file tree
Showing 11 changed files with 299 additions and 170 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ def test_03_accounts_only_with_account_currency_balance(self):

pe = get_payment_entry(si.doctype, si.name)
pe.paid_amount = 95
pe.source_exchange_rate = 84.211
pe.source_exchange_rate = 84.2105
pe.received_amount = 8000
pe.references = []
pe.save().submit()
Expand Down Expand Up @@ -229,7 +229,7 @@ def test_03_accounts_only_with_account_currency_balance(self):
row = next(x for x in je.accounts if x.account == self.debtors_usd)
self.assertEqual(flt(row.credit_in_account_currency, precision), 5.0) # in USD
row = next(x for x in je.accounts if x.account != self.debtors_usd)
self.assertEqual(flt(row.debit_in_account_currency, precision), 421.06) # in INR
self.assertEqual(flt(row.debit_in_account_currency, precision), 421.05) # in INR

# total_debit and total_credit will be 0.0, as JV is posting only to account currency fields
self.assertEqual(flt(je.total_debit, precision), 0.0)
Expand Down
232 changes: 145 additions & 87 deletions erpnext/accounts/doctype/payment_entry/payment_entry.js
Original file line number Diff line number Diff line change
Expand Up @@ -324,11 +324,6 @@ frappe.ui.form.on("Payment Entry", {
"write_off_difference_amount",
frm.doc.difference_amount && frm.doc.party && frm.doc.total_allocated_amount > party_amount
);

frm.toggle_display(
"set_exchange_gain_loss",
frm.doc.paid_amount && frm.doc.received_amount && frm.doc.difference_amount
);
},

set_dynamic_labels: function (frm) {
Expand Down Expand Up @@ -1119,36 +1114,34 @@ frappe.ui.form.on("Payment Entry", {
},

set_unallocated_amount: function (frm) {
var unallocated_amount = 0;
var total_deductions = frappe.utils.sum(
$.map(frm.doc.deductions || [], function (d) {
return flt(d.amount);
})
);
let unallocated_amount = 0;
let deductions_to_consider = 0;

for (const row of frm.doc.deductions || []) {
if (!row.is_exchange_gain_loss) deductions_to_consider += flt(row.amount);
}
const included_taxes = get_included_taxes(frm);

if (frm.doc.party) {
if (
frm.doc.payment_type == "Receive" &&
frm.doc.base_total_allocated_amount < frm.doc.base_received_amount + total_deductions &&
frm.doc.total_allocated_amount <
frm.doc.paid_amount + total_deductions / frm.doc.source_exchange_rate
frm.doc.base_total_allocated_amount < frm.doc.base_paid_amount + deductions_to_consider
) {
unallocated_amount =
(frm.doc.base_received_amount +
total_deductions -
flt(frm.doc.base_total_taxes_and_charges) -
frm.doc.base_total_allocated_amount) /
(frm.doc.base_paid_amount +
deductions_to_consider -
frm.doc.base_total_allocated_amount -
included_taxes) /
frm.doc.source_exchange_rate;
} else if (
frm.doc.payment_type == "Pay" &&
frm.doc.base_total_allocated_amount < frm.doc.base_paid_amount - total_deductions &&
frm.doc.total_allocated_amount <
frm.doc.received_amount + total_deductions / frm.doc.target_exchange_rate
frm.doc.base_total_allocated_amount < frm.doc.base_received_amount - deductions_to_consider
) {
unallocated_amount =
(frm.doc.base_paid_amount +
flt(frm.doc.base_total_taxes_and_charges) -
(total_deductions + frm.doc.base_total_allocated_amount)) /
(frm.doc.base_received_amount -
deductions_to_consider -
frm.doc.base_total_allocated_amount -
included_taxes) /
frm.doc.target_exchange_rate;
}
}
Expand Down Expand Up @@ -1242,77 +1235,85 @@ frappe.ui.form.on("Payment Entry", {
},

write_off_difference_amount: function (frm) {
frm.events.set_deductions_entry(frm, "write_off_account");
frm.events.set_write_off_deduction(frm);
},

set_exchange_gain_loss: function (frm) {
frm.events.set_deductions_entry(frm, "exchange_gain_loss_account");
base_paid_amount: function (frm) {
frm.events.set_exchange_gain_loss_deduction(frm);
},

set_deductions_entry: function (frm, account) {
if (frm.doc.difference_amount) {
frappe.call({
method: "erpnext.accounts.doctype.payment_entry.payment_entry.get_company_defaults",
args: {
company: frm.doc.company,
},
callback: function (r, rt) {
if (r.message) {
const write_off_row = $.map(frm.doc["deductions"] || [], function (t) {
return t.account == r.message[account] ? t : null;
});
base_received_amount: function (frm) {
frm.events.set_exchange_gain_loss_deduction(frm);
},

const difference_amount = flt(
frm.doc.difference_amount,
precision("difference_amount")
);

const add_deductions = (details) => {
let row = null;
if (!write_off_row.length && difference_amount) {
row = frm.add_child("deductions");
row.account = details[account];
row.cost_center = details["cost_center"];
} else {
row = write_off_row[0];
}
set_exchange_gain_loss_deduction: async function (frm) {
// wait for allocate_party_amount_against_ref_docs to finish
await frappe.after_ajax();
const base_paid_amount = frm.doc.base_paid_amount || 0;
const base_received_amount = frm.doc.base_received_amount || 0;
const exchange_gain_loss = flt(
base_paid_amount - base_received_amount,
get_deduction_amount_precision()
);

if (row) {
row.amount = flt(row.amount) + difference_amount;
} else {
frappe.msgprint(__("No gain or loss in the exchange rate"));
}
refresh_field("deductions");
};

if (!r.message[account]) {
frappe.prompt(
{
label: __("Please Specify Account"),
fieldname: account,
fieldtype: "Link",
options: "Account",
get_query: () => ({
filters: {
company: frm.doc.company,
},
}),
},
(values) => {
const details = Object.assign({}, r.message, values);
add_deductions(details);
},
__(frappe.unscrub(account))
);
} else {
add_deductions(r.message);
}
if (!exchange_gain_loss) {
frm.events.delete_exchange_gain_loss(frm);
return;
}

frm.events.set_unallocated_amount(frm);
}
},
});
const account_fieldname = "exchange_gain_loss_account";
let row = (frm.doc.deductions || []).find((t) => t.is_exchange_gain_loss);

if (!row) {
const response = await get_company_defaults(frm.doc.company);

const account =
response.message?.[account_fieldname] ||
(await prompt_for_missing_account(frm, account_fieldname));

row = frm.add_child("deductions");
row.account = account;
row.cost_center = response.message?.cost_center;
row.is_exchange_gain_loss = 1;
}

row.amount = exchange_gain_loss;
frm.refresh_field("deductions");
frm.events.set_unallocated_amount(frm);
},

delete_exchange_gain_loss: function (frm) {
const exchange_gain_loss_row = (frm.doc.deductions || []).find((row) => row.is_exchange_gain_loss);

if (!exchange_gain_loss_row) return;

exchange_gain_loss_row.amount = 0;
frm.get_field("deductions").grid.grid_rows[exchange_gain_loss_row.idx - 1].remove();
frm.refresh_field("deductions");
},

set_write_off_deduction: async function (frm) {
const difference_amount = flt(frm.doc.difference_amount, get_deduction_amount_precision());
if (!difference_amount) return;

const account_fieldname = "write_off_account";
const response = await get_company_defaults(frm.doc.company);
const write_off_account =
response.message?.[account_fieldname] ||
(await prompt_for_missing_account(frm, account_fieldname));

if (!write_off_account) return;

let row = (frm.doc["deductions"] || []).find((t) => t.account == write_off_account);
if (!row) {
row = frm.add_child("deductions");
row.account = write_off_account;
row.cost_center = response.message?.cost_center;
}

row.amount = flt(row.amount) + difference_amount;
frm.refresh_field("deductions");
frm.events.set_unallocated_amount(frm);
},

bank_account: function (frm) {
Expand Down Expand Up @@ -1778,6 +1779,13 @@ frappe.ui.form.on("Advance Taxes and Charges", {
});

frappe.ui.form.on("Payment Entry Deduction", {
before_deductions_remove: function (doc, cdt, cdn) {
const row = frappe.get_doc(cdt, cdn);
if (row.is_exchange_gain_loss && row.amount) {
frappe.throw(__("Cannot delete Exchange Gain/Loss row"));
}
},

amount: function (frm) {
frm.events.set_unallocated_amount(frm);
},
Expand All @@ -1799,3 +1807,53 @@ function set_default_party_type(frm) {

if (party_type) frm.set_value("party_type", party_type);
}

function get_included_taxes(frm) {
let included_taxes = 0;
for (const tax of frm.doc.taxes) {
if (!tax.included_in_paid_amount) continue;

if (tax.add_deduct_tax == "Add") {
included_taxes += tax.base_tax_amount;
} else {
included_taxes -= tax.base_tax_amount;
}
}

return included_taxes;
}

function get_company_defaults(company) {
return frappe.call({
method: "erpnext.accounts.doctype.payment_entry.payment_entry.get_company_defaults",
args: {
company: company,
},
});
}

function prompt_for_missing_account(frm, account) {
return new Promise((resolve) => {
const dialog = frappe.prompt(
{
label: __(frappe.unscrub(account)),
fieldname: account,
fieldtype: "Link",
options: "Account",
get_query: () => ({
filters: {
company: frm.doc.company,
},
}),
},
(values) => resolve(values?.[account]),
__("Please Specify Account")
);

dialog.on_hide = () => resolve("");
});
}

function get_deduction_amount_precision() {
return frappe.meta.get_field_precision(frappe.meta.get_field("Payment Entry Deduction", "amount"));
}
8 changes: 1 addition & 7 deletions erpnext/accounts/doctype/payment_entry/payment_entry.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@
"section_break_34",
"total_allocated_amount",
"base_total_allocated_amount",
"set_exchange_gain_loss",
"column_break_36",
"unallocated_amount",
"difference_amount",
Expand Down Expand Up @@ -390,11 +389,6 @@
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "set_exchange_gain_loss",
"fieldtype": "Button",
"label": "Set Exchange Gain / Loss"
},
{
"fieldname": "column_break_36",
"fieldtype": "Column Break"
Expand Down Expand Up @@ -801,7 +795,7 @@
"table_fieldname": "payment_entries"
}
],
"modified": "2024-05-31 17:07:06.197249",
"modified": "2024-11-07 11:19:19.320883",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry",
Expand Down
Loading

0 comments on commit ae93f7f

Please sign in to comment.