mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-25 16:04:46 +00:00
[calculations] [client/server] first cut
This commit is contained in:
@@ -20,8 +20,9 @@
|
||||
// cur_frm.cscript.fname - Details fieldname
|
||||
|
||||
wn.provide("erpnext.buying");
|
||||
wn.require("app/js/transaction.js");
|
||||
|
||||
erpnext.buying.BuyingController = wn.ui.form.Controller.extend({
|
||||
erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
||||
setup: function() {
|
||||
var me = this;
|
||||
|
||||
@@ -42,50 +43,39 @@ erpnext.buying.BuyingController = wn.ui.form.Controller.extend({
|
||||
}
|
||||
},
|
||||
|
||||
refresh: function() {
|
||||
this.frm.clear_custom_buttons();
|
||||
erpnext.hide_naming_series();
|
||||
validate: function() {
|
||||
|
||||
if(this.frm.fields_dict.supplier)
|
||||
this.frm.toggle_display("contact_section", this.frm.doc.supplier);
|
||||
|
||||
if(this.frm.fields_dict.currency)
|
||||
this.set_dynamic_labels();
|
||||
},
|
||||
|
||||
price_list_name: function(callback_fn) {
|
||||
var me = this;
|
||||
|
||||
if(this.frm.doc.price_list_name) {
|
||||
if(!this.frm.doc.price_list_currency) {
|
||||
// set price list currency
|
||||
supplier: function() {
|
||||
if(this.frm.doc.supplier || this.frm.doc.credit_to) {
|
||||
if(!this.frm.doc.company) {
|
||||
this.frm.set_value("supplier", null);
|
||||
msgprint(wn._("Please specify Company"));
|
||||
} else {
|
||||
var me = this;
|
||||
var price_list_name = this.frm.doc.price_list_name;
|
||||
|
||||
this.frm.call({
|
||||
method: "setup.utils.get_price_list_currency",
|
||||
args: {args: {
|
||||
price_list_name: this.frm.doc.price_list_name,
|
||||
use_for: "buying"
|
||||
}},
|
||||
doc: this.frm.doc,
|
||||
method: "set_supplier_defaults",
|
||||
freeze: true,
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
me.price_list_currency();
|
||||
if (typeof callback_fn === "function")
|
||||
callback_fn(me.frm.doc, me.frm.doc.doctype, me.frm.doc.name);
|
||||
me.frm.refresh_fields();
|
||||
if(me.frm.doc.price_list_name !== price_list_name) me.price_list_name();
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
me.price_list_currency();
|
||||
if (typeof callback_fn === "function")
|
||||
callback_fn(me.frm.doc, me.frm.doc.doctype, me.frm.doc.name);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
item_code: function(doc, cdt, cdn) {
|
||||
var me = this;
|
||||
var item = wn.model.get_doc(cdt, cdn);
|
||||
if(item.item_code) {
|
||||
if(!this.validate_company_and_party()) {
|
||||
if(!this.validate_company_and_party("supplier")) {
|
||||
item.item_code = null;
|
||||
refresh_field("item_code", item.name, item.parentfield);
|
||||
} else {
|
||||
@@ -109,65 +99,115 @@ erpnext.buying.BuyingController = wn.ui.form.Controller.extend({
|
||||
}
|
||||
},
|
||||
callback: function(r) {
|
||||
// TODO: calculate
|
||||
if(!r.exc) {
|
||||
me.ref_rate(me.frm.doc, cdt, cdn);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
validate_company_and_party: function() {
|
||||
var valid = true;
|
||||
$.each(["company", "supplier"], function(i, fieldname) {
|
||||
if(!me.frm.doc[fieldname]) {
|
||||
valid = false;
|
||||
msgprint(wn._("Please specify") + ": " +
|
||||
wn.meta.get_label(me.frm.doc.doctype, fieldname, me.frm.doc.name) +
|
||||
". " + wn._("It is needed to fetch Item Details."));
|
||||
}
|
||||
});
|
||||
return valid;
|
||||
price_list_name: function(callback_fn) {
|
||||
this._super("buying");
|
||||
},
|
||||
|
||||
update_item_details: function(doc, dt, dn, callback) {
|
||||
if(!this.frm.doc.__islocal) return;
|
||||
|
||||
calculate_taxes_and_totals: function() {
|
||||
this._super();
|
||||
this.calculate_outstanding_amount();
|
||||
this.frm.refresh_fields();
|
||||
},
|
||||
|
||||
calculate_item_values: function() {
|
||||
var me = this;
|
||||
var children = getchildren(this.tname, this.frm.doc.name, this.fname);
|
||||
if(children && children.length) {
|
||||
this.frm.call({
|
||||
doc: me.frm.doc,
|
||||
method: "update_item_details",
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
refresh_field(me.fname);
|
||||
me.load_defaults(me.frm.doc, dt, dn, callback);
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.load_taxes(doc, dt, dn, callback);
|
||||
|
||||
if(this.frm.doc.doctype != "Purchase Invoice") {
|
||||
wn.meta.docfield_map[this.tname]["rate"] = $.extend({},
|
||||
wn.meta.docfield_map[this.tname]["purchase_rate"]);
|
||||
}
|
||||
|
||||
$.each(this.frm.item_doclist, function(i, item) {
|
||||
if(me.frm.doc.doctype != "Purchase Invoice") {
|
||||
item.rate = item.purchase_rate;
|
||||
}
|
||||
|
||||
wn.model.round_floats_in(item);
|
||||
item.import_amount = flt(item.import_rate * item.qty, precision("import_amount", item));
|
||||
item.item_tax_amount = 0.0;
|
||||
|
||||
me._set_in_company_currency(item, "import_ref_rate", "purchase_ref_rate");
|
||||
me._set_in_company_currency(item, "import_rate", "rate");
|
||||
me._set_in_company_currency(item, "import_amount", "amount");
|
||||
});
|
||||
},
|
||||
|
||||
calculate_net_total: function() {
|
||||
var me = this;
|
||||
|
||||
this.frm.doc.net_total = this.frm.doc.net_total_import = 0.0;
|
||||
$.each(this.frm.item_doclist, function(i, item) {
|
||||
me.frm.doc.net_total += item.amount;
|
||||
me.frm.doc.net_total_import += item.import_amount;
|
||||
});
|
||||
|
||||
wn.model.round_floats_in(this.frm.doc, ["net_total", "net_total_import"]);
|
||||
},
|
||||
|
||||
calculate_totals: function() {
|
||||
var tax_count = this.frm.tax_doclist.length;
|
||||
this.frm.doc.grand_total = flt(
|
||||
tax_count ? this.frm.tax_doclist[tax_count - 1].total : this.frm.doc.net_total,
|
||||
precision("grand_total"));
|
||||
this.frm.doc.grand_total_import = flt(this.frm.doc.grand_total / this.frm.doc.conversion_rate,
|
||||
precision("grand_total_import"));
|
||||
|
||||
this.frm.doc.total_tax = flt(this.frm.doc.grand_total - this.frm.doc.net_total,
|
||||
precision("total_tax"));
|
||||
|
||||
if(wn.meta.get_docfield(this.frm.doc.doctype, "rounded_total", this.frm.doc.name)) {
|
||||
this.frm.doc.rounded_total = Math.round(this.frm.doc.grand_total);
|
||||
}
|
||||
|
||||
if(wn.meta.get_docfield(this.frm.doc.doctype, "rounded_total_import", this.frm.doc.name)) {
|
||||
this.frm.doc.rounded_total_import = Math.round(this.frm.doc.grand_total_import);
|
||||
}
|
||||
},
|
||||
|
||||
currency: function() {
|
||||
this.price_list_currency();
|
||||
_cleanup: function() {
|
||||
this._super();
|
||||
this.frm.doc.in_words = this.frm.doc.in_words_import = "";
|
||||
|
||||
// except in purchase invoice, rate field is purchase_rate
|
||||
// reset fieldname of rate
|
||||
if(this.frm.doc.doctype != "Purchase Invoice") {
|
||||
delete wn.meta.docfield_map[this.tname]["rate"];
|
||||
|
||||
$.each(this.frm.item_doclist, function(i, item) {
|
||||
item.purchase_rate = item.rate;
|
||||
delete item["rate"];
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
company: function() {
|
||||
this.set_dynamic_labels();
|
||||
calculate_outstanding_amount: function() {
|
||||
if(this.frm.doc.doctype == "Purchase Invoice" && this.frm.doc.docstatus < 2) {
|
||||
wn.model.round_floats_in(this.frm.doc, ["total_advance", "write_off_amount"]);
|
||||
this.frm.doc.total_amount_to_pay = flt(this.frm.doc.grand_total - this.frm.doc.write_off_amount,
|
||||
precision("total_amount_to_pay"));
|
||||
this.frm.doc.outstanding_amount = flt(this.frm.doc.total_amount_to_pay - this.frm.doc.total_advance,
|
||||
precision("outstanding_amount"));
|
||||
}
|
||||
},
|
||||
|
||||
price_list_currency: function() {
|
||||
this.frm.toggle_reqd("plc_conversion_rate",
|
||||
!!(this.frm.doc.price_list_name && this.frm.doc.price_list_currency));
|
||||
|
||||
this.set_dynamic_labels();
|
||||
|
||||
if(this.frm.doc.price_list_currency === this.get_company_currency())
|
||||
this.frm.set_value("plc_conversion_rate", 1.0);
|
||||
else if(this.frm.doc.price_list_currency === this.frm.doc.currency)
|
||||
this.frm.set_value("plc_conversion_rate", this.frm.doc.conversion_rate || 1.0);
|
||||
set_item_tax_amount: function(item, tax, current_tax_amount) {
|
||||
// item_tax_amount is the total tax amount applied on that item
|
||||
// stored for valuation
|
||||
//
|
||||
// TODO: rename item_tax_amount to valuation_tax_amount
|
||||
if(["Valuation", "Valuation and Total"].indexOf(tax.category) != -1) {
|
||||
// accumulate only if tax is for Valuation / Valuation and Total
|
||||
item.item_tax_amount += flt(current_tax_amount, precision("item_tax_amount", item));
|
||||
}
|
||||
},
|
||||
|
||||
set_dynamic_labels: function(doc, dt, dn) {
|
||||
@@ -265,10 +305,6 @@ erpnext.buying.BuyingController = wn.ui.form.Controller.extend({
|
||||
$wrapper.find('[data-grid-fieldname="'+fname+'"]').text(label);
|
||||
});
|
||||
},
|
||||
|
||||
get_company_currency: function() {
|
||||
return erpnext.get_currency(this.frm.doc.company);
|
||||
}
|
||||
});
|
||||
|
||||
// to save previous state of cur_frm.cscript
|
||||
@@ -284,54 +320,6 @@ $.extend(cur_frm.cscript, prev_cscript);
|
||||
var tname = cur_frm.cscript.tname;
|
||||
var fname = cur_frm.cscript.fname;
|
||||
|
||||
cur_frm.cscript.get_default_schedule_date = function(doc) {
|
||||
var ch = getchildren( tname, doc.name, fname);
|
||||
if (flt(ch.length) > 0){
|
||||
$c_obj(make_doclist(doc.doctype, doc.name), 'get_default_schedule_date', '', function(r, rt) { refresh_field(fname); });
|
||||
}
|
||||
}
|
||||
|
||||
cur_frm.cscript.load_taxes = function(doc, cdt, cdn, callback) {
|
||||
// run if this is not executed from dt_map...
|
||||
doc = locals[doc.doctype][doc.name];
|
||||
if(doc.supplier || getchildren('Purchase Taxes and Charges', doc.name, 'purchase_tax_details', doc.doctype).length) {
|
||||
if(callback) {
|
||||
callback(doc, cdt, cdn);
|
||||
}
|
||||
} else {
|
||||
$c_obj(make_doclist(doc.doctype, doc.name),'load_default_taxes','',function(r,rt){
|
||||
refresh_field('purchase_tax_details');
|
||||
if(callback) callback(doc, cdt, cdn);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Gets called after existing item details are update to fill in
|
||||
// remaining default values
|
||||
cur_frm.cscript.load_defaults = function(doc, dt, dn, callback) {
|
||||
if(!cur_frm.doc.__islocal) { return; }
|
||||
|
||||
doc = locals[doc.doctype][doc.name];
|
||||
var fields_to_refresh = wn.model.set_default_values(doc);
|
||||
if(fields_to_refresh) { refresh_many(fields_to_refresh); }
|
||||
|
||||
fields_to_refresh = null;
|
||||
var children = getchildren(cur_frm.cscript.tname, doc.name, cur_frm.cscript.fname);
|
||||
if(!children) { return; }
|
||||
for(var i=0; i<children.length; i++) {
|
||||
wn.model.set_default_values(children[i]);
|
||||
}
|
||||
refresh_field(cur_frm.cscript.fname);
|
||||
cur_frm.cscript.load_taxes(doc, dt, dn, callback);
|
||||
}
|
||||
|
||||
// ======================== Conversion Rate ==========================================
|
||||
cur_frm.cscript.conversion_rate = function(doc,cdt,cdn) {
|
||||
cur_frm.cscript.calc_amount( doc, 1);
|
||||
}
|
||||
|
||||
//==================== Item Code Get Query =======================================================
|
||||
// Only Is Purchase Item = 'Yes' and Items not moved to trash are allowed.
|
||||
cur_frm.fields_dict[fname].grid.get_field("item_code").get_query = function(doc, cdt, cdn) {
|
||||
|
||||
@@ -69,17 +69,6 @@ class DocType(BuyingController):
|
||||
msgprint(_("Hey there! You need to put at least one item in \
|
||||
the item table."), raise_exception=True)
|
||||
|
||||
|
||||
def get_default_schedule_date( self, obj):
|
||||
for d in getlist( obj.doclist, obj.fname):
|
||||
item = sql("select lead_time_days from `tabItem` where name = '%s' and (ifnull(end_of_life,'')='' or end_of_life = '0000-00-00' or end_of_life > now())" % cstr(d.item_code) , as_dict = 1)
|
||||
ltd = item and cint(item[0]['lead_time_days']) or 0
|
||||
if ltd and obj.doc.transaction_date:
|
||||
if d.fields.has_key('lead_time_date') or obj.doc.doctype == 'Material Request':
|
||||
d.lead_time_date = cstr(add_days( obj.doc.transaction_date, cint(ltd)))
|
||||
if not d.fields.has_key('prevdoc_docname') or (d.fields.has_key('prevdoc_docname') and not d.prevdoc_docname):
|
||||
d.schedule_date = cstr( add_days( obj.doc.transaction_date, cint(ltd)))
|
||||
|
||||
# Client Trigger functions
|
||||
#------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -39,26 +39,6 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
|
||||
cur_frm.add_custom_button('Unstop Purchase Order', cur_frm.cscript['Unstop Purchase Order']);
|
||||
|
||||
},
|
||||
|
||||
onload_post_render: function(doc, dt, dn) {
|
||||
var me = this;
|
||||
var callback1 = function(doc, dt, dn) {
|
||||
var callback2 = function(doc, dt, dn) {
|
||||
if(doc.__islocal) cur_frm.cscript.get_default_schedule_date(doc);
|
||||
}
|
||||
me.update_item_details(doc, dt, dn, callback2);
|
||||
}
|
||||
|
||||
// TODO: improve this
|
||||
if(this.frm.doc.__islocal) {
|
||||
if (this.frm.fields_dict.price_list_name && this.frm.doc.price_list_name) {
|
||||
this.price_list_name(callback1);
|
||||
} else {
|
||||
callback1(doc, dt, dn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var new_cscript = new erpnext.buying.PurchaseOrderController({frm: cur_frm});
|
||||
@@ -66,28 +46,6 @@ var new_cscript = new erpnext.buying.PurchaseOrderController({frm: cur_frm});
|
||||
// for backward compatibility: combine new and previous states
|
||||
$.extend(cur_frm.cscript, new_cscript);
|
||||
|
||||
cur_frm.cscript.onload = function(doc, cdt, cdn) {
|
||||
// set missing values in parent doc
|
||||
set_missing_values(doc, {
|
||||
fiscal_year: sys_defaults.fiscal_year,
|
||||
conversion_rate: 1,
|
||||
currency: sys_defaults.currency,
|
||||
status: "Draft",
|
||||
transaction_date: get_today(),
|
||||
is_subcontracted: "No"
|
||||
});
|
||||
}
|
||||
|
||||
cur_frm.cscript.supplier = function(doc,dt,dn) {
|
||||
if (doc.supplier) {
|
||||
get_server_fields('get_default_supplier_address',
|
||||
JSON.stringify({ supplier: doc.supplier }),'', doc, dt, dn, 1, function() {
|
||||
cur_frm.refresh();
|
||||
});
|
||||
$(cur_frm.fields_dict.contact_section.row.wrapper).toggle(true);
|
||||
}
|
||||
}
|
||||
|
||||
cur_frm.cscript.supplier_address = cur_frm.cscript.contact_person = function(doc,dt,dn) {
|
||||
if(doc.supplier) get_server_fields('get_supplier_address', JSON.stringify({supplier: doc.supplier, address: doc.supplier_address, contact: doc.contact_person}),'', doc, dt, dn, 1);
|
||||
}
|
||||
@@ -111,10 +69,6 @@ cur_frm.fields_dict.contact_person.on_new = function(dn) {
|
||||
locals['Contact'][dn].supplier_name = locals[cur_frm.doctype][cur_frm.docname].supplier_name;
|
||||
}
|
||||
|
||||
cur_frm.cscript.transaction_date = function(doc,cdt,cdn){
|
||||
if(doc.__islocal){ cur_frm.cscript.get_default_schedule_date(doc); }
|
||||
}
|
||||
|
||||
cur_frm.fields_dict['po_details'].grid.get_field('project_name').get_query = function(doc, cdt, cdn) {
|
||||
return 'SELECT `tabProject`.name FROM `tabProject` \
|
||||
WHERE `tabProject`.status not in ("Completed", "Cancelled") \
|
||||
|
||||
@@ -65,10 +65,6 @@ class DocType(BuyingController):
|
||||
self.validate_for_subcontracting()
|
||||
self.update_raw_materials_supplied("po_raw_material_details")
|
||||
|
||||
|
||||
def get_default_schedule_date(self):
|
||||
get_obj(dt = 'Purchase Common').get_default_schedule_date(self)
|
||||
|
||||
def validate_fiscal_year(self):
|
||||
get_obj(dt = 'Purchase Common').validate_fiscal_year(self.doc.fiscal_year,self.doc.transaction_date,'PO Date')
|
||||
|
||||
@@ -101,7 +97,6 @@ class DocType(BuyingController):
|
||||
"""[['Supplier Quotation', 'Purchase Order'],
|
||||
['Supplier Quotation Item', 'Purchase Order Item'],
|
||||
['Purchase Taxes and Charges', 'Purchase Taxes and Charges']]""")
|
||||
self.get_default_schedule_date()
|
||||
for d in getlist(self.doclist, 'po_details'):
|
||||
if d.prevdoc_detail_docname and not d.schedule_date:
|
||||
d.schedule_date = webnotes.conn.get_value("Material Request Item",
|
||||
|
||||
@@ -26,29 +26,11 @@ wn.require('app/buying/doctype/purchase_common/purchase_common.js');
|
||||
erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.extend({
|
||||
refresh: function() {
|
||||
this._super();
|
||||
|
||||
|
||||
if (this.frm.doc.docstatus === 1) {
|
||||
cur_frm.add_custom_button("Make Purchase Order", cur_frm.cscript.make_purchase_order);
|
||||
}
|
||||
},
|
||||
|
||||
onload_post_render: function(doc, dt, dn) {
|
||||
var me = this;
|
||||
var callback = function(doc, dt, dn) {
|
||||
cur_frm.cscript.load_taxes(me.frm.doc);
|
||||
}
|
||||
|
||||
// TODO: improve this
|
||||
if(this.frm.doc.__islocal) {
|
||||
if (this.frm.fields_dict.price_list_name && this.frm.doc.price_list_name) {
|
||||
this.price_list_name(callback);
|
||||
} else {
|
||||
callback(doc, dt, dn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
var new_cscript = new erpnext.buying.SupplierQuotationController({frm: cur_frm});
|
||||
@@ -56,19 +38,6 @@ var new_cscript = new erpnext.buying.SupplierQuotationController({frm: cur_frm})
|
||||
// for backward compatibility: combine new and previous states
|
||||
$.extend(cur_frm.cscript, new_cscript);
|
||||
|
||||
|
||||
cur_frm.cscript.onload = function(doc, dt, dn) {
|
||||
// set missing values in parent doc
|
||||
set_missing_values(doc, {
|
||||
fiscal_year: sys_defaults.fiscal_year,
|
||||
conversion_rate: 1,
|
||||
currency: sys_defaults.currency,
|
||||
status: "Draft",
|
||||
transaction_date: get_today(),
|
||||
is_subcontracted: "No"
|
||||
});
|
||||
}
|
||||
|
||||
cur_frm.cscript.make_purchase_order = function() {
|
||||
var new_po_name = wn.model.make_new_doc_and_get_name("Purchase Order");
|
||||
$c("dt_map", {
|
||||
|
||||
@@ -65,7 +65,10 @@ def get_item_details(args):
|
||||
out.purchase_ref_rate = out.discount_rate = out.purchase_rate = \
|
||||
out.import_ref_rate = out.import_rate = 0.0
|
||||
out.update(_get_price_list_rate(args, item_bean, meta))
|
||||
|
||||
|
||||
if args.doctype == "Material Request":
|
||||
out.min_order_qty = flt(item.min_order_qty)
|
||||
|
||||
return out
|
||||
|
||||
def _get_basic_details(args, item_bean):
|
||||
|
||||
Reference in New Issue
Block a user