Post GL Entry based on rounded total in Sales/Purchase Invoice (#11542)
This commit is contained in:
parent
1783549e75
commit
877e1bb377
@ -17,12 +17,13 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
|
|||||||
if(!this.frm.doc.supplier && this.frm.doc.credit_to) {
|
if(!this.frm.doc.supplier && this.frm.doc.credit_to) {
|
||||||
this.frm.set_df_property("credit_to", "print_hide", 0);
|
this.frm.set_df_property("credit_to", "print_hide", 0);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
this.frm.set_value("disable_rounded_total", frappe.sys_defaults.disable_rounded_total);
|
||||||
}
|
}
|
||||||
|
|
||||||
// formatter for material request item
|
// formatter for material request item
|
||||||
this.frm.set_indicator_formatter('item_code',
|
this.frm.set_indicator_formatter('item_code',
|
||||||
function(doc) { return (doc.qty<=doc.received_qty) ? "green" : "orange" })
|
function(doc) { return (doc.qty<=doc.received_qty) ? "green" : "orange" })
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
refresh: function(doc) {
|
refresh: function(doc) {
|
||||||
|
@ -2104,6 +2104,38 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"depends_on": "eval:!doc.disable_rounded_total",
|
||||||
|
"fieldname": "base_rounded_total",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Rounded Total (Company Currency)",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 1,
|
||||||
|
"options": "Company:company:default_currency",
|
||||||
|
"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_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -2229,6 +2261,38 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"depends_on": "eval:!doc.disable_rounded_total",
|
||||||
|
"fieldname": "rounded_total",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Rounded Total",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 1,
|
||||||
|
"options": "currency",
|
||||||
|
"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_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -2324,6 +2388,37 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"depends_on": "grand_total",
|
||||||
|
"fieldname": "disable_rounded_total",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Disable Rounded Total",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"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_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -3576,7 +3671,7 @@
|
|||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"menu_index": 0,
|
"menu_index": 0,
|
||||||
"modified": "2017-11-15 01:04:15.308603",
|
"modified": "2017-11-16 01:04:15.308603",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Purchase Invoice",
|
"name": "Purchase Invoice",
|
||||||
|
@ -77,8 +77,10 @@ class PurchaseInvoice(BuyingController):
|
|||||||
if not self.cash_bank_account and flt(self.paid_amount):
|
if not self.cash_bank_account and flt(self.paid_amount):
|
||||||
frappe.throw(_("Cash or Bank Account is mandatory for making payment entry"))
|
frappe.throw(_("Cash or Bank Account is mandatory for making payment entry"))
|
||||||
|
|
||||||
if flt(self.paid_amount) + flt(self.write_off_amount) \
|
if (flt(self.paid_amount) + flt(self.write_off_amount)
|
||||||
- flt(self.grand_total) > 1/(10**(self.precision("base_grand_total") + 1)):
|
- flt(self.get("rounded_total") or self.grand_total)
|
||||||
|
> 1/(10**(self.precision("base_grand_total") + 1))):
|
||||||
|
|
||||||
frappe.throw(_("""Paid amount + Write Off Amount can not be greater than Grand Total"""))
|
frappe.throw(_("""Paid amount + Write Off Amount can not be greater than Grand Total"""))
|
||||||
|
|
||||||
def create_remarks(self):
|
def create_remarks(self):
|
||||||
@ -359,9 +361,10 @@ class PurchaseInvoice(BuyingController):
|
|||||||
return gl_entries
|
return gl_entries
|
||||||
|
|
||||||
def make_supplier_gl_entry(self, gl_entries):
|
def make_supplier_gl_entry(self, gl_entries):
|
||||||
if self.grand_total:
|
grand_total = self.rounded_total or self.grand_total
|
||||||
|
if grand_total:
|
||||||
# Didnot use base_grand_total to book rounding loss gle
|
# Didnot use base_grand_total to book rounding loss gle
|
||||||
grand_total_in_company_currency = flt(self.grand_total * self.conversion_rate,
|
grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
|
||||||
self.precision("grand_total"))
|
self.precision("grand_total"))
|
||||||
gl_entries.append(
|
gl_entries.append(
|
||||||
self.get_gl_dict({
|
self.get_gl_dict({
|
||||||
@ -371,7 +374,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
"against": self.against_expense_account,
|
"against": self.against_expense_account,
|
||||||
"credit": grand_total_in_company_currency,
|
"credit": grand_total_in_company_currency,
|
||||||
"credit_in_account_currency": grand_total_in_company_currency \
|
"credit_in_account_currency": grand_total_in_company_currency \
|
||||||
if self.party_account_currency==self.company_currency else self.grand_total,
|
if self.party_account_currency==self.company_currency else grand_total,
|
||||||
"against_voucher": self.return_against if cint(self.is_return) else self.name,
|
"against_voucher": self.return_against if cint(self.is_return) else self.name,
|
||||||
"against_voucher_type": self.doctype,
|
"against_voucher_type": self.doctype,
|
||||||
}, self.party_account_currency)
|
}, self.party_account_currency)
|
||||||
|
@ -35,7 +35,7 @@ class TestPurchaseInvoice(unittest.TestCase):
|
|||||||
dl = wrapper
|
dl = wrapper
|
||||||
|
|
||||||
expected_gl_entries = {
|
expected_gl_entries = {
|
||||||
"_Test Payable - _TC": [0, 1512.30],
|
"_Test Payable - _TC": [0, 1512.0],
|
||||||
"_Test Account Cost for Goods Sold - _TC": [1250, 0],
|
"_Test Account Cost for Goods Sold - _TC": [1250, 0],
|
||||||
"_Test Account Shipping Charges - _TC": [100, 0],
|
"_Test Account Shipping Charges - _TC": [100, 0],
|
||||||
"_Test Account Excise Duty - _TC": [140, 0],
|
"_Test Account Excise Duty - _TC": [140, 0],
|
||||||
@ -44,6 +44,7 @@ class TestPurchaseInvoice(unittest.TestCase):
|
|||||||
"_Test Account CST - _TC": [29.88, 0],
|
"_Test Account CST - _TC": [29.88, 0],
|
||||||
"_Test Account VAT - _TC": [156.25, 0],
|
"_Test Account VAT - _TC": [156.25, 0],
|
||||||
"_Test Account Discount - _TC": [0, 168.03],
|
"_Test Account Discount - _TC": [0, 168.03],
|
||||||
|
"Round Off - _TC": [0, 0.3]
|
||||||
}
|
}
|
||||||
gl_entries = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
|
gl_entries = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
|
||||||
where voucher_type = 'Purchase Invoice' and voucher_no = %s""", dl.name, as_dict=1)
|
where voucher_type = 'Purchase Invoice' and voucher_no = %s""", dl.name, as_dict=1)
|
||||||
@ -233,6 +234,7 @@ class TestPurchaseInvoice(unittest.TestCase):
|
|||||||
jv.submit()
|
jv.submit()
|
||||||
|
|
||||||
pi = frappe.copy_doc(test_records[0])
|
pi = frappe.copy_doc(test_records[0])
|
||||||
|
pi.disable_rounded_total = 1
|
||||||
pi.append("advances", {
|
pi.append("advances", {
|
||||||
"reference_type": "Journal Entry",
|
"reference_type": "Journal Entry",
|
||||||
"reference_name": jv.name,
|
"reference_name": jv.name,
|
||||||
@ -242,6 +244,13 @@ class TestPurchaseInvoice(unittest.TestCase):
|
|||||||
"remarks": jv.remark
|
"remarks": jv.remark
|
||||||
})
|
})
|
||||||
pi.insert()
|
pi.insert()
|
||||||
|
|
||||||
|
self.assertEqual(pi.outstanding_amount, 1212.30)
|
||||||
|
|
||||||
|
pi.disable_rounded_total = 0
|
||||||
|
pi.save()
|
||||||
|
self.assertEqual(pi.outstanding_amount, 1212.0)
|
||||||
|
|
||||||
pi.submit()
|
pi.submit()
|
||||||
pi.load_from_db()
|
pi.load_from_db()
|
||||||
|
|
||||||
@ -249,8 +258,6 @@ class TestPurchaseInvoice(unittest.TestCase):
|
|||||||
where reference_type='Purchase Invoice'
|
where reference_type='Purchase Invoice'
|
||||||
and reference_name=%s and debit_in_account_currency=300""", pi.name))
|
and reference_name=%s and debit_in_account_currency=300""", pi.name))
|
||||||
|
|
||||||
self.assertEqual(pi.outstanding_amount, 1212.30)
|
|
||||||
|
|
||||||
pi.cancel()
|
pi.cancel()
|
||||||
|
|
||||||
self.assertFalse(frappe.db.sql("""select name from `tabJournal Entry Account`
|
self.assertFalse(frappe.db.sql("""select name from `tabJournal Entry Account`
|
||||||
@ -491,7 +498,7 @@ class TestPurchaseInvoice(unittest.TestCase):
|
|||||||
pi.load_from_db()
|
pi.load_from_db()
|
||||||
|
|
||||||
#check outstanding after advance allocation
|
#check outstanding after advance allocation
|
||||||
self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total - pi.total_advance))
|
self.assertEqual(flt(pi.outstanding_amount), flt(pi.rounded_total - pi.total_advance))
|
||||||
|
|
||||||
#added to avoid Document has been modified exception
|
#added to avoid Document has been modified exception
|
||||||
jv = frappe.get_doc("Journal Entry", jv.name)
|
jv = frappe.get_doc("Journal Entry", jv.name)
|
||||||
@ -499,7 +506,7 @@ class TestPurchaseInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
pi.load_from_db()
|
pi.load_from_db()
|
||||||
#check outstanding after advance cancellation
|
#check outstanding after advance cancellation
|
||||||
self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total + pi.total_advance))
|
self.assertEqual(flt(pi.outstanding_amount), flt(pi.rounded_total + pi.total_advance))
|
||||||
|
|
||||||
def test_outstanding_amount_after_advance_payment_entry_cancelation(self):
|
def test_outstanding_amount_after_advance_payment_entry_cancelation(self):
|
||||||
pe = frappe.get_doc({
|
pe = frappe.get_doc({
|
||||||
@ -538,7 +545,7 @@ class TestPurchaseInvoice(unittest.TestCase):
|
|||||||
pi.load_from_db()
|
pi.load_from_db()
|
||||||
|
|
||||||
#check outstanding after advance allocation
|
#check outstanding after advance allocation
|
||||||
self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total - pi.total_advance))
|
self.assertEqual(flt(pi.outstanding_amount), flt(pi.rounded_total - pi.total_advance))
|
||||||
|
|
||||||
#added to avoid Document has been modified exception
|
#added to avoid Document has been modified exception
|
||||||
pe = frappe.get_doc("Payment Entry", pe.name)
|
pe = frappe.get_doc("Payment Entry", pe.name)
|
||||||
@ -546,7 +553,7 @@ class TestPurchaseInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
pi.load_from_db()
|
pi.load_from_db()
|
||||||
#check outstanding after advance cancellation
|
#check outstanding after advance cancellation
|
||||||
self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total + pi.total_advance))
|
self.assertEqual(flt(pi.outstanding_amount), flt(pi.rounded_total + pi.total_advance))
|
||||||
|
|
||||||
def unlink_payment_on_cancel_of_invoice(enable=1):
|
def unlink_payment_on_cancel_of_invoice(enable=1):
|
||||||
accounts_settings = frappe.get_doc("Accounts Settings")
|
accounts_settings = frappe.get_doc("Accounts Settings")
|
||||||
|
@ -632,9 +632,10 @@ class SalesInvoice(SellingController):
|
|||||||
return gl_entries
|
return gl_entries
|
||||||
|
|
||||||
def make_customer_gl_entry(self, gl_entries):
|
def make_customer_gl_entry(self, gl_entries):
|
||||||
if self.grand_total:
|
grand_total = self.rounded_total or self.grand_total
|
||||||
|
if grand_total:
|
||||||
# Didnot use base_grand_total to book rounding loss gle
|
# Didnot use base_grand_total to book rounding loss gle
|
||||||
grand_total_in_company_currency = flt(self.grand_total * self.conversion_rate,
|
grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
|
||||||
self.precision("grand_total"))
|
self.precision("grand_total"))
|
||||||
|
|
||||||
gl_entries.append(
|
gl_entries.append(
|
||||||
@ -645,7 +646,7 @@ class SalesInvoice(SellingController):
|
|||||||
"against": self.against_income_account,
|
"against": self.against_income_account,
|
||||||
"debit": grand_total_in_company_currency,
|
"debit": grand_total_in_company_currency,
|
||||||
"debit_in_account_currency": grand_total_in_company_currency \
|
"debit_in_account_currency": grand_total_in_company_currency \
|
||||||
if self.party_account_currency==self.company_currency else self.grand_total,
|
if self.party_account_currency==self.company_currency else grand_total,
|
||||||
"against_voucher": self.return_against if cint(self.is_return) else self.name,
|
"against_voucher": self.return_against if cint(self.is_return) else self.name,
|
||||||
"against_voucher_type": self.doctype
|
"against_voucher_type": self.doctype
|
||||||
}, self.party_account_currency)
|
}, self.party_account_currency)
|
||||||
|
@ -546,7 +546,7 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
def test_outstanding(self):
|
def test_outstanding(self):
|
||||||
w = self.make()
|
w = self.make()
|
||||||
self.assertEquals(w.outstanding_amount, w.base_grand_total)
|
self.assertEquals(w.outstanding_amount, w.base_rounded_total)
|
||||||
|
|
||||||
def test_payment(self):
|
def test_payment(self):
|
||||||
w = self.make()
|
w = self.make()
|
||||||
@ -560,7 +560,7 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
jv.insert()
|
jv.insert()
|
||||||
jv.submit()
|
jv.submit()
|
||||||
|
|
||||||
self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), 161.8)
|
self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), 162.0)
|
||||||
|
|
||||||
link_data = get_dynamic_link_map().get('Sales Invoice', [])
|
link_data = get_dynamic_link_map().get('Sales Invoice', [])
|
||||||
link_doctypes = [d.parent for d in link_data]
|
link_doctypes = [d.parent for d in link_data]
|
||||||
@ -569,7 +569,7 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
self.assertTrue(link_doctypes.index('GL Entry') > link_doctypes.index('Journal Entry Account'))
|
self.assertTrue(link_doctypes.index('GL Entry') > link_doctypes.index('Journal Entry Account'))
|
||||||
|
|
||||||
jv.cancel()
|
jv.cancel()
|
||||||
self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), 561.8)
|
self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), 562.0)
|
||||||
|
|
||||||
def test_sales_invoice_gl_entry_without_perpetual_inventory(self):
|
def test_sales_invoice_gl_entry_without_perpetual_inventory(self):
|
||||||
si = frappe.copy_doc(test_records[1])
|
si = frappe.copy_doc(test_records[1])
|
||||||
@ -848,7 +848,7 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
self.assertTrue(frappe.db.sql("""select name from `tabJournal Entry Account`
|
self.assertTrue(frappe.db.sql("""select name from `tabJournal Entry Account`
|
||||||
where reference_name=%s and credit_in_account_currency=300""", si.name))
|
where reference_name=%s and credit_in_account_currency=300""", si.name))
|
||||||
|
|
||||||
self.assertEqual(si.outstanding_amount, 261.8)
|
self.assertEqual(si.outstanding_amount, 262.0)
|
||||||
|
|
||||||
si.cancel()
|
si.cancel()
|
||||||
|
|
||||||
@ -1152,7 +1152,8 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
si.load_from_db()
|
si.load_from_db()
|
||||||
|
|
||||||
#check outstanding after advance allocation
|
#check outstanding after advance allocation
|
||||||
self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total - si.total_advance, si.precision("outstanding_amount")))
|
self.assertEqual(flt(si.outstanding_amount),
|
||||||
|
flt(si.rounded_total - si.total_advance, si.precision("outstanding_amount")))
|
||||||
|
|
||||||
#added to avoid Document has been modified exception
|
#added to avoid Document has been modified exception
|
||||||
jv = frappe.get_doc("Journal Entry", jv.name)
|
jv = frappe.get_doc("Journal Entry", jv.name)
|
||||||
@ -1160,7 +1161,8 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
si.load_from_db()
|
si.load_from_db()
|
||||||
#check outstanding after advance cancellation
|
#check outstanding after advance cancellation
|
||||||
self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total + si.total_advance, si.precision("outstanding_amount")))
|
self.assertEqual(flt(si.outstanding_amount),
|
||||||
|
flt(si.rounded_total + si.total_advance, si.precision("outstanding_amount")))
|
||||||
|
|
||||||
def test_outstanding_amount_after_advance_payment_entry_cancelation(self):
|
def test_outstanding_amount_after_advance_payment_entry_cancelation(self):
|
||||||
pe = frappe.get_doc({
|
pe = frappe.get_doc({
|
||||||
@ -1199,7 +1201,8 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
si.load_from_db()
|
si.load_from_db()
|
||||||
|
|
||||||
#check outstanding after advance allocation
|
#check outstanding after advance allocation
|
||||||
self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total - si.total_advance, si.precision("outstanding_amount")))
|
self.assertEqual(flt(si.outstanding_amount),
|
||||||
|
flt(si.rounded_total - si.total_advance, si.precision("outstanding_amount")))
|
||||||
|
|
||||||
#added to avoid Document has been modified exception
|
#added to avoid Document has been modified exception
|
||||||
pe = frappe.get_doc("Payment Entry", pe.name)
|
pe = frappe.get_doc("Payment Entry", pe.name)
|
||||||
@ -1207,7 +1210,8 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
si.load_from_db()
|
si.load_from_db()
|
||||||
#check outstanding after advance cancellation
|
#check outstanding after advance cancellation
|
||||||
self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total + si.total_advance, si.precision("outstanding_amount")))
|
self.assertEqual(flt(si.outstanding_amount),
|
||||||
|
flt(si.rounded_total + si.total_advance, si.precision("outstanding_amount")))
|
||||||
|
|
||||||
def test_multiple_uom_in_selling(self):
|
def test_multiple_uom_in_selling(self):
|
||||||
frappe.db.sql("""delete from `tabItem Price`
|
frappe.db.sql("""delete from `tabItem Price`
|
||||||
|
@ -66,9 +66,9 @@ class AccountsController(TransactionBase):
|
|||||||
if cint(is_paid) == 1:
|
if cint(is_paid) == 1:
|
||||||
if flt(self.paid_amount) == 0 and flt(self.outstanding_amount) > 0:
|
if flt(self.paid_amount) == 0 and flt(self.outstanding_amount) > 0:
|
||||||
if self.cash_bank_account:
|
if self.cash_bank_account:
|
||||||
self.paid_amount = flt(flt(self.grand_total) - flt(self.write_off_amount),
|
self.paid_amount = flt(flt(self.outstanding_amount), self.precision("paid_amount"))
|
||||||
self.precision("paid_amount"))
|
self.base_paid_amount = flt(self.paid_amount * self.conversion_rate,
|
||||||
self.base_paid_amount = flt(self.paid_amount * self.conversion_rate, self.precision("base_paid_amount"))
|
self.precision("base_paid_amount"))
|
||||||
else:
|
else:
|
||||||
# show message that the amount is not paid
|
# show message that the amount is not paid
|
||||||
self.paid_amount = 0
|
self.paid_amount = 0
|
||||||
@ -598,6 +598,12 @@ class AccountsController(TransactionBase):
|
|||||||
for item in duplicate_list:
|
for item in duplicate_list:
|
||||||
self.remove(item)
|
self.remove(item)
|
||||||
|
|
||||||
|
def is_rounded_total_disabled(self):
|
||||||
|
if self.meta.get_field("disable_rounded_total"):
|
||||||
|
return self.disable_rounded_total
|
||||||
|
else:
|
||||||
|
return frappe.db.get_single_value("Global Defaults", "disable_rounded_total")
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_tax_rate(account_head):
|
def get_tax_rate(account_head):
|
||||||
return frappe.db.get_value("Account", account_head, ["tax_rate", "account_name"], as_dict=True)
|
return frappe.db.get_value("Account", account_head, ["tax_rate", "account_name"], as_dict=True)
|
||||||
|
@ -28,8 +28,7 @@ class SellingController(StockController):
|
|||||||
super(SellingController, self).onload()
|
super(SellingController, self).onload()
|
||||||
if self.doctype in ("Sales Order", "Delivery Note", "Sales Invoice"):
|
if self.doctype in ("Sales Order", "Delivery Note", "Sales Invoice"):
|
||||||
for item in self.get("items"):
|
for item in self.get("items"):
|
||||||
item.update(get_bin_details(item.item_code,
|
item.update(get_bin_details(item.item_code, item.warehouse))
|
||||||
item.warehouse))
|
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
super(SellingController, self).validate()
|
super(SellingController, self).validate()
|
||||||
@ -114,14 +113,15 @@ class SellingController(StockController):
|
|||||||
|
|
||||||
def set_total_in_words(self):
|
def set_total_in_words(self):
|
||||||
from frappe.utils import money_in_words
|
from frappe.utils import money_in_words
|
||||||
disable_rounded_total = cint(frappe.db.get_value("Global Defaults", None, "disable_rounded_total"))
|
|
||||||
|
|
||||||
if self.meta.get_field("base_in_words"):
|
if self.meta.get_field("base_in_words"):
|
||||||
self.base_in_words = money_in_words(disable_rounded_total and
|
base_amount = abs(self.base_grand_total
|
||||||
abs(self.base_grand_total) or abs(self.base_rounded_total), self.company_currency)
|
if self.is_rounded_total_disabled() else self.base_rounded_total)
|
||||||
|
self.base_in_words = money_in_words(base_amount, self.company_currency)
|
||||||
|
|
||||||
if self.meta.get_field("in_words"):
|
if self.meta.get_field("in_words"):
|
||||||
self.in_words = money_in_words(disable_rounded_total and
|
amount = abs(self.grand_total if self.is_rounded_total_disabled() else self.rounded_total)
|
||||||
abs(self.grand_total) or abs(self.rounded_total), self.currency)
|
self.in_words = money_in_words(amount, self.currency)
|
||||||
|
|
||||||
def calculate_commission(self):
|
def calculate_commission(self):
|
||||||
if self.meta.get_field("commission_rate"):
|
if self.meta.get_field("commission_rate"):
|
||||||
|
@ -328,14 +328,18 @@ class calculate_taxes_and_totals(object):
|
|||||||
self.set_rounded_total()
|
self.set_rounded_total()
|
||||||
|
|
||||||
def set_rounded_total(self):
|
def set_rounded_total(self):
|
||||||
if frappe.db.get_single_value("Global Defaults", "disable_rounded_total"):
|
if self.doc.meta.get_field("rounded_total"):
|
||||||
|
if self.doc.is_rounded_total_disabled():
|
||||||
self.doc.rounded_total = self.doc.base_rounded_total = 0
|
self.doc.rounded_total = self.doc.base_rounded_total = 0
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.doc.meta.get_field("rounded_total"):
|
|
||||||
self.doc.rounded_total = round_based_on_smallest_currency_fraction(self.doc.grand_total,
|
self.doc.rounded_total = round_based_on_smallest_currency_fraction(self.doc.grand_total,
|
||||||
self.doc.currency, self.doc.precision("rounded_total"))
|
self.doc.currency, self.doc.precision("rounded_total"))
|
||||||
|
|
||||||
|
#if print_in_rate is set, we would have already calculated rounding adjustment
|
||||||
|
self.doc.rounding_adjustment += flt(self.doc.rounded_total - self.doc.grand_total,
|
||||||
|
self.doc.precision("rounding_adjustment"))
|
||||||
|
|
||||||
if self.doc.meta.get_field("base_rounded_total"):
|
if self.doc.meta.get_field("base_rounded_total"):
|
||||||
company_currency = erpnext.get_company_currency(self.doc.company)
|
company_currency = erpnext.get_company_currency(self.doc.company)
|
||||||
|
|
||||||
@ -343,6 +347,9 @@ class calculate_taxes_and_totals(object):
|
|||||||
round_based_on_smallest_currency_fraction(self.doc.base_grand_total,
|
round_based_on_smallest_currency_fraction(self.doc.base_grand_total,
|
||||||
company_currency, self.doc.precision("base_rounded_total"))
|
company_currency, self.doc.precision("base_rounded_total"))
|
||||||
|
|
||||||
|
self.doc.base_rounding_adjustment += flt(self.doc.base_rounded_total - self.doc.base_grand_total,
|
||||||
|
self.doc.precision("base_rounding_adjustment"))
|
||||||
|
|
||||||
def _cleanup(self):
|
def _cleanup(self):
|
||||||
for tax in self.doc.get("taxes"):
|
for tax in self.doc.get("taxes"):
|
||||||
tax.item_wise_tax_detail = json.dumps(tax.item_wise_tax_detail, separators=(',', ':'))
|
tax.item_wise_tax_detail = json.dumps(tax.item_wise_tax_detail, separators=(',', ':'))
|
||||||
@ -404,7 +411,8 @@ class calculate_taxes_and_totals(object):
|
|||||||
actual_tax_amount = flt(actual_taxes_dict.get(tax.row_id, 0)) * flt(tax.rate) / 100
|
actual_tax_amount = flt(actual_taxes_dict.get(tax.row_id, 0)) * flt(tax.rate) / 100
|
||||||
actual_taxes_dict.setdefault(tax.idx, actual_tax_amount)
|
actual_taxes_dict.setdefault(tax.idx, actual_tax_amount)
|
||||||
|
|
||||||
return flt(self.doc.grand_total - sum(actual_taxes_dict.values()), self.doc.precision("grand_total"))
|
return flt(self.doc.grand_total - sum(actual_taxes_dict.values()),
|
||||||
|
self.doc.precision("grand_total"))
|
||||||
|
|
||||||
|
|
||||||
def calculate_total_advance(self):
|
def calculate_total_advance(self):
|
||||||
@ -442,30 +450,31 @@ class calculate_taxes_and_totals(object):
|
|||||||
self.doc.round_floats_in(self.doc, ["grand_total", "total_advance", "write_off_amount"])
|
self.doc.round_floats_in(self.doc, ["grand_total", "total_advance", "write_off_amount"])
|
||||||
self._set_in_company_currency(self.doc, ['write_off_amount'])
|
self._set_in_company_currency(self.doc, ['write_off_amount'])
|
||||||
|
|
||||||
|
if self.doc.doctype in ["Sales Invoice", "Purchase Invoice"]:
|
||||||
|
grand_total = self.doc.rounded_total or self.doc.grand_total
|
||||||
if self.doc.party_account_currency == self.doc.currency:
|
if self.doc.party_account_currency == self.doc.currency:
|
||||||
total_amount_to_pay = flt(self.doc.grand_total - self.doc.total_advance
|
total_amount_to_pay = flt(grand_total - self.doc.total_advance
|
||||||
- flt(self.doc.write_off_amount), self.doc.precision("grand_total"))
|
- flt(self.doc.write_off_amount), self.doc.precision("grand_total"))
|
||||||
else:
|
else:
|
||||||
total_amount_to_pay = flt(flt(self.doc.grand_total *
|
total_amount_to_pay = flt(flt(grand_total *
|
||||||
self.doc.conversion_rate, self.doc.precision("grand_total")) - self.doc.total_advance
|
self.doc.conversion_rate, self.doc.precision("grand_total")) - self.doc.total_advance
|
||||||
- flt(self.doc.base_write_off_amount), self.doc.precision("grand_total"))
|
- flt(self.doc.base_write_off_amount), self.doc.precision("grand_total"))
|
||||||
|
|
||||||
if self.doc.doctype == "Sales Invoice":
|
|
||||||
self.doc.round_floats_in(self.doc, ["paid_amount"])
|
self.doc.round_floats_in(self.doc, ["paid_amount"])
|
||||||
|
change_amount = 0
|
||||||
|
|
||||||
|
if self.doc.doctype == "Sales Invoice":
|
||||||
self.calculate_write_off_amount()
|
self.calculate_write_off_amount()
|
||||||
self.calculate_change_amount()
|
self.calculate_change_amount()
|
||||||
|
change_amount = self.doc.change_amount \
|
||||||
|
if self.doc.party_account_currency == self.doc.currency else self.doc.base_change_amount
|
||||||
|
|
||||||
paid_amount = self.doc.paid_amount \
|
paid_amount = self.doc.paid_amount \
|
||||||
if self.doc.party_account_currency == self.doc.currency else self.doc.base_paid_amount
|
if self.doc.party_account_currency == self.doc.currency else self.doc.base_paid_amount
|
||||||
|
|
||||||
change_amount = self.doc.change_amount \
|
|
||||||
if self.doc.party_account_currency == self.doc.currency else self.doc.base_change_amount
|
|
||||||
|
|
||||||
self.doc.outstanding_amount = flt(total_amount_to_pay - flt(paid_amount) +
|
self.doc.outstanding_amount = flt(total_amount_to_pay - flt(paid_amount) + flt(change_amount),
|
||||||
flt(change_amount), self.doc.precision("outstanding_amount"))
|
self.doc.precision("outstanding_amount"))
|
||||||
|
|
||||||
elif self.doc.doctype == "Purchase Invoice":
|
|
||||||
self.doc.outstanding_amount = flt(total_amount_to_pay, self.doc.precision("outstanding_amount"))
|
|
||||||
|
|
||||||
def calculate_paid_amount(self):
|
def calculate_paid_amount(self):
|
||||||
paid_amount = base_paid_amount = 0.0
|
paid_amount = base_paid_amount = 0.0
|
||||||
@ -485,7 +494,9 @@ class calculate_taxes_and_totals(object):
|
|||||||
def calculate_change_amount(self):
|
def calculate_change_amount(self):
|
||||||
self.doc.change_amount = 0.0
|
self.doc.change_amount = 0.0
|
||||||
self.doc.base_change_amount = 0.0
|
self.doc.base_change_amount = 0.0
|
||||||
if self.doc.paid_amount > self.doc.grand_total and not self.doc.is_return \
|
|
||||||
|
if self.doc.doctype == "Sales Invoice" \
|
||||||
|
and self.doc.paid_amount > self.doc.grand_total and not self.doc.is_return \
|
||||||
and any([d.type == "Cash" for d in self.doc.payments]):
|
and any([d.type == "Cash" for d in self.doc.payments]):
|
||||||
|
|
||||||
self.doc.change_amount = flt(self.doc.paid_amount - self.doc.grand_total +
|
self.doc.change_amount = flt(self.doc.paid_amount - self.doc.grand_total +
|
||||||
@ -496,8 +507,8 @@ class calculate_taxes_and_totals(object):
|
|||||||
|
|
||||||
def calculate_write_off_amount(self):
|
def calculate_write_off_amount(self):
|
||||||
if flt(self.doc.change_amount) > 0:
|
if flt(self.doc.change_amount) > 0:
|
||||||
self.doc.write_off_amount = flt(self.doc.grand_total - self.doc.paid_amount + self.doc.change_amount,
|
self.doc.write_off_amount = flt(self.doc.grand_total - self.doc.paid_amount
|
||||||
self.doc.precision("write_off_amount"))
|
+ self.doc.change_amount, self.doc.precision("write_off_amount"))
|
||||||
self.doc.base_write_off_amount = flt(self.doc.write_off_amount * self.doc.conversion_rate,
|
self.doc.base_write_off_amount = flt(self.doc.write_off_amount * self.doc.conversion_rate,
|
||||||
self.doc.precision("base_write_off_amount"))
|
self.doc.precision("base_write_off_amount"))
|
||||||
|
|
||||||
|
@ -422,13 +422,27 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
|
|||||||
frappe.model.round_floats_in(this.frm.doc, ["grand_total", "base_grand_total"]);
|
frappe.model.round_floats_in(this.frm.doc, ["grand_total", "base_grand_total"]);
|
||||||
|
|
||||||
// rounded totals
|
// rounded totals
|
||||||
this.set_rounded_total()
|
this.set_rounded_total();
|
||||||
},
|
},
|
||||||
|
|
||||||
set_rounded_total: function() {
|
set_rounded_total: function() {
|
||||||
|
var disable_rounded_total = 0;
|
||||||
|
if(frappe.meta.get_docfield(this.frm.doc.doctype, "disable_rounded_total", this.frm.doc.name)) {
|
||||||
|
disable_rounded_total = this.frm.doc.disable_rounded_total;
|
||||||
|
} else if (frappe.sys_defaults.disable_rounded_total) {
|
||||||
|
disable_rounded_total = frappe.sys_defaults.disable_rounded_total;
|
||||||
|
}
|
||||||
|
if(disable_rounded_total) {
|
||||||
|
this.frm.doc.rounded_total = 0;
|
||||||
|
this.frm.doc.base_rounded_total = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(frappe.meta.get_docfield(this.frm.doc.doctype, "rounded_total", this.frm.doc.name)) {
|
if(frappe.meta.get_docfield(this.frm.doc.doctype, "rounded_total", this.frm.doc.name)) {
|
||||||
this.frm.doc.rounded_total = round_based_on_smallest_currency_fraction(this.frm.doc.grand_total,
|
this.frm.doc.rounded_total = round_based_on_smallest_currency_fraction(this.frm.doc.grand_total,
|
||||||
this.frm.doc.currency, precision("rounded_total"));
|
this.frm.doc.currency, precision("rounded_total"));
|
||||||
|
this.frm.doc.rounding_adjustment += flt(this.frm.doc.rounded_total - this.frm.doc.grand_total,
|
||||||
|
precision("rounding_adjustment"));
|
||||||
}
|
}
|
||||||
if(frappe.meta.get_docfield(this.frm.doc.doctype, "base_rounded_total", this.frm.doc.name)) {
|
if(frappe.meta.get_docfield(this.frm.doc.doctype, "base_rounded_total", this.frm.doc.name)) {
|
||||||
var company_currency = this.get_company_currency();
|
var company_currency = this.get_company_currency();
|
||||||
@ -436,6 +450,9 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
|
|||||||
this.frm.doc.base_rounded_total =
|
this.frm.doc.base_rounded_total =
|
||||||
round_based_on_smallest_currency_fraction(this.frm.doc.base_grand_total,
|
round_based_on_smallest_currency_fraction(this.frm.doc.base_grand_total,
|
||||||
company_currency, precision("base_rounded_total"));
|
company_currency, precision("base_rounded_total"));
|
||||||
|
|
||||||
|
this.frm.doc.base_rounding_adjustment += flt(this.frm.doc.base_rounded_total -
|
||||||
|
this.frm.doc.base_grand_total, precision("rounding_adjustment"));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -560,20 +577,22 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
|
|||||||
if(this.frm.doc.is_return || this.frm.doc.docstatus > 0) return;
|
if(this.frm.doc.is_return || this.frm.doc.docstatus > 0) return;
|
||||||
|
|
||||||
frappe.model.round_floats_in(this.frm.doc, ["grand_total", "total_advance", "write_off_amount"]);
|
frappe.model.round_floats_in(this.frm.doc, ["grand_total", "total_advance", "write_off_amount"]);
|
||||||
|
|
||||||
|
if(in_list(["Sales Invoice", "Purchase Invoice"], this.frm.doc.doctype)) {
|
||||||
|
var grand_total = this.frm.doc.rounded_total || this.frm.doc.grand_total;
|
||||||
|
|
||||||
if(this.frm.doc.party_account_currency == this.frm.doc.currency) {
|
if(this.frm.doc.party_account_currency == this.frm.doc.currency) {
|
||||||
var total_amount_to_pay = flt((this.frm.doc.grand_total - this.frm.doc.total_advance
|
var total_amount_to_pay = flt((grand_total - this.frm.doc.total_advance
|
||||||
- this.frm.doc.write_off_amount), precision("grand_total"));
|
- this.frm.doc.write_off_amount), precision("grand_total"));
|
||||||
} else {
|
} else {
|
||||||
var total_amount_to_pay = flt(
|
var total_amount_to_pay = flt(
|
||||||
(flt(this.frm.doc.grand_total*this.frm.doc.conversion_rate, precision("grand_total"))
|
(flt(grand_total*this.frm.doc.conversion_rate, precision("grand_total"))
|
||||||
- this.frm.doc.total_advance - this.frm.doc.base_write_off_amount),
|
- this.frm.doc.total_advance - this.frm.doc.base_write_off_amount),
|
||||||
precision("base_grand_total")
|
precision("base_grand_total")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.frm.doc.doctype == "Sales Invoice" || this.frm.doc.doctype == "Purchase Invoice") {
|
|
||||||
frappe.model.round_floats_in(this.frm.doc, ["paid_amount"]);
|
frappe.model.round_floats_in(this.frm.doc, ["paid_amount"]);
|
||||||
|
|
||||||
this.set_in_company_currency(this.frm.doc, ["paid_amount"]);
|
this.set_in_company_currency(this.frm.doc, ["paid_amount"]);
|
||||||
|
|
||||||
if(this.frm.refresh_field){
|
if(this.frm.refresh_field){
|
||||||
@ -581,11 +600,10 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
|
|||||||
this.frm.refresh_field("base_paid_amount");
|
this.frm.refresh_field("base_paid_amount");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.frm.doc.doctype == "Sales Invoice"){
|
if(this.frm.doc.doctype == "Sales Invoice") {
|
||||||
this.set_default_payment(total_amount_to_pay, update_paid_amount);
|
this.set_default_payment(total_amount_to_pay, update_paid_amount);
|
||||||
this.calculate_paid_amount();
|
this.calculate_paid_amount();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.calculate_change_amount();
|
this.calculate_change_amount();
|
||||||
|
|
||||||
var paid_amount = (this.frm.doc.party_account_currency == this.frm.doc.currency) ?
|
var paid_amount = (this.frm.doc.party_account_currency == this.frm.doc.currency) ?
|
||||||
@ -593,9 +611,6 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
|
|||||||
|
|
||||||
this.frm.doc.outstanding_amount = flt(total_amount_to_pay - flt(paid_amount) +
|
this.frm.doc.outstanding_amount = flt(total_amount_to_pay - flt(paid_amount) +
|
||||||
flt(this.frm.doc.change_amount * this.frm.doc.conversion_rate), precision("outstanding_amount"));
|
flt(this.frm.doc.change_amount * this.frm.doc.conversion_rate), precision("outstanding_amount"));
|
||||||
|
|
||||||
} else if(this.frm.doc.doctype == "Purchase Invoice") {
|
|
||||||
this.frm.doc.outstanding_amount = flt(total_amount_to_pay, precision("outstanding_amount"));
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -636,7 +651,9 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
|
|||||||
calculate_change_amount: function(){
|
calculate_change_amount: function(){
|
||||||
this.frm.doc.change_amount = 0.0;
|
this.frm.doc.change_amount = 0.0;
|
||||||
this.frm.doc.base_change_amount = 0.0;
|
this.frm.doc.base_change_amount = 0.0;
|
||||||
if(this.frm.doc.paid_amount > this.frm.doc.grand_total && !this.frm.doc.is_return) {
|
if(this.frm.doc.doctype == "Sales Invoice"
|
||||||
|
&& this.frm.doc.paid_amount > this.frm.doc.grand_total && !this.frm.doc.is_return) {
|
||||||
|
|
||||||
var payment_types = $.map(this.frm.doc.payments, function(d) { return d.type; });
|
var payment_types = $.map(this.frm.doc.payments, function(d) { return d.type; });
|
||||||
if (in_list(payment_types, 'Cash')) {
|
if (in_list(payment_types, 'Cash')) {
|
||||||
this.frm.doc.change_amount = flt(this.frm.doc.paid_amount - this.frm.doc.grand_total +
|
this.frm.doc.change_amount = flt(this.frm.doc.paid_amount - this.frm.doc.grand_total +
|
||||||
|
@ -57,7 +57,8 @@ class GlobalDefaults(Document):
|
|||||||
self.disable_rounded_total = cint(self.disable_rounded_total)
|
self.disable_rounded_total = cint(self.disable_rounded_total)
|
||||||
|
|
||||||
# Make property setters to hide rounded total fields
|
# Make property setters to hide rounded total fields
|
||||||
for doctype in ("Quotation", "Sales Order", "Sales Invoice", "Delivery Note"):
|
for doctype in ("Quotation", "Sales Order", "Sales Invoice", "Delivery Note",
|
||||||
|
"Supplier Quotation", "Purchase Order"):
|
||||||
make_property_setter(doctype, "base_rounded_total", "hidden", self.disable_rounded_total, "Check")
|
make_property_setter(doctype, "base_rounded_total", "hidden", self.disable_rounded_total, "Check")
|
||||||
make_property_setter(doctype, "base_rounded_total", "print_hide", 1, "Check")
|
make_property_setter(doctype, "base_rounded_total", "print_hide", 1, "Check")
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user