fix(pos): multiple pos round off cases
This commit is contained in:
parent
056a0ec421
commit
17445c7e04
@ -84,20 +84,12 @@ class POSInvoiceMergeLog(Document):
|
|||||||
sales_invoice.set_posting_time = 1
|
sales_invoice.set_posting_time = 1
|
||||||
sales_invoice.posting_date = getdate(self.posting_date)
|
sales_invoice.posting_date = getdate(self.posting_date)
|
||||||
sales_invoice.save()
|
sales_invoice.save()
|
||||||
self.write_off_fractional_amount(sales_invoice, data)
|
|
||||||
sales_invoice.submit()
|
sales_invoice.submit()
|
||||||
|
|
||||||
self.consolidated_invoice = sales_invoice.name
|
self.consolidated_invoice = sales_invoice.name
|
||||||
|
|
||||||
return sales_invoice.name
|
return sales_invoice.name
|
||||||
|
|
||||||
def write_off_fractional_amount(self, invoice, data):
|
|
||||||
pos_invoice_grand_total = sum(d.grand_total for d in data)
|
|
||||||
|
|
||||||
if abs(pos_invoice_grand_total - invoice.grand_total) < 1:
|
|
||||||
invoice.write_off_amount += -1 * (pos_invoice_grand_total - invoice.grand_total)
|
|
||||||
invoice.save()
|
|
||||||
|
|
||||||
def process_merging_into_credit_note(self, data):
|
def process_merging_into_credit_note(self, data):
|
||||||
credit_note = self.get_new_sales_invoice()
|
credit_note = self.get_new_sales_invoice()
|
||||||
credit_note.is_return = 1
|
credit_note.is_return = 1
|
||||||
@ -110,7 +102,6 @@ class POSInvoiceMergeLog(Document):
|
|||||||
# TODO: return could be against multiple sales invoice which could also have been consolidated?
|
# TODO: return could be against multiple sales invoice which could also have been consolidated?
|
||||||
# credit_note.return_against = self.consolidated_invoice
|
# credit_note.return_against = self.consolidated_invoice
|
||||||
credit_note.save()
|
credit_note.save()
|
||||||
self.write_off_fractional_amount(credit_note, data)
|
|
||||||
credit_note.submit()
|
credit_note.submit()
|
||||||
|
|
||||||
self.consolidated_credit_note = credit_note.name
|
self.consolidated_credit_note = credit_note.name
|
||||||
|
@ -5,6 +5,7 @@ import json
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
|
from frappe.tests.utils import change_settings
|
||||||
|
|
||||||
from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import init_user_and_profile
|
from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import init_user_and_profile
|
||||||
from erpnext.accounts.doctype.pos_invoice.pos_invoice import make_sales_return
|
from erpnext.accounts.doctype.pos_invoice.pos_invoice import make_sales_return
|
||||||
@ -280,3 +281,100 @@ class TestPOSInvoiceMergeLog(unittest.TestCase):
|
|||||||
frappe.set_user("Administrator")
|
frappe.set_user("Administrator")
|
||||||
frappe.db.sql("delete from `tabPOS Profile`")
|
frappe.db.sql("delete from `tabPOS Profile`")
|
||||||
frappe.db.sql("delete from `tabPOS Invoice`")
|
frappe.db.sql("delete from `tabPOS Invoice`")
|
||||||
|
|
||||||
|
@change_settings("System Settings", {"number_format": "#,###.###", "currency_precision": 3, "float_precision": 3})
|
||||||
|
def test_consolidation_round_off_error_3(self):
|
||||||
|
frappe.db.sql("delete from `tabPOS Invoice`")
|
||||||
|
|
||||||
|
try:
|
||||||
|
make_stock_entry(
|
||||||
|
to_warehouse="_Test Warehouse - _TC",
|
||||||
|
item_code="_Test Item",
|
||||||
|
rate=8000,
|
||||||
|
qty=10,
|
||||||
|
)
|
||||||
|
init_user_and_profile()
|
||||||
|
|
||||||
|
item_rates = [69, 59, 29]
|
||||||
|
for i in [1, 2]:
|
||||||
|
inv = create_pos_invoice(is_return=1, do_not_save=1)
|
||||||
|
inv.items = []
|
||||||
|
for rate in item_rates:
|
||||||
|
inv.append("items", {
|
||||||
|
"item_code": "_Test Item",
|
||||||
|
"warehouse": "_Test Warehouse - _TC",
|
||||||
|
"qty": -1,
|
||||||
|
"rate": rate,
|
||||||
|
"income_account": "Sales - _TC",
|
||||||
|
"expense_account": "Cost of Goods Sold - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
})
|
||||||
|
inv.append("taxes", {
|
||||||
|
"account_head": "_Test Account VAT - _TC",
|
||||||
|
"charge_type": "On Net Total",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "VAT",
|
||||||
|
"doctype": "Sales Taxes and Charges",
|
||||||
|
"rate": 15,
|
||||||
|
"included_in_print_rate": 1
|
||||||
|
})
|
||||||
|
inv.payments = []
|
||||||
|
inv.append('payments', {
|
||||||
|
'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': -157
|
||||||
|
})
|
||||||
|
inv.paid_amount = -157
|
||||||
|
inv.save()
|
||||||
|
inv.submit()
|
||||||
|
|
||||||
|
consolidate_pos_invoices()
|
||||||
|
|
||||||
|
inv.load_from_db()
|
||||||
|
consolidated_invoice = frappe.get_doc('Sales Invoice', inv.consolidated_invoice)
|
||||||
|
self.assertEqual(consolidated_invoice.status, 'Return')
|
||||||
|
self.assertEqual(consolidated_invoice.rounding_adjustment, -0.001)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
frappe.set_user("Administrator")
|
||||||
|
frappe.db.sql("delete from `tabPOS Profile`")
|
||||||
|
frappe.db.sql("delete from `tabPOS Invoice`")
|
||||||
|
|
||||||
|
def test_consolidation_rounding_adjustment(self):
|
||||||
|
'''
|
||||||
|
Test if the rounding adjustment is calculated correctly
|
||||||
|
'''
|
||||||
|
frappe.db.sql("delete from `tabPOS Invoice`")
|
||||||
|
|
||||||
|
try:
|
||||||
|
make_stock_entry(
|
||||||
|
to_warehouse="_Test Warehouse - _TC",
|
||||||
|
item_code="_Test Item",
|
||||||
|
rate=8000,
|
||||||
|
qty=10,
|
||||||
|
)
|
||||||
|
|
||||||
|
init_user_and_profile()
|
||||||
|
|
||||||
|
inv = create_pos_invoice(qty=1, rate=69.5, do_not_save=True)
|
||||||
|
inv.append('payments', {
|
||||||
|
'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 70
|
||||||
|
})
|
||||||
|
inv.insert()
|
||||||
|
inv.submit()
|
||||||
|
|
||||||
|
inv2 = create_pos_invoice(qty=1, rate=59.5, do_not_save=True)
|
||||||
|
inv2.append('payments', {
|
||||||
|
'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 60
|
||||||
|
})
|
||||||
|
inv2.insert()
|
||||||
|
inv2.submit()
|
||||||
|
|
||||||
|
consolidate_pos_invoices()
|
||||||
|
|
||||||
|
inv.load_from_db()
|
||||||
|
consolidated_invoice = frappe.get_doc('Sales Invoice', inv.consolidated_invoice)
|
||||||
|
self.assertEqual(consolidated_invoice.rounding_adjustment, 1)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
frappe.set_user("Administrator")
|
||||||
|
frappe.db.sql("delete from `tabPOS Profile`")
|
||||||
|
frappe.db.sql("delete from `tabPOS Invoice`")
|
@ -263,6 +263,9 @@ class SalesInvoice(SellingController):
|
|||||||
self.process_common_party_accounting()
|
self.process_common_party_accounting()
|
||||||
|
|
||||||
def validate_pos_return(self):
|
def validate_pos_return(self):
|
||||||
|
if self.is_consolidated:
|
||||||
|
# pos return is already validated in pos invoice
|
||||||
|
return
|
||||||
|
|
||||||
if self.is_pos and self.is_return:
|
if self.is_pos and self.is_return:
|
||||||
total_amount_in_payments = 0
|
total_amount_in_payments = 0
|
||||||
|
@ -270,7 +270,8 @@ class calculate_taxes_and_totals(object):
|
|||||||
shipping_rule.apply(self.doc)
|
shipping_rule.apply(self.doc)
|
||||||
|
|
||||||
def calculate_taxes(self):
|
def calculate_taxes(self):
|
||||||
if not self.doc.get('is_consolidated'):
|
rounding_adjustment_computed = self.doc.get('is_consolidated') and self.doc.get('rounding_adjustment')
|
||||||
|
if not rounding_adjustment_computed:
|
||||||
self.doc.rounding_adjustment = 0
|
self.doc.rounding_adjustment = 0
|
||||||
|
|
||||||
# maintain actual tax rate based on idx
|
# maintain actual tax rate based on idx
|
||||||
@ -326,7 +327,7 @@ class calculate_taxes_and_totals(object):
|
|||||||
if i == (len(self.doc.get("taxes")) - 1) and self.discount_amount_applied \
|
if i == (len(self.doc.get("taxes")) - 1) and self.discount_amount_applied \
|
||||||
and self.doc.discount_amount \
|
and self.doc.discount_amount \
|
||||||
and self.doc.apply_discount_on == "Grand Total" \
|
and self.doc.apply_discount_on == "Grand Total" \
|
||||||
and not self.doc.get('is_consolidated'):
|
and not rounding_adjustment_computed:
|
||||||
self.doc.rounding_adjustment = flt(self.doc.grand_total
|
self.doc.rounding_adjustment = flt(self.doc.grand_total
|
||||||
- flt(self.doc.discount_amount) - tax.total,
|
- flt(self.doc.discount_amount) - tax.total,
|
||||||
self.doc.precision("rounding_adjustment"))
|
self.doc.precision("rounding_adjustment"))
|
||||||
@ -465,20 +466,22 @@ class calculate_taxes_and_totals(object):
|
|||||||
self.doc.total_net_weight += d.total_weight
|
self.doc.total_net_weight += d.total_weight
|
||||||
|
|
||||||
def set_rounded_total(self):
|
def set_rounded_total(self):
|
||||||
if not self.doc.get('is_consolidated'):
|
if self.doc.get('is_consolidated') and self.doc.get('rounding_adjustment'):
|
||||||
if self.doc.meta.get_field("rounded_total"):
|
return
|
||||||
if self.doc.is_rounded_total_disabled():
|
|
||||||
self.doc.rounded_total = self.doc.base_rounded_total = 0
|
|
||||||
return
|
|
||||||
|
|
||||||
self.doc.rounded_total = round_based_on_smallest_currency_fraction(self.doc.grand_total,
|
if self.doc.meta.get_field("rounded_total"):
|
||||||
self.doc.currency, self.doc.precision("rounded_total"))
|
if self.doc.is_rounded_total_disabled():
|
||||||
|
self.doc.rounded_total = self.doc.base_rounded_total = 0
|
||||||
|
return
|
||||||
|
|
||||||
#if print_in_rate is set, we would have already calculated rounding adjustment
|
self.doc.rounded_total = round_based_on_smallest_currency_fraction(self.doc.grand_total,
|
||||||
self.doc.rounding_adjustment += flt(self.doc.rounded_total - self.doc.grand_total,
|
self.doc.currency, self.doc.precision("rounded_total"))
|
||||||
self.doc.precision("rounding_adjustment"))
|
|
||||||
|
|
||||||
self._set_in_company_currency(self.doc, ["rounding_adjustment", "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"))
|
||||||
|
|
||||||
|
self._set_in_company_currency(self.doc, ["rounding_adjustment", "rounded_total"])
|
||||||
|
|
||||||
def _cleanup(self):
|
def _cleanup(self):
|
||||||
if not self.doc.get('is_consolidated'):
|
if not self.doc.get('is_consolidated'):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user