From 68dfc934bf4b671aae16ebe31af2b4218c6d6ed2 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Tue, 14 Apr 2015 11:56:42 -0400 Subject: [PATCH 1/7] [hotfix] [report] Received Items to be Billed --- .../received_items_to_be_billed.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/received_items_to_be_billed/received_items_to_be_billed.json b/erpnext/accounts/report/received_items_to_be_billed/received_items_to_be_billed.json index bd3be600e8..697cee019a 100644 --- a/erpnext/accounts/report/received_items_to_be_billed/received_items_to_be_billed.json +++ b/erpnext/accounts/report/received_items_to_be_billed/received_items_to_be_billed.json @@ -5,12 +5,12 @@ "doctype": "Report", "idx": 1, "is_standard": "Yes", - "modified": "2015-03-30 05:38:45.024005", + "modified": "2015-04-14 11:56:02.323769", "modified_by": "Administrator", "module": "Accounts", "name": "Received Items To Be Billed", "owner": "Administrator", - "query": "select\n `tabPurchase Receipt`.`name` as \"Purchase Receipt:Link/Purchase Receipt:120\",\n `tabPurchase Receipt`.`supplier` as \"Supplier:Link/Supplier:120\",\n\t`tabPurchase Receipt`.`posting_date` as \"Date:Date\",\n\t`tabPurchase Receipt Item`.`project_name` as \"Project\",\n\t`tabPurchase Receipt Item`.`item_code` as \"Item:Link/Item:120\",\n\t(`tabPurchase Receipt Item`.`qty` - ifnull((select sum(qty) from `tabPurchase Invoice Item` \n\t where `tabPurchase Invoice Item`.purchase_receipt = `tabPurchase Receipt`.name and\n `tabPurchase Invoice Item`.docstatus = 1 and\n\t `tabPurchase Invoice Item`.pr_detail = `tabPurchase Receipt Item`.name), 0))\n\t as \"Qty:Float:110\",\n\t(`tabPurchase Receipt Item`.`base_amount` - ifnull((select sum(base_amount) \n from `tabPurchase Invoice Item` \n where `tabPurchase Invoice Item`.purchase_receipt = `tabPurchase Receipt`.name and\n `tabPurchase Invoice Item`.docstatus = 1 and\n `tabPurchase Invoice Item`.pr_detail = `tabPurchase Receipt Item`.name), 0))\n\t as \"Amount:Currency:110\",\n\t`tabPurchase Receipt Item`.`item_name` as \"Item Name::150\",\n\t`tabPurchase Receipt Item`.`description` as \"Description::200\",\n\t`tabPurchase Receipt`.`company` as \"Company:Link/Company:\",\nfrom `tabPurchase Receipt`, `tabPurchase Receipt Item`\nwhere\n `tabPurchase Receipt`.docstatus = 1 and\n `tabPurchase Receipt`.name = `tabPurchase Receipt Item`.parent and\n (`tabPurchase Receipt Item`.qty > ifnull((select sum(qty) from `tabPurchase Invoice Item` \n where `tabPurchase Invoice Item`.purchase_receipt = `tabPurchase Receipt`.name and\n `tabPurchase Invoice Item`.docstatus=1 and \n `tabPurchase Invoice Item`.pr_detail = `tabPurchase Receipt Item`.name), 0))\norder by `tabPurchase Receipt`.`name` desc", + "query": "select\n `tabPurchase Receipt`.`name` as \"Purchase Receipt:Link/Purchase Receipt:120\",\n `tabPurchase Receipt`.`supplier` as \"Supplier:Link/Supplier:120\",\n\t`tabPurchase Receipt`.`posting_date` as \"Date:Date\",\n\t`tabPurchase Receipt Item`.`project_name` as \"Project\",\n\t`tabPurchase Receipt Item`.`item_code` as \"Item:Link/Item:120\",\n\t(`tabPurchase Receipt Item`.`qty` - ifnull((select sum(qty) from `tabPurchase Invoice Item` \n\t where `tabPurchase Invoice Item`.purchase_receipt = `tabPurchase Receipt`.name and\n `tabPurchase Invoice Item`.docstatus = 1 and\n\t `tabPurchase Invoice Item`.pr_detail = `tabPurchase Receipt Item`.name), 0))\n\t as \"Qty:Float:110\",\n\t(`tabPurchase Receipt Item`.`base_amount` - ifnull((select sum(base_amount) \n from `tabPurchase Invoice Item` \n where `tabPurchase Invoice Item`.purchase_receipt = `tabPurchase Receipt`.name and\n `tabPurchase Invoice Item`.docstatus = 1 and\n `tabPurchase Invoice Item`.pr_detail = `tabPurchase Receipt Item`.name), 0))\n\t as \"Amount:Currency:110\",\n\t`tabPurchase Receipt Item`.`item_name` as \"Item Name::150\",\n\t`tabPurchase Receipt Item`.`description` as \"Description::200\",\n\t`tabPurchase Receipt`.`company` as \"Company:Link/Company:\"\nfrom `tabPurchase Receipt`, `tabPurchase Receipt Item`\nwhere\n `tabPurchase Receipt`.docstatus = 1 and\n `tabPurchase Receipt`.name = `tabPurchase Receipt Item`.parent and\n (`tabPurchase Receipt Item`.qty > ifnull((select sum(qty) from `tabPurchase Invoice Item` \n where `tabPurchase Invoice Item`.purchase_receipt = `tabPurchase Receipt`.name and\n `tabPurchase Invoice Item`.docstatus=1 and \n `tabPurchase Invoice Item`.pr_detail = `tabPurchase Receipt Item`.name), 0))\norder by `tabPurchase Receipt`.`name` desc", "ref_doctype": "Purchase Invoice", "report_name": "Received Items To Be Billed", "report_type": "Query Report" From c3daa91c8a0fe56ecbd3508970008fbc5aac9c1d Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 16 Apr 2015 13:13:18 +0530 Subject: [PATCH 2/7] Reset no-copy fields for recurring docs and patch to fix --- .../doctype/purchase_order/purchase_order.py | 11 +++++ erpnext/patches.txt | 3 +- erpnext/patches/v4_2/fix_recurring_orders.py | 41 +++++++++++++++++++ .../doctype/sales_order/sales_order.py | 11 +++++ 4 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 erpnext/patches/v4_2/fix_recurring_orders.py diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 09f303f6aa..6a06d24b46 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -198,6 +198,17 @@ class PurchaseOrder(BuyingController): def on_update(self): pass + def before_recurring(self): + super(PurchaseOrder, self).before_recurring() + + for field in ("per_received", "per_billed"): + self.set(field, None) + + for d in self.get("po_details"): + for field in ("received_qty", "billed_amt", "prevdoc_doctype", "prevdoc_docname", + "prevdoc_detail_docname", "supplier_quotation", "supplier_quotation_item"): + d.set(field, None) + def set_missing_values(source, target): target.ignore_pricing_rule = 1 target.run_method("set_missing_values") diff --git a/erpnext/patches.txt b/erpnext/patches.txt index e3437a56f5..6e84b7bb6d 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -95,4 +95,5 @@ erpnext.patches.v4_2.update_landed_cost_voucher erpnext.patches.v4_2.set_item_has_batch erpnext.patches.v4_2.update_stock_uom_for_dn_in_sle erpnext.patches.v4_2.repost_reserved_qty -erpnext.patches.v4_2.repost_sle_for_si_with_no_warehouse \ No newline at end of file +erpnext.patches.v4_2.repost_sle_for_si_with_no_warehouse +erpnext.patches.v4_2.fix_recurring_orders \ No newline at end of file diff --git a/erpnext/patches/v4_2/fix_recurring_orders.py b/erpnext/patches/v4_2/fix_recurring_orders.py new file mode 100644 index 0000000000..ea1724a040 --- /dev/null +++ b/erpnext/patches/v4_2/fix_recurring_orders.py @@ -0,0 +1,41 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + sales_orders = frappe.db.sql("""select name from `tabSales Order` + where docstatus = 1 and ifnull(is_recurring, 0) = 1 + and (per_delivered > 0 or per_billed > 0)""", as_dict=1) + + for so in sales_orders: + if not frappe.db.exists("Delivery Note Item", {"against_sales_order": so.name, "docstatus": 1}): + frappe.db.sql("""update `tabSales Order` set per_delivered = 0, + delivery_status = 'Not Delivered' where name = %s""", so.name) + frappe.db.sql("""update `tabSales Order Item` set delivered_qty = 0 + where parent = %s""", so.name) + + if not frappe.db.exists("Sales Invoice Item", {"sales_order": so.name, "docstatus": 1}): + frappe.db.sql("""update `tabSales Order` set per_billed = 0, + billing_status = 'Not Billed' where name = %s""", so.name) + frappe.db.sql("""update `tabSales Order Item` set billed_amt = 0 + where parent = %s""", so.name) + + purchase_orders = frappe.db.sql("""select name from `tabPurchase Order` + where docstatus = 1 and ifnull(is_recurring, 0) = 1 + and (per_received > 0 or per_billed > 0)""", as_dict=1) + + for po in purchase_orders: + if not frappe.db.exists("Purchase Receipt Item", {"prevdoc_doctype": "Purchase Order", + "prevdoc_docname": po.name, "docstatus": 1}): + frappe.db.sql("""update `tabPurchase Order` set per_received = 0 + where name = %s""", po.name) + frappe.db.sql("""update `tabPurchase Order Item` set received_qty = 0 + where parent = %s""", po.name) + + if not frappe.db.exists("Purchase Invoice Item", {"purchase_order": po.name, "docstatus": 1}): + frappe.db.sql("""update `tabPurchase Order` set per_billed = 0 + where name = %s""", po.name) + frappe.db.sql("""update `tabPurchase Order Item` set billed_amt = 0 + where parent = %s""", po.name) \ No newline at end of file diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 5b0f7e9708..040b999afb 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -249,6 +249,17 @@ class SalesOrder(SellingController): def get_portal_page(self): return "order" if self.docstatus==1 else None + def before_recurring(self): + super(SalesOrder, self).before_recurring() + + for field in ("delivery_status", "per_delivered", "billing_status", "per_billed"): + self.set(field, None) + + for d in self.get("sales_order_details"): + for field in ("delivered_qty", "billed_amt", "planned_qty", "prevdoc_docname"): + d.set(field, None) + + @frappe.whitelist() def make_material_request(source_name, target_doc=None): def postprocess(source, doc): From 2029ea9abf2864a0a8c3c8e18b62e2e543451be1 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 16 Apr 2015 17:55:35 +0530 Subject: [PATCH 3/7] toggle editable price list rate --- erpnext/selling/sales_common.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index 117232dc2c..585872e9c7 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -17,7 +17,6 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ onload: function() { this._super(); this.setup_queries(); - this.toggle_editable_price_list_rate(); }, onload_post_render: function() { @@ -104,6 +103,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ var packing_list_exists = (this.frm.doc.packing_details || []).length; this.frm.toggle_display("packing_list", packing_list_exists ? true : false); } + this.toggle_editable_price_list_rate(); }, customer: function() { From 1a6299176aa699f4920734b9cae74025d4ffc408 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 16 Apr 2015 19:22:42 +0530 Subject: [PATCH 4/7] delete gl entries on cancellation of sales invoice, if grand total is zero --- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 8b23115e9a..9d1769b723 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -464,7 +464,7 @@ class SalesInvoice(SellingController): def make_gl_entries(self, repost_future_gle=True): gl_entries = self.get_gl_entries() - + if gl_entries: from erpnext.accounts.general_ledger import make_gl_entries @@ -481,6 +481,10 @@ class SalesInvoice(SellingController): and cint(frappe.defaults.get_global_default("auto_accounting_for_stock")): items, warehouses = self.get_items_and_warehouses() update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items) + elif self.docstatus == 2 and cint(self.update_stock) \ + and cint(frappe.defaults.get_global_default("auto_accounting_for_stock")): + from erpnext.accounts.general_ledger import delete_gl_entries + delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name) def get_gl_entries(self, warehouse_account=None): from erpnext.accounts.general_ledger import merge_similar_entries @@ -509,7 +513,7 @@ class SalesInvoice(SellingController): "debit": self.grand_total, "remarks": self.remarks, "against_voucher": self.name, - "against_voucher_type": self.doctype, + "against_voucher_type": self.doctype }) ) @@ -543,6 +547,7 @@ class SalesInvoice(SellingController): # expense account gl entries if cint(frappe.defaults.get_global_default("auto_accounting_for_stock")) \ and cint(self.update_stock): + gl_entries += super(SalesInvoice, self).get_gl_entries() def make_pos_gl_entries(self, gl_entries): From 2ba88c4a5fd7f28f4e141921982c37fec63b2687 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 17 Apr 2015 12:05:00 +0530 Subject: [PATCH 5/7] patch: delete gle for cancelled invoices --- erpnext/patches.txt | 3 ++- .../delete_gl_entries_for_cancelled_invoices.py | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 erpnext/patches/v4_2/delete_gl_entries_for_cancelled_invoices.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 6e84b7bb6d..60df4ce6d9 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -96,4 +96,5 @@ erpnext.patches.v4_2.set_item_has_batch erpnext.patches.v4_2.update_stock_uom_for_dn_in_sle erpnext.patches.v4_2.repost_reserved_qty erpnext.patches.v4_2.repost_sle_for_si_with_no_warehouse -erpnext.patches.v4_2.fix_recurring_orders \ No newline at end of file +erpnext.patches.v4_2.fix_recurring_orders +erpnext.patches.v4_2.delete_gl_entries_for_cancelled_invoices diff --git a/erpnext/patches/v4_2/delete_gl_entries_for_cancelled_invoices.py b/erpnext/patches/v4_2/delete_gl_entries_for_cancelled_invoices.py new file mode 100644 index 0000000000..0e7796a666 --- /dev/null +++ b/erpnext/patches/v4_2/delete_gl_entries_for_cancelled_invoices.py @@ -0,0 +1,13 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + cancelled_invoices = frappe.db.sql_list("""select name from `tabSales Invoice` + where docstatus = 2 and ifnull(update_stock, 0) = 1""") + + frappe.db.sql("""delete from `tabGL Entry` + where voucher_type = 'Sales Invoice' and voucher_no in (%s)""" + % (', '.join(['%s']*len(cancelled_invoices))), tuple(cancelled_invoices)) \ No newline at end of file From 4743cbe002f286e1dcc8e42dd4e534079f24f11f Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 17 Apr 2015 15:55:19 +0530 Subject: [PATCH 6/7] issue fixed in accounts receivable report --- .../accounts_receivable/accounts_receivable.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index a546799a5d..0fd41f426d 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -135,23 +135,23 @@ class AccountsReceivableReport(object): def prepare_conditions(self): conditions = [""] - values = {} + values = [] if self.filters.company: - conditions.append("company=%(company)s") - values["company"] = self.filters.company + conditions.append("company=%s") + values.append(self.filters.company) if self.filters.account: - conditions.append("account=%(account)s") - values["account"] = self.filters.account + conditions.append("account=%s") + values.apppend(self.filters.account) else: account_map = self.get_account_map() if not account_map: frappe.throw(_("No Customer Accounts found.")) else: - accounts_list = ["'{0}'".format(frappe.db.escape(ac)) for ac in account_map] - conditions.append("account in ({0})".format(", ".join(accounts_list))) - + conditions.append("account in ({0})".format(", ".join(["%s"] * len(account_map)))) + values += account_map.keys() + return " and ".join(conditions), values def get_gl_entries_for(self, account, against_voucher_type, against_voucher): From e7eb92ce7014dc99cd7c8c3a80812e91e9785f78 Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Fri, 17 Apr 2015 16:32:11 +0600 Subject: [PATCH 7/7] bumped to version 4.25.0 --- erpnext/__version__.py | 2 +- erpnext/hooks.py | 2 +- setup.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/__version__.py b/erpnext/__version__.py index 31f0e77b85..44a6b216e7 100644 --- a/erpnext/__version__.py +++ b/erpnext/__version__.py @@ -1,2 +1,2 @@ from __future__ import unicode_literals -__version__ = '4.24.4' +__version__ = '4.25.0' diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 80174239a4..0896777186 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -5,7 +5,7 @@ app_publisher = "Web Notes Technologies Pvt. Ltd. and Contributors" app_description = "Open Source Enterprise Resource Planning for Small and Midsized Organizations" app_icon = "icon-th" app_color = "#e74c3c" -app_version = "4.24.4" +app_version = "4.25.0" error_report_email = "support@erpnext.com" diff --git a/setup.py b/setup.py index 4efe4d2d64..ecb2e6e0ee 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ from setuptools import setup, find_packages import os -version = "4.24.4" +version = "4.25.0" with open("requirements.txt", "r") as f: install_requires = f.readlines()