From 2f1db57fe1b048a07e970d295bab90d210e80e7f Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Tue, 8 Nov 2016 12:39:33 +0530 Subject: [PATCH] Added status field in sales invoice and purchase invoice --- erpnext/accounts/doctype/gl_entry/gl_entry.py | 1 + .../purchase_invoice/purchase_invoice.json | 31 ++++++++++++++++++- .../purchase_invoice/purchase_invoice.py | 2 ++ .../doctype/sales_invoice/sales_invoice.json | 31 ++++++++++++++++++- .../doctype/sales_invoice/sales_invoice.py | 2 ++ .../sales_invoice/sales_invoice_list.js | 4 +-- erpnext/controllers/accounts_controller.py | 11 ++++++- erpnext/controllers/status_updater.py | 18 ++++++++++- erpnext/hooks.py | 1 + erpnext/patches.txt | 1 + erpnext/patches/v7_1/update_invoice_status.py | 30 ++++++++++++++++++ 11 files changed, 126 insertions(+), 6 deletions(-) create mode 100644 erpnext/patches/v7_1/update_invoice_status.py diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py index fddabcb918..5773813955 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -195,6 +195,7 @@ def update_outstanding_amt(account, party_type, party, against_voucher_type, aga if against_voucher_type in ["Sales Invoice", "Purchase Invoice"]: ref_doc = frappe.get_doc(against_voucher_type, against_voucher) ref_doc.db_set('outstanding_amount', bal) + ref_doc.set_status(update=True) def validate_frozen_account(account, adv_adj=None): frozen_account = frappe.db.get_value("Account", account, "freeze_account") diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index 01e57848ad..15468575cd 100755 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -2771,6 +2771,35 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "Draft", + "fieldname": "status", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Status", + "length": 0, + "no_copy": 0, + "options": "\nDraft\nSubmitted\nPaid\nUnpaid\nOverdue\nCancelled", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -3264,7 +3293,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2016-11-03 15:54:34.750548", + "modified": "2016-11-08 11:49:00.752417", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice", diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 22de07fa39..5c2b62cd02 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -65,6 +65,7 @@ class PurchaseInvoice(BuyingController): self.validate_fixed_asset() self.validate_fixed_asset_account() self.create_remarks() + self.set_status() def validate_cash(self): if not self.cash_bank_account and flt(self.paid_amount): @@ -596,6 +597,7 @@ class PurchaseInvoice(BuyingController): self.make_gl_entries_on_cancel() self.update_project() self.update_fixed_asset() + frappe.db.set(self, 'status', 'Cancelled') def update_project(self): project_list = [] diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index ddbd648596..b4747cecd5 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -3065,6 +3065,35 @@ "unique": 0, "width": "50%" }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "Draft", + "fieldname": "status", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 1, + "in_list_view": 0, + "label": "Status", + "length": 0, + "no_copy": 1, + "options": "\nDraft\nSubmitted\nPaid\nUnpaid\nOverdue\nCancelled", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -4010,7 +4039,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2016-11-03 15:55:41.249414", + "modified": "2016-11-08 11:47:43.494612", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 521b0eb048..4e0a6b493c 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -86,6 +86,7 @@ class SalesInvoice(SellingController): self.update_packing_list() self.set_billing_hours_and_amount() self.update_timesheet_billing_for_project() + self.set_status() def before_save(self): set_account_for_mode_of_payment(self) @@ -158,6 +159,7 @@ class SalesInvoice(SellingController): self.update_stock_ledger() self.make_gl_entries_on_cancel() + frappe.db.set(self, 'status', 'Cancelled') def update_status_updater_args(self): if cint(self.update_stock): diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice_list.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice_list.js index 55e8b211b9..5e21d7abef 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice_list.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice_list.js @@ -10,9 +10,9 @@ frappe.listview_settings['Sales Invoice'] = { return [__("Return"), "darkgrey", "is_return,=,Yes"]; } else if(flt(doc.outstanding_amount)==0) { return [__("Paid"), "green", "outstanding_amount,=,0"] - } else if (flt(doc.outstanding_amount) > 0 && doc.due_date > frappe.datetime.get_today()) { + } else if (flt(doc.outstanding_amount) > 0 && doc.due_date >= frappe.datetime.get_today()) { return [__("Unpaid"), "orange", "outstanding_amount,>,0|due_date,>,Today"] - } else if (flt(doc.outstanding_amount) > 0 && doc.due_date <= frappe.datetime.get_today()) { + } else if (flt(doc.outstanding_amount) > 0 && doc.due_date < frappe.datetime.get_today()) { return [__("Overdue"), "red", "outstanding_amount,>,0|due_date,<=,Today"] } }, diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 3d2f16b4b5..b436670141 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -720,4 +720,13 @@ def get_advance_payment_entries(party_type, party, party_account, and docstatus = 1 and unallocated_amount > 0 """.format(party_account_field), (party_account, party_type, party, payment_type), as_dict=1) - return list(payment_entries_against_order) + list(unallocated_payment_entries) \ No newline at end of file + return list(payment_entries_against_order) + list(unallocated_payment_entries) + +def update_invoice_status(): + # Daily update the status of the invoices + + frappe.db.sql(""" update `tabSales Invoice` set status = 'Overdue' + where due_date < CURDATE() and docstatus = 1 and outstanding_amount > 0""") + + frappe.db.sql(""" update `tabPurchase Invoice` set status = 'Overdue' + where due_date < CURDATE() and docstatus = 1 and outstanding_amount > 0""") \ No newline at end of file diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py index 157c385661..cb783b4db3 100644 --- a/erpnext/controllers/status_updater.py +++ b/erpnext/controllers/status_updater.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import frappe -from frappe.utils import flt, comma_or +from frappe.utils import flt, comma_or, nowdate, getdate from frappe import _ from frappe.model.document import Document from erpnext.accounts.party_status import notify_status @@ -41,6 +41,22 @@ status_map = { ["Cancelled", "eval:self.docstatus==2"], ["Closed", "eval:self.status=='Closed'"], ], + "Sales Invoice": [ + ["Draft", None], + ["Submitted", "eval:self.docstatus==1"], + ["Paid", "eval:self.outstanding_amount==0 and self.docstatus==1"], + ["Unpaid", "eval:self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.docstatus==1"], + ["Overdue", "eval:self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.docstatus==1"], + ["Cancelled", "eval:self.docstatus==2"], + ], + "Purchase Invoice": [ + ["Draft", None], + ["Submitted", "eval:self.docstatus==1"], + ["Paid", "eval:self.outstanding_amount==0 and self.docstatus==1"], + ["Unpaid", "eval:self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.docstatus==1"], + ["Overdue", "eval:self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.docstatus==1"], + ["Cancelled", "eval:self.docstatus==2"], + ], "Purchase Order": [ ["Draft", None], ["To Receive and Bill", "eval:self.per_received < 100 and self.per_billed < 100 and self.docstatus == 1"], diff --git a/erpnext/hooks.py b/erpnext/hooks.py index cef798b58c..90c7f51824 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -189,6 +189,7 @@ scheduler_events = { "erpnext.stock.reorder_item.reorder_item", "erpnext.setup.doctype.email_digest.email_digest.send", "erpnext.support.doctype.issue.issue.auto_close_tickets", + "erpnext.controllers.accounts_controller.update_invoice_status", "erpnext.accounts.doctype.fiscal_year.fiscal_year.auto_create_fiscal_year", "erpnext.hr.doctype.employee.employee.send_birthday_reminders", "erpnext.projects.doctype.task.task.set_tasks_as_overdue", diff --git a/erpnext/patches.txt b/erpnext/patches.txt index b53bbc64eb..57dbc59839 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -346,3 +346,4 @@ execute:frappe.db.sql("update `tabStock Entry` set total_amount = null where pur erpnext.patches.v7_0.repost_gle_for_pi_with_update_stock #2016-11-01 erpnext.patches.v7_1.add_account_user_role_for_timesheet erpnext.patches.v7_0.set_base_amount_in_invoice_payment_table +erpnext.patches.v7_1.update_invoice_status \ No newline at end of file diff --git a/erpnext/patches/v7_1/update_invoice_status.py b/erpnext/patches/v7_1/update_invoice_status.py new file mode 100644 index 0000000000..5a2d013f31 --- /dev/null +++ b/erpnext/patches/v7_1/update_invoice_status.py @@ -0,0 +1,30 @@ +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + frappe.reload_doc('accounts', 'doctype', 'sales_invoice') + frappe.reload_doc('accounts', 'doctype', 'purchase_invoice') + + frappe.db.sql(""" + update + `tabPurchase Invoice` + set + status = (Case When outstanding_amount = 0 and docstatus = 1 then 'Paid' + when due_date < CURDATE() and outstanding_amount > 0 and docstatus =1 then 'Overdue' + when due_date >= CURDATE() and outstanding_amount > 0 and docstatus =1 then 'Unpaid' + when docstatus = 2 then 'Cancelled' + else 'Draft' + End)""") + + frappe.db.sql(""" + update + `tabSales Invoice` + set status = (Case When outstanding_amount = 0 and docstatus = 1 then 'Paid' + when due_date < CURDATE() and outstanding_amount > 0 and docstatus =1 then 'Overdue' + when due_date >= CURDATE() and outstanding_amount > 0 and docstatus =1 then 'Unpaid' + when docstatus = 2 then 'Cancelled' + else 'Draft' + End)""") \ No newline at end of file