diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 9845dd2c68..152584976b 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals import frappe -__version__ = '7.1.8' +__version__ = '7.1.9' def get_default_company(user=None): '''Get default company for user''' 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 13456da1d4..0c8d1ac786 100755 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -2870,6 +2870,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\nReturn\nDebit Note Issued\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, @@ -3380,7 +3409,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2016-11-07 05:56:20.055208", + "modified": "2016-11-09 14:18:47.094777", "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/purchase_invoice/purchase_invoice_list.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice_list.js index afcd61f228..8283acc4f1 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice_list.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice_list.js @@ -14,7 +14,9 @@ frappe.listview_settings['Purchase Invoice'] = { } else { return [__("Unpaid"), "orange", "outstanding_amount,>,0|due,>=,Today"]; } - } else if(flt(doc.outstanding_amount)==0 && doc.docstatus==1) { + } else if(flt(doc.outstanding_amount) < 0 && doc.docstatus == 1) { + return [__("Debit Note Issued"), "darkgrey", "outstanding_amount,<,0"] + }else if(flt(doc.outstanding_amount)==0 && doc.docstatus==1) { return [__("Paid"), "green", "outstanding_amount,=,0"]; } } diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index 4dfe79061b..602eabca52 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -3175,6 +3175,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\nReturn\nCredit Note Issued\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, @@ -4153,7 +4182,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2016-11-07 05:38:56.281432", + "modified": "2016-11-09 14:18:24.760263", "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..3c9c4b428d 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice_list.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice_list.js @@ -10,9 +10,11 @@ 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) { + return [__("Credit Note Issued"), "darkgrey", "outstanding_amount,<,0"] + }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..fcddc8fb3d 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,26 @@ status_map = { ["Cancelled", "eval:self.docstatus==2"], ["Closed", "eval:self.status=='Closed'"], ], + "Sales Invoice": [ + ["Draft", None], + ["Submitted", "eval:self.docstatus==1"], + ["Return", "eval:self.is_return==1 and self.docstatus==1"], + ["Credit Note Issued", "eval:self.outstanding_amount < 0 and self.docstatus==1"], + ["Paid", "eval:self.outstanding_amount==0 and self.docstatus==1 and self.is_return==0"], + ["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"], + ["Return", "eval:self.is_return==1 and self.docstatus==1"], + ["Debit Note Issued", "eval:self.outstanding_amount < 0 and self.docstatus==1"], + ["Paid", "eval:self.outstanding_amount==0 and self.docstatus==1 and self.is_return==0"], + ["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 7f402f7071..4a984704a1 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 04e5bfce6a..db5ccd18d1 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -346,3 +346,5 @@ execute:frappe.db.sql("update `tabStock Entry` set total_amount = null where pur erpnext.patches.v7_1.save_stock_settings 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 diff --git a/erpnext/patches/v7_0/set_base_amount_in_invoice_payment_table.py b/erpnext/patches/v7_0/set_base_amount_in_invoice_payment_table.py new file mode 100644 index 0000000000..89ce43bfa3 --- /dev/null +++ b/erpnext/patches/v7_0/set_base_amount_in_invoice_payment_table.py @@ -0,0 +1,23 @@ +from __future__ import unicode_literals +import frappe +from frappe.utils import flt + +def execute(): + si_list = frappe.db.sql(""" + select distinct parent + from `tabSales Invoice Payment` + where docstatus!=2 and amount != 0 and base_amount = 0 + """) + + count = 0 + for d in si_list: + si = frappe.get_doc("Sales Invoice", d[0]) + for p in si.get("payments"): + if p.amount and not p.base_amount: + base_amount = flt(p.amount*si.conversion_rate, si.precision("base_paid_amount")) + frappe.db.set_value("Sales Invoice Payment", p.name, "base_amount", base_amount, update_modified=False) + + count +=1 + + if count % 200 == 0: + frappe.db.commit() \ 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..851af80f7a --- /dev/null +++ b/erpnext/patches/v7_1/update_invoice_status.py @@ -0,0 +1,34 @@ +# 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 and is_return = 0 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 outstanding_amount < 0 and docstatus =1 then 'Debit Note Issued' + when is_return = 1 and docstatus =1 then 'Return' + when docstatus = 2 then 'Cancelled' + else 'Draft' + End)""") + + frappe.db.sql(""" + update + `tabSales Invoice` + set status = (Case When outstanding_amount = 0 and docstatus = 1 and is_return = 0 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 outstanding_amount < 0 and docstatus =1 then 'Credit Note Issued' + when is_return = 1 and docstatus =1 then 'Return' + when docstatus = 2 then 'Cancelled' + else 'Draft' + End)""") \ No newline at end of file