From db59ffb76d5650a888833e8c947abb777fde3d5b Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Wed, 11 Sep 2013 13:05:24 +0530 Subject: [PATCH] [usability] item price moved to price list --- accounts/doctype/sales_invoice/pos.js | 2 +- accounts/doctype/sales_invoice/pos.py | 13 +++--- .../purchase_common/purchase_common.js | 12 +----- buying/utils.py | 13 +++--- controllers/accounts_controller.py | 6 +-- controllers/queries.py | 8 ---- manufacturing/doctype/bom/bom.py | 4 +- patches/january_2013/purchase_price_list.py | 12 ------ .../p03_buying_selling_for_price_list.py | 6 +-- patches/patch_list.py | 2 +- ...modify_item_price_include_in_price_list.py | 18 ++++++++ public/js/transaction.js | 5 +-- selling/doctype/sales_bom/sales_bom.py | 6 +-- .../doctype/sales_bom_item/sales_bom_item.txt | 11 ++--- selling/doctype/sales_common/sales_common.js | 10 ----- selling/utils.py | 13 +++--- .../currency_exchange/currency_exchange.js | 2 - {stock => setup}/doctype/item_price/README.md | 0 .../doctype/item_price/__init__.py | 0 .../doctype/item_price/item_price.py | 4 +- .../doctype/item_price/item_price.txt | 43 ++++--------------- setup/doctype/price_list/price_list.js | 38 ---------------- setup/doctype/price_list/price_list.py | 24 +++++++---- setup/doctype/price_list/price_list.txt | 27 ++---------- setup/doctype/price_list/test_price_list.py | 18 ++++++++ stock/doctype/item/item.js | 20 --------- stock/doctype/item/item.py | 23 ++-------- stock/doctype/item/item.txt | 21 +-------- stock/doctype/item/test_item.py | 23 +--------- stock/report/item_prices/item_prices.py | 25 +++++------ .../item_wise_price_list.txt | 4 +- website/helpers/product.py | 5 ++- 32 files changed, 129 insertions(+), 289 deletions(-) delete mode 100644 patches/january_2013/purchase_price_list.py create mode 100644 patches/september_2013/p03_modify_item_price_include_in_price_list.py rename {stock => setup}/doctype/item_price/README.md (100%) rename {stock => setup}/doctype/item_price/__init__.py (100%) rename {stock => setup}/doctype/item_price/item_price.py (57%) rename {stock => setup}/doctype/item_price/item_price.txt (53%) diff --git a/accounts/doctype/sales_invoice/pos.js b/accounts/doctype/sales_invoice/pos.js index f04328fd09c..8837aed14b0 100644 --- a/accounts/doctype/sales_invoice/pos.js +++ b/accounts/doctype/sales_invoice/pos.js @@ -193,7 +193,7 @@ erpnext.POS = Class.extend({ ', { item_code: obj.name, - item_price: format_currency(obj.ref_rate, obj.ref_currency), + item_price: format_currency(obj.ref_rate, obj.currency), item_name: obj.name===obj.item_name ? "" : obj.item_name, item_image: image })).appendTo($wrap); diff --git a/accounts/doctype/sales_invoice/pos.py b/accounts/doctype/sales_invoice/pos.py index 1b867cb8dbc..08340f76c5e 100644 --- a/accounts/doctype/sales_invoice/pos.py +++ b/accounts/doctype/sales_invoice/pos.py @@ -15,11 +15,14 @@ def get_items(price_list, item=None, item_group=None): if item: condition = "and i.name='%s'" % item - return webnotes.conn.sql("""select - i.name, i.item_name, i.image, ip.ref_rate, ip.ref_currency - from `tabItem` i LEFT JOIN `tabItem Price` ip - ON ip.parent=i.name - and ip.price_list=%s + return webnotes.conn.sql("""select i.name, i.item_name, i.image, + pl_items.ref_rate, pl_items.currency + from `tabItem` i LEFT JOIN + (select ip.item_code, ip.ref_rate, pl.currency from + `tabItem Price` ip, `tabPrice List` pl + where ip.parent=%s and ip.parent = pl.name) pl_items + ON + pl_items.item_code=i.name where i.is_sales_item='Yes'%s""" % ('%s', condition), (price_list), as_dict=1) diff --git a/buying/doctype/purchase_common/purchase_common.js b/buying/doctype/purchase_common/purchase_common.js index 5785b1a9d57..2dfe65515a8 100644 --- a/buying/doctype/purchase_common/purchase_common.js +++ b/buying/doctype/purchase_common/purchase_common.js @@ -24,16 +24,6 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({ filters: { 'buying_or_selling': "Buying" } } }); - - this.frm.set_query("price_list_currency", function() { - return{ - query: "controllers.queries.get_price_list_currency", - filters: { - 'price_list': me.frm.doc.buying_price_list, - 'buying_or_selling': "Buying" - } - } - }); } $.each([["supplier", "supplier"], @@ -152,7 +142,7 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({ }, buying_price_list: function() { - this.get_price_list_currency("buying"); + this.get_price_list_currency("Buying"); }, import_ref_rate: function(doc, cdt, cdn) { diff --git a/buying/utils.py b/buying/utils.py index 33326d9e59c..f4fb2f3ff87 100644 --- a/buying/utils.py +++ b/buying/utils.py @@ -89,12 +89,15 @@ def _get_price_list_rate(args, item_bean, meta): # try fetching from price list if args.buying_price_list and args.price_list_currency: - price_list_rate = item_bean.doclist.get({ - "parentfield": "ref_rate_details", - "price_list": args.buying_price_list, - "ref_currency": args.price_list_currency, - "buying_or_selling": "Buying"}) + price_list_rate = webnotes.conn.sql("""select ip.ref_rate from `tabItem Price` ip, + `tabPrice List` pl where ip.parent = pl.name and ip.parent=%s and + ip.item_code=%s and pl.buying_or_selling='Buying'""", + (args.buying_price_list, args.item_code), as_dict=1) + if price_list_rate: + from utilities.transaction_base import validate_currency + validate_currency(args, item_bean.doc, meta) + out.import_ref_rate = \ flt(price_list_rate[0].ref_rate * args.plc_conversion_rate / args.conversion_rate) diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py index eb71f21ce73..1247e668c09 100644 --- a/controllers/accounts_controller.py +++ b/controllers/accounts_controller.py @@ -59,13 +59,13 @@ class AccountsController(TransactionBase): # TODO - change this, since price list now has only one currency allowed if self.meta.get_field(fieldname) and self.doc.fields.get(fieldname): - if not self.doc.price_list_currency: - self.doc.fields.update(get_price_list_currency(self.doc.fields.get(fieldname))) + self.doc.fields.update(get_price_list_currency(self.doc.fields.get(fieldname))) if self.doc.price_list_currency: if self.doc.price_list_currency == company_currency: self.doc.plc_conversion_rate = 1.0 - elif not self.doc.plc_conversion_rate: + elif not self.doc.plc_conversion_rate or \ + (flt(self.doc.plc_conversion_rate)==1 and company_currency!= self.doc.price_list_currency): exchange = self.doc.price_list_currency + "-" + company_currency self.doc.plc_conversion_rate = flt(webnotes.conn.get_value("Currency Exchange", exchange, "exchange_rate")) diff --git a/controllers/queries.py b/controllers/queries.py index 02c992b729a..637d5e18cd8 100644 --- a/controllers/queries.py +++ b/controllers/queries.py @@ -157,14 +157,6 @@ def get_project_name(doctype, txt, searchfield, start, page_len, filters): order by `tabProject`.name asc limit %(start)s, %(page_len)s """ % {'cond': cond,'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype, searchfield),'start': start, 'page_len': page_len}) - -def get_price_list_currency(doctype, txt, searchfield, start, page_len, filters): - return webnotes.conn.sql("""select ref_currency from `tabItem Price` - where price_list = %s and buying_or_selling = %s - and `%s` like %s order by ref_currency asc limit %s, %s""" % - ("%s", "%s", searchfield, "%s", "%s", "%s"), - (filters["price_list"], filters['buying_or_selling'], "%%%s%%" % txt, - start, page_len)) def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len, filters): return webnotes.conn.sql("""select `tabDelivery Note`.name, `tabDelivery Note`.customer_name diff --git a/manufacturing/doctype/bom/bom.py b/manufacturing/doctype/bom/bom.py index cb4b8c52365..9a566123c78 100644 --- a/manufacturing/doctype/bom/bom.py +++ b/manufacturing/doctype/bom/bom.py @@ -121,8 +121,8 @@ class DocType: elif self.doc.rm_cost_as_per == "Price List": if not self.doc.buying_price_list: webnotes.throw(_("Please select Price List")) - rate = webnotes.conn.get_value("Item Price", {"price_list": self.doc.buying_price_list, - "parent": arg["item_code"]}, "ref_rate") or 0 + rate = webnotes.conn.get_value("Item Price", {"parent": self.doc.buying_price_list, + "item_code": arg["item_code"]}, "ref_rate") or 0 elif self.doc.rm_cost_as_per == 'Standard Rate': rate = arg['standard_rate'] diff --git a/patches/january_2013/purchase_price_list.py b/patches/january_2013/purchase_price_list.py deleted file mode 100644 index 89509cf0874..00000000000 --- a/patches/january_2013/purchase_price_list.py +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. -# License: GNU General Public License v3. See license.txt - -import webnotes - -def execute(): - webnotes.reload_doc("stock", "doctype", "item_price") - - # check for selling - webnotes.conn.sql("""update `tabItem Price` set buying_or_selling = "Selling" - where ifnull(buying_or_selling, '')=''""") - \ No newline at end of file diff --git a/patches/june_2013/p03_buying_selling_for_price_list.py b/patches/june_2013/p03_buying_selling_for_price_list.py index c71646a8f50..1998d7ea624 100644 --- a/patches/june_2013/p03_buying_selling_for_price_list.py +++ b/patches/june_2013/p03_buying_selling_for_price_list.py @@ -6,7 +6,7 @@ from webnotes.utils import cint def execute(): webnotes.reload_doc("setup", "doctype", "price_list") - webnotes.reload_doc("stock", "doctype", "item_price") + webnotes.reload_doc("setup", "doctype", "item_price") for price_list in webnotes.conn.sql_list("""select name from `tabPrice List`"""): buying, selling = False, False @@ -15,7 +15,5 @@ def execute(): buying = buying or cint(b) selling = selling or cint(s) - buying_or_selling = "Selling" if selling else "Buying" + buying_or_selling = "Buying" if buying else "Selling" webnotes.conn.set_value("Price List", price_list, "buying_or_selling", buying_or_selling) - webnotes.conn.sql("""update `tabItem Price` set buying_or_selling=%s - where price_list_name=%s""", (buying_or_selling, price_list)) diff --git a/patches/patch_list.py b/patches/patch_list.py index 3c13e0eb471..7d9f839c2e1 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -121,7 +121,6 @@ patch_list = [ "patches.january_2013.update_country_info", "patches.january_2013.remove_tds_entry_from_gl_mapper", "patches.january_2013.update_number_format", - "patches.january_2013.purchase_price_list", "execute:webnotes.reload_doc('core', 'doctype', 'print_format') #2013-01", "execute:webnotes.reload_doc('accounts','Print Format','Payment Receipt Voucher')", "patches.january_2013.update_fraction_for_usd", @@ -263,4 +262,5 @@ patch_list = [ "patches.september_2013.p01_update_communication", "execute:webnotes.reload_doc('setup', 'doctype', 'features_setup') # 2013-09-05", "patches.september_2013.p02_fix_serial_no_status", + "patches.september_2013.p03_modify_item_price_include_in_price_list", ] \ No newline at end of file diff --git a/patches/september_2013/p03_modify_item_price_include_in_price_list.py b/patches/september_2013/p03_modify_item_price_include_in_price_list.py new file mode 100644 index 00000000000..f29f8f5bf06 --- /dev/null +++ b/patches/september_2013/p03_modify_item_price_include_in_price_list.py @@ -0,0 +1,18 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes + +def execute(): + webnotes.reload_doc("setup", "doctype", "price_list") + webnotes.reload_doc("setup", "doctype", "item_price") + webnotes.conn.sql("""update `tabItem Price` set parenttype='Price List', + parentfield='item_prices', item_code=parent""") + + # re-arranging idx of items + webnotes.conn.sql("""update `tabItem Price` set parent=price_list, idx=0""") + for pl in webnotes.conn.sql("""select name from `tabPrice List`"""): + webnotes.conn.sql("""set @name=0""") + webnotes.conn.sql("""update `tabItem Price` set idx = @name := IF(ISNULL( @name ), 0, @name + 1) + where idx=0 and parent=%s""", pl[0]) \ No newline at end of file diff --git a/public/js/transaction.js b/public/js/transaction.js index 0ff957a820b..3f0f9e5a0d7 100644 --- a/public/js/transaction.js +++ b/public/js/transaction.js @@ -149,6 +149,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ }, price_list_currency: function() { + var me=this; this.set_dynamic_labels(); var company_currency = this.get_company_currency(); @@ -156,7 +157,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ this.get_exchange_rate(this.frm.doc.price_list_currency, company_currency, function(exchange_rate) { if(exchange_rate) { - me.frm.set_value("price_list_currency", exchange_rate); + me.frm.set_value("plc_conversion_rate", exchange_rate); me.plc_conversion_rate(); } }); @@ -348,8 +349,6 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ } }); - console.log(distinct_items); - var rows = $.map(distinct_items, function(item) { var item_tax_record = item_tax[item.item_code || item.item_name]; if(!item_tax_record) { return null; } diff --git a/selling/doctype/sales_bom/sales_bom.py b/selling/doctype/sales_bom/sales_bom.py index 15d8fd1e5b7..2e56f2a10fb 100644 --- a/selling/doctype/sales_bom/sales_bom.py +++ b/selling/doctype/sales_bom/sales_bom.py @@ -31,13 +31,9 @@ class DocType: def get_item_details(self, name): det = webnotes.conn.sql("""select description, stock_uom from `tabItem` where name = %s""", name) - rate = webnotes.conn.sql("""select ref_rate from `tabItem Price` - where price_list = %s and parent = %s - and ref_currency = %s""", (self.doc.price_list, name, self.doc.currency)) return { 'description' : det and det[0][0] or '', - 'uom': det and det[0][1] or '', - 'rate': rate and flt(rate[0][0]) or 0.00 + 'uom': det and det[0][1] or '' } def check_duplicate(self, finder=0): diff --git a/selling/doctype/sales_bom_item/sales_bom_item.txt b/selling/doctype/sales_bom_item/sales_bom_item.txt index 1bd456b9e7d..9e880bc8cde 100644 --- a/selling/doctype/sales_bom_item/sales_bom_item.txt +++ b/selling/doctype/sales_bom_item/sales_bom_item.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-23 16:55:51", "docstatus": 0, - "modified": "2013-07-10 14:54:19", + "modified": "2013-09-09 15:47:56", "modified_by": "Administrator", "owner": "Administrator" }, @@ -53,17 +53,18 @@ "label": "Description", "oldfieldname": "description", "oldfieldtype": "Text", - "print_width": "300px", - "width": "300px" + "print_width": "300px" }, { "doctype": "DocField", "fieldname": "rate", "fieldtype": "Float", - "in_list_view": 1, + "hidden": 1, + "in_list_view": 0, "label": "Rate", "oldfieldname": "rate", - "oldfieldtype": "Currency" + "oldfieldtype": "Currency", + "print_hide": 1 }, { "doctype": "DocField", diff --git a/selling/doctype/sales_common/sales_common.js b/selling/doctype/sales_common/sales_common.js index 0308dfcd259..dc58377e4bf 100644 --- a/selling/doctype/sales_common/sales_common.js +++ b/selling/doctype/sales_common/sales_common.js @@ -49,16 +49,6 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ this.frm.set_query("selling_price_list", function() { return { filters: { buying_or_selling: "Selling" } }; }); - - this.frm.set_query("price_list_currency", function() { - return { - query: "controllers.queries.get_price_list_currency", - filters: { - price_list: me.frm.doc.selling_price_list, - buying_or_selling: "Selling" - } - }; - }); } if(!this.fname) { diff --git a/selling/utils.py b/selling/utils.py index ca995125d19..224944dd884 100644 --- a/selling/utils.py +++ b/selling/utils.py @@ -141,20 +141,19 @@ def _get_basic_details(args, item_bean, warehouse_fieldname): return out def _get_price_list_rate(args, item_bean, meta): - base_ref_rate = item_bean.doclist.get({ - "parentfield": "ref_rate_details", - "price_list": args.selling_price_list, - "ref_currency": args.price_list_currency, - "buying_or_selling": "Selling"}) + ref_rate = webnotes.conn.sql("""select ip.ref_rate from `tabItem Price` ip, + `tabPrice List` pl where ip.parent = pl.name and ip.parent=%s and + ip.item_code=%s and pl.buying_or_selling='Selling'""", + (args.selling_price_list, args.item_code), as_dict=1) - if not base_ref_rate: + if not ref_rate: return {} # found price list rate - now we can validate from utilities.transaction_base import validate_currency validate_currency(args, item_bean.doc, meta) - return {"ref_rate": flt(base_ref_rate[0].ref_rate) * flt(args.plc_conversion_rate) / flt(args.conversion_rate)} + return {"ref_rate": flt(ref_rate[0].ref_rate) * flt(args.plc_conversion_rate) / flt(args.conversion_rate)} def _get_item_discount(item_group, customer): parent_item_groups = [x[0] for x in webnotes.conn.sql("""SELECT parent.name diff --git a/setup/doctype/currency_exchange/currency_exchange.js b/setup/doctype/currency_exchange/currency_exchange.js index 5fd43050dfe..bf9c5163677 100644 --- a/setup/doctype/currency_exchange/currency_exchange.js +++ b/setup/doctype/currency_exchange/currency_exchange.js @@ -23,8 +23,6 @@ $.extend(cur_frm.cscript, { set_exchange_rate_label: function() { if(cur_frm.doc.from_currency && cur_frm.doc.to_currency) { var default_label = wn._(wn.meta.docfield_map[cur_frm.doctype]["exchange_rate"].label); - console.log(default_label + - repl(" (1 %(from_currency)s = [?] %(to_currency)s)", cur_frm.doc)); cur_frm.fields_dict.exchange_rate.set_label(default_label + repl(" (1 %(from_currency)s = [?] %(to_currency)s)", cur_frm.doc)); } diff --git a/stock/doctype/item_price/README.md b/setup/doctype/item_price/README.md similarity index 100% rename from stock/doctype/item_price/README.md rename to setup/doctype/item_price/README.md diff --git a/stock/doctype/item_price/__init__.py b/setup/doctype/item_price/__init__.py similarity index 100% rename from stock/doctype/item_price/__init__.py rename to setup/doctype/item_price/__init__.py diff --git a/stock/doctype/item_price/item_price.py b/setup/doctype/item_price/item_price.py similarity index 57% rename from stock/doctype/item_price/item_price.py rename to setup/doctype/item_price/item_price.py index 26d0f769688..3256c80d422 100644 --- a/stock/doctype/item_price/item_price.py +++ b/setup/doctype/item_price/item_price.py @@ -1,5 +1,7 @@ # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. -# License: GNU General Public License v3. See license.txt +# MIT License. See license.txt + +# For license information, please see license.txt from __future__ import unicode_literals import webnotes diff --git a/stock/doctype/item_price/item_price.txt b/setup/doctype/item_price/item_price.txt similarity index 53% rename from stock/doctype/item_price/item_price.txt rename to setup/doctype/item_price/item_price.txt index 3a73a00602e..2964cd96f4c 100644 --- a/stock/doctype/item_price/item_price.txt +++ b/setup/doctype/item_price/item_price.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-02 16:29:48", "docstatus": 0, - "modified": "2013-08-09 14:46:58", + "modified": "2013-09-11 12:38:24", "modified_by": "Administrator", "owner": "Administrator" }, @@ -11,18 +11,20 @@ "doctype": "DocType", "in_create": 0, "istable": 1, - "module": "Stock", + "module": "Setup", "name": "__common__", "read_only": 0 }, { "doctype": "DocField", + "in_filter": 1, "in_list_view": 1, "name": "__common__", "parent": "Item Price", "parentfield": "fields", "parenttype": "DocType", - "permlevel": 0 + "permlevel": 0, + "reqd": 1 }, { "doctype": "DocType", @@ -30,49 +32,22 @@ }, { "doctype": "DocField", - "fieldname": "price_list", + "fieldname": "item_code", "fieldtype": "Link", - "in_filter": 1, - "label": "Price List Name", + "label": "Item Code", "oldfieldname": "price_list_name", "oldfieldtype": "Select", - "options": "Price List", - "reqd": 1, + "options": "Item", "search_index": 1 }, { "doctype": "DocField", "fieldname": "ref_rate", "fieldtype": "Currency", - "in_filter": 1, "label": "Ref Rate", "oldfieldname": "ref_rate", "oldfieldtype": "Currency", - "options": "ref_currency", - "reqd": 1, + "options": "currency", "search_index": 0 - }, - { - "doctype": "DocField", - "fieldname": "ref_currency", - "fieldtype": "Link", - "in_filter": 1, - "label": "Currency", - "oldfieldname": "ref_currency", - "oldfieldtype": "Select", - "options": "Currency", - "read_only": 1, - "reqd": 0, - "search_index": 1 - }, - { - "default": "Selling", - "doctype": "DocField", - "fieldname": "buying_or_selling", - "fieldtype": "Select", - "label": "Valid for Buying or Selling?", - "options": "Buying\nSelling", - "read_only": 1, - "reqd": 1 } ] \ No newline at end of file diff --git a/setup/doctype/price_list/price_list.js b/setup/doctype/price_list/price_list.js index 5de8da5585e..f3adc727579 100644 --- a/setup/doctype/price_list/price_list.js +++ b/setup/doctype/price_list/price_list.js @@ -3,44 +3,6 @@ $.extend(cur_frm.cscript, { onload: function() { - cur_frm.cscript.show_item_prices(); erpnext.add_for_territory(); }, - - refresh: function(doc) { - cur_frm.set_intro(""); - if(doc.__islocal) { - cur_frm.toggle_display("item_prices_section", false); - cur_frm.set_intro("Save this list to begin."); - return; - } else { - cur_frm.cscript.show_item_prices(); - } - }, - - show_item_prices: function() { - var item_price = wn.model.get("Item Price", {price_list: cur_frm.doc.name}); - - var show = item_price && item_price.length; - - cur_frm.toggle_display("item_prices_section", show); - $(cur_frm.fields_dict.item_prices.wrapper).empty(); - if (!show) return; - - var out = '\ - \ - \ - \ - \ - ' - + $.map(item_price.sort(function(a, b) { return a.parent.localeCompare(b.parent); }), function(d) { - return '' - + '' - + '' - + '' - }).join("\n") - + '\ -
' + wn._("Item Code") + '' + wn._("Price") + '
' + d.parent + '' + format_currency(d.ref_rate, d.ref_currency) + '
'; - $(out).appendTo($(cur_frm.fields_dict.item_prices.wrapper)); - } }); \ No newline at end of file diff --git a/setup/doctype/price_list/price_list.py b/setup/doctype/price_list/price_list.py index 112ce95e593..2fcaf218dcd 100644 --- a/setup/doctype/price_list/price_list.py +++ b/setup/doctype/price_list/price_list.py @@ -8,11 +8,9 @@ from webnotes.utils import comma_or, cint from webnotes.model.controller import DocListController import webnotes.defaults +class PriceListDuplicateItem(Exception): pass + class DocType(DocListController): - def onload(self): - self.doclist.extend(webnotes.conn.sql("""select * from `tabItem Price` - where price_list=%s""", self.doc.name, as_dict=True, update={"doctype": "Item Price"})) - def validate(self): if self.doc.buying_or_selling not in ["Buying", "Selling"]: msgprint(_(self.meta.get_label("buying_or_selling")) + " " + _("must be one of") + " " + @@ -29,17 +27,24 @@ class DocType(DocListController): else: # at least one territory self.validate_table_has_rows("valid_for_territories") + + # check for duplicate items + self.check_duplicate_items() def on_update(self): self.set_default_if_missing() cart_settings = webnotes.get_obj("Shopping Cart Settings") if cint(cart_settings.doc.enabled): cart_settings.validate_price_lists() + + def check_duplicate_items(self): + item_codes = [] + for d in self.doclist.get({"parentfield": "item_prices"}): + if d.item_code not in item_codes: + item_codes.append(d.item_code) + else: + msgprint(_("Duplicate Item ") + ": " + d.item_code, raise_exception=PriceListDuplicateItem) - def on_trash(self): - webnotes.conn.sql("""delete from `tabItem Price` where price_list = %s""", - self.doc.name) - def set_default_if_missing(self): if self.doc.buying_or_selling=="Selling": if not webnotes.conn.get_value("Selling Settings", None, "selling_price_list"): @@ -47,4 +52,5 @@ class DocType(DocListController): elif self.doc.buying_or_selling=="Buying": if not webnotes.conn.get_value("Buying Settings", None, "buying_price_list"): - webnotes.set_value("Buying Settings", "Buying Settings", "buying_price_list", self.doc.name) \ No newline at end of file + webnotes.set_value("Buying Settings", "Buying Settings", "buying_price_list", self.doc.name) + diff --git a/setup/doctype/price_list/price_list.txt b/setup/doctype/price_list/price_list.txt index febf47180f4..46905a65918 100644 --- a/setup/doctype/price_list/price_list.txt +++ b/setup/doctype/price_list/price_list.txt @@ -2,7 +2,7 @@ { "creation": "2013-01-25 11:35:09", "docstatus": 0, - "modified": "2013-07-26 11:19:06", + "modified": "2013-09-06 15:03:38", "modified_by": "Administrator", "owner": "Administrator" }, @@ -94,28 +94,9 @@ { "doctype": "DocField", "fieldname": "item_prices", - "fieldtype": "HTML", - "label": "Item Prices" - }, - { - "doctype": "DocField", - "fieldname": "column_break_10", - "fieldtype": "Column Break" - }, - { - "depends_on": "eval:!doc.__islocal", - "doctype": "DocField", - "fieldname": "section_break_1", - "fieldtype": "Section Break", - "label": "How to upload" - }, - { - "depends_on": "eval:!doc.__islocal", - "doctype": "DocField", - "fieldname": "how_to_upload", - "fieldtype": "HTML", - "label": "How to upload", - "options": "
Use the Data Import Tool to upload, update Item Prices in bulk:\n
    \n
  1. Go to Data Import Tool.\n
  2. Select \"Item\"\n
  3. Check on \"With Data\"\n
  4. Download \"Item Price\" from Child Tables.\n
  5. Update the prices required and add new rows if required.\n
  6. Check on \"Overwrite\"\n
  7. Upload the modified sheet.\n
\n" + "fieldtype": "Table", + "label": "Item Prices", + "options": "Item Price" }, { "amend": 0, diff --git a/setup/doctype/price_list/test_price_list.py b/setup/doctype/price_list/test_price_list.py index bfa64ec6d6c..2310f51478f 100644 --- a/setup/doctype/price_list/test_price_list.py +++ b/setup/doctype/price_list/test_price_list.py @@ -1,6 +1,18 @@ # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. # License: GNU General Public License v3. See license.txt +from __future__ import unicode_literals +import unittest +import webnotes +from setup.doctype.price_list.price_list import PriceListDuplicateItem + +class TestItem(unittest.TestCase): + def test_duplicate_item(self): + price_list = webnotes.bean(copy=test_records[0]) + item_price = price_list.doclist.get({"doctype": "Item Price"})[0] + price_list.doclist.append(webnotes.doc(item_price.fields.copy())) + self.assertRaises(PriceListDuplicateItem, price_list.insert) + test_records = [ [ { @@ -13,6 +25,12 @@ test_records = [ "doctype": "For Territory", "parentfield": "valid_for_territories", "territory": "All Territories" + }, + { + "doctype": "Item Price", + "parentfield": "item_prices", + "item_code": "_Test Item", + "ref_rate": 100 } ], [ diff --git a/stock/doctype/item/item.js b/stock/doctype/item/item.js index abf1e9e6581..a83032e8f26 100644 --- a/stock/doctype/item/item.js +++ b/stock/doctype/item/item.js @@ -1,26 +1,6 @@ // Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. // License: GNU General Public License v3. See license.txt -wn.provide("erpnext.stock"); - -erpnext.stock.Item = wn.ui.form.Controller.extend({ - onload: function() { - this.frm.add_fetch("price_list", "currency", "ref_currency"); - this.frm.add_fetch("price_list", "buying_or_selling", "buying_or_selling"); - }, - - ref_rate_details_add: function(doc, cdt, cdn) { - var row = wn.model.get_doc(cdt, cdn); - if(row.price_list && !row.ref_currency) { - // execute fetch - var df = wn.meta.get_docfield(row.doctype, "price_list", row.parent); - this.frm.script_manager.validate_link_and_fetch(df, row.name, row.price_list); - } - } -}); - -cur_frm.script_manager.make(erpnext.stock.Item); - cur_frm.cscript.refresh = function(doc) { // make sensitive fields(has_serial_no, is_stock_item, valuation_method) // read only if any stock ledger entry exists diff --git a/stock/doctype/item/item.py b/stock/doctype/item/item.py index e6c277ee086..7219ade7f17 100644 --- a/stock/doctype/item/item.py +++ b/stock/doctype/item/item.py @@ -11,7 +11,6 @@ from webnotes import msgprint, _ from webnotes.model.controller import DocListController -class PriceListCurrencyMismatch(Exception): pass class WarehouseNotSet(Exception): pass class DocType(DocListController): @@ -32,9 +31,8 @@ class DocType(DocListController): self.check_stock_uom_with_bin() self.validate_conversion_factor() self.add_default_uom_in_conversion_factor_table() - self.valiadte_item_type() + self.validate_item_type() self.check_for_active_boms() - self.validate_price_lists() self.fill_customer_code() self.check_item_tax() self.validate_barcode() @@ -87,7 +85,7 @@ class DocType(DocListController): As UOM: %s is not Stock UOM of Item: %s""" % (d.uom, d.uom, self.doc.name)), raise_exception=1) - def valiadte_item_type(self): + def validate_item_type(self): if cstr(self.doc.is_manufactured_item) == "No": self.doc.is_pro_applicable = "No" @@ -125,22 +123,7 @@ class DocType(DocListController): 'is_pro_applicable' :'Allow Production Order'} for d in fl: if cstr(self.doc.fields.get(d)) != 'Yes': - _check_for_active_boms(fl[d]) - - def validate_price_lists(self): - price_lists=[] - for d in getlist(self.doclist,'ref_rate_details'): - if d.price_list in price_lists: - msgprint(_("Cannot have two prices for same Price List") + ": " + d.price_list, - raise_exception= webnotes.DuplicateEntryError) - else: - price_list_currency = webnotes.conn.get_value("Price List", d.price_list, "currency") - if price_list_currency and d.ref_currency != price_list_currency: - msgprint(_("Currency does not match Price List Currency for Price List") \ - + ": " + d.price_list, raise_exception=PriceListCurrencyMismatch) - - price_lists.append(d.price_list) - + _check_for_active_boms(fl[d]) def fill_customer_code(self): """ Append all the customer codes and insert into "customer_code" field of item table """ diff --git a/stock/doctype/item/item.txt b/stock/doctype/item/item.txt index eb05503b329..c70b9911db3 100644 --- a/stock/doctype/item/item.txt +++ b/stock/doctype/item/item.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-03 10:45:46", "docstatus": 0, - "modified": "2013-08-30 16:21:38", + "modified": "2013-09-11 11:50:10", "modified_by": "Administrator", "owner": "Administrator" }, @@ -625,25 +625,6 @@ "options": "Item Tax", "read_only": 0 }, - { - "doctype": "DocField", - "fieldname": "price_list_section", - "fieldtype": "Section Break", - "label": "Price Lists and Rates", - "options": "icon-money", - "read_only": 0 - }, - { - "description": "Create a price list from Price List master and enter standard ref rates against each of them. On selection of a price list in Quotation, Sales Order or Delivery Note, corresponding ref rate will be fetched for this item.", - "doctype": "DocField", - "fieldname": "ref_rate_details", - "fieldtype": "Table", - "label": "Item Prices", - "oldfieldname": "ref_rate_details", - "oldfieldtype": "Table", - "options": "Item Price", - "read_only": 0 - }, { "doctype": "DocField", "fieldname": "inspection_criteria", diff --git a/stock/doctype/item/test_item.py b/stock/doctype/item/test_item.py index 7be6ea56edc..12bb4e05783 100644 --- a/stock/doctype/item/test_item.py +++ b/stock/doctype/item/test_item.py @@ -9,20 +9,6 @@ test_ignore = ["BOM"] test_dependencies = ["Warehouse"] class TestItem(unittest.TestCase): - def test_duplicate_price_list(self): - item = webnotes.bean(copy=test_records[0]) - item.doc.item_code = "_Test Item 10" - item_price = item.doclist.get({"doctype": "Item Price"})[0] - item.doclist.append(webnotes.doc(item_price.fields.copy())) - self.assertRaises(webnotes.DuplicateEntryError, item.insert) - - def test_price_list_mismatch(self): - from stock.doctype.item.item import PriceListCurrencyMismatch - item = webnotes.bean(copy=test_records[0]) - item.doc.item_code = "_Test Item 11" - item_price = item.doclist.get({"doctype": "Item Price"})[0].ref_currency="USD" - self.assertRaises(PriceListCurrencyMismatch, item.insert) - def test_default_warehouse(self): from stock.doctype.item.item import WarehouseNotSet item = webnotes.bean(copy=test_records[0]) @@ -57,14 +43,7 @@ test_records = [ "warehouse_reorder_level": 20, "warehouse_reorder_qty": 20, "material_request_type": "Purchase" - }, { - "doctype": "Item Price", - "parentfield": "ref_rate_details", - "price_list": "_Test Price List", - "ref_rate": 100, - "ref_currency": "INR", - "buying_or_selling": "Selling" - } + }, ], [{ "doctype": "Item", diff --git a/stock/report/item_prices/item_prices.py b/stock/report/item_prices/item_prices.py index 0a6b29a7231..70c06779865 100644 --- a/stock/report/item_prices/item_prices.py +++ b/stock/report/item_prices/item_prices.py @@ -23,8 +23,8 @@ def execute(filters=None): item_map[item]["description"], item_map[item]["stock_uom"], flt(last_purchase_rate.get(item, 0), precision), flt(val_rate_map.get(item, 0), precision), - pl.get(item, {}).get("selling"), - pl.get(item, {}).get("buying"), + pl.get(item, {}).get("Selling"), + pl.get(item, {}).get("Buying"), flt(bom_rate.get(item, 0), precision), flt(item_map[item]["standard_rate"], precision) ]) @@ -56,24 +56,21 @@ def get_price_list(): """Get selling & buying price list of every item""" rate = {} - - price_list = webnotes.conn.sql("""select parent, selling, buying, - concat(price_list, " - ", ref_currency, " ", ref_rate) as price - from `tabItem Price` where docstatus<2""", as_dict=1) + + price_list = webnotes.conn.sql("""select ip.item_code, pl.buying_or_selling, + concat(pl.name, " - ", pl.currency, " ", ip.ref_rate) as price + from `tabItem Price` ip, `tabPrice List` pl where + ip.parent = pl.name and pl.docstatus<2""", as_dict=1) for j in price_list: if j.price: - if j.selling: - rate.setdefault(j.parent, {}).setdefault("selling", []).append(j.price) - if j.buying: - rate.setdefault(j.parent, {}).setdefault("buying", []).append(j.price) - + rate.setdefault(j.item_code, {}).setdefault(j.buying_or_selling, []).append(j.price) item_rate_map = {} for item in rate: - item_rate_map.setdefault(item, {}).setdefault("selling", - ", ".join(rate[item].get("selling", []))) - item_rate_map[item]["buying"] = ", ".join(rate[item].get("buying", [])) + for buying_or_selling in rate[item]: + item_rate_map.setdefault(item, {}).setdefault(buying_or_selling, + ", ".join(rate[item].get(buying_or_selling, []))) return item_rate_map diff --git a/stock/report/item_wise_price_list/item_wise_price_list.txt b/stock/report/item_wise_price_list/item_wise_price_list.txt index 2d5996a92ed..b3d5717a41f 100644 --- a/stock/report/item_wise_price_list/item_wise_price_list.txt +++ b/stock/report/item_wise_price_list/item_wise_price_list.txt @@ -2,7 +2,7 @@ { "creation": "2013-02-22 18:01:55", "docstatus": 0, - "modified": "2013-05-07 11:52:00", + "modified": "2013-09-10 15:50:26", "modified_by": "Administrator", "owner": "Administrator" }, @@ -10,7 +10,7 @@ "doctype": "Report", "is_standard": "Yes", "name": "__common__", - "query": "select\n item.name as \"ID:Link/Item:120\", \n item.item_name as \"Item Name::120\", \n item_price.price_list as \"Price List::80\",\n item_price.ref_currency as \"Currency::40\", \n item_price.ref_rate as \"Rate:Float:80\",\n item.description as \"Description::160\",\n item.item_group as \"Item Group:Link/Item Group:100\",\n item.brand as \"Brand::100\"\nfrom `tabItem` item, `tabItem Price` item_price\nwhere\n item_price.parent = item.name", + "query": "select\n item.name as \"ID:Link/Item:120\", \n item.item_name as \"Item Name::120\", \n item_price.parent as \"Price List::80\",\n price_list.currency as \"Currency::40\", \n item_price.ref_rate as \"Rate:Float:80\",\n item.description as \"Description::160\",\n item.item_group as \"Item Group:Link/Item Group:100\",\n item.brand as \"Brand::100\"\nfrom `tabItem` item, `tabItem Price` item_price, `tabPrice List` price_list\nwhere\n item_price.item_code = item.name and\n item_price.parent = price_list.name", "ref_doctype": "Item", "report_name": "Item-Wise Price List", "report_type": "Query Report" diff --git a/website/helpers/product.py b/website/helpers/product.py index 8d817d07cf9..d8da05aa0c3 100644 --- a/website/helpers/product.py +++ b/website/helpers/product.py @@ -27,8 +27,9 @@ def get_product_info(item_code): else: in_stock = -1 - price = price_list and webnotes.conn.sql("""select ref_rate, ref_currency from - `tabItem Price` where parent=%s and price_list=%s""", + price = price_list and webnotes.conn.sql("""select ip.ref_rate, pl.ref_currency from + `tabItem Price` ip, `tabPrice List` pl where ip.parent = pl.name and + ip.item_code=%s and ip.parent=%s""", (item_code, price_list), as_dict=1) or [] price = price and price[0] or None