[selling] [calculations] client side calculations, cleanup, patch fixes

This commit is contained in:
Anand Doshi
2013-05-21 19:35:06 +05:30
parent b5aa8da0dd
commit f309613a7d
23 changed files with 1174 additions and 1318 deletions

View File

@@ -54,10 +54,8 @@ erpnext.buying.PurchaseInvoiceController = erpnext.buying.BuyingController.exten
}
});
var new_cscript = new erpnext.buying.PurchaseInvoiceController({frm: cur_frm});
// for backward compatibility: combine new and previous states
$.extend(cur_frm.cscript, new_cscript);
$.extend(cur_frm.cscript, new erpnext.buying.PurchaseInvoiceController({frm: cur_frm}));
cur_frm.cscript.onload = function(doc,dt,dn) {

View File

@@ -26,48 +26,62 @@ wn.require('app/selling/doctype/sales_common/sales_common.js');
wn.require('app/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js');
wn.require('app/utilities/doctype/sms_control/sms_control.js');
// On Load
// -------
cur_frm.cscript.onload = function(doc,dt,dn) {
cur_frm.cscript.manage_rounded_total();
if(!doc.customer && doc.debit_to) wn.meta.get_docfield(dt, 'debit_to', dn).print_hide = 0;
if (doc.__islocal) {
if(!doc.due_date) set_multiple(dt,dn,{due_date:get_today()});
if(!doc.posting_date) set_multiple(dt,dn,{posting_date:get_today()});
if(!doc.currency && sys_defaults.currency) set_multiple(dt,dn,{currency:sys_defaults.currency});
if(!doc.price_list_currency) set_multiple(dt, dn, {price_list_currency: doc.currency, plc_conversion_rate: 1});
erpnext.selling.SalesInvoiceController = erpnext.selling.SellingController.extend({
onload: function() {
this._super();
// show debit_to in print format
if(!this.frm.doc.customer && this.frm.doc.debit_to) {
this.frm.set_df_property("debit_to", "print_hide", 0);
}
},
refresh: function(doc, dt, dn) {
this._super();
cur_frm.cscript.is_opening(doc, dt, dn);
}
}
// Show / Hide button
cur_frm.clear_custom_buttons();
// if (!cur_frm.cscript.is_onload) cur_frm.cscript.hide_price_list_currency(doc, dt, dn);
cur_frm.cscript.onload_post_render = function(doc, dt, dn) {
var callback = function(doc, dt, dn) {
// called from mapper, update the account names for items and customer
var callback2 = function(doc, dt, dn) {
if(doc.customer && doc.__islocal) {
$c_obj(make_doclist(doc.doctype,doc.name),
'load_default_accounts','',
function(r,rt) {
refresh_field('entries');
cur_frm.cscript.customer(doc,dt,dn,onload=true);
}
);
if(doc.docstatus==1) {
cur_frm.add_custom_button('View Ledger', cur_frm.cscript.view_ledger_entry);
cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms);
if(doc.is_pos==1 && doc.update_stock!=1)
cur_frm.add_custom_button('Make Delivery', cur_frm.cscript['Make Delivery Note']);
if(doc.outstanding_amount!=0)
cur_frm.add_custom_button('Make Payment Entry', cur_frm.cscript.make_bank_voucher);
}
cur_frm.cscript.hide_fields(doc, dt, dn);
},
is_pos: function() {
if(cint(this.frm.doc.is_pos)) {
if(!this.frm.doc.company) {
this.frm.set_value("is_pos", 0);
msgprint(wn._("Please specify Company to proceed"));
} else {
var me = this;
this.frm.call({
doc: me.frm.doc,
method: "set_missing_values",
});
}
}
// defined in sales_common.js
var callback1 = function(doc, dt, dn) {
//for previously created sales invoice, set required field related to pos
cur_frm.cscript.update_item_details(doc, dt, dn, callback2);
}
if(doc.is_pos ==1) cur_frm.cscript.is_pos(doc, dt, dn,callback1);
else cur_frm.cscript.update_item_details(doc, dt, dn, callback2);
}
cur_frm.cscript.hide_price_list_currency(doc, dt, dn, callback);
}
// TODO toggle display of fields
},
debit_to: function() {
this.customer();
},
});
// for backward compatibility: combine new and previous states
$.extend(cur_frm.cscript, new erpnext.selling.SalesInvoiceController({frm: cur_frm}));
// Hide Fields
// ------------
@@ -104,50 +118,6 @@ cur_frm.cscript.hide_fields = function(doc, cdt, cdn) {
}
// Refresh
// -------
cur_frm.cscript.refresh = function(doc, dt, dn) {
cur_frm.cscript.is_opening(doc, dt, dn);
erpnext.hide_naming_series();
// Show / Hide button
cur_frm.clear_custom_buttons();
if (!cur_frm.cscript.is_onload) cur_frm.cscript.hide_price_list_currency(doc, dt, dn);
if(doc.docstatus==1) {
cur_frm.add_custom_button('View Ledger', cur_frm.cscript.view_ledger_entry);
cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms);
if(doc.is_pos==1 && doc.update_stock!=1)
cur_frm.add_custom_button('Make Delivery', cur_frm.cscript['Make Delivery Note']);
if(doc.outstanding_amount!=0)
cur_frm.add_custom_button('Make Payment Entry', cur_frm.cscript.make_bank_voucher);
}
cur_frm.cscript.hide_fields(doc, dt, dn);
}
//fetch retail transaction related fields
//--------------------------------------------
cur_frm.cscript.is_pos = function(doc,dt,dn,callback){
cur_frm.cscript.hide_fields(doc, dt, dn);
if(doc.is_pos == 1){
if (!doc.company) {
msgprint("Please select company to proceed");
doc.is_pos = 0;
refresh_field('is_pos');
}
else {
var callback1 = function(r,rt){
if(callback) callback(doc, dt, dn);
cur_frm.refresh();
}
$c_obj(make_doclist(dt,dn),'set_pos_fields','',callback1);
}
}
}
cur_frm.cscript.mode_of_payment = function(doc) {
cur_frm.call({
method: "get_bank_cash_account",
@@ -168,66 +138,10 @@ cur_frm.cscript.warehouse = function(doc, cdt , cdn) {
}
}
//Customer
cur_frm.cscript.customer = function(doc,dt,dn,onload) {
cur_frm.toggle_display("contact_section", doc.customer);
var pl = doc.price_list_name;
var callback = function(r,rt) {
var callback2 = function(doc, dt, dn) {
doc = locals[dt][dn];
if(doc.debit_to && doc.posting_date){
get_server_fields('get_cust_and_due_date','','',doc,dt,dn,1,
function(doc, dt, dn) {
cur_frm.refresh();
if (!onload && (pl != doc.price_list_name)) cur_frm.cscript.price_list_name(doc, dt, dn);
});
}
}
var doc = locals[cur_frm.doctype][cur_frm.docname];
get_server_fields('get_debit_to','','',doc, dt, dn, 0, callback2);
}
var args = onload ? 'onload':''
if(doc.customer) $c_obj(make_doclist(doc.doctype, doc.name), 'get_default_customer_address', args, callback);
}
cur_frm.cscript.customer_address = cur_frm.cscript.contact_person = function(doc,dt,dn) {
if(doc.customer) get_server_fields('get_customer_address', JSON.stringify({customer: doc.customer, address: doc.customer_address, contact: doc.contact_person}),'', doc, dt, dn, 1);
}
// Set Due Date = posting date + credit days
cur_frm.cscript.debit_to = function(doc,dt,dn) {
var callback2 = function(r,rt) {
var doc = locals[cur_frm.doctype][cur_frm.docname];
cur_frm.refresh();
}
var callback = function(r,rt) {
var doc = locals[cur_frm.doctype][cur_frm.docname];
if(doc.customer) $c_obj(make_doclist(dt,dn), 'get_default_customer_address', '', callback2);
cur_frm.toggle_display("contact_section", doc.customer);
cur_frm.refresh();
}
if(doc.debit_to && doc.posting_date){
get_server_fields('get_cust_and_due_date','','',doc,dt,dn,1,callback);
}
}
//refresh advance amount
//-------------------------------------------------
cur_frm.cscript.write_off_outstanding_amount_automatically = function(doc) {
if (doc.write_off_outstanding_amount_automatically == 1)
doc.write_off_amount = flt(doc.grand_total) - flt(doc.paid_amount);
@@ -244,9 +158,6 @@ cur_frm.cscript.write_off_amount = function(doc) {
cur_frm.cscript.write_off_outstanding_amount_automatically(doc);
}
//Set debit and credit to zero on adding new row
//----------------------------------------------
cur_frm.fields_dict['entries'].grid.onrowadd = function(doc, cdt, cdn){
cl = getchildren('Sales Invoice Item', doc.name, cur_frm.cscript.fname, doc.doctype);

View File

@@ -41,7 +41,6 @@ class DocType(SellingController):
def validate(self):
super(DocType, self).validate()
self.fetch_missing_values()
self.validate_posting_time()
self.so_dn_required()
self.validate_proj_cust()
@@ -50,7 +49,6 @@ class DocType(SellingController):
sales_com_obj.check_active_sales_items(self)
sales_com_obj.check_conversion_rate(self)
sales_com_obj.validate_max_discount(self, 'entries')
sales_com_obj.get_allocated_sum(self)
sales_com_obj.validate_fiscal_year(self.doc.fiscal_year,
self.doc.posting_date,'Posting Date')
self.validate_customer()
@@ -134,25 +132,16 @@ class DocType(SellingController):
self.validate_recurring_invoice()
self.convert_to_recurring()
def fetch_missing_values(self):
# fetch contact and address details for customer, if they are not mentioned
if not (self.doc.contact_person and self.doc.customer_address):
for fieldname, val in self.get_default_address_and_contact("customer").items():
if not self.doc.fields.get(fieldname) and self.meta.get_field(fieldname):
self.doc.fields[fieldname] = val
# fetch missing item values
for item in self.doclist.get({"parentfield": "entries"}):
if item.fields.get("item_code"):
ret = get_obj('Sales Common').get_item_details(item.fields, self)
for fieldname, value in ret.items():
if self.meta.get_field(fieldname, parentfield="entries") and \
not item.fields.get(fieldname):
item.fields[fieldname] = value
def set_missing_values(self, for_validate=False):
super(DocType, self).set_missing_values(for_validate)
self.set_pos_fields(for_validate)
# fetch pos details, if they are not fetched
if cint(self.doc.is_pos):
self.set_pos_fields(for_validate=True)
def set_customer_defaults(self):
# TODO cleanup these methods
self.doc.fields.update(self.get_debit_to())
self.get_cust_and_due_date()
super(DocType, self).set_customer_defaults()
def update_time_log_batch(self, sales_invoice):
for d in self.doclist.get({"doctype":"Sales Invoice Item"}):
@@ -173,10 +162,11 @@ class DocType(SellingController):
"""Set retail related fields from pos settings"""
if cint(self.doc.is_pos) != 1:
return
from selling.utils import get_pos_settings, apply_pos_settings
pos = get_pos_settings(self.doc.company)
if self.pos_settings:
pos = self.pos_settings[0]
if pos:
self.doc.conversion_rate = flt(pos.conversion_rate)
if not self.doc.debit_to:
@@ -193,7 +183,7 @@ class DocType(SellingController):
# set pos values in items
for item in self.doclist.get({"parentfield": "entries"}):
if item.fields.get('item_code'):
for fieldname, val in self.apply_pos_settings(item.fields).items():
for fieldname, val in apply_pos_settings(pos, item.fields).items():
if (not for_validate) or (for_validate and not item.fields.get(fieldname)):
item.fields[fieldname] = val
@@ -203,7 +193,7 @@ class DocType(SellingController):
# fetch charges
if self.doc.charge and not len(self.doclist.get({"parentfield": "other_charges"})):
self.get_other_charges()
self.set_taxes()
def get_customer_account(self):
"""Get Account Head to which amount needs to be Debited based on Customer"""
@@ -272,86 +262,14 @@ class DocType(SellingController):
ret = self.get_debit_to()
self.doc.debit_to = ret.get('debit_to')
def load_default_accounts(self):
"""
Loads default accounts from items, customer when called from mapper
"""
self.get_income_expense_account('entries')
def get_income_expense_account(self,doctype):
for d in getlist(self.doclist, doctype):
if d.item_code:
item = webnotes.conn.get_value("Item", d.item_code, ["default_income_account",
"default_sales_cost_center", "purchase_account"], as_dict=True)
d.income_account = item['default_income_account'] or ""
d.cost_center = item['default_sales_cost_center'] or ""
if cint(webnotes.defaults.get_global_default("auto_inventory_accounting")) \
and cint(self.doc.is_pos) and cint(self.doc.update_stock):
d.expense_account = item['purchase_account'] or ""
def get_item_details(self, args=None):
import json
args = args and json.loads(args) or {}
if args.get('item_code'):
ret = get_obj('Sales Common').get_item_details(args, self)
if cint(self.doc.is_pos) == 1 and self.pos_settings:
ret = self.apply_pos_settings(args, ret)
return ret
elif cint(self.doc.is_pos) == 1 and self.pos_settings:
for doc in self.doclist.get({"parentfield": "entries"}):
if doc.fields.get('item_code'):
ret = self.apply_pos_settings(doc.fields)
for r in ret:
if not doc.fields.get(r):
doc.fields[r] = ret[r]
@property
def pos_settings(self):
if not hasattr(self, "_pos_settings"):
dtl = webnotes.conn.sql("""select * from `tabPOS Setting` where user = %s
and company = %s""", (webnotes.session['user'], self.doc.company), as_dict=1)
if not dtl:
dtl = webnotes.conn.sql("""select * from `tabPOS Setting`
where ifnull(user,'') = '' and company = %s""", self.doc.company, as_dict=1)
self._pos_settings = dtl
from selling.utils import get_pos_settings
self._pos_settings = get_pos_settings({"company": self.doc.company})
return self._pos_settings
def apply_pos_settings(self, args, ret=None):
if not ret: ret = {}
pos = self.pos_settings[0]
item = webnotes.conn.sql("""select default_income_account, default_sales_cost_center,
default_warehouse, purchase_account from tabItem where name = %s""",
args.get('item_code'), as_dict=1)
if item:
item = item[0]
ret.update({
"income_account": item.get("default_income_account") \
or pos.get("income_account") or args.get("income_account"),
"cost_center": item.get("default_sales_cost_center") \
or pos.get("cost_center") or args.get("cost_center"),
"warehouse": item.get("default_warehouse") \
or pos.get("warehouse") or args.get("warehouse"),
"expense_account": item.get("purchase_account") \
or pos.get("expense_account") or args.get("expense_account")
})
if ret.get("warehouse"):
ret["actual_qty"] = flt(webnotes.conn.get_value("Bin",
{"item_code": args.get("item_code"), "warehouse": args.get("warehouse")},
"actual_qty"))
return ret
def get_barcode_details(self, barcode):
return get_obj('Sales Common').get_barcode_details(barcode)
@@ -375,14 +293,6 @@ class DocType(SellingController):
return get_obj('Sales Common').get_tc_details(self)
def load_default_taxes(self):
self.doclist = get_obj('Sales Common').load_default_taxes(self)
def get_other_charges(self):
self.doclist = get_obj('Sales Common').get_other_charges(self)
def get_advances(self):
super(DocType, self).get_advances(self.doc.debit_to,
"Sales Invoice Advance", "advance_adjustment_details", "credit")
@@ -611,7 +521,9 @@ class DocType(SellingController):
else:
self.doclist = self.doc.clear_table(self.doclist, 'packing_details')
webnotes.conn.set(self.doc,'paid_amount',0)
# TODO
# move to calculations
webnotes.conn.set(self.doc, 'outstanding_amount',
flt(self.doc.grand_total) - flt(self.doc.total_advance) -
flt(self.doc.paid_amount) - flt(self.doc.write_off_amount))

View File

@@ -1,8 +1,8 @@
[
{
"creation": "2013-05-06 12:03:41",
"creation": "2013-05-21 16:16:41",
"docstatus": 0,
"modified": "2013-05-09 17:34:14",
"modified": "2013-05-21 18:25:07",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -224,11 +224,12 @@
"doctype": "DocField",
"fieldname": "entries",
"fieldtype": "Table",
"label": "Entries",
"label": "Sales Invoice Items",
"oldfieldname": "entries",
"oldfieldtype": "Table",
"options": "Sales Invoice Item",
"read_only": 0
"read_only": 0,
"reqd": 1
},
{
"doctype": "DocField",
@@ -460,6 +461,15 @@
"print_hide": 1,
"read_only": 1
},
{
"doctype": "DocField",
"fieldname": "other_charges_total_export",
"fieldtype": "Currency",
"label": "Total Taxes and Charges (Export)",
"options": "currency",
"print_hide": 1,
"read_only": 1
},
{
"doctype": "DocField",
"fieldname": "other_charges_calculation",

View File

@@ -1,8 +1,8 @@
[
{
"creation": "2013-04-10 08:35:44",
"creation": "2013-04-19 13:30:26",
"docstatus": 0,
"modified": "2013-04-17 14:05:20",
"modified": "2013-05-21 16:43:21",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -107,7 +107,7 @@
"oldfieldtype": "Currency",
"options": "currency",
"print_hide": 1,
"read_only": 0,
"read_only": 1,
"reqd": 0
},
{
@@ -163,7 +163,7 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"print_hide": 1,
"read_only": 0,
"read_only": 1,
"reqd": 1,
"search_index": 0
},