From 4d7a1c1f358778eb072ac0c23f6d20766fec5bc4 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 2 May 2013 15:19:00 +0530 Subject: [PATCH 1/2] [script report] payments made with ageing --- accounts/page/accounts_home/accounts_home.js | 5 ++ .../accounts_payable/accounts_payable.py | 6 +- .../accounts_receivable.py | 6 +- .../payment_collection_with_ageing.py | 10 ++- .../payment_made_with_ageing/__init__.py | 0 .../payment_made_with_ageing.js | 40 +++++++++ .../payment_made_with_ageing.py | 89 +++++++++++++++++++ .../payment_made_with_ageing.txt | 22 +++++ 8 files changed, 173 insertions(+), 5 deletions(-) create mode 100644 accounts/report/payment_made_with_ageing/__init__.py create mode 100644 accounts/report/payment_made_with_ageing/payment_made_with_ageing.js create mode 100644 accounts/report/payment_made_with_ageing/payment_made_with_ageing.py create mode 100644 accounts/report/payment_made_with_ageing/payment_made_with_ageing.txt diff --git a/accounts/page/accounts_home/accounts_home.js b/accounts/page/accounts_home/accounts_home.js index 7038fe9720..d2b0a0ea0d 100644 --- a/accounts/page/accounts_home/accounts_home.js +++ b/accounts/page/accounts_home/accounts_home.js @@ -212,6 +212,11 @@ wn.module_page["Accounts"] = [ route: "query-report/Payment Collection With Ageing", doctype: "Journal Voucher" }, + { + "label":wn._("Payment Made With Ageing"), + route: "query-report/Payment Made With Ageing", + doctype: "Journal Voucher" + }, ] } ] diff --git a/accounts/report/accounts_payable/accounts_payable.py b/accounts/report/accounts_payable/accounts_payable.py index 4e9b2c88ba..71aeb35ce0 100644 --- a/accounts/report/accounts_payable/accounts_payable.py +++ b/accounts/report/accounts_payable/accounts_payable.py @@ -1,6 +1,7 @@ from __future__ import unicode_literals import webnotes from webnotes.utils import getdate, nowdate, flt, cstr +from webnotes import msgprint, _ from accounts.report.accounts_receivable.accounts_receivable import get_ageing_data def execute(filters=None): @@ -79,13 +80,16 @@ def get_conditions(filters, before_report_date=True): supplier_accounts = [] if filters.get("account"): supplier_accounts = [filters["account"]] - elif filters.get("company"): + else: supplier_accounts = webnotes.conn.sql_list("""select name from `tabAccount` where ifnull(master_type, '') = 'Supplier' and docstatus < 2 %s""" % conditions, filters) if supplier_accounts: conditions += " and account in (%s)" % (", ".join(['%s']*len(supplier_accounts))) + else: + msgprint(_("No Supplier Accounts found. Supplier Accounts are identified based on \ + 'Master Type' value in account record."), raise_exception=1) if filters.get("report_date"): if before_report_date: diff --git a/accounts/report/accounts_receivable/accounts_receivable.py b/accounts/report/accounts_receivable/accounts_receivable.py index 47908c3f13..d791fad23f 100644 --- a/accounts/report/accounts_receivable/accounts_receivable.py +++ b/accounts/report/accounts_receivable/accounts_receivable.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals import webnotes +from webnotes import msgprint, _ from webnotes.utils import getdate, nowdate, flt, cstr def execute(filters=None): @@ -68,13 +69,16 @@ def get_conditions(filters, upto_report_date=True): customer_accounts = [] if filters.get("account"): customer_accounts = [filters["account"]] - elif filters.get("company"): + else: customer_accounts = webnotes.conn.sql_list("""select name from `tabAccount` where ifnull(master_type, '') = 'Customer' and docstatus < 2 %s""" % conditions, filters) if customer_accounts: conditions += " and account in (%s)" % (", ".join(['%s']*len(customer_accounts))) + else: + msgprint(_("No Customer Accounts found. Customer Accounts are identified based on \ + 'Master Type' value in account record."), raise_exception=1) if filters.get("report_date"): if upto_report_date: diff --git a/accounts/report/payment_collection_with_ageing/payment_collection_with_ageing.py b/accounts/report/payment_collection_with_ageing/payment_collection_with_ageing.py index 50f74e0e82..12688525c6 100644 --- a/accounts/report/payment_collection_with_ageing/payment_collection_with_ageing.py +++ b/accounts/report/payment_collection_with_ageing/payment_collection_with_ageing.py @@ -16,6 +16,7 @@ from __future__ import unicode_literals import webnotes +from webnotes import msgprint, _ from accounts.report.accounts_receivable.accounts_receivable import get_ageing_data def execute(filters=None): @@ -55,13 +56,16 @@ def get_conditions(filters): customer_accounts = [] if filters.get("account"): customer_accounts = [filters["account"]] - elif filters.get("company"): + else: + cond = filters.get("company") and (" and company = '%s'" % filters["company"]) or "" customer_accounts = webnotes.conn.sql_list("""select name from `tabAccount` - where ifnull(master_type, '') = 'Customer' and docstatus < 2 - and company = %s""", filters["company"]) + where ifnull(master_type, '') = 'Customer' and docstatus < 2 %s""" % cond) if customer_accounts: conditions += " and jvd.account in (%s)" % (", ".join(['%s']*len(customer_accounts))) + else: + msgprint(_("No Customer Accounts found. Customer Accounts are identified based on \ + 'Master Type' value in account record."), raise_exception=1) if filters.get("from_date"): conditions += " and jv.posting_date >= '%s'" % filters["from_date"] if filters.get("to_date"): conditions += " and jv.posting_date <= '%s'" % filters["to_date"] diff --git a/accounts/report/payment_made_with_ageing/__init__.py b/accounts/report/payment_made_with_ageing/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/accounts/report/payment_made_with_ageing/payment_made_with_ageing.js b/accounts/report/payment_made_with_ageing/payment_made_with_ageing.js new file mode 100644 index 0000000000..533fe614d7 --- /dev/null +++ b/accounts/report/payment_made_with_ageing/payment_made_with_ageing.js @@ -0,0 +1,40 @@ +wn.query_reports["Payment Made With Ageing"] = { + "filters": [ + { + fieldname: "from_date", + label: "From Date", + fieldtype: "Date", + default: wn.defaults.get_user_default("year_start_date"), + }, + { + fieldname:"to_date", + label: "To Date", + fieldtype: "Date", + default: get_today() + }, + { + fieldname:"account", + label: "Supplier Account", + fieldtype: "Link", + options: "Account", + get_query: function() { + return { + query: "accounts.utils.get_account_list", + filters: { + is_pl_account: "No", + debit_or_credit: "Credit", + company: wn.query_report.filters_by_name.company.get_value(), + master_type: "Supplier" + } + } + } + }, + { + fieldname:"company", + label: "Company", + fieldtype: "Link", + options: "Company", + default: sys_defaults.company + }, + ] +} \ No newline at end of file diff --git a/accounts/report/payment_made_with_ageing/payment_made_with_ageing.py b/accounts/report/payment_made_with_ageing/payment_made_with_ageing.py new file mode 100644 index 0000000000..e7f13ef121 --- /dev/null +++ b/accounts/report/payment_made_with_ageing/payment_made_with_ageing.py @@ -0,0 +1,89 @@ +# ERPNext - web based ERP (http://erpnext.com) +# Copyright (C) 2012 Web Notes Technologies Pvt Ltd +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from __future__ import unicode_literals +import webnotes +from webnotes import msgprint, _ +from accounts.report.accounts_receivable.accounts_receivable import get_ageing_data + +def execute(filters=None): + if not filters: filters = {} + + columns = get_columns() + entries = get_entries(filters) + pi_posting_date_map = get_pi_posting_date_map() + + data = [] + for d in entries: + against_voucher_date = d.against_voucher and pi_posting_date_map[d.against_voucher] or "" + + row = [d.name, d.account, d.posting_date, d.against_voucher, against_voucher_date, + d.debit, d.credit, d.cheque_no, d.cheque_date, d.remark] + + if d.against_voucher: + row += get_ageing_data(against_voucher_date, d.posting_date, d.debit or -1*d.credit) + else: + row += ["", "", "", "", ""] + + data.append(row) + + return columns, data + +def get_columns(): + return ["Journal Voucher:Link/Journal Voucher:140", "Account:Link/Account:140", + "Posting Date:Date:100", "Against Invoice:Link/Purchase Invoice:130", + "Against Invoice Posting Date:Date:130", "Debit:Currency:120", "Credit:Currency:120", + "Reference No::100", "Reference Date:Date:100", "Remarks::150", "Age:Int:40", + "0-30:Currency:100", "30-60:Currency:100", "60-90:Currency:100", "90-Above:Currency:100" + ] + +def get_conditions(filters): + conditions = "" + supplier_accounts = [] + if filters.get("account"): + supplier_accounts = [filters["account"]] + else: + cond = filters.get("company") and (" and company = '%s'" % filters["company"]) or "" + supplier_accounts = webnotes.conn.sql_list("""select name from `tabAccount` + where ifnull(master_type, '') = 'Supplier' and docstatus < 2 %s""" % cond) + + if supplier_accounts: + conditions += " and jvd.account in (%s)" % (", ".join(['%s']*len(supplier_accounts))) + else: + msgprint(_("No Supplier Accounts found. Supplier Accounts are identified based on \ + 'Master Type' value in account record."), raise_exception=1) + + if filters.get("from_date"): conditions += " and jv.posting_date >= '%s'" % filters["from_date"] + if filters.get("to_date"): conditions += " and jv.posting_date <= '%s'" % filters["to_date"] + + return conditions, supplier_accounts + +def get_entries(filters): + conditions, supplier_accounts = get_conditions(filters) + entries = webnotes.conn.sql("""select jv.name, jvd.account, jv.posting_date, + jvd.against_voucher, jvd.debit, jvd.credit, jv.cheque_no, jv.cheque_date, jv.remark + from `tabJournal Voucher Detail` jvd, `tabJournal Voucher` jv + where jvd.parent = jv.name and jv.docstatus=1 %s order by jv.name DESC""" % + (conditions), tuple(supplier_accounts), as_dict=1) + + return entries + +def get_pi_posting_date_map(): + pi_posting_date_map = {} + for t in webnotes.conn.sql("""select name, posting_date from `tabPurchase Invoice`"""): + pi_posting_date_map[t[0]] = t[1] + + return pi_posting_date_map \ No newline at end of file diff --git a/accounts/report/payment_made_with_ageing/payment_made_with_ageing.txt b/accounts/report/payment_made_with_ageing/payment_made_with_ageing.txt new file mode 100644 index 0000000000..c5c85da89a --- /dev/null +++ b/accounts/report/payment_made_with_ageing/payment_made_with_ageing.txt @@ -0,0 +1,22 @@ +[ + { + "creation": "2013-05-02 12:10:21", + "docstatus": 0, + "modified": "2013-05-02 12:10:21", + "modified_by": "Administrator", + "owner": "Administrator" + }, + { + "add_total_row": 1, + "doctype": "Report", + "is_standard": "Yes", + "name": "__common__", + "ref_doctype": "Journal Voucher", + "report_name": "Payment Made With Ageing", + "report_type": "Script Report" + }, + { + "doctype": "Report", + "name": "Payment Made With Ageing" + } +] \ No newline at end of file From f5f478ee78deee8d77f5d65ad31cecbb33aaee08 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Thu, 2 May 2013 15:36:33 +0530 Subject: [PATCH 2/2] [item] [naming] by series or code / [naming series] optionally set number of digits --- home/page/latest_updates/latest_updates.js | 4 +- .../global_defaults/global_defaults.py | 1 + .../global_defaults/global_defaults.txt | 18 ++++- setup/doctype/naming_series/naming_series.py | 9 ++- setup/doctype/naming_series/naming_series.txt | 8 +- stock/doctype/item/item.js | 6 +- stock/doctype/item/item.py | 7 ++ stock/doctype/item/item.txt | 77 ++++++++++++++++--- 8 files changed, 108 insertions(+), 22 deletions(-) diff --git a/home/page/latest_updates/latest_updates.js b/home/page/latest_updates/latest_updates.js index e11b9c9243..f254bf2349 100644 --- a/home/page/latest_updates/latest_updates.js +++ b/home/page/latest_updates/latest_updates.js @@ -1,6 +1,8 @@ erpnext.updates = [ ["2nd May", ["Buying: Warehouse must belong to same company as transaction", - "Price List": "Added Currency Field. One price list can have only one currency"]], + "Price List: Added Currency Field. One price list can have only one currency", + "Item: Naming can now be by series or item code", + "Naming Series: Set number of digits in series (optionally)"]], ["18th April", ["Cost Center: Set a default Cost Center for a Company"]], ["12th April", ["Employee: List of Leave Approvers who can approve the Employee's Leave Applications"]], ["10th April", ["Redesigned File Uploads and added File Manager in Setup"]], diff --git a/setup/doctype/global_defaults/global_defaults.py b/setup/doctype/global_defaults/global_defaults.py index 8275513dc9..191a47edf2 100644 --- a/setup/doctype/global_defaults/global_defaults.py +++ b/setup/doctype/global_defaults/global_defaults.py @@ -31,6 +31,7 @@ keydict = { 'item_group': 'default_item_group', 'customer_group': 'default_customer_group', 'cust_master_name': 'cust_master_name', + "item_naming_by": "item_naming_by", 'supplier_type': 'default_supplier_type', 'supp_master_name': 'supp_master_name', 'territory': 'default_territory', diff --git a/setup/doctype/global_defaults/global_defaults.txt b/setup/doctype/global_defaults/global_defaults.txt index 7f81618469..853bb57705 100644 --- a/setup/doctype/global_defaults/global_defaults.txt +++ b/setup/doctype/global_defaults/global_defaults.txt @@ -1,8 +1,8 @@ [ { - "creation": "2013-03-25 11:08:14", + "creation": "2013-04-01 15:05:24", "docstatus": 0, - "modified": "2013-03-28 15:41:03", + "modified": "2013-05-02 15:05:21", "modified_by": "Administrator", "owner": "Administrator" }, @@ -27,8 +27,6 @@ "permlevel": 0 }, { - "amend": 0, - "cancel": 0, "create": 1, "doctype": "DocPerm", "name": "__common__", @@ -167,6 +165,13 @@ "read_only": 0, "width": "50%" }, + { + "doctype": "DocField", + "fieldname": "item_naming_by", + "fieldtype": "Select", + "label": "Item Naming By", + "options": "Item Code\nNaming Series" + }, { "doctype": "DocField", "fieldname": "default_item_group", @@ -502,6 +507,11 @@ "label": "SMS Sender Name", "read_only": 0 }, + { + "amend": 0, + "cancel": 0, + "doctype": "DocPerm" + }, { "doctype": "DocPerm" } diff --git a/setup/doctype/naming_series/naming_series.py b/setup/doctype/naming_series/naming_series.py index 7b804f8a96..3a6b36d1ff 100644 --- a/setup/doctype/naming_series/naming_series.py +++ b/setup/doctype/naming_series/naming_series.py @@ -123,7 +123,14 @@ class DocType: def validate_series_name(self, n): import re - if not re.match('[a-zA-Z0-9]+(([-/][a-zA-Z0-9])?[-/][a-zA-Z0-9]*)*',n): + if "." in n: + parts = n.split(".") + if len(parts) > 2: + msgprint("Only one dot (.) allowed in " + n, raise_exception=1) + if not re.match("#+$", parts[-1]): + msgprint("Numbering series must be in hashes (e.g. ####)", raise_exception=1) + n = n[0] + if not re.match("^[a-zA-Z0-9-/]*$", n): msgprint('Special Characters except "-" and "/" not allowed in naming series') raise Exception diff --git a/setup/doctype/naming_series/naming_series.txt b/setup/doctype/naming_series/naming_series.txt index 3de9e5cfab..0dab9e970d 100644 --- a/setup/doctype/naming_series/naming_series.txt +++ b/setup/doctype/naming_series/naming_series.txt @@ -1,8 +1,8 @@ [ { - "creation": "2013-01-10 16:34:23", + "creation": "2013-01-25 11:35:08", "docstatus": 0, - "modified": "2013-01-22 14:56:34", + "modified": "2013-05-02 15:34:41", "modified_by": "Administrator", "owner": "Administrator" }, @@ -25,8 +25,6 @@ "permlevel": 0 }, { - "amend": 0, - "cancel": 0, "create": 1, "doctype": "DocPerm", "name": "__common__", @@ -62,7 +60,7 @@ "fieldname": "help_html", "fieldtype": "HTML", "label": "Help HTML", - "options": "
\nEdit list of Series in the box below. Each Series Prefix on a new line.

\nAllowed special characters are \"/\" and \"-\"
\nExamples:
\nINV-
\nINV-10-
\nINVK-
\n
" + "options": "
\nEdit list of Series in the box below. Rules:\n
    \n
  • Each Series Prefix on a new line.
  • \n
  • Allowed special characters are \"/\" and \"-\"
  • \n
  • Optionally, set the number of digits in the series using dot (.) followed by hashes (#). For example, \".####\" means that the series will have four digits. Default is five digits.
  • \n
\nExamples:
\nINV-
\nINV-10-
\nINVK-
\nINV-.####
\n
" }, { "doctype": "DocField", diff --git a/stock/doctype/item/item.js b/stock/doctype/item/item.js index 2635f3e904..a344ad3ce9 100644 --- a/stock/doctype/item/item.js +++ b/stock/doctype/item/item.js @@ -20,7 +20,11 @@ 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 - cur_frm.toggle_enable("item_code", doc.__islocal); + cur_frm.toggle_display("naming_series", sys_defaults.item_naming_by=="Naming Series" + && doc.__islocal) + cur_frm.toggle_display("item_code", sys_defaults.item_naming_by!="Naming Series" + && doc.__islocal) + if ((!doc.__islocal) && (doc.is_stock_item == 'Yes')) { var callback = function(r, rt) { diff --git a/stock/doctype/item/item.py b/stock/doctype/item/item.py index 8a804d8c13..63275047ad 100644 --- a/stock/doctype/item/item.py +++ b/stock/doctype/item/item.py @@ -27,6 +27,13 @@ from webnotes.model.controller import DocListController class PriceListCurrencyMismatch(Exception): pass class DocType(DocListController): + def autoname(self): + if webnotes.conn.get_default("item_naming_by")=="Naming Series": + from webnotes.model.doc import make_autoname + self.doc.item_code = make_autoname(self.doc.naming_series+'.#####') + + self.doc.name = self.doc.item_code + def validate(self): if not self.doc.stock_uom: msgprint(_("Please enter Default Unit of Measure"), raise_exception=1) diff --git a/stock/doctype/item/item.txt b/stock/doctype/item/item.txt index 3497402076..274719eec5 100644 --- a/stock/doctype/item/item.txt +++ b/stock/doctype/item/item.txt @@ -1,8 +1,8 @@ [ { - "creation": "2013-03-28 15:56:38", + "creation": "2013-04-25 10:56:55", "docstatus": 0, - "modified": "2013-04-23 11:44:39", + "modified": "2013-05-02 15:10:53", "modified_by": "Administrator", "owner": "Administrator" }, @@ -34,7 +34,6 @@ "parent": "Item", "parentfield": "permissions", "parenttype": "DocType", - "permlevel": 0, "read": 1, "submit": 0 }, @@ -51,6 +50,13 @@ "oldfieldtype": "Section Break", "read_only": 0 }, + { + "doctype": "DocField", + "fieldname": "naming_series", + "fieldtype": "Select", + "label": "Naming Series", + "options": "\nITEM" + }, { "description": "Item will be saved by this name in the data base.", "doctype": "DocField", @@ -877,17 +883,12 @@ "label": "Website Description", "read_only": 0 }, - { - "cancel": 1, - "create": 1, - "doctype": "DocPerm", - "role": "Material Master Manager", - "write": 1 - }, { "cancel": 0, "create": 0, "doctype": "DocPerm", + "permlevel": 1, + "report": 0, "role": "Material Manager", "write": 0 }, @@ -895,7 +896,63 @@ "cancel": 0, "create": 0, "doctype": "DocPerm", + "permlevel": 0, + "report": 1, + "role": "Material Manager", + "write": 0 + }, + { + "cancel": 0, + "create": 0, + "doctype": "DocPerm", + "permlevel": 1, + "report": 0, "role": "Material User", "write": 0 + }, + { + "cancel": 0, + "create": 0, + "doctype": "DocPerm", + "permlevel": 0, + "report": 1, + "role": "Material User", + "write": 0 + }, + { + "cancel": 1, + "create": 1, + "doctype": "DocPerm", + "permlevel": 0, + "report": 1, + "role": "Material Master Manager", + "write": 1 + }, + { + "cancel": 0, + "create": 0, + "doctype": "DocPerm", + "permlevel": 1, + "report": 0, + "role": "Material Master Manager", + "write": 0 + }, + { + "cancel": 1, + "create": 1, + "doctype": "DocPerm", + "permlevel": 0, + "report": 1, + "role": "System Manager", + "write": 1 + }, + { + "cancel": 0, + "create": 0, + "doctype": "DocPerm", + "permlevel": 1, + "report": 0, + "role": "System Manager", + "write": 0 } ] \ No newline at end of file