mirror of
https://github.com/frappe/erpnext.git
synced 2026-02-22 19:06:36 +00:00
fix: consolidating pos invoices on the basis of accounting dimensions (#46961)
* fix: consolidating pos invoices on the basis of accounting dimensions
* fix: project field
(cherry picked from commit c85edc3346)
Co-authored-by: Diptanil Saha <diptanil@frappe.io>
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
# For license information, please see license.txt
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
|
||||||
|
import hashlib
|
||||||
import json
|
import json
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
@@ -302,10 +303,17 @@ class POSInvoiceMergeLog(Document):
|
|||||||
accounting_dimensions = get_checks_for_pl_and_bs_accounts()
|
accounting_dimensions = get_checks_for_pl_and_bs_accounts()
|
||||||
accounting_dimensions_fields = [d.fieldname for d in accounting_dimensions]
|
accounting_dimensions_fields = [d.fieldname for d in accounting_dimensions]
|
||||||
dimension_values = frappe.db.get_value(
|
dimension_values = frappe.db.get_value(
|
||||||
"POS Profile", {"name": invoice.pos_profile}, accounting_dimensions_fields, as_dict=1
|
"POS Profile",
|
||||||
|
{"name": invoice.pos_profile},
|
||||||
|
[*accounting_dimensions_fields, "cost_center", "project"],
|
||||||
|
as_dict=1,
|
||||||
)
|
)
|
||||||
for dimension in accounting_dimensions:
|
for dimension in accounting_dimensions:
|
||||||
dimension_value = dimension_values.get(dimension.fieldname)
|
dimension_value = (
|
||||||
|
data[0].get(dimension.fieldname)
|
||||||
|
if data[0].get(dimension.fieldname)
|
||||||
|
else dimension_values.get(dimension.fieldname)
|
||||||
|
)
|
||||||
|
|
||||||
if not dimension_value and (dimension.mandatory_for_pl or dimension.mandatory_for_bs):
|
if not dimension_value and (dimension.mandatory_for_pl or dimension.mandatory_for_bs):
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
@@ -317,6 +325,14 @@ class POSInvoiceMergeLog(Document):
|
|||||||
|
|
||||||
invoice.set(dimension.fieldname, dimension_value)
|
invoice.set(dimension.fieldname, dimension_value)
|
||||||
|
|
||||||
|
invoice.set(
|
||||||
|
"cost_center",
|
||||||
|
data[0].get("cost_center") if data[0].get("cost_center") else dimension_values.get("cost_center"),
|
||||||
|
)
|
||||||
|
invoice.set(
|
||||||
|
"project", data[0].get("project") if data[0].get("project") else dimension_values.get("project")
|
||||||
|
)
|
||||||
|
|
||||||
if self.merge_invoices_based_on == "Customer Group":
|
if self.merge_invoices_based_on == "Customer Group":
|
||||||
invoice.flags.ignore_pos_profile = True
|
invoice.flags.ignore_pos_profile = True
|
||||||
invoice.pos_profile = ""
|
invoice.pos_profile = ""
|
||||||
@@ -446,9 +462,34 @@ def get_invoice_customer_map(pos_invoices):
|
|||||||
pos_invoice_customer_map.setdefault(customer, [])
|
pos_invoice_customer_map.setdefault(customer, [])
|
||||||
pos_invoice_customer_map[customer].append(invoice)
|
pos_invoice_customer_map[customer].append(invoice)
|
||||||
|
|
||||||
|
for customer, invoices in pos_invoice_customer_map.items():
|
||||||
|
pos_invoice_customer_map[customer] = split_invoices_by_accounting_dimension(invoices)
|
||||||
|
|
||||||
return pos_invoice_customer_map
|
return pos_invoice_customer_map
|
||||||
|
|
||||||
|
|
||||||
|
def split_invoices_by_accounting_dimension(pos_invoices):
|
||||||
|
# pos_invoices = {
|
||||||
|
# {'dim_field1': 'dim_field1_value1', 'dim_field2': 'dim_field2_value1'}: [],
|
||||||
|
# {'dim_field1': 'dim_field1_value2', 'dim_field2': 'dim_field2_value1'}: []
|
||||||
|
# }
|
||||||
|
pos_invoice_accounting_dimensions_map = {}
|
||||||
|
for invoice in pos_invoices:
|
||||||
|
dimension_fields = [d.fieldname for d in get_checks_for_pl_and_bs_accounts()]
|
||||||
|
accounting_dimensions = frappe.db.get_value(
|
||||||
|
"POS Invoice", invoice.pos_invoice, [*dimension_fields, "cost_center", "project"], as_dict=1
|
||||||
|
)
|
||||||
|
|
||||||
|
accounting_dimensions_dic_hash = hashlib.sha256(
|
||||||
|
json.dumps(accounting_dimensions).encode()
|
||||||
|
).hexdigest()
|
||||||
|
|
||||||
|
pos_invoice_accounting_dimensions_map.setdefault(accounting_dimensions_dic_hash, [])
|
||||||
|
pos_invoice_accounting_dimensions_map[accounting_dimensions_dic_hash].append(invoice)
|
||||||
|
|
||||||
|
return pos_invoice_accounting_dimensions_map
|
||||||
|
|
||||||
|
|
||||||
def consolidate_pos_invoices(pos_invoices=None, closing_entry=None):
|
def consolidate_pos_invoices(pos_invoices=None, closing_entry=None):
|
||||||
invoices = pos_invoices or (closing_entry and closing_entry.get("pos_transactions"))
|
invoices = pos_invoices or (closing_entry and closing_entry.get("pos_transactions"))
|
||||||
if frappe.flags.in_test and not invoices:
|
if frappe.flags.in_test and not invoices:
|
||||||
@@ -532,20 +573,21 @@ def split_invoices(invoices):
|
|||||||
|
|
||||||
def create_merge_logs(invoice_by_customer, closing_entry=None):
|
def create_merge_logs(invoice_by_customer, closing_entry=None):
|
||||||
try:
|
try:
|
||||||
for customer, invoices in invoice_by_customer.items():
|
for customer, invoices_acc_dim in invoice_by_customer.items():
|
||||||
for _invoices in split_invoices(invoices):
|
for invoices in invoices_acc_dim.values():
|
||||||
merge_log = frappe.new_doc("POS Invoice Merge Log")
|
for _invoices in split_invoices(invoices):
|
||||||
merge_log.posting_date = (
|
merge_log = frappe.new_doc("POS Invoice Merge Log")
|
||||||
getdate(closing_entry.get("posting_date")) if closing_entry else nowdate()
|
merge_log.posting_date = (
|
||||||
)
|
getdate(closing_entry.get("posting_date")) if closing_entry else nowdate()
|
||||||
merge_log.posting_time = (
|
)
|
||||||
get_time(closing_entry.get("posting_time")) if closing_entry else nowtime()
|
merge_log.posting_time = (
|
||||||
)
|
get_time(closing_entry.get("posting_time")) if closing_entry else nowtime()
|
||||||
merge_log.customer = customer
|
)
|
||||||
merge_log.pos_closing_entry = closing_entry.get("name") if closing_entry else None
|
merge_log.customer = customer
|
||||||
merge_log.set("pos_invoices", _invoices)
|
merge_log.pos_closing_entry = closing_entry.get("name") if closing_entry else None
|
||||||
merge_log.save(ignore_permissions=True)
|
merge_log.set("pos_invoices", _invoices)
|
||||||
merge_log.submit()
|
merge_log.save(ignore_permissions=True)
|
||||||
|
merge_log.submit()
|
||||||
if closing_entry:
|
if closing_entry:
|
||||||
closing_entry.set_status(update=True, status="Submitted")
|
closing_entry.set_status(update=True, status="Submitted")
|
||||||
closing_entry.db_set("error_message", "")
|
closing_entry.db_set("error_message", "")
|
||||||
|
|||||||
@@ -455,3 +455,58 @@ 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`")
|
||||||
|
|
||||||
|
def test_separate_consolidated_invoice_for_different_accounting_dimensions(self):
|
||||||
|
"""
|
||||||
|
Creating 3 POS Invoices where first POS Invoice has different Cost Center than the other two.
|
||||||
|
Consolidate the Invoices.
|
||||||
|
Check whether the first POS Invoice is consolidated with a separate Sales Invoice than the other two.
|
||||||
|
Check whether the second and third POS Invoice are consolidated with the same Sales Invoice.
|
||||||
|
"""
|
||||||
|
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
|
||||||
|
|
||||||
|
frappe.db.sql("delete from `tabPOS Invoice`")
|
||||||
|
|
||||||
|
create_cost_center(cost_center_name="_Test POS Cost Center 1", is_group=0)
|
||||||
|
create_cost_center(cost_center_name="_Test POS Cost Center 2", is_group=0)
|
||||||
|
|
||||||
|
try:
|
||||||
|
test_user, pos_profile = init_user_and_profile()
|
||||||
|
|
||||||
|
pos_inv = create_pos_invoice(rate=300, do_not_submit=1)
|
||||||
|
pos_inv.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 300})
|
||||||
|
pos_inv.cost_center = "_Test POS Cost Center 1 - _TC"
|
||||||
|
pos_inv.save()
|
||||||
|
pos_inv.submit()
|
||||||
|
|
||||||
|
pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1)
|
||||||
|
pos_inv2.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3200})
|
||||||
|
pos_inv.cost_center = "_Test POS Cost Center 2 - _TC"
|
||||||
|
pos_inv2.save()
|
||||||
|
pos_inv2.submit()
|
||||||
|
|
||||||
|
pos_inv3 = create_pos_invoice(rate=2300, do_not_submit=1)
|
||||||
|
pos_inv3.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 2300})
|
||||||
|
pos_inv.cost_center = "_Test POS Cost Center 2 - _TC"
|
||||||
|
pos_inv3.save()
|
||||||
|
pos_inv3.submit()
|
||||||
|
|
||||||
|
consolidate_pos_invoices()
|
||||||
|
|
||||||
|
pos_inv.load_from_db()
|
||||||
|
self.assertTrue(frappe.db.exists("Sales Invoice", pos_inv.consolidated_invoice))
|
||||||
|
|
||||||
|
pos_inv2.load_from_db()
|
||||||
|
self.assertTrue(frappe.db.exists("Sales Invoice", pos_inv2.consolidated_invoice))
|
||||||
|
|
||||||
|
self.assertFalse(pos_inv.consolidated_invoice == pos_inv3.consolidated_invoice)
|
||||||
|
|
||||||
|
pos_inv3.load_from_db()
|
||||||
|
self.assertTrue(frappe.db.exists("Sales Invoice", pos_inv3.consolidated_invoice))
|
||||||
|
|
||||||
|
self.assertTrue(pos_inv2.consolidated_invoice == pos_inv3.consolidated_invoice)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
frappe.set_user("Administrator")
|
||||||
|
frappe.db.sql("delete from `tabPOS Profile`")
|
||||||
|
frappe.db.sql("delete from `tabPOS Invoice`")
|
||||||
|
|||||||
Reference in New Issue
Block a user