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 (69%) 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 f04328fd09..8837aed14b 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 1b867cb8db..08340f76c5 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 5785b1a9d5..2dfe65515a 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 33326d9e59..f4fb2f3ff8 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 eb71f21ce7..1247e668c0 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 02c992b729..637d5e18cd 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 cb4b8c5236..9a566123c7 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 89509cf087..0000000000 --- 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 c71646a8f5..1998d7ea62 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 3c13e0eb47..7d9f839c2e 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 0000000000..f29f8f5bf0 --- /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 0ff957a820..3f0f9e5a0d 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 15d8fd1e5b..2e56f2a10f 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 1bd456b9e7..9e880bc8cd 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 0308dfcd25..dc58377e4b 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 ca995125d1..224944dd88 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 5fd43050df..bf9c516367 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 69% rename from stock/doctype/item_price/item_price.py rename to setup/doctype/item_price/item_price.py index 26d0f76968..3256c80d42 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 3a73a00602..2964cd96f4 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 5de8da5585..f3adc72757 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 112ce95e59..2fcaf218dc 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 febf47180f..46905a6591 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 bfa64ec6d6..2310f51478 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 abf1e9e658..a83032e8f2 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 e6c277ee08..7219ade7f1 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 eb05503b32..c70b9911db 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 7be6ea56ed..12bb4e0578 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 0a6b29a723..70c0677986 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 2d5996a92e..b3d5717a41 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 8d817d07cf..d8da05aa0c 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