diff --git a/accounts/Print Format/POS Invoice/POS Invoice.txt b/accounts/Print Format/POS Invoice/POS Invoice.txt index aab8e18491..7f1bba4c96 100644 --- a/accounts/Print Format/POS Invoice/POS Invoice.txt +++ b/accounts/Print Format/POS Invoice/POS Invoice.txt @@ -2,14 +2,14 @@ { "creation": "2011-12-21 11:08:55", "docstatus": 0, - "modified": "2013-09-13 17:17:47", + "modified": "2014-01-08 19:32:16", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n \n \n \n \n \n \n \n
RECEIPT NO: DATE:
M/s
\n\n
\n\n\n", + "html": "\n\t\n\n\t\t\n\t\t\n\n\t\t\n\t\t\n\t\n\n\t\n\t\t\n\t\t
\n\t\t
\n\t\t
\n\t\t
\n\t\t
\n\t\n", "module": "Accounts", "name": "__common__", "print_format_type": "Client", diff --git a/accounts/doctype/pos_setting/pos_setting.js b/accounts/doctype/pos_setting/pos_setting.js index 8c5f254a52..dc13bb50ca 100755 --- a/accounts/doctype/pos_setting/pos_setting.js +++ b/accounts/doctype/pos_setting/pos_setting.js @@ -7,7 +7,7 @@ cur_frm.cscript.onload = function(doc,cdt,cdn){ }); cur_frm.set_query("selling_price_list", function() { - return { filters: { buying_or_selling: "Selling" } }; + return { filters: { selling: 1 } }; }); } diff --git a/accounts/report/accounts_payable/accounts_payable.py b/accounts/report/accounts_payable/accounts_payable.py index f9266dc9ea..1bd8a9f323 100644 --- a/accounts/report/accounts_payable/accounts_payable.py +++ b/accounts/report/accounts_payable/accounts_payable.py @@ -9,18 +9,20 @@ from accounts.report.accounts_receivable.accounts_receivable import get_ageing_d def execute(filters=None): if not filters: filters = {} - columns = get_columns() + supplier_naming_by = webnotes.conn.get_value("Buying Settings", None, "supp_master_name") + columns = get_columns(supplier_naming_by) entries = get_gl_entries(filters) - account_supplier = dict(webnotes.conn.sql("""select account.name, supplier.supplier_name - from `tabAccount` account, `tabSupplier` supplier - where account.master_type="Supplier" and supplier.name=account.master_name""")) - + account_map = dict(((r.name, r) for r in webnotes.conn.sql("""select acc.name, + supp.supplier_name, supp.name as supplier + from `tabAccount` acc, `tabSupplier` supp + where acc.master_type="Supplier" and supp.name=acc.master_name""", as_dict=1))) + entries_after_report_date = [[gle.voucher_type, gle.voucher_no] for gle in get_gl_entries(filters, before_report_date=False)] - + account_supplier_type_map = get_account_supplier_type_map() voucher_detail_map = get_voucher_details() - + # Age of the invoice on this date age_on = getdate(filters.get("report_date")) > getdate(nowdate()) \ and nowdate() or filters.get("report_date") @@ -37,9 +39,7 @@ def execute(filters=None): if abs(flt(outstanding_amount)) > 0.01: paid_amount = invoiced_amount - outstanding_amount - row = [gle.posting_date, gle.account, account_supplier.get(gle.account, ""), - gle.voucher_type, gle.voucher_no, gle.remarks, - account_supplier_type_map.get(gle.account), + row = [gle.posting_date, gle.account, gle.voucher_type, gle.voucher_no, voucher_details.get("due_date", ""), voucher_details.get("bill_no", ""), voucher_details.get("bill_date", ""), invoiced_amount, paid_amount, outstanding_amount] @@ -50,21 +50,38 @@ def execute(filters=None): else: ageing_based_on_date = gle.posting_date - row += get_ageing_data(age_on, ageing_based_on_date, outstanding_amount) + row += get_ageing_data(age_on, ageing_based_on_date, outstanding_amount) + \ + [account_map.get(gle.account).get("supplier") or ""] + + if supplier_naming_by == "Naming Series": + row += [account_map.get(gle.account).get("supplier_name") or ""] + + row += [account_supplier_type_map.get(gle.account), gle.remarks] data.append(row) - + + for i in range(0, len(data)): + data[i].insert(4, """""" \ + % ("/".join(["#Form", data[i][2], data[i][3]]),)) + return columns, data -def get_columns(): - return [ - "Posting Date:Date:80", "Account:Link/Account:150", "Supplier::150", "Voucher Type::110", - "Voucher No::120", "Remarks::150", "Supplier Type:Link/Supplier Type:120", - "Due Date:Date:80", "Bill No::80", "Bill Date:Date:80", +def get_columns(supplier_naming_by): + columns = [ + "Posting Date:Date:80", "Account:Link/Account:150", "Voucher Type::110", + "Voucher No::120", "::30", "Due Date:Date:80", "Bill No::80", "Bill Date:Date:80", "Invoiced Amount:Currency:100", "Paid Amount:Currency:100", "Outstanding Amount:Currency:100", "Age:Int:50", "0-30:Currency:100", - "30-60:Currency:100", "60-90:Currency:100", "90-Above:Currency:100" + "30-60:Currency:100", "60-90:Currency:100", "90-Above:Currency:100", + "Supplier:Link/Supplier:150" ] - + + if supplier_naming_by == "Naming Series": + columns += ["Supplier Name::110"] + + columns += ["Supplier Type:Link/Supplier Type:120", "Remarks::150"] + + return columns + def get_gl_entries(filters, before_report_date=True): conditions, supplier_accounts = get_conditions(filters, before_report_date) gl_entries = [] @@ -102,10 +119,10 @@ def get_conditions(filters, before_report_date=True): def get_account_supplier_type_map(): account_supplier_type_map = {} - for each in webnotes.conn.sql("""select t2.name, t1.supplier_type from `tabSupplier` t1, - `tabAccount` t2 where t1.name = t2.master_name group by t2.name"""): + for each in webnotes.conn.sql("""select acc.name, supp.supplier_type from `tabSupplier` supp, + `tabAccount` acc where supp.name = acc.master_name group by acc.name"""): account_supplier_type_map[each[0]] = each[1] - + return account_supplier_type_map def get_voucher_details(): diff --git a/accounts/report/accounts_receivable/accounts_receivable.py b/accounts/report/accounts_receivable/accounts_receivable.py index 7758b24744..de96abb7d7 100644 --- a/accounts/report/accounts_receivable/accounts_receivable.py +++ b/accounts/report/accounts_receivable/accounts_receivable.py @@ -15,20 +15,28 @@ class AccountsReceivableReport(object): else self.filters.report_date def run(self): - return self.get_columns(), self.get_data() + customer_naming_by = webnotes.conn.get_value("Selling Settings", None, "cust_master_name") + return self.get_columns(customer_naming_by), self.get_data(customer_naming_by) - def get_columns(self): - return [ + def get_columns(self, customer_naming_by): + columns = [ "Posting Date:Date:80", "Account:Link/Account:150", "Voucher Type::110", "Voucher No::120", "::30", "Due Date:Date:80", "Invoiced Amount:Currency:100", "Payment Received:Currency:100", "Outstanding Amount:Currency:100", "Age:Int:50", "0-30:Currency:100", "30-60:Currency:100", "60-90:Currency:100", "90-Above:Currency:100", - "Customer:Link/Customer:200", "Territory:Link/Territory:80", "Remarks::200" + "Customer:Link/Customer:200" ] - - def get_data(self): + + if customer_naming_by == "Naming Series": + columns += ["Customer Name::110"] + + columns += ["Territory:Link/Territory:80", "Remarks::200"] + + return columns + + def get_data(self, customer_naming_by): data = [] future_vouchers = self.get_entries_after(self.filters.report_date) for gle in self.get_entries_till(self.filters.report_date): @@ -42,18 +50,23 @@ class AccountsReceivableReport(object): gle.voucher_type, gle.voucher_no, due_date, invoiced_amount, payment_received, outstanding_amount] - entry_date = due_date if self.filters.ageing_based_on=="Due Date" \ + entry_date = due_date if self.filters.ageing_based_on == "Due Date" \ else gle.posting_date - row += get_ageing_data(self.age_as_on, entry_date, outstanding_amount) - row += [self.get_customer(gle.account), self.get_territory(gle.account), gle.remarks] + row += get_ageing_data(self.age_as_on, entry_date, outstanding_amount) + \ + [self.get_customer(gle.account)] + + if customer_naming_by == "Naming Series": + row += [self.get_customer_name(gle.account)] + + row += [self.get_territory(gle.account), gle.remarks] data.append(row) - for i in range(0,len(data)): + for i in range(0, len(data)): data[i].insert(4, """""" \ % ("/".join(["#Form", data[i][2], data[i][3]]),)) return data - + def get_entries_after(self, report_date): # returns a distinct list return list(set([(e.voucher_type, e.voucher_no) for e in self.get_gl_entries() @@ -85,18 +98,21 @@ class AccountsReceivableReport(object): return flt(gle.debit) - flt(gle.credit) - payment_received def get_customer(self, account): + return self.get_account_map().get(account).get("customer") or "" + + def get_customer_name(self, account): return self.get_account_map().get(account).get("customer_name") or "" - + def get_territory(self, account): return self.get_account_map().get(account).get("territory") or "" def get_account_map(self): if not hasattr(self, "account_map"): self.account_map = dict(((r.name, r) for r in webnotes.conn.sql("""select - account.name, customer.name as customer_name, customer.territory - from `tabAccount` account, `tabCustomer` customer - where account.master_type="Customer" - and customer.name=account.master_name""", as_dict=True))) + acc.name, cust.name as customer, cust.customer_name, cust.territory + from `tabAccount` acc, `tabCustomer` cust + where acc.master_type="Customer" + and cust.name=acc.master_name""", as_dict=True))) return self.account_map @@ -155,7 +171,7 @@ class AccountsReceivableReport(object): def execute(filters=None): return AccountsReceivableReport(filters).run() - + def get_ageing_data(age_as_on, entry_date, outstanding_amount): # [0-30, 30-60, 60-90, 90-above] outstanding_range = [0.0, 0.0, 0.0, 0.0] diff --git a/buying/doctype/purchase_common/purchase_common.js b/buying/doctype/purchase_common/purchase_common.js index 9661f6edaf..14b8279245 100644 --- a/buying/doctype/purchase_common/purchase_common.js +++ b/buying/doctype/purchase_common/purchase_common.js @@ -22,7 +22,7 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({ if(this.frm.fields_dict.buying_price_list) { this.frm.set_query("buying_price_list", function() { return{ - filters: { 'buying_or_selling': "Buying" } + filters: { 'buying': 1 } } }); } diff --git a/buying/doctype/supplier/supplier.js b/buying/doctype/supplier/supplier.js index 061861643d..ec4d3e606f 100644 --- a/buying/doctype/supplier/supplier.js +++ b/buying/doctype/supplier/supplier.js @@ -95,6 +95,6 @@ cur_frm.cscript.make_contact = function() { cur_frm.fields_dict['default_price_list'].get_query = function(doc,cdt,cdn) { return{ - filters:{'buying_or_selling': "Buying"} + filters:{'buying': 1} } } \ No newline at end of file diff --git a/buying/utils.py b/buying/utils.py index 0d9c8fa838..35d89c559d 100644 --- a/buying/utils.py +++ b/buying/utils.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import webnotes -from webnotes import msgprint, _ +from webnotes import msgprint, _, throw from webnotes.utils import getdate, flt, add_days, cstr import json @@ -90,7 +90,7 @@ 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_or_selling='Buying'""", + where price_list=%s and item_code=%s and buying=1""", (args.buying_price_list, args.item_code), as_dict=1) if price_list_rate: @@ -122,14 +122,12 @@ def _validate_item_details(args, item): # validate if purchase item or subcontracted item if item.is_purchase_item != "Yes": - msgprint(_("Item") + (" %s: " % item.name) + _("not a purchase item"), - raise_exception=True) + throw(_("Item") + (" %s: " % item.name) + _("not a purchase item")) if args.is_subcontracted == "Yes" and item.is_sub_contracted_item != "Yes": - msgprint(_("Item") + (" %s: " % item.name) + + throw(_("Item") + (" %s: " % item.name) + _("not a sub-contracted item.") + - _("Please select a sub-contracted item or do not sub-contract the transaction."), - raise_exception=True) + _("Please select a sub-contracted item or do not sub-contract the transaction.")) def get_last_purchase_details(item_code, doc_name=None, conversion_rate=1.0): """returns last purchase details in stock uom""" diff --git a/config.json b/config.json index c09c2afac9..8499ee84d3 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "app_name": "ERPNext", - "app_version": "3.4.3", + "app_version": "3.5.1", "base_template": "app/portal/templates/base.html", "modules": { "Accounts": { @@ -74,5 +74,5 @@ "type": "module" } }, - "requires_framework_version": "==3.4.2" + "requires_framework_version": "==3.5.0" } \ No newline at end of file diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py index 839dce0b4b..a65bf260ee 100644 --- a/controllers/accounts_controller.py +++ b/controllers/accounts_controller.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import webnotes -from webnotes import _, msgprint +from webnotes import _, msgprint, throw from webnotes.utils import flt, cint, today, cstr from webnotes.model.code import get_obj from setup.utils import get_company_currency @@ -50,8 +50,8 @@ class AccountsController(TransactionBase): if accounts: if not filter(lambda x: cstr(x.freeze_account) in ["", "No"], accounts): - msgprint(_("Account for this ") + fieldname + _(" has been freezed. ") + - self.doc.doctype + _(" can not be made."), raise_exception=1) + throw(_("Account for this ") + fieldname + _(" has been freezed. ") + + self.doc.doctype + _(" can not be made.")) def set_price_list_currency(self, buying_or_selling): if self.meta.get_field("currency"): @@ -179,17 +179,17 @@ class AccountsController(TransactionBase): """ if tax.charge_type in ["On Previous Row Amount", "On Previous Row Total"] and \ (not tax.row_id or cint(tax.row_id) >= tax.idx): - msgprint((_("Row") + " # %(idx)s [%(taxes_doctype)s]: " + \ + throw((_("Row") + " # %(idx)s [%(taxes_doctype)s]: " + \ _("Please specify a valid") + " %(row_id_label)s") % { "idx": tax.idx, "taxes_doctype": tax.doctype, "row_id_label": self.meta.get_label("row_id", parentfield=self.other_fname) - }, raise_exception=True) + }) def validate_inclusive_tax(self, tax): def _on_previous_row_error(row_range): - msgprint((_("Row") + " # %(idx)s [%(doctype)s]: " + + throw((_("Row") + " # %(idx)s [%(doctype)s]: " + _("to be included in Item's rate, it is required that: ") + " [" + _("Row") + " # %(row_range)s] " + _("also be included in Item's rate")) % { "idx": tax.idx, @@ -200,12 +200,12 @@ class AccountsController(TransactionBase): parentfield=self.other_fname), "charge_type": tax.charge_type, "row_range": row_range - }, raise_exception=True) + }) if cint(tax.included_in_print_rate): if tax.charge_type == "Actual": # inclusive tax cannot be of type Actual - msgprint((_("Row") + throw((_("Row") + " # %(idx)s [%(doctype)s]: %(charge_type_label)s = \"%(charge_type)s\" " + "cannot be included in Item's rate") % { "idx": tax.idx, @@ -213,7 +213,7 @@ class AccountsController(TransactionBase): "charge_type_label": self.meta.get_label("charge_type", parentfield=self.other_fname), "charge_type": tax.charge_type, - }, raise_exception=True) + }) elif tax.charge_type == "On Previous Row Amount" and \ not cint(self.tax_doclist[tax.row_id - 1].included_in_print_rate): # referred row should also be inclusive diff --git a/install_erpnext.py b/install_erpnext.py index c95a03d3e5..e285d4bbfe 100644 --- a/install_erpnext.py +++ b/install_erpnext.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import os, sys import argparse +import subprocess is_redhat = is_debian = None root_password = None @@ -19,7 +20,7 @@ requirements = [ "jinja2", "markdown2", "markupsafe", - "mysql-python", + "mysql-python==1.2.4", "pygeoip", "python-dateutil", "python-memcached", @@ -80,7 +81,7 @@ def validate_install(): return is_redhat, is_debian def install_using_yum(): - packages = "python python-setuptools gcc python-devel MySQL-python git memcached ntp vim-enhanced screen" + packages = "gcc MySQL-python git memcached ntp vim-enhanced screen" print "-"*80 print "Installing Packages: (This may take some time)" @@ -88,7 +89,10 @@ def install_using_yum(): print "-"*80 exec_in_shell("yum install -y %s" % packages) - if not exec_in_shell("which mysql"): + + try: + exec_in_shell("which mysql") + except subprocess.CalledProcessError: packages = "mysql mysql-server mysql-devel" print "Installing Packages:", packages exec_in_shell("yum install -y %s" % packages) @@ -101,26 +105,19 @@ def install_using_yum(): exec_in_shell('mysqladmin -u root password "%s"' % (root_password,)) print "Root password set as", root_password - # install htop - if not exec_in_shell("which htop"): - try: - exec_in_shell("cd /tmp && rpm -i --force http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.2-2.el6.rf.x86_64.rpm && yum install -y htop") - except: - pass - update_config_for_redhat() def update_config_for_redhat(): import re # set to autostart on startup - for service in ("mysqld", "memcached", "ntpd"): + for service in ("mysqld", "memcached"): exec_in_shell("chkconfig --level 2345 %s on" % service) exec_in_shell("service %s restart" % service) def install_using_apt(): exec_in_shell("apt-get update") - packages = "python python-setuptools python-dev build-essential python-pip python-mysqldb git memcached ntp vim screen htop" + packages = "python python-setuptools python-dev build-essential python-mysqldb git memcached ntp vim screen htop" print "-"*80 print "Installing Packages: (This may take some time)" print packages @@ -132,7 +129,9 @@ def install_using_apt(): exec_in_shell("echo mysql-server mysql-server/root_password password %s | sudo debconf-set-selections" % root_password) exec_in_shell("echo mysql-server mysql-server/root_password_again password %s | sudo debconf-set-selections" % root_password) - if not exec_in_shell("which mysql"): + try: + exec_in_shell("which mysql") + except subprocess.CalledProcessError: packages = "mysql-server libmysqlclient-dev" print "Installing Packages:", packages exec_in_shell("apt-get install -y %s" % packages) @@ -140,7 +139,7 @@ def install_using_apt(): update_config_for_debian() def update_config_for_debian(): - for service in ("mysql", "ntpd"): + for service in ("mysql",): exec_in_shell("service %s restart" % service) def install_python_modules(): @@ -148,13 +147,14 @@ def install_python_modules(): print "Installing Python Modules: (This may take some time)" print "-"*80 - if not exec_in_shell("which pip"): - exec_in_shell("easy_install pip") + try: + exec_in_shell("which pip2.7") + except subprocess.CalledProcessError: + exec_in_shell("easy_install-2.7 pip") - exec_in_shell("pip install --upgrade pip") - exec_in_shell("pip install --upgrade setuptools") - exec_in_shell("pip install --upgrade virtualenv") - exec_in_shell("pip install {}".format(' '.join(requirements))) + exec_in_shell("pip2.7 install --upgrade setuptools --no-use-wheel") + exec_in_shell("pip2.7 install --upgrade setuptools") + exec_in_shell("pip2.7 install {}".format(' '.join(requirements))) def install_erpnext(install_path): print @@ -200,7 +200,7 @@ def setup_folders(install_path): app = os.path.join(install_path, "app") if not os.path.exists(app): print "Cloning erpnext" - exec_in_shell("cd %s && git clone https://github.com/webnotes/erpnext.git app" % install_path) + exec_in_shell("cd %s && git clone --branch master https://github.com/webnotes/erpnext.git app" % install_path) exec_in_shell("cd app && git config core.filemode false") if not os.path.exists(app): raise Exception, "Couldn't clone erpnext repository" @@ -208,7 +208,7 @@ def setup_folders(install_path): lib = os.path.join(install_path, "lib") if not os.path.exists(lib): print "Cloning wnframework" - exec_in_shell("cd %s && git clone https://github.com/webnotes/wnframework.git lib" % install_path) + exec_in_shell("cd %s && git clone --branch master https://github.com/webnotes/wnframework.git lib" % install_path) exec_in_shell("cd lib && git config core.filemode false") if not os.path.exists(lib): raise Exception, "Couldn't clone wnframework repository" @@ -243,28 +243,8 @@ def post_install(install_path): def exec_in_shell(cmd): # using Popen instead of os.system - as recommended by python docs - from subprocess import Popen - import tempfile - - with tempfile.TemporaryFile() as stdout: - with tempfile.TemporaryFile() as stderr: - p = Popen(cmd, shell=True, stdout=stdout, stderr=stderr) - p.wait() - - stdout.seek(0) - out = stdout.read() - if out: out = out.decode('utf-8') - - stderr.seek(0) - err = stderr.read() - if err: err = err.decode('utf-8') - - if err and any((kw in err.lower() for kw in ["traceback", "error", "exception"])): - print out - raise Exception, err - else: - print "." - + import subprocess + out = subprocess.check_output(cmd, shell=True) return out def parse_args(): diff --git a/patches/1401/p01_make_buying_selling_as_check_box_in_price_list.py b/patches/1401/p01_make_buying_selling_as_check_box_in_price_list.py new file mode 100644 index 0000000000..b764a7f935 --- /dev/null +++ b/patches/1401/p01_make_buying_selling_as_check_box_in_price_list.py @@ -0,0 +1,29 @@ +# Copyright (c) 2014, Web Notes Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes + +def execute(): + webnotes.reload_doc("stock", "doctype", "price_list") + webnotes.reload_doc("stock", "doctype", "item_price") + + if "buying_or_selling" in webnotes.conn.get_table_columns("Price List"): + webnotes.conn.sql("""update `tabPrice List` set + selling = + case + when buying_or_selling='Selling' + then 1 + end, + buying = + case + when buying_or_selling='Buying' + then 1 + end + """) + webnotes.conn.sql("""update `tabItem Price` ip, `tabPrice List` pl + set ip.buying=pl.buying, ip.selling=pl.selling + where ip.price_list=pl.name""") + + webnotes.conn.sql("""update `tabItem Price` set selling=1 where ifnull(selling, 0)=0 and + ifnull(buying, 0)=0""") \ 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 2f92fe6a9e..15da085e53 100644 --- a/patches/june_2013/p03_buying_selling_for_price_list.py +++ b/patches/june_2013/p03_buying_selling_for_price_list.py @@ -8,20 +8,7 @@ from webnotes.utils import cint def execute(): webnotes.reload_doc("stock", "doctype", "price_list") webnotes.reload_doc("stock", "doctype", "item_price") - - try: - for price_list in webnotes.conn.sql_list("""select name from `tabPrice List`"""): - buying, selling = False, False - for b, s in webnotes.conn.sql("""select distinct buying, selling - from `tabItem Price` where price_list_name=%s""", price_list): - buying = buying or cint(b) - selling = selling or cint(s) - - buying_or_selling = "Selling" if selling else "Buying" - webnotes.conn.set_value("Price List", price_list, "buying_or_selling", buying_or_selling) - except webnotes.SQLError, e: - if e.args[0] == 1054: - webnotes.conn.sql("""update `tabPrice List` set buying_or_selling='Selling' - where ifnull(buying_or_selling, '')='' """) - else: - raise \ No newline at end of file + + webnotes.conn.sql("""update `tabPrice List` pl, `tabItem Price` ip + set pl.selling=ip.selling, pl.buying=ip.buying + where pl.name=ip.price_list_name""") \ No newline at end of file diff --git a/patches/october_2013/p02_update_price_list_and_item_details_in_item_price.py b/patches/october_2013/p02_update_price_list_and_item_details_in_item_price.py index 3b4ca833f1..b92f7d052a 100644 --- a/patches/october_2013/p02_update_price_list_and_item_details_in_item_price.py +++ b/patches/october_2013/p02_update_price_list_and_item_details_in_item_price.py @@ -12,9 +12,7 @@ def execute(): where ip.item_code=i.name""") webnotes.conn.sql("""update `tabItem Price` ip, `tabPrice List` pl - set ip.price_list=pl.name, ip.currency=pl.currency, - ip.buying_or_selling=pl.buying_or_selling - where ip.parent=pl.name""") + set ip.price_list=pl.name, ip.currency=pl.currency where ip.parent=pl.name""") webnotes.conn.sql("""update `tabItem Price` set parent=null, parenttype=null, parentfield=null, idx=null""") \ No newline at end of file diff --git a/patches/patch_list.py b/patches/patch_list.py index e4d2975ea3..04a9288c60 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -264,4 +264,5 @@ patch_list = [ "execute:webnotes.delete_doc('DocType', 'Warehouse Type')", "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", ] \ No newline at end of file diff --git a/public/js/transaction.js b/public/js/transaction.js index 4c4a810ed2..0fe0535c6b 100644 --- a/public/js/transaction.js +++ b/public/js/transaction.js @@ -330,8 +330,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ doctype: tax.doctype, row_id_label: wn.meta.get_label(tax.doctype, "row_id", tax.name) }); - msgprint(msg); - throw msg; + wn.throw(msg); } }, @@ -347,8 +346,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ charge_type_label: wn.meta.get_label(tax.doctype, "charge_type", tax.name), charge_type: tax.charge_type }); - msgprint(msg); - throw msg; + wn.throw(msg); }; var on_previous_row_error = function(row_range) { @@ -363,8 +361,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ row_range: row_range, }); - msgprint(msg); - throw msg; + wn.throw(msg); }; if(cint(tax.included_in_print_rate)) { diff --git a/selling/doctype/customer/customer.js b/selling/doctype/customer/customer.js index 5e0ccc98f2..5d046904d3 100644 --- a/selling/doctype/customer/customer.js +++ b/selling/doctype/customer/customer.js @@ -122,6 +122,6 @@ cur_frm.fields_dict.lead_name.get_query = function(doc,cdt,cdn) { cur_frm.fields_dict['default_price_list'].get_query = function(doc,cdt,cdn) { return{ - filters:{'buying_or_selling': "Selling"} + filters:{'selling': 1} } } diff --git a/selling/sales_common.js b/selling/sales_common.js index dddc2b568d..f4f643015e 100644 --- a/selling/sales_common.js +++ b/selling/sales_common.js @@ -48,7 +48,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ if(this.frm.fields_dict.selling_price_list) { this.frm.set_query("selling_price_list", function() { - return { filters: { buying_or_selling: "Selling" } }; + return { filters: { selling: 1 } }; }); } diff --git a/selling/utils/__init__.py b/selling/utils/__init__.py index 5974da7d8b..85c20e86d8 100644 --- a/selling/utils/__init__.py +++ b/selling/utils/__init__.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import webnotes -from webnotes import msgprint, _ +from webnotes import msgprint, _, throw from webnotes.utils import flt, cint, comma_and import json @@ -100,7 +100,7 @@ def _get_item_code(barcode=None, serial_no=None): where name=%s""", serial_no) if not item_code: - msgprint(_("No Item found with ") + input_type + ": %s" % (barcode or serial_no), raise_exception=True) + throw(_("No Item found with ") + input_type + ": %s" % (barcode or serial_no)) return item_code[0] @@ -111,14 +111,12 @@ def _validate_item_details(args, item): # validate if sales item or service item if args.order_type == "Maintenance": if item.is_service_item != "Yes": - msgprint(_("Item") + (" %s: " % item.name) + + throw(_("Item") + (" %s: " % item.name) + _("not a service item.") + - _("Please select a service item or change the order type to Sales."), - raise_exception=True) + _("Please select a service item or change the order type to Sales.")) elif item.is_sales_item != "Yes": - msgprint(_("Item") + (" %s: " % item.name) + _("not a sales item"), - raise_exception=True) + throw(_("Item") + (" %s: " % item.name) + _("not a sales item")) def _get_basic_details(args, item_bean, warehouse_fieldname): item = item_bean.doc @@ -147,7 +145,7 @@ def _get_basic_details(args, item_bean, warehouse_fieldname): 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 buying_or_selling='Selling'""", + where price_list=%s and item_code=%s and selling=1""", (args.selling_price_list, args.item_code), as_dict=1) if not ref_rate: diff --git a/setup/page/setup_wizard/setup_wizard.py b/setup/page/setup_wizard/setup_wizard.py index c1d3571ea5..ededd472a8 100644 --- a/setup/page/setup_wizard/setup_wizard.py +++ b/setup/page/setup_wizard/setup_wizard.py @@ -98,7 +98,8 @@ def create_price_lists(args): { "doctype": "Price List", "price_list_name": "Standard " + pl_type, - "buying_or_selling": pl_type, + "buying": 1 if pl_type == "Buying" else 0, + "selling": 1 if pl_type == "Selling" else 0, "currency": args["currency"] }, { diff --git a/stock/doctype/item_price/item_price.js b/stock/doctype/item_price/item_price.js index bece26c6b5..9f38fdb18e 100644 --- a/stock/doctype/item_price/item_price.js +++ b/stock/doctype/item_price/item_price.js @@ -2,11 +2,10 @@ // License: GNU General Public License v3. See license.txt $.extend(cur_frm.cscript, { - onload: function () { - // Fetch price list details - cur_frm.add_fetch("price_list", "buying_or_selling", "buying_or_selling"); + cur_frm.add_fetch("price_list", "buying", "buying"); + cur_frm.add_fetch("price_list", "selling", "selling"); cur_frm.add_fetch("price_list", "currency", "currency"); // Fetch item details diff --git a/stock/doctype/item_price/item_price.py b/stock/doctype/item_price/item_price.py index 072d70096e..e2c9f2fcb0 100644 --- a/stock/doctype/item_price/item_price.py +++ b/stock/doctype/item_price/item_price.py @@ -1,7 +1,5 @@ # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -# For license information, please see license.txt +# License: GNU General Public License v3. See license.txt from __future__ import unicode_literals import webnotes @@ -19,8 +17,8 @@ class DocType: self.update_item_details() def update_price_list_details(self): - self.doc.buying_or_selling, self.doc.currency = webnotes.conn.get_value("Price List", - self.doc.price_list, ["buying_or_selling", "currency"]) + 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", diff --git a/stock/doctype/item_price/item_price.txt b/stock/doctype/item_price/item_price.txt index fc411eb1d6..f329a5ff07 100644 --- a/stock/doctype/item_price/item_price.txt +++ b/stock/doctype/item_price/item_price.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-02 16:29:48", "docstatus": 0, - "modified": "2013-10-31 12:59:02", + "modified": "2014-01-07 19:16:49", "modified_by": "Administrator", "owner": "Administrator" }, @@ -43,6 +43,13 @@ "doctype": "DocType", "name": "Item Price" }, + { + "doctype": "DocField", + "fieldname": "price_list_details", + "fieldtype": "Section Break", + "label": "Price List", + "options": "icon-tags" + }, { "doctype": "DocField", "fieldname": "price_list", @@ -52,6 +59,29 @@ "options": "Price List", "reqd": 1 }, + { + "doctype": "DocField", + "fieldname": "buying", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Buying", + "read_only": 1 + }, + { + "doctype": "DocField", + "fieldname": "selling", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Selling", + "read_only": 1 + }, + { + "doctype": "DocField", + "fieldname": "item_details", + "fieldtype": "Section Break", + "label": "Item", + "options": "icon-tag" + }, { "doctype": "DocField", "fieldname": "item_code", @@ -83,16 +113,6 @@ "fieldname": "col_br_1", "fieldtype": "Column Break" }, - { - "doctype": "DocField", - "fieldname": "buying_or_selling", - "fieldtype": "Select", - "in_filter": 1, - "in_list_view": 1, - "label": "Valid for Buying or Selling?", - "options": "Selling\nBuying", - "reqd": 0 - }, { "doctype": "DocField", "fieldname": "item_name", diff --git a/stock/doctype/price_list/price_list.css b/stock/doctype/price_list/price_list.css deleted file mode 100644 index 61b069442f..0000000000 --- a/stock/doctype/price_list/price_list.css +++ /dev/null @@ -1,7 +0,0 @@ -.table-grid tbody tr { - cursor: pointer; -} - -.table-grid thead tr { - height: 50px; -} \ No newline at end of file diff --git a/stock/doctype/price_list/price_list.py b/stock/doctype/price_list/price_list.py index d0e5d2b6d4..40841cfaac 100644 --- a/stock/doctype/price_list/price_list.py +++ b/stock/doctype/price_list/price_list.py @@ -3,16 +3,15 @@ from __future__ import unicode_literals import webnotes -from webnotes import msgprint, _ -from webnotes.utils import comma_or, cint +from webnotes import msgprint, _, throw +from webnotes.utils import cint from webnotes.model.controller import DocListController import webnotes.defaults class DocType(DocListController): 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") + " " + - comma_or(["Buying", "Selling"]), raise_exception=True) + if not cint(self.doc.buying) and not cint(self.doc.selling): + throw(_("Price List must be applicable for Buying or Selling")) if not self.doclist.get({"parentfield": "valid_for_territories"}): # if no territory, set default territory @@ -25,24 +24,24 @@ class DocType(DocListController): else: # at least one territory self.validate_table_has_rows("valid_for_territories") - + def on_update(self): self.set_default_if_missing() self.update_item_price() cart_settings = webnotes.get_obj("Shopping Cart Settings") if cint(cart_settings.doc.enabled): cart_settings.validate_price_lists() - + def set_default_if_missing(self): - if self.doc.buying_or_selling=="Selling": + if cint(self.doc.selling): if not webnotes.conn.get_value("Selling Settings", None, "selling_price_list"): webnotes.set_value("Selling Settings", "Selling Settings", "selling_price_list", self.doc.name) - elif self.doc.buying_or_selling=="Buying": + elif cint(self.doc.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) def update_item_price(self): webnotes.conn.sql("""update `tabItem Price` set currency=%s, - buying_or_selling=%s, modified=NOW() where price_list=%s""", - (self.doc.currency, self.doc.buying_or_selling, self.doc.name)) \ No newline at end of file + buying=%s, selling=%s, modified=NOW() where price_list=%s""", + (self.doc.currency, cint(self.doc.buying), cint(self.doc.selling), self.doc.name)) \ 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 d43076bcc8..69c3ecbc4c 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": "2013-10-31 19:24:33", + "modified": "2014-01-06 18:28:23", "modified_by": "Administrator", "owner": "Administrator" }, @@ -61,14 +61,19 @@ "reqd": 1 }, { - "default": "Selling", "doctype": "DocField", - "fieldname": "buying_or_selling", - "fieldtype": "Select", + "fieldname": "buying", + "fieldtype": "Check", "in_list_view": 1, - "label": "Valid for Buying or Selling?", - "options": "Buying\nSelling", - "reqd": 1 + "label": "Buying" + }, + { + "doctype": "DocField", + "fieldname": "selling", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Selling", + "reqd": 0 }, { "doctype": "DocField", diff --git a/stock/doctype/price_list/test_price_list.py b/stock/doctype/price_list/test_price_list.py index 86dcd1a594..bdcacc3452 100644 --- a/stock/doctype/price_list/test_price_list.py +++ b/stock/doctype/price_list/test_price_list.py @@ -12,7 +12,7 @@ test_records = [ "doctype": "Price List", "price_list_name": "_Test Price List", "currency": "INR", - "buying_or_selling": "Selling" + "selling": 1 }, { "doctype": "Applicable Territory", @@ -25,7 +25,7 @@ test_records = [ "doctype": "Price List", "price_list_name": "_Test Price List 2", "currency": "INR", - "buying_or_selling": "Selling" + "selling": 1 }, { "doctype": "Applicable Territory", @@ -38,7 +38,7 @@ test_records = [ "doctype": "Price List", "price_list_name": "_Test Price List India", "currency": "INR", - "buying_or_selling": "Selling" + "selling": 1 }, { "doctype": "Applicable Territory", @@ -51,7 +51,7 @@ test_records = [ "doctype": "Price List", "price_list_name": "_Test Price List Rest of the World", "currency": "USD", - "buying_or_selling": "Selling" + "selling": 1 }, { "doctype": "Applicable Territory", diff --git a/stock/report/item_prices/item_prices.py b/stock/report/item_prices/item_prices.py index da8b5007d5..e744cc73e4 100644 --- a/stock/report/item_prices/item_prices.py +++ b/stock/report/item_prices/item_prices.py @@ -65,13 +65,13 @@ def get_price_list(): rate = {} - price_list = webnotes.conn.sql("""select item_code, buying_or_selling, + price_list = webnotes.conn.sql("""select item_code, buying, selling, concat(price_list, " - ", currency, " ", ref_rate) as price from `tabItem Price`""", as_dict=1) for j in price_list: if j.price: - rate.setdefault(j.item_code, {}).setdefault(j.buying_or_selling, []).append(j.price) + rate.setdefault(j.item_code, {}).setdefault("Buying" if j.buying else "Selling", []).append(j.price) item_rate_map = {} for item in rate: diff --git a/stock/report/item_wise_price_list_rate/__init__.py b/stock/report/item_wise_price_list_rate/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/stock/report/item_wise_price_list_rate/item_wise_price_list_rate.txt b/stock/report/item_wise_price_list_rate/item_wise_price_list_rate.txt new file mode 100644 index 0000000000..f4d1d67ca4 --- /dev/null +++ b/stock/report/item_wise_price_list_rate/item_wise_price_list_rate.txt @@ -0,0 +1,22 @@ +[ + { + "creation": "2013-09-25 10:21:15", + "docstatus": 0, + "modified": "2014-01-07 18:35:22", + "modified_by": "Administrator", + "owner": "Administrator" + }, + { + "doctype": "Report", + "is_standard": "Yes", + "json": "{\"filters\":[[\"Item Price\",\"price_list\",\"like\",\"%\"],[\"Item Price\",\"item_code\",\"like\",\"%\"]],\"columns\":[[\"name\",\"Item Price\"],[\"price_list\",\"Item Price\"],[\"item_code\",\"Item Price\"],[\"item_name\",\"Item Price\"],[\"item_description\",\"Item Price\"],[\"ref_rate\",\"Item Price\"],[\"buying\",\"Item Price\"],[\"selling\",\"Item Price\"],[\"currency\",\"Item Price\"]],\"sort_by\":\"Item Price.modified\",\"sort_order\":\"desc\",\"sort_by_next\":\"\",\"sort_order_next\":\"desc\"}", + "name": "__common__", + "ref_doctype": "Price List", + "report_name": "Item-wise Price List Rate", + "report_type": "Report Builder" + }, + { + "doctype": "Report", + "name": "Item-wise Price List Rate" + } +] \ No newline at end of file diff --git a/utilities/demo/demo_docs/Item_Price.csv b/utilities/demo/demo_docs/Item_Price.csv index d70b7b3e67..cd7a13937f 100644 --- a/utilities/demo/demo_docs/Item_Price.csv +++ b/utilities/demo/demo_docs/Item_Price.csv @@ -1,49 +1,49 @@ -Data Import Template,,,,,,, -Table:,Item Price,,,,,, -,,,,,,, -,,,,,,, -Notes:,,,,,,, -Please do not change the template headings.,,,,,,, -First data column must be blank.,,,,,,, -"If you are uploading new records, leave the ""name"""" (ID) column blank.""",,,,,,, -"If you are uploading new records, ""Naming Series"""" becomes mandatory"," if present.""",,,,,, -Only mandatory fields are necessary for new records. You can delete non-mandatory columns if you wish.,,,,,,, -"For updating, you can update only selective columns.",,,,,,, -You can only upload upto 5000 records in one go. (may be less in some cases),,,,,,, -,,,,,,, -DocType:,Item Price,,,,,, -Column Labels:,ID,Price List,Item Code,Rate,Valid for Buying or Selling?,Item Name,Item Description -Column Name:,name,price_list,item_code,ref_rate,buying_or_selling,item_name,item_description -Mandatory:,Yes,Yes,Yes,Yes,No,No,No -Type:,Data (text),Link,Link,Currency,Select,Data,Text -Info:,,Valid Price List,Valid Item,,"One of: Selling, Buying",, -Start entering data below this line,,,,,,, -,,Standard Buying,Base Bearing Plate,15,Buying,, -,,Standard Buying,Base Plate,20,Buying,, -,,Standard Buying,Bearing Block,10,Buying,, -,,Standard Buying,Bearing Collar,20,Buying,, -,,Standard Buying,Bearing Pipe,15,Buying,, -,,Standard Buying,Blade Rib,10,Buying,, -,,Standard Buying,Disc Collars,74,Buying,, -,,Standard Buying,External Disc,45,Buying,, -,,Standard Buying,Internal Disc,33,Buying,, -,,Standard Buying,Shaft,30,Buying,, -,,Standard Buying,Stand,40,Buying,, -,,Standard Buying,Upper Bearing Plate,50,Buying,, -,,Standard Buying,Wing Sheet,22,Buying,, -,,Standard Selling,Wind Turbine,21,Selling,, -,,Standard Selling,Wind Mill A Series,28,Selling,, -,,Standard Selling,Wind MIll C Series,14,Selling,, -,,Standard Selling,Base Bearing Plate,28,Selling,, -,,Standard Selling,Base Plate,21,Selling,, -,,Standard Selling,Bearing Block,14,Selling,, -,,Standard Selling,Bearing Collar,103.6,Selling,, -,,Standard Selling,Bearing Pipe,63,Selling,, -,,Standard Selling,Blade Rib,46.2,Selling,, -,,Standard Selling,Disc Collars,42,Selling,, -,,Standard Selling,External Disc,56,Selling,, -,,Standard Selling,Internal Disc,70,Selling,, -,,Standard Selling,Shaft,340,Selling,, -,,Standard Selling,Stand,400,Selling,, -,,Standard Selling,Upper Bearing Plate,300,Selling,, -,,Standard Selling,Wing Sheet,30.8,Selling,, \ No newline at end of file +Data Import Template,,,,,,,, +Table:,Item Price,,,,,,, +,,,,,,,, +,,,,,,,, +Notes:,,,,,,,, +Please do not change the template headings.,,,,,,,, +First data column must be blank.,,,,,,,, +"If you are uploading new records, leave the ""name"" (ID) column blank.",,,,,,,, +"If you are uploading new records, ""Naming Series"" becomes mandatory, if present.",,,,,,,, +Only mandatory fields are necessary for new records. You can delete non-mandatory columns if you wish.,,,,,,,, +"For updating, you can update only selective columns.",,,,,,,, +You can only upload upto 5000 records in one go. (may be less in some cases),,,,,,,, +,,,,,,,, +DocType:,Item Price,,,,,,, +Column Labels:,ID,Price List,Item Code,Rate,Buying,Selling,Item Name,Item Description +Column Name:,name,price_list,item_code,ref_rate,buying,selling,item_name,item_description +Mandatory:,Yes,Yes,Yes,Yes,No,No,No,No +Type:,Data (text),Link,Link,Currency,Check,Check,Data,Text +Info:,,Valid Price List,Valid Item,,0 or 1,0 or 1,, +Start entering data below this line,,,,,,,, +,,Standard Buying,Base Bearing Plate,15,1,,, +,,Standard Buying,Base Plate,20,1,,, +,,Standard Buying,Bearing Block,10,1,,, +,,Standard Buying,Bearing Collar,20,1,,, +,,Standard Buying,Bearing Pipe,15,1,,, +,,Standard Buying,Blade Rib,10,1,,, +,,Standard Buying,Disc Collars,74,1,,, +,,Standard Buying,External Disc,45,1,,, +,,Standard Buying,Internal Disc,33,1,,, +,,Standard Buying,Shaft,30,1,,, +,,Standard Buying,Stand,40,1,,, +,,Standard Buying,Upper Bearing Plate,50,1,,, +,,Standard Buying,Wing Sheet,22,1,,, +,,Standard Selling,Wind Turbine,21,,1,, +,,Standard Selling,Wind Mill A Series,28,,1,, +,,Standard Selling,Wind MIll C Series,14,,1,, +,,Standard Selling,Base Bearing Plate,28,,1,, +,,Standard Selling,Base Plate,21,,1,, +,,Standard Selling,Bearing Block,14,,1,, +,,Standard Selling,Bearing Collar,103.6,,1,, +,,Standard Selling,Bearing Pipe,63,,1,, +,,Standard Selling,Blade Rib,46.2,,1,, +,,Standard Selling,Disc Collars,42,,1,, +,,Standard Selling,External Disc,56,,1,, +,,Standard Selling,Internal Disc,70,,1,, +,,Standard Selling,Shaft,340,,1,, +,,Standard Selling,Stand,400,,1,, +,,Standard Selling,Upper Bearing Plate,300,,1,, +,,Standard Selling,Wing Sheet,30.8,,1,,