diff --git a/accounts/doctype/sales_invoice/pos.js b/accounts/doctype/sales_invoice/pos.js index 1d58f2d2dc0..b71b45e55b3 100644 --- a/accounts/doctype/sales_invoice/pos.js +++ b/accounts/doctype/sales_invoice/pos.js @@ -530,6 +530,7 @@ erpnext.POS = Class.extend({ else if (operation == "decrease-qty") d.qty != 1 ? d.qty -= 1 : d.qty = 1; + me.frm.script_manager.trigger("qty", d.doctype, d.name); me.refresh(); } }); diff --git a/buying/doctype/supplier/supplier.js b/buying/doctype/supplier/supplier.js index ec4d3e606fd..d0e5f957f9e 100644 --- a/buying/doctype/supplier/supplier.js +++ b/buying/doctype/supplier/supplier.js @@ -3,7 +3,7 @@ wn.require('app/setup/doctype/contact_control/contact_control.js'); -cur_frm.cscript.refresh = function(doc,dt,dn) { +cur_frm.cscript.refresh = function(doc, dt, dn) { cur_frm.cscript.make_dashboard(doc); erpnext.hide_naming_series(); @@ -93,7 +93,7 @@ cur_frm.cscript.make_contact = function() { cur_frm.contact_list.run(); } -cur_frm.fields_dict['default_price_list'].get_query = function(doc,cdt,cdn) { +cur_frm.fields_dict['default_price_list'].get_query = function(doc, cdt, cdn) { return{ filters:{'buying': 1} } diff --git a/buying/utils.py b/buying/utils.py index 35d89c559d0..ec13454dbe9 100644 --- a/buying/utils.py +++ b/buying/utils.py @@ -89,8 +89,10 @@ 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 = webnotes.conn.sql("""select ref_rate from `tabItem Price` - where price_list=%s and item_code=%s and buying=1""", + price_list_rate = webnotes.conn.sql("""select ip.ref_rate from + `tabItem Price` ip, `tabPrice List` pl + where ip.price_list=pl.name and ip.price_list=%s and + ip.item_code=%s and ip.buying=1 and pl.enabled=1""", (args.buying_price_list, args.item_code), as_dict=1) if price_list_rate: diff --git a/config.json b/config.json index c2524671a04..450e2bca6de 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "app_name": "ERPNext", - "app_version": "3.6.2", + "app_version": "3.6.3", "base_template": "app/portal/templates/base.html", "modules": { "Accounts": { @@ -74,5 +74,5 @@ "type": "module" } }, - "requires_framework_version": "==3.7.2" + "requires_framework_version": "==3.7.3" } \ No newline at end of file diff --git a/hr/doctype/salary_manager/salary_manager.js b/hr/doctype/salary_manager/salary_manager.js index 032c29e5090..ec485ca6716 100644 --- a/hr/doctype/salary_manager/salary_manager.js +++ b/hr/doctype/salary_manager/salary_manager.js @@ -43,7 +43,7 @@ cur_frm.cscript.make_jv = function(doc, dt, dn) { jv = locals['Journal Voucher'][jv]; jv.voucher_type = 'Bank Voucher'; jv.user_remark = wn._('Payment of salary for the month: ') + doc.month + - wn._('and fiscal year: ') + doc.fiscal_year; + wn._(' and fiscal year: ') + doc.fiscal_year; jv.fiscal_year = doc.fiscal_year; jv.company = doc.company; jv.posting_date = dateutil.obj_to_str(new Date()); diff --git a/install_erpnext.py b/install_erpnext.py index e285d4bbfea..8e1448362bd 100644 --- a/install_erpnext.py +++ b/install_erpnext.py @@ -20,7 +20,7 @@ requirements = [ "jinja2", "markdown2", "markupsafe", - "mysql-python==1.2.4", + "mysql-python", "pygeoip", "python-dateutil", "python-memcached", diff --git a/patches/1401/update_billing_status_for_zero_value_order.py b/patches/1401/update_billing_status_for_zero_value_order.py new file mode 100644 index 00000000000..afeed55ed4a --- /dev/null +++ b/patches/1401/update_billing_status_for_zero_value_order.py @@ -0,0 +1,29 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +import webnotes +from webnotes.utils import flt + +def execute(): + for order_type in ["Sales", "Purchase"]: + for d in webnotes.conn.sql("""select par.name, sum(ifnull(child.qty, 0)) as total_qty + from `tab%s Order` par, `tab%s Order Item` child + where par.name = child.parent and par.docstatus = 1 + and ifnull(par.net_total, 0) = 0 group by par.name""" % + (order_type, order_type), as_dict=1): + + billed_qty = flt(webnotes.conn.sql("""select sum(ifnull(qty, 0)) + from `tab%s Invoice Item` where %s=%s and docstatus=1""" % + (order_type, "sales_order" if order_type=="Sales" else "purchase_order", '%s'), + (d.name))[0][0]) + + per_billed = ((d.total_qty if billed_qty > d.total_qty else billed_qty)\ + / d.total_qty)*100 + webnotes.conn.set_value(order_type+ " Order", d.name, "per_billed", per_billed) + + if order_type == "Sales": + if per_billed < 0.001: billing_status = "Not Billed" + elif per_billed >= 99.99: billing_status = "Fully Billed" + else: billing_status = "Partly Billed" + + webnotes.conn.set_value("Sales Order", d.name, "billing_status", billing_status) \ No newline at end of file diff --git a/patches/patch_list.py b/patches/patch_list.py index 04a9288c609..5bf730af0b2 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -265,4 +265,6 @@ patch_list = [ "patches.1312.p02_update_item_details_in_item_price", "patches.1401.p01_move_related_property_setters_to_custom_field", "patches.1401.p01_make_buying_selling_as_check_box_in_price_list", + "patches.1401.update_billing_status_for_zero_value_order", + "execute:webnotes.reload_doc('stock', 'doctype', 'price_list') #2014-01-20", ] \ No newline at end of file diff --git a/public/js/conf.js b/public/js/conf.js index 929bfcaa593..1fe21c76110 100644 --- a/public/js/conf.js +++ b/public/js/conf.js @@ -24,16 +24,17 @@ $(document).bind('toolbar_setup', function() { wn.provide('wn.ui.misc'); wn.ui.misc.about = function() { if(!wn.ui.misc.about_dialog) { - var d = new wn.ui.Dialog({title: wn._('About ERPNext')}) + var d = new wn.ui.Dialog({title: wn._('About')}) $(d.body).html(repl("
\ -

"+wn._("ERPNext is an open-source web based ERP made by Web Notes Technologies Pvt Ltd.\ - to provide an integrated tool to manage most processes in a small organization.\ - For more information about Web Notes, or to buy hosting servies, go to ")+ - "https://erpnext.com.

\ -

"+wn._("To report an issue, go to ")+"GitHub Issues

\ -
\ +

ERPNext

\ +

v" + wn.boot.app_version + "

\ +

"+wn._("An open source ERP made for the web.

") + + "

"+wn._("To report an issue, go to ")+"GitHub Issues

\ +

http://erpnext.org.

\

License: GNU General Public License Version 3

\ +
\ +

© 2014 Web Notes Technologies Pvt. Ltd and contributers

\
", wn.app)); wn.ui.misc.about_dialog = d; diff --git a/public/js/toolbar.js b/public/js/toolbar.js index e0affaf61df..1d6fa919b23 100644 --- a/public/js/toolbar.js +++ b/public/js/toolbar.js @@ -21,6 +21,6 @@ erpnext.toolbar.setup = function() { '+wn._('Live Chat')+''); } - $("#toolbar-tools").append('
  • \ + $("#toolbar-tools").append('
  • \ Latest Updates
  • '); -} \ No newline at end of file +} diff --git a/selling/doctype/customer/customer.js b/selling/doctype/customer/customer.js index 5d046904d39..fb5d8879474 100644 --- a/selling/doctype/customer/customer.js +++ b/selling/doctype/customer/customer.js @@ -18,7 +18,7 @@ cur_frm.cscript.load_defaults = function(doc, dt, dn) { cur_frm.add_fetch('lead_name', 'company_name', 'customer_name'); cur_frm.add_fetch('default_sales_partner','commission_rate','default_commission_rate'); -cur_frm.cscript.refresh = function(doc,dt,dn) { +cur_frm.cscript.refresh = function(doc, dt, dn) { cur_frm.cscript.setup_dashboard(doc); erpnext.hide_naming_series(); @@ -107,20 +107,20 @@ cur_frm.cscript.make_contact = function() { } -cur_frm.fields_dict['customer_group'].get_query = function(doc,dt,dn) { +cur_frm.fields_dict['customer_group'].get_query = function(doc, dt, dn) { return{ filters:{'is_group': 'No'} } } -cur_frm.fields_dict.lead_name.get_query = function(doc,cdt,cdn) { +cur_frm.fields_dict.lead_name.get_query = function(doc, cdt, cdn) { return{ query:"controllers.queries.lead_query" } } -cur_frm.fields_dict['default_price_list'].get_query = function(doc,cdt,cdn) { +cur_frm.fields_dict['default_price_list'].get_query = function(doc, cdt, cdn) { return{ filters:{'selling': 1} } diff --git a/selling/utils/__init__.py b/selling/utils/__init__.py index f495f58e442..b71c9d41cee 100644 --- a/selling/utils/__init__.py +++ b/selling/utils/__init__.py @@ -150,8 +150,10 @@ def _get_basic_details(args, item_bean, warehouse_fieldname): return out def _get_price_list_rate(args, item_bean, meta): - ref_rate = webnotes.conn.sql("""select ref_rate from `tabItem Price` - where price_list=%s and item_code=%s and selling=1""", + ref_rate = webnotes.conn.sql("""select ip.ref_rate from + `tabItem Price` ip, `tabPrice List` pl + where ip.price_list=pl.name and ip.price_list=%s and + ip.item_code=%s and ip.selling=1 and pl.enabled=1""", (args.selling_price_list, args.item_code), as_dict=1) if not ref_rate: diff --git a/selling/utils/product.py b/selling/utils/product.py index 32ff85ad120..22bb8808211 100644 --- a/selling/utils/product.py +++ b/selling/utils/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, currency from - `tabItem Price` where item_code=%s and price_list=%s""", + price = price_list and webnotes.conn.sql("""select ip.ref_rate, ip.currency from + `tabItem Price` ip, `tabPrice List` pl where ip.price_list=pl.name and + ip.item_code=%s and ip.price_list=%s and pl.enabled=1""", (item_code, price_list), as_dict=1) or [] price = price and price[0] or None diff --git a/setup/doctype/company/company.py b/setup/doctype/company/company.py index 88d9dcaaa51..34e5ca4a597 100644 --- a/setup/doctype/company/company.py +++ b/setup/doctype/company/company.py @@ -244,8 +244,6 @@ class DocType: webnotes.conn.set(self.doc, a, account_name) _set_default_accounts({ - "default_income_account": "Sales", - "default_expense_account": "Cost of Goods Sold", "receivables_group": "Accounts Receivable", "payables_group": "Accounts Payable", "default_cash_account": "Cash" @@ -257,8 +255,6 @@ class DocType: "stock_adjustment_account": "Stock Adjustment", "expenses_included_in_valuation": "Expenses Included In Valuation" }) - - def create_default_cost_center(self): cc_list = [ diff --git a/setup/page/setup_wizard/setup_wizard.py b/setup/page/setup_wizard/setup_wizard.py index ededd472a84..943d8b66fe5 100644 --- a/setup/page/setup_wizard/setup_wizard.py +++ b/setup/page/setup_wizard/setup_wizard.py @@ -98,6 +98,7 @@ def create_price_lists(args): { "doctype": "Price List", "price_list_name": "Standard " + pl_type, + "enabled": 1, "buying": 1 if pl_type == "Buying" else 0, "selling": 1 if pl_type == "Selling" else 0, "currency": args["currency"] diff --git a/setup/utils.py b/setup/utils.py index 0571c15a54d..68a5a5ab45c 100644 --- a/setup/utils.py +++ b/setup/utils.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import webnotes -from webnotes import _, msgprint +from webnotes import _, msgprint, throw import json def get_company_currency(company): @@ -11,8 +11,8 @@ def get_company_currency(company): if not currency: currency = webnotes.conn.get_default("currency") if not currency: - msgprint(_('Please specify Default Currency in Company Master \ - and Global Defaults'), raise_exception=True) + throw(_('Please specify Default Currency in Company Master \ + and Global Defaults')) return currency @@ -32,5 +32,14 @@ def get_ancestors_of(doctype, name): @webnotes.whitelist() def get_price_list_currency(price_list): - return {"price_list_currency": webnotes.conn.get_value("Price List", price_list, - "currency")} \ No newline at end of file + price_list_currency = webnotes.conn.get_value("Price List", {"name": price_list, + "enabled": 1}, "currency") + + if not price_list_currency: + throw("{message}: {price_list} {disabled}".format(**{ + "message": _("Price List"), + "price_list": price_list, + "disabled": _("is disabled.") + })) + else: + return {"price_list_currency": price_list_currency} \ No newline at end of file diff --git a/stock/doctype/item_price/item_price.py b/stock/doctype/item_price/item_price.py index e2c9f2fcb04..cb07e706cf4 100644 --- a/stock/doctype/item_price/item_price.py +++ b/stock/doctype/item_price/item_price.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import webnotes -from webnotes import _ +from webnotes import throw, _ class ItemPriceDuplicateItem(webnotes.ValidationError): pass @@ -12,26 +12,36 @@ class DocType: self.doc, self.doclist = d, dl def validate(self): + self.validate_price_list() self.check_duplicate_item() self.update_price_list_details() self.update_item_details() - def update_price_list_details(self): - self.doc.buying, self.doc.selling, self.doc.currency = webnotes.conn.get_value("Price List", - self.doc.price_list, ["buying", "selling", "currency"]) - - def update_item_details(self): - self.doc.item_name, self.doc.item_description = webnotes.conn.get_value("Item", - self.doc.item_code, ["item_name", "description"]) + def validate_price_list(self): + enabled = webnotes.conn.get_value("Price List", self.doc.price_list, "enabled") + if not enabled: + throw("{message}: {price_list} {disabled}".format(**{ + "message": _("Price List"), + "price_list": self.doc.price_list, + "disabled": _("is disabled.") + })) def check_duplicate_item(self): if webnotes.conn.sql("""select name from `tabItem Price` where item_code=%s and price_list=%s and name!=%s""", (self.doc.item_code, self.doc.price_list, self.doc.name)): - webnotes.throw("{duplicate_item}: {item_code}, {already}: {price_list}".format(**{ + throw("{duplicate_item}: {item_code}, {already}: {price_list}".format(**{ "duplicate_item": _("Duplicate Item"), "item_code": self.doc.item_code, "already": _("already available in Price List"), "price_list": self.doc.price_list }), ItemPriceDuplicateItem) + + def update_price_list_details(self): + self.doc.buying, self.doc.selling, self.doc.currency = webnotes.conn.get_value("Price List", + {"name": self.doc.price_list, "enabled": 1}, ["buying", "selling", "currency"]) + + def update_item_details(self): + self.doc.item_name, self.doc.item_description = webnotes.conn.get_value("Item", + self.doc.item_code, ["item_name", "description"]) \ No newline at end of file diff --git a/stock/doctype/price_list/price_list.txt b/stock/doctype/price_list/price_list.txt index 69c3ecbc4cd..daa89d1cc57 100644 --- a/stock/doctype/price_list/price_list.txt +++ b/stock/doctype/price_list/price_list.txt @@ -2,7 +2,7 @@ { "creation": "2013-01-25 11:35:09", "docstatus": 0, - "modified": "2014-01-06 18:28:23", + "modified": "2014-01-17 13:29:39", "modified_by": "Administrator", "owner": "Administrator" }, @@ -42,6 +42,18 @@ "doctype": "DocType", "name": "Price List" }, + { + "default": "1", + "doctype": "DocField", + "fieldname": "enabled", + "fieldtype": "Check", + "label": "Enabled" + }, + { + "doctype": "DocField", + "fieldname": "sb_1", + "fieldtype": "Section Break" + }, { "doctype": "DocField", "fieldname": "price_list_name", diff --git a/stock/doctype/price_list/test_price_list.py b/stock/doctype/price_list/test_price_list.py index bdcacc34528..803be27e5ca 100644 --- a/stock/doctype/price_list/test_price_list.py +++ b/stock/doctype/price_list/test_price_list.py @@ -11,6 +11,7 @@ test_records = [ { "doctype": "Price List", "price_list_name": "_Test Price List", + "enabled": 1, "currency": "INR", "selling": 1 }, @@ -24,6 +25,7 @@ test_records = [ { "doctype": "Price List", "price_list_name": "_Test Price List 2", + "enabled": 1, "currency": "INR", "selling": 1 }, @@ -37,6 +39,7 @@ test_records = [ { "doctype": "Price List", "price_list_name": "_Test Price List India", + "enabled": 1, "currency": "INR", "selling": 1 }, @@ -50,6 +53,7 @@ test_records = [ { "doctype": "Price List", "price_list_name": "_Test Price List Rest of the World", + "enabled": 1, "currency": "USD", "selling": 1 }, diff --git a/stock/doctype/warehouse/warehouse.py b/stock/doctype/warehouse/warehouse.py index db4ee405f54..e1b0ef3cc9d 100644 --- a/stock/doctype/warehouse/warehouse.py +++ b/stock/doctype/warehouse/warehouse.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import webnotes from webnotes.utils import cint, validate_email_add -from webnotes import msgprint, _ +from webnotes import throw, msgprint, _ class DocType: def __init__(self, doc, doclist=[]): @@ -18,7 +18,7 @@ class DocType: def validate(self): if self.doc.email_id and not validate_email_add(self.doc.email_id): - msgprint("Please enter valid Email Id", raise_exception=1) + throw(_("Please enter valid Email Id")) self.update_parent_account() @@ -76,8 +76,8 @@ class DocType: for d in bins: if d['actual_qty'] or d['reserved_qty'] or d['ordered_qty'] or \ d['indented_qty'] or d['projected_qty'] or d['planned_qty']: - msgprint("""Warehouse: %s can not be deleted as qty exists for item: %s""" - % (self.doc.name, d['item_code']), raise_exception=1) + throw("""Warehouse: %s can not be deleted as qty exists for item: %s""" + % (self.doc.name, d['item_code'])) else: webnotes.conn.sql("delete from `tabBin` where name = %s", d['name']) @@ -88,8 +88,8 @@ class DocType: if webnotes.conn.sql("""select name from `tabStock Ledger Entry` where warehouse = %s""", self.doc.name): - msgprint("""Warehouse can not be deleted as stock ledger entry - exists for this warehouse.""", raise_exception=1) + throw(_("""Warehouse can not be deleted as stock ledger entry + exists for this warehouse.""")) def before_rename(self, olddn, newdn, merge=False): # Add company abbr if not provided diff --git a/stock/report/item_prices/item_prices.py b/stock/report/item_prices/item_prices.py index 18228ff64b3..c9efd69829e 100644 --- a/stock/report/item_prices/item_prices.py +++ b/stock/report/item_prices/item_prices.py @@ -16,7 +16,6 @@ def execute(filters=None): val_rate_map = get_valuation_rate() precision = get_currency_precision() or 2 - data = [] for item in sorted(item_map): data.append([item, item_map[item]["item_name"], @@ -65,9 +64,10 @@ def get_price_list(): rate = {} - price_list = webnotes.conn.sql("""select item_code, buying, selling, - concat(price_list, " - ", currency, " ", ref_rate) as price - from `tabItem Price`""", as_dict=1) + price_list = webnotes.conn.sql("""select ip.item_code, ip.buying, ip.selling, + concat(ip.price_list, " - ", ip.currency, " ", ip.ref_rate) as price + from `tabItem Price` ip, `tabPrice List` pl + where ip.price_list=pl.name and pl.enabled=1""", as_dict=1) for j in price_list: if j.price: diff --git a/utilities/transaction_base.py b/utilities/transaction_base.py index f783faa9ec2..6c515a52b65 100644 --- a/utilities/transaction_base.py +++ b/utilities/transaction_base.py @@ -78,8 +78,9 @@ class TransactionBase(StatusUpdater): 3. Clears existing Sales Team and fetches the one mentioned in Customer """ customer_defaults = self.get_customer_defaults() - - customer_defaults["selling_price_list"] = self.get_user_default_price_list("Selling") or \ + + customer_defaults["selling_price_list"] = \ + self.get_user_default_price_list("selling_price_list") or \ customer_defaults.get("price_list") or \ webnotes.conn.get_value("Customer Group", self.doc.customer_group, "default_price_list") or self.doc.selling_price_list @@ -91,11 +92,11 @@ class TransactionBase(StatusUpdater): if self.meta.get_field("sales_team") and self.doc.customer: self.set_sales_team_for_customer() - def get_user_default_price_list(self, price_list_for): - from webnotes.defaults import get_user_default_as_list - user_default_price_list = get_user_default_as_list("selling_price_list" - if price_list_for=="Selling" else "buying_price_list") - return user_default_price_list[0] if len(user_default_price_list)==1 else "" + def get_user_default_price_list(self, price_list): + from webnotes.defaults import get_defaults_for + user_default_price_list = get_defaults_for(webnotes.session.user).get(price_list) + return cstr(user_default_price_list) \ + if not isinstance(user_default_price_list, list) else "" def set_sales_team_for_customer(self): from webnotes.model import default_fields @@ -128,7 +129,7 @@ class TransactionBase(StatusUpdater): if supplier.default_currency: out["currency"] = supplier.default_currency - out["buying_price_list"] = self.get_user_default_price_list("Buying") or \ + out["buying_price_list"] = self.get_user_default_price_list("buying_price_list") or \ supplier.default_price_list or self.doc.buying_price_list return out