mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-17 08:28:44 +00:00
fix: don't convert item margin on exchange rate refresh
Changing the transaction/posting date re-triggers the `currency` handler, which fetches a fresh exchange rate and, whenever it differs from the current one, divided every Amount-type item margin and Actual tax charge by the new rate. `margin_rate_or_amount` is an amount in the transaction currency, so dividing it is only meaningful when the document actually switches currency; on a mere rate refresh it silently shrinks the margin every time. Track the currency the rendered document is denominated in and convert margins/actual charges only on a real currency change, while still updating `conversion_rate` so base amounts recalculate correctly. Also remove the duplicated `currency()` override in quotation.js: it re-ran the same fetch-and-convert block after `super.currency()` (double converting margins) and lacked the `load_after_mapping` guard. The base handler already covers Quotation via `transaction_date`. Fixes #45210
This commit is contained in:
@@ -600,6 +600,10 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
|
||||
refresh() {
|
||||
erpnext.toggle_naming_series();
|
||||
erpnext.hide_company(this.frm);
|
||||
// Remember the currency the rendered document is denominated in, so that a
|
||||
// real currency change can be told apart from a mere exchange rate refresh
|
||||
// (e.g. triggered by a date change).
|
||||
this._doc_currency = this.frm.doc.currency;
|
||||
this.set_dynamic_labels();
|
||||
this.setup_sms();
|
||||
this.setup_quality_inspection();
|
||||
@@ -1470,6 +1474,10 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
|
||||
let me = this;
|
||||
this.set_dynamic_labels();
|
||||
let company_currency = this.get_company_currency();
|
||||
// Currency the stored margins/actual charges are denominated in, captured
|
||||
// before this trigger updates the tracker for the next one.
|
||||
let previous_currency = this._doc_currency;
|
||||
this._doc_currency = this.frm.doc.currency;
|
||||
// Added `load_after_mapping` to determine if document is loading after mapping from another doc
|
||||
if (
|
||||
this.frm.doc.currency &&
|
||||
@@ -1482,8 +1490,14 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
|
||||
company_currency,
|
||||
function (exchange_rate) {
|
||||
if (exchange_rate != me.frm.doc.conversion_rate) {
|
||||
me.set_margin_amount_based_on_currency(exchange_rate);
|
||||
me.set_actual_charges_based_on_currency(exchange_rate);
|
||||
// Margins and actual charges are amounts in the transaction
|
||||
// currency; convert them only when the currency itself changed,
|
||||
// not when just the exchange rate was refreshed (e.g. by a date
|
||||
// change), otherwise the entered margin keeps shrinking.
|
||||
if (previous_currency !== me.frm.doc.currency) {
|
||||
me.set_margin_amount_based_on_currency(exchange_rate);
|
||||
me.set_actual_charges_based_on_currency(exchange_rate);
|
||||
}
|
||||
me.frm.set_value("conversion_rate", exchange_rate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,26 +382,6 @@ erpnext.selling.QuotationController = class QuotationController extends erpnext.
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
currency() {
|
||||
super.currency();
|
||||
let me = this;
|
||||
const company_currency = this.get_company_currency();
|
||||
if (this.frm.doc.currency && this.frm.doc.currency !== company_currency) {
|
||||
this.get_exchange_rate(
|
||||
this.frm.doc.transaction_date,
|
||||
this.frm.doc.currency,
|
||||
company_currency,
|
||||
function (exchange_rate) {
|
||||
if (exchange_rate != me.frm.doc.conversion_rate) {
|
||||
me.set_margin_amount_based_on_currency(exchange_rate);
|
||||
me.set_actual_charges_based_on_currency(exchange_rate);
|
||||
me.frm.set_value("conversion_rate", exchange_rate);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
disable_customer_if_creating_from_opportunity(doc) {
|
||||
if (doc.opportunity) {
|
||||
this.frm.set_df_property("party_name", "read_only", 1);
|
||||
|
||||
Reference in New Issue
Block a user