I’m working on a contribution and looking for the multicurrency controller(s) but they seem to be baked into taxes_and_totals.py
and the “items” table schema that occurs in a bunch of doctypes. Is there another place I should be looking? I guess more specifically, I’m looking for a method that fetches the conversion rate and rounding equation, I’d like those pieces to be consistent across ERPNext.
3 Likes
“Is there another place I should be looking?”
imo no you are on target taxes_and_totals.py - and also too transaction.js that extends it - together implement multi-currency
'warehouse': in_list('Purchase Receipt', 'Purchase Invoice') ? item.from_warehouse : item.warehouse,
'posting_date': posting_date,
'posting_time': posting_time,
'qty': item.qty * item.conversion_factor,
'serial_no': item.serial_no,
'batch_no': item.batch_no,
'voucher_type': voucher_type,
'company': company,
'allow_zero_valuation_rate': item.allow_zero_valuation_rate
}
frappe.call({
method: 'erpnext.stock.utils.get_incoming_rate',
args: {
args: item_args
},
callback: function(r) {
frappe.model.set_value(item.doctype, item.name, 'rate', r.message * item.conversion_factor);
}
});
}
serial_no(doc, cdt, cdn) {
var me = this;
var item = frappe.get_doc(cdt, cdn);
if (item && item.doctype === 'Purchase Receipt Item Supplied') {
return;
}
if (item && item.serial_no) {
if (!item.item_code) {
this.frm.trigger("item_code", cdt, cdn);
}
else {
// Replace all occurences of comma with line feed
item.serial_no = item.serial_no.replace(/,/g, '\n');
item.conversion_factor = item.conversion_factor || 1;
refresh_field("serial_no", item.name, item.parentfield);
if (!doc.is_return && cint(frappe.user_defaults.set_qty_in_transactions_based_on_serial_no_input)) {
setTimeout(() => {
me.update_qty(cdt, cdn);
if (!item.item_code) {
this.frm.trigger("item_code", cdt, cdn);
}
else {
// Replace all occurences of comma with line feed
item.serial_no = item.serial_no.replace(/,/g, '\n');
item.conversion_factor = item.conversion_factor || 1;
refresh_field("serial_no", item.name, item.parentfield);
if (!doc.is_return && cint(frappe.user_defaults.set_qty_in_transactions_based_on_serial_no_input)) {
setTimeout(() => {
me.update_qty(cdt, cdn);
}, 10000);
}
}
}
}
update_qty(cdt, cdn) {
var valid_serial_nos = [];
var serialnos = [];
var item = frappe.get_doc(cdt, cdn);
Many thanks for shilgod’s insight Quotation Item triggers - #6 by schilgod
That ahha moment how jQuery.extend() | jQuery API Documentation aparently interfaces and extends a python object with a js object with this statement really escapes me:
erpnext.TransactionController = erpnext.taxes_and_totals.extend({
jquery.extend - An object that will receive the new properties if additional objects are passed in or that will extend the jQuery namespace if it is the sole argument.
1 Like
@clarkej , sorry, I need to put one correction here!
It’s not jquery.extend
This feature rely on: John Resig - Simple JavaScript Inheritance
It’s an old intent to implement inheritance, using classes into JavaScript, instead of the prototyping method.
2 Likes
@max_morais_dmm thanks for the correction.
@clarkej apologies, my bad.
good catch thanks very much you both for your help - so then you are saying
erpnext.TransactionController = erpnext.taxes_and_totals.extend({
in fact extends this
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
setup() {
this.fetch_round_off_accounts();
}
apply_pricing_rule_on_item(item) {
let effective_item_rate = item.price_list_rate;
let item_rate = item.rate;
if (in_list(["Sales Order", "Quotation"], item.parenttype) && item.blanket_order_rate) {
effective_item_rate = item.blanket_order_rate;
}
if (item.margin_type == "Percentage") {
item.rate_with_margin = flt(effective_item_rate)
+ flt(effective_item_rate) * ( flt(item.margin_rate_or_amount) / 100);
} else {
item.rate_with_margin = flt(effective_item_rate) + flt(item.margin_rate_or_amount);
}
This file has been truncated. show original
and not the (controller template) py - I surely overlooked that.
edit:
So how ERPNext uses the model view controller MVC triad, the js implements the client-side form ‘view’
erpnext/erpnext/public/js/controllers at develop · frappe/erpnext · GitHub
So that when a user makes a request from a form web page, a controller is responsible for returning the response to that request:
erpnext/erpnext/controllers at develop · frappe/erpnext · GitHub
And that interaction involves consulting the ‘model’ for (master or transaction) state data.