Merge pull request #6657 from rohitwaghchaure/invoice_unlink_feature

[Feature] Provision to allow unlink the payment against the invoice
This commit is contained in:
Nabin Hait 2016-10-20 16:36:57 +05:30 committed by GitHub
commit 725b547641
7 changed files with 104 additions and 8 deletions

View File

@ -10,6 +10,7 @@
"doctype": "DocType", "doctype": "DocType",
"document_type": "Other", "document_type": "Other",
"editable_grid": 1, "editable_grid": 1,
"engine": "InnoDB",
"fields": [ "fields": [
{ {
"allow_on_submit": 0, "allow_on_submit": 0,
@ -194,6 +195,33 @@
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "1",
"fieldname": "unlink_payment_on_cancellation_of_invoice",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Unlink Payment on Cancellation of Invoice",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
} }
], ],
"hide_heading": 0, "hide_heading": 0,
@ -207,8 +235,8 @@
"issingle": 1, "issingle": 1,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2016-10-05 16:13:10.978208", "modified": "2016-10-20 16:12:38.595075",
"modified_by": "rohitw1991@gmail.com", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Accounts Settings", "name": "Accounts Settings",
"owner": "Administrator", "owner": "Administrator",

View File

@ -578,7 +578,8 @@ class PurchaseInvoice(BuyingController):
if not self.is_return: if not self.is_return:
from erpnext.accounts.utils import unlink_ref_doc_from_payment_entries from erpnext.accounts.utils import unlink_ref_doc_from_payment_entries
unlink_ref_doc_from_payment_entries(self.doctype, self.name) if frappe.db.get_single_value('Accounts Settings', 'unlink_payment_on_cancellation_of_invoice'):
unlink_ref_doc_from_payment_entries(self.doctype, self.name)
self.update_prevdoc_status() self.update_prevdoc_status()
self.update_billing_status_for_zero_amount_refdoc("Purchase Order") self.update_billing_status_for_zero_amount_refdoc("Purchase Order")

View File

@ -6,7 +6,7 @@ from __future__ import unicode_literals
import unittest import unittest
import frappe import frappe
import frappe.model import frappe.model
from frappe.utils import cint, flt, today from frappe.utils import cint, flt, today, nowdate
import frappe.defaults import frappe.defaults
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory, \ from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory, \
test_records as pr_test_records test_records as pr_test_records
@ -17,6 +17,12 @@ test_dependencies = ["Item", "Cost Center"]
test_ignore = ["Serial No"] test_ignore = ["Serial No"]
class TestPurchaseInvoice(unittest.TestCase): class TestPurchaseInvoice(unittest.TestCase):
def setUp(self):
unlink_payment_on_cancel_of_invoice()
def tearDown(self):
unlink_payment_on_cancel_of_invoice(0)
def test_gl_entries_without_auto_accounting_for_stock(self): def test_gl_entries_without_auto_accounting_for_stock(self):
set_perpetual_inventory(0) set_perpetual_inventory(0)
self.assertTrue(not cint(frappe.defaults.get_global_default("auto_accounting_for_stock"))) self.assertTrue(not cint(frappe.defaults.get_global_default("auto_accounting_for_stock")))
@ -55,6 +61,27 @@ class TestPurchaseInvoice(unittest.TestCase):
set_perpetual_inventory(0) set_perpetual_inventory(0)
def test_payment_entry_unlink_against_purchase_invoice(self):
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
unlink_payment_on_cancel_of_invoice(0)
pi_doc = make_purchase_invoice()
pe = get_payment_entry("Purchase Invoice", pi_doc.name, bank_account="_Test Bank - _TC")
pe.reference_no = "1"
pe.reference_date = nowdate()
pe.paid_from_account_currency = pi_doc.currency
pe.paid_to_account_currency = pi_doc.currency
pe.source_exchange_rate = 1
pe.target_exchange_rate = 1
pe.paid_amount = pi_doc.grand_total
pe.save(ignore_permissions=True)
pe.submit()
pi_doc = frappe.get_doc('Purchase Invoice', pi_doc.name)
self.assertRaises(frappe.LinkExistsError, pi_doc.cancel)
def test_gl_entries_with_auto_accounting_for_stock_against_pr(self): def test_gl_entries_with_auto_accounting_for_stock_against_pr(self):
set_perpetual_inventory(1) set_perpetual_inventory(1)
self.assertEqual(cint(frappe.defaults.get_global_default("auto_accounting_for_stock")), 1) self.assertEqual(cint(frappe.defaults.get_global_default("auto_accounting_for_stock")), 1)
@ -411,6 +438,11 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertEquals(frappe.db.get_value("Serial No", pi.get("items")[0].rejected_serial_no, self.assertEquals(frappe.db.get_value("Serial No", pi.get("items")[0].rejected_serial_no,
"warehouse"), pi.get("items")[0].rejected_warehouse) "warehouse"), pi.get("items")[0].rejected_warehouse)
def unlink_payment_on_cancel_of_invoice(enable=1):
accounts_settings = frappe.get_doc("Accounts Settings")
accounts_settings.unlink_payment_on_cancellation_of_invoice = enable
accounts_settings.save()
def make_purchase_invoice(**args): def make_purchase_invoice(**args):
pi = frappe.new_doc("Purchase Invoice") pi = frappe.new_doc("Purchase Invoice")
args = frappe._dict(args) args = frappe._dict(args)

View File

@ -136,7 +136,8 @@ class SalesInvoice(SellingController):
self.check_close_sales_order("sales_order") self.check_close_sales_order("sales_order")
from erpnext.accounts.utils import unlink_ref_doc_from_payment_entries from erpnext.accounts.utils import unlink_ref_doc_from_payment_entries
unlink_ref_doc_from_payment_entries(self.doctype, self.name) if frappe.db.get_single_value('Accounts Settings', 'unlink_payment_on_cancellation_of_invoice'):
unlink_ref_doc_from_payment_entries(self.doctype, self.name)
if self.is_return: if self.is_return:
# NOTE status updating bypassed for is_return # NOTE status updating bypassed for is_return

View File

@ -4,8 +4,9 @@ from __future__ import unicode_literals
import frappe import frappe
import unittest, copy import unittest, copy
from frappe.utils import nowdate, add_days, flt from frappe.utils import nowdate, add_days, flt, nowdate
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import unlink_payment_on_cancel_of_invoice
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
from erpnext.exceptions import InvalidAccountCurrency, InvalidCurrency from erpnext.exceptions import InvalidAccountCurrency, InvalidCurrency
from erpnext.stock.doctype.serial_no.serial_no import SerialNoWarehouseError from erpnext.stock.doctype.serial_no.serial_no import SerialNoWarehouseError
@ -19,6 +20,12 @@ class TestSalesInvoice(unittest.TestCase):
w.submit() w.submit()
return w return w
def setUp(self):
unlink_payment_on_cancel_of_invoice()
def tearDown(self):
unlink_payment_on_cancel_of_invoice(0)
def test_timestamp_change(self): def test_timestamp_change(self):
w = frappe.copy_doc(test_records[0]) w = frappe.copy_doc(test_records[0])
w.docstatus = 0 w.docstatus = 0
@ -78,6 +85,28 @@ class TestSalesInvoice(unittest.TestCase):
self.assertEquals(si.base_grand_total, 1627.05) self.assertEquals(si.base_grand_total, 1627.05)
self.assertEquals(si.grand_total, 1627.05) self.assertEquals(si.grand_total, 1627.05)
def test_payment_entry_unlink_against_invoice(self):
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
si = frappe.copy_doc(test_records[0])
si.is_pos = 0
si.insert()
si.submit()
pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank - _TC")
pe.reference_no = "1"
pe.reference_date = nowdate()
pe.paid_from_account_currency = si.currency
pe.paid_to_account_currency = si.currency
pe.source_exchange_rate = 1
pe.target_exchange_rate = 1
pe.paid_amount = si.grand_total
pe.insert()
pe.submit()
unlink_payment_on_cancel_of_invoice(0)
si = frappe.get_doc('Sales Invoice', si.name)
self.assertRaises(frappe.LinkExistsError, si.cancel)
def test_sales_invoice_calculation_export_currency(self): def test_sales_invoice_calculation_export_currency(self):
si = frappe.copy_doc(test_records[2]) si = frappe.copy_doc(test_records[2])
si.currency = "USD" si.currency = "USD"

View File

@ -7,4 +7,8 @@
* Credit Controller: Role that is allowed to submit transactions that exceed credit limits set. * Credit Controller: Role that is allowed to submit transactions that exceed credit limits set.
* Make Payment via Journal Entry: If checked, on invoice if uer has clicked on payment system open the journal entry else payment entry
* Unlink Payment on Cancellation of Invoice: If checked system inlink the payment against the invoice else shows the link error.
{next} {next}

View File

@ -340,3 +340,4 @@ erpnext.patches.v7_0.update_status_of_zero_amount_sales_order
erpnext.patches.v7_1.add_field_for_task_dependent erpnext.patches.v7_1.add_field_for_task_dependent
erpnext.patches.v7_0.repost_bin_qty_and_item_projected_qty erpnext.patches.v7_0.repost_bin_qty_and_item_projected_qty
erpnext.patches.v7_1.set_prefered_contact_email erpnext.patches.v7_1.set_prefered_contact_email
execute:frappe.db.sql("update `tabSingles` set value = 1 where field = 'unlink_payment_on_cancellation_of_invoice' and doctype = 'Accounts Settings'")