Ability to hold payment for disputed invoices #12048 (#13298)

* add new fields to Supplier Master:
- on_hold: To signal the Customer is blocked from completing certain transactions
- hold_type: 3 options - All, invoices and payments

* sanitize `on_hold` field input

* show hold status in list view

* add `release_date` field to Supplier Master:
- specifies the date when transaction restraint will be removed

* reset release date if supplier is not on hold

* add validation to stop transactions when Supplier is blocked

* add test cases

* return empty list for outstanding references if supplier is blocked

* block make button:payment if supplier is blocked

* adjust test cases

* PEP 8 clean up

* more tests

* adds new fields to Purchase Invoice:
- release_date: once set, invoice will be on hold until set date
- hold_comment: so user can add comment pertaining to why invoice is on hold

* implement individual purchase invoice on hold logic

* allow user to change release date

* update manual

* final cleanup including more validation and tests

* update supplier manual

* make default for release_date argument todays date

* remove Auto Repeat added by mistake

* add on_hold_field to purchase invoice

* add 'On Hold' or 'Temporarily on Hold' status for purchase invoice in list view

* implement explicit payment hold in purchase invoice

* update manual

* add dialog for saving comment

* bug fix, refactor, clean up

* more test cases
This commit is contained in:
tundebabzy
2018-05-16 07:01:41 +01:00
committed by Rushabh Mehta
parent 1906cadd94
commit ad08d4ce96
16 changed files with 865 additions and 38 deletions

View File

@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe, erpnext
from frappe import _, throw
from frappe.utils import today, flt, cint, fmt_money, formatdate, getdate, add_days, add_months, get_last_day
from frappe.utils import today, flt, cint, fmt_money, formatdate, getdate, add_days, add_months, get_last_day, nowdate
from erpnext.setup.utils import get_exchange_rate
from erpnext.accounts.utils import get_fiscal_years, validate_fiscal_year, get_account_currency
from erpnext.utilities.transaction_base import TransactionBase
@@ -36,10 +36,29 @@ class AccountsController(TransactionBase):
if self.doctype in relevant_docs:
self.set_payment_schedule()
def ensure_supplier_is_not_blocked(self):
is_supplier_payment = self.doctype == 'Payment Entry' and self.party_type == 'Supplier'
is_buying_invoice = self.doctype in ['Purchase Invoice', 'Purchase Order']
supplier = None
supplier_name = None
if is_buying_invoice or is_supplier_payment:
supplier_name = self.supplier if is_buying_invoice else self.party
supplier = frappe.get_doc('Supplier', supplier_name)
if supplier and supplier_name and supplier.on_hold:
if (is_buying_invoice and supplier.hold_type in ['All', 'Invoices']) or \
(is_supplier_payment and supplier.hold_type in ['All', 'Payments']):
if not supplier.release_date or getdate(nowdate()) <= supplier.release_date:
frappe.msgprint(
_('{0} is blocked so this transaction cannot proceed'.format(supplier_name)), raise_exception=1)
def validate(self):
if self.get("_action") and self._action != "update_after_submit":
self.set_missing_values(for_validate=True)
self.ensure_supplier_is_not_blocked()
self.validate_date_with_fiscal_year()
if self.meta.get_field("currency"):
@@ -969,3 +988,18 @@ def get_due_date(term, posting_date=None, bill_date=None):
elif term.due_date_based_on == "Month(s) after the end of the invoice month":
due_date = add_months(get_last_day(date), term.credit_months)
return due_date
def get_supplier_block_status(party_name):
"""
Returns a dict containing the values of `on_hold`, `release_date` and `hold_type` of
a `Supplier`
"""
supplier = frappe.get_doc('Supplier', party_name)
info = {
'on_hold': supplier.on_hold,
'release_date': supplier.release_date,
'hold_type': supplier.hold_type
}
return info