diff --git a/erpnext/buying/doctype/purchase_common/purchase_common.js b/erpnext/buying/doctype/purchase_common/purchase_common.js index c3ef365f68..3c63508991 100644 --- a/erpnext/buying/doctype/purchase_common/purchase_common.js +++ b/erpnext/buying/doctype/purchase_common/purchase_common.js @@ -75,7 +75,7 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({ }, buying_price_list: function() { - this.get_price_list_currency("Buying"); + this.apply_price_list(); }, price_list_rate: function(doc, cdt, cdn) { diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index df5370ae19..3df62e7934 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe from frappe import _, throw from frappe.utils import flt, cint, today -from erpnext.setup.utils import get_company_currency +from erpnext.setup.utils import get_company_currency, get_exchange_rate from erpnext.accounts.utils import get_fiscal_year, validate_fiscal_year from erpnext.utilities.transaction_base import TransactionBase import json @@ -68,7 +68,7 @@ class AccountsController(TransactionBase): self.plc_conversion_rate = 1.0 elif not self.plc_conversion_rate: - self.plc_conversion_rate = self.get_exchange_rate( + self.plc_conversion_rate = get_exchange_rate( self.price_list_currency, company_currency) # currency @@ -78,13 +78,9 @@ class AccountsController(TransactionBase): elif self.currency == company_currency: self.conversion_rate = 1.0 elif not self.conversion_rate: - self.conversion_rate = self.get_exchange_rate(self.currency, + self.conversion_rate = get_exchange_rate(self.currency, company_currency) - def get_exchange_rate(self, from_currency, to_currency): - exchange = "%s-%s" % (from_currency, to_currency) - return flt(frappe.db.get_value("Currency Exchange", exchange, "exchange_rate")) - def set_missing_item_details(self): """set missing item values""" from erpnext.stock.get_item_details import get_item_details diff --git a/erpnext/public/js/transaction.js b/erpnext/public/js/transaction.js index 3c99ced701..1790a47252 100644 --- a/erpnext/public/js/transaction.js +++ b/erpnext/public/js/transaction.js @@ -241,31 +241,13 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ if(flt(this.frm.doc.conversion_rate)>0.0) { if(this.frm.doc.ignore_pricing_rule) { this.calculate_taxes_and_totals(); - } else { - this.apply_pricing_rule(); + } else if (!this.in_apply_price_list){ + this.apply_price_list(); } } }, - get_price_list_currency: function(buying_or_selling) { - var me = this; - var fieldname = buying_or_selling.toLowerCase() + "_price_list"; - if(this.frm.doc[fieldname]) { - return this.frm.call({ - method: "erpnext.setup.utils.get_price_list_currency", - args: { - price_list: this.frm.doc[fieldname], - }, - callback: function(r) { - if(!r.exc) { - me.price_list_currency(); - } - } - }); - } - }, - get_exchange_rate: function(from_currency, to_currency, callback) { var exchange_name = from_currency + "-" + to_currency; frappe.model.with_doc("Currency Exchange", exchange_name, function(name) { @@ -277,22 +259,17 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ price_list_currency: function() { var me=this; this.set_dynamic_labels(); - - var company_currency = this.get_company_currency(); - if(this.frm.doc.price_list_currency !== company_currency) { - this.get_exchange_rate(this.frm.doc.price_list_currency, company_currency, - function(exchange_rate) { - if(exchange_rate) { - me.frm.set_value("plc_conversion_rate", exchange_rate); - me.plc_conversion_rate(); - } - }); - } else { - this.plc_conversion_rate(); - } + this.set_plc_conversion_rate(); }, plc_conversion_rate: function() { + this.set_plc_conversion_rate(); + if(!this.in_apply_price_list) { + this.apply_price_list(); + } + }, + + set_plc_conversion_rate: function() { if(this.frm.doc.price_list_currency === this.get_company_currency()) { this.frm.set_value("plc_conversion_rate", 1.0); } @@ -351,9 +328,22 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ apply_pricing_rule: function(item, calculate_taxes_and_totals) { var me = this; - var item_list = this._get_item_list(item); - var args = { - "item_list": item_list, + return this.frm.call({ + method: "erpnext.accounts.doctype.pricing_rule.pricing_rule.apply_pricing_rule", + args: { args: this._get_args(item) }, + callback: function(r) { + if (!r.exc) { + me._set_values_for_item_list(r.message); + if(calculate_taxes_and_totals) me.calculate_taxes_and_totals(); + } + } + }); + }, + + _get_args: function(item) { + var me = this; + return { + "item_list": this._get_item_list(item), "customer": me.frm.doc.customer, "customer_group": me.frm.doc.customer_group, "territory": me.frm.doc.territory, @@ -371,22 +361,6 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ "parenttype": me.frm.doc.doctype, "parent": me.frm.doc.name }; - return this.frm.call({ - method: "erpnext.accounts.doctype.pricing_rule.pricing_rule.apply_pricing_rule", - args: { args: args }, - callback: function(r) { - if (!r.exc) { - $.each(r.message, function(i, d) { - $.each(d, function(k, v) { - if (["doctype", "name"].indexOf(k)===-1) { - frappe.model.set_value(d.doctype, d.name, k, v); - } - }); - }); - if(calculate_taxes_and_totals) me.calculate_taxes_and_totals(); - } - } - }); }, _get_item_list: function(item) { @@ -412,6 +386,33 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ return item_list; }, + _set_values_for_item_list: function(children) { + $.each(children, function(i, d) { + $.each(d, function(k, v) { + if (["doctype", "name"].indexOf(k)===-1) { + frappe.model.set_value(d.doctype, d.name, k, v); + } + }); + }); + }, + + apply_price_list: function() { + var me = this; + return this.frm.call({ + method: "erpnext.stock.get_item_details.apply_price_list", + args: { args: this._get_args() }, + callback: function(r) { + if (!r.exc) { + me.in_apply_price_list = true; + me.frm.set_value("price_list_currency", r.message.parent.price_list_currency); + me.frm.set_value("plc_conversion_rate", r.message.parent.plc_conversion_rate); + me.in_apply_price_list = false; + me._set_values_for_item_list(r.message.children); + } + } + }); + }, + included_in_print_rate: function(doc, cdt, cdn) { var tax = frappe.get_doc(cdt, cdn); try { diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index 2021490bb7..fff7ef9cd3 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -137,7 +137,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ }, selling_price_list: function() { - this.get_price_list_currency("Selling"); + this.apply_price_list(); }, price_list_rate: function(doc, cdt, cdn) { diff --git a/erpnext/setup/utils.py b/erpnext/setup/utils.py index a734ffd127..e7d78abb42 100644 --- a/erpnext/setup/utils.py +++ b/erpnext/setup/utils.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import frappe from frappe import _, throw +from frappe.utils import flt def get_company_currency(company): currency = frappe.db.get_value("Company", company, "default_currency") @@ -28,16 +29,6 @@ def get_ancestors_of(doctype, name): where lft<%s and rgt>%s order by lft desc""" % (doctype, "%s", "%s"), (lft, rgt)) return result or [] -@frappe.whitelist() -def get_price_list_currency(price_list): - price_list_currency = frappe.db.get_value("Price List", {"name": price_list, - "enabled": 1}, "currency") - - if not price_list_currency: - throw(_("Price List {0} is disabled").format(price_list)) - else: - return {"price_list_currency": price_list_currency} - def before_tests(): # complete setup if missing from erpnext.setup.page.setup_wizard.setup_wizard import setup_account @@ -64,3 +55,7 @@ def before_tests(): frappe.db.sql("delete from `tabSalary Slip`") frappe.db.sql("delete from `tabItem Price`") frappe.db.commit() + +def get_exchange_rate(from_currency, to_currency): + exchange = "%s-%s" % (from_currency, to_currency) + return flt(frappe.db.get_value("Currency Exchange", exchange, "exchange_rate")) diff --git a/erpnext/startup/__init__.py b/erpnext/startup/__init__.py index 576ab05627..a3b96cf46c 100644 --- a/erpnext/startup/__init__.py +++ b/erpnext/startup/__init__.py @@ -2,17 +2,17 @@ # ERPNext - web based ERP (http://erpnext.com) # Copyright (C) 2012 Web Notes Technologies Pvt Ltd -# +# # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program. If not, see . @@ -26,11 +26,3 @@ user_defaults = { "Company": "company", "Territory": "territory" } - -def get_monthly_bulk_mail_limit(): - import frappe - # if global settings, then 500 or unlimited - if frappe.db.get_value('Outgoing Email Settings', None, 'mail_server'): - return 999999 - else: - return 500 diff --git a/erpnext/stock/doctype/item_price/item_price.json b/erpnext/stock/doctype/item_price/item_price.json index 6b50349dc2..e3535b1519 100644 --- a/erpnext/stock/doctype/item_price/item_price.json +++ b/erpnext/stock/doctype/item_price/item_price.json @@ -1,7 +1,7 @@ { "allow_import": 1, "autoname": "RFD/.#####", - "creation": "2013-05-02 16:29:48.000000", + "creation": "2013-05-02 16:29:48", "description": "Multiple Item prices.", "docstatus": 0, "doctype": "DocType", @@ -72,6 +72,15 @@ "reqd": 1, "search_index": 0 }, + { + "fieldname": "currency", + "fieldtype": "Link", + "hidden": 0, + "label": "Currency", + "options": "Currency", + "permlevel": 0, + "read_only": 1 + }, { "fieldname": "col_br_1", "fieldtype": "Column Break", @@ -90,22 +99,13 @@ "label": "Item Description", "permlevel": 0, "read_only": 1 - }, - { - "fieldname": "currency", - "fieldtype": "Link", - "hidden": 1, - "label": "Currency", - "options": "Currency", - "permlevel": 0, - "read_only": 1 } ], "icon": "icon-flag", "idx": 1, "in_create": 0, "istable": 0, - "modified": "2014-02-10 17:27:32.000000", + "modified": "2014-07-08 15:38:23.653034", "modified_by": "Administrator", "module": "Stock", "name": "Item Price", diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index fe320d153a..f9a1d9fa1a 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -7,6 +7,7 @@ from frappe import _, throw from frappe.utils import flt, cint, add_days import json from erpnext.accounts.doctype.pricing_rule.pricing_rule import get_pricing_rule_for_item +from erpnext.setup.utils import get_exchange_rate @frappe.whitelist() def get_item_details(args): @@ -30,27 +31,7 @@ def get_item_details(args): "ignore_pricing_rule": 0/1 } """ - - if isinstance(args, basestring): - args = json.loads(args) - - args = frappe._dict(args) - - if not args.get("transaction_type"): - if args.get("parenttype")=="Material Request" or \ - frappe.get_meta(args.get("parenttype")).get_field("supplier"): - args.transaction_type = "buying" - else: - args.transaction_type = "selling" - - if not args.get("price_list"): - args.price_list = args.get("selling_price_list") or args.get("buying_price_list") - - if args.barcode: - args.item_code = get_item_code(barcode=args.barcode) - elif not args.item_code and args.serial_no: - args.item_code = get_item_code(serial_no=args.serial_no) - + args = process_args(args) item_doc = frappe.get_doc("Item", args.item_code) item = item_doc @@ -86,6 +67,29 @@ def get_item_details(args): return out +def process_args(args): + if isinstance(args, basestring): + args = json.loads(args) + + args = frappe._dict(args) + + if not args.get("transaction_type"): + if args.get("parenttype")=="Material Request" or \ + frappe.get_meta(args.get("parenttype")).get_field("supplier"): + args.transaction_type = "buying" + else: + args.transaction_type = "selling" + + if not args.get("price_list"): + args.price_list = args.get("selling_price_list") or args.get("buying_price_list") + + if args.barcode: + args.item_code = get_item_code(barcode=args.barcode) + elif not args.item_code and args.serial_no: + args.item_code = get_item_code(serial_no=args.serial_no) + + return args + def get_item_code(barcode=None, serial_no=None): if barcode: item_code = frappe.db.get_value("Item", {"barcode": barcode}) @@ -273,3 +277,74 @@ def get_projected_qty(item_code, warehouse): def get_available_qty(item_code, warehouse): return frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, ["projected_qty", "actual_qty"], as_dict=True) or {} + +@frappe.whitelist() +def apply_price_list(args): + """ + args = { + "item_list": [{"doctype": "", "name": "", "item_code": "", "brand": "", "item_group": ""}, ...], + "conversion_rate": 1.0, + "selling_price_list": None, + "price_list_currency": None, + "plc_conversion_rate": 1.0, + "parenttype": "", + "parent": "", + "supplier": None, + "transaction_date": None, + "conversion_rate": 1.0, + "buying_price_list": None, + "transaction_type": "selling", + "ignore_pricing_rule": 0/1 + } + """ + args = process_args(args) + + parent = get_price_list_currency_and_exchange_rate(args) + children = [] + + if "item_list" in args: + item_list = args.get("item_list") + del args["item_list"] + + args.update(parent) + + for item in item_list: + args_copy = frappe._dict(args.copy()) + args_copy.update(item) + item_details = apply_price_list_on_item(args_copy) + children.append(item_details) + + return { + "parent": parent, + "children": children + } + +def apply_price_list_on_item(args): + item_details = frappe._dict() + item_doc = frappe.get_doc("Item", args.item_code) + get_price_list_rate(args, item_doc, item_details) + item_details.discount_percentage = 0.0 + item_details.update(get_pricing_rule_for_item(args)) + return item_details + +def get_price_list_currency(price_list): + result = frappe.db.get_value("Price List", {"name": price_list, + "enabled": 1}, ["name", "currency"], as_dict=True) + + if not result: + throw(_("Price List {0} is disabled").format(price_list)) + + return result.currency + +def get_price_list_currency_and_exchange_rate(args): + price_list_currency = get_price_list_currency(args.price_list) + plc_conversion_rate = args.plc_conversion_rate + + if (not plc_conversion_rate) or (price_list_currency != args.price_list_currency): + plc_conversion_rate = get_exchange_rate(price_list_currency, args.currency) \ + or plc_conversion_rate + + return { + "price_list_currency": price_list_currency, + "plc_conversion_rate": plc_conversion_rate + }