From 17771a55fb7dee46aa7c3428a8d4951468de9a2f Mon Sep 17 00:00:00 2001 From: Ritvik Sardana Date: Tue, 1 Aug 2023 19:28:40 +0530 Subject: [PATCH 01/10] fix: added code for batched items in POS --- .../doctype/pos_invoice/pos_invoice.py | 9 ++-- .../pos_invoice_merge_log.py | 48 ++++++++++++++----- 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index 4b2fcec75791..0c481fa71dff 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -276,10 +276,10 @@ def validate_payment_amount(self): if self.is_return and entry.amount > 0: frappe.throw(_("Row #{0} (Payment Table): Amount must be negative").format(entry.idx)) - if self.is_return: - invoice_total = self.rounded_total or self.grand_total - if total_amount_in_payments and total_amount_in_payments < invoice_total: - frappe.throw(_("Total payments amount can't be greater than {}").format(-invoice_total)) + # if self.is_return: + # invoice_total = self.rounded_total or self.grand_total + # if total_amount_in_payments and total_amount_in_payments < invoice_total: + # frappe.throw(_("Total payments amount can't be greater than {}").format(-invoice_total)) def validate_loyalty_transaction(self): if self.redeem_loyalty_points and ( @@ -595,7 +595,6 @@ def get_pos_reserved_qty(item_code, warehouse): .where( (p_inv.name == p_item.parent) & (IfNull(p_inv.consolidated_invoice, "") == "") - & (p_inv.is_return == 0) & (p_item.docstatus == 1) & (p_item.item_code == item_code) & (p_item.warehouse == warehouse) diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py index d8cbcc141bda..da69e1b12bc0 100644 --- a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py +++ b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py @@ -83,20 +83,30 @@ def on_submit(self): pos_invoice_docs = [ frappe.get_cached_doc("POS Invoice", d.pos_invoice) for d in self.pos_invoices ] + batched_invoices = self.get_batched_invoices(pos_invoice_docs) - returns = [d for d in pos_invoice_docs if d.get("is_return") == 1] - sales = [d for d in pos_invoice_docs if d.get("is_return") == 0] + for invoice in batched_invoices: + sales_invoice, credit_note = "", "" + if not invoice[0].get("is_return"): + sales_invoice = self.process_merging_into_sales_invoice(invoice) + else: + credit_note = self.process_merging_into_credit_note(invoice) - sales_invoice, credit_note = "", "" - if returns: - credit_note = self.process_merging_into_credit_note(returns) + self.save() # save consolidated_sales_invoice & consolidated_credit_note ref in merge log + self.update_pos_invoices(pos_invoice_docs, sales_invoice, credit_note) - if sales: - sales_invoice = self.process_merging_into_sales_invoice(sales) + # returns = [d for d in pos_invoice_docs if d.get("is_return") == 1] + # sales = [d for d in pos_invoice_docs if d.get("is_return") == 0] - self.save() # save consolidated_sales_invoice & consolidated_credit_note ref in merge log + # sales_invoice, credit_note = "", "" + # if returns: + # credit_note = self.process_merging_into_credit_note(returns) - self.update_pos_invoices(pos_invoice_docs, sales_invoice, credit_note) + # if sales: + # sales_invoice = self.process_merging_into_sales_invoice(sales) + + # self.save() # save consolidated_sales_invoice & consolidated_credit_note ref in merge log + # self.update_pos_invoices(pos_invoice_docs, sales_invoice, credit_note) def on_cancel(self): pos_invoice_docs = [ @@ -108,7 +118,6 @@ def on_cancel(self): def process_merging_into_sales_invoice(self, data): sales_invoice = self.get_new_sales_invoice() - sales_invoice = self.merge_pos_invoice_into(sales_invoice, data) sales_invoice.is_consolidated = 1 @@ -276,6 +285,21 @@ def cancel_linked_invoices(self): si.flags.ignore_validate = True si.cancel() + def get_batched_invoices(self, pos_invoice_docs): + grouped_batch = [] + current_batch = [] + for item in pos_invoice_docs: + if not current_batch: + current_batch.append(item) + elif current_batch[-1].get("is_return") != item.get("is_return"): + grouped_batch.append(current_batch) + current_batch = [item] + else: + current_batch.append(item) + + grouped_batch.append(current_batch) + return grouped_batch + def update_item_wise_tax_detail(consolidate_tax_row, tax_row): consolidated_tax_detail = json.loads(consolidate_tax_row.item_wise_tax_detail) @@ -385,13 +409,15 @@ def split_invoices(invoices): for d in invoices if d.is_return and d.return_against ] + print(pos_return_docs, invoices, _invoices, sep="-") + # breakpoint() for pos_invoice in pos_return_docs: for item in pos_invoice.items: if not item.serial_no and not item.serial_and_batch_bundle: continue return_against_is_added = any( - d for d in _invoices if d.pos_invoice == pos_invoice.return_against + d for d in invoices if d.pos_invoice == pos_invoice.return_against ) if return_against_is_added: break From 5b1aa07ecb7e36e71cd61914b392fa0dffaf76b4 Mon Sep 17 00:00:00 2001 From: Ritvik Sardana Date: Thu, 3 Aug 2023 16:10:28 +0530 Subject: [PATCH 02/10] fix: fixed SABB error --- .../pos_invoice_merge_log.py | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py index da69e1b12bc0..9978912ecca6 100644 --- a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py +++ b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py @@ -171,21 +171,23 @@ def merge_pos_invoice_into(self, invoice, data): for item in doc.get("items"): found = False - for i in items: - if ( - i.item_code == item.item_code - and not i.serial_no - and not i.batch_no - and i.uom == item.uom - and i.net_rate == item.net_rate - and i.warehouse == item.warehouse - ): - found = True - i.qty = i.qty + item.qty - i.amount = i.amount + item.net_amount - i.net_amount = i.amount - i.base_amount = i.base_amount + item.base_net_amount - i.base_net_amount = i.base_amount + if not item.serial_and_batch_bundle: + for i in items: + + if ( + i.item_code == item.item_code + and not i.serial_no + and not i.batch_no + and i.uom == item.uom + and i.net_rate == item.net_rate + and i.warehouse == item.warehouse + ): + found = True + i.qty = i.qty + item.qty + i.amount = i.amount + item.net_amount + i.net_amount = i.amount + i.base_amount = i.base_amount + item.base_net_amount + i.base_net_amount = i.base_amount if not found: item.rate = item.net_rate From c9d5a623504b6f9f580f72d19d572029ba99f1e8 Mon Sep 17 00:00:00 2001 From: Ritvik Sardana Date: Fri, 4 Aug 2023 16:47:49 +0530 Subject: [PATCH 03/10] fix: POS Runtime Effect completed --- .../doctype/pos_invoice/pos_invoice.py | 1 + .../pos_invoice_merge_log.py | 75 ++++++------------- .../serial_and_batch_bundle.py | 11 ++- 3 files changed, 33 insertions(+), 54 deletions(-) diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index 0c481fa71dff..ac39877f88c4 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -542,6 +542,7 @@ def get_stock_availability(item_code, warehouse): is_stock_item = True bin_qty = get_bin_qty(item_code, warehouse) pos_sales_qty = get_pos_reserved_qty(item_code, warehouse) + return bin_qty - pos_sales_qty, is_stock_item else: is_stock_item = True diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py index 9978912ecca6..c8f14220c155 100644 --- a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py +++ b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py @@ -83,30 +83,19 @@ def on_submit(self): pos_invoice_docs = [ frappe.get_cached_doc("POS Invoice", d.pos_invoice) for d in self.pos_invoices ] - batched_invoices = self.get_batched_invoices(pos_invoice_docs) - for invoice in batched_invoices: - sales_invoice, credit_note = "", "" - if not invoice[0].get("is_return"): - sales_invoice = self.process_merging_into_sales_invoice(invoice) - else: - credit_note = self.process_merging_into_credit_note(invoice) + returns = [d for d in pos_invoice_docs if d.get("is_return") == 1] + sales = [d for d in pos_invoice_docs if d.get("is_return") == 0] - self.save() # save consolidated_sales_invoice & consolidated_credit_note ref in merge log - self.update_pos_invoices(pos_invoice_docs, sales_invoice, credit_note) + sales_invoice, credit_note = "", "" + if returns: + credit_note = self.process_merging_into_credit_note(returns) - # returns = [d for d in pos_invoice_docs if d.get("is_return") == 1] - # sales = [d for d in pos_invoice_docs if d.get("is_return") == 0] + if sales: + sales_invoice = self.process_merging_into_sales_invoice(sales) - # sales_invoice, credit_note = "", "" - # if returns: - # credit_note = self.process_merging_into_credit_note(returns) - - # if sales: - # sales_invoice = self.process_merging_into_sales_invoice(sales) - - # self.save() # save consolidated_sales_invoice & consolidated_credit_note ref in merge log - # self.update_pos_invoices(pos_invoice_docs, sales_invoice, credit_note) + self.save() # save consolidated_sales_invoice & consolidated_credit_note ref in merge log + self.update_pos_invoices(pos_invoice_docs, sales_invoice, credit_note) def on_cancel(self): pos_invoice_docs = [ @@ -171,23 +160,20 @@ def merge_pos_invoice_into(self, invoice, data): for item in doc.get("items"): found = False - if not item.serial_and_batch_bundle: - for i in items: - - if ( - i.item_code == item.item_code - and not i.serial_no - and not i.batch_no - and i.uom == item.uom - and i.net_rate == item.net_rate - and i.warehouse == item.warehouse - ): - found = True - i.qty = i.qty + item.qty - i.amount = i.amount + item.net_amount - i.net_amount = i.amount - i.base_amount = i.base_amount + item.base_net_amount - i.base_net_amount = i.base_amount + for i in items: + if ( + i.item_code == item.item_code + and not i.serial_and_batch_bundle + and i.uom == item.uom + and i.net_rate == item.net_rate + and i.warehouse == item.warehouse + ): + found = True + i.qty = i.qty + item.qty + i.amount = i.amount + item.net_amount + i.net_amount = i.amount + i.base_amount = i.base_amount + item.base_net_amount + i.base_net_amount = i.base_amount if not found: item.rate = item.net_rate @@ -287,21 +273,6 @@ def cancel_linked_invoices(self): si.flags.ignore_validate = True si.cancel() - def get_batched_invoices(self, pos_invoice_docs): - grouped_batch = [] - current_batch = [] - for item in pos_invoice_docs: - if not current_batch: - current_batch.append(item) - elif current_batch[-1].get("is_return") != item.get("is_return"): - grouped_batch.append(current_batch) - current_batch = [item] - else: - current_batch.append(item) - - grouped_batch.append(current_batch) - return grouped_batch - def update_item_wise_tax_detail(consolidate_tax_row, tax_row): consolidated_tax_detail = json.loads(consolidate_tax_row.item_wise_tax_detail) diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index 43bd7ac78cb5..fcf2bce43474 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -3,7 +3,7 @@ import collections import csv -from collections import defaultdict +from collections import Counter, defaultdict from typing import Dict, List import frappe @@ -1197,6 +1197,7 @@ def get_reserved_serial_nos_for_pos(kwargs): filters=[ ["POS Invoice", "consolidated_invoice", "is", "not set"], ["POS Invoice", "docstatus", "=", 1], + ["POS Invoice", "is_return", "=", 0], ["POS Invoice Item", "item_code", "=", kwargs.item_code], ["POS Invoice", "name", "!=", kwargs.ignore_voucher_no], ], @@ -1242,8 +1243,14 @@ def get_reserved_serial_nos_for_pos(kwargs): child_doc, parent_doc, ignore_voucher_detail_no=kwargs.get("ignore_voucher_detail_no") ) ) + # Counter is used to create a hashmap of serial nos, which contains count of each serial no + # ignore serial nos inlcudes serial nos which are sold and returned + # so we need to subtract returned serial nos from ignore serial nos after creating a counter of each - return list(set(ignore_serial_nos) - set(returned_serial_nos)) + ignore_serial_nos_counter = Counter(ignore_serial_nos) + returned_serial_nos_counter = Counter(returned_serial_nos) + + return list(ignore_serial_nos_counter - returned_serial_nos_counter) def get_reserved_batches_for_pos(kwargs): From 510543680b3683ced4fb609f50381a688cd9ccc4 Mon Sep 17 00:00:00 2001 From: Ritvik Sardana Date: Fri, 4 Aug 2023 16:55:30 +0530 Subject: [PATCH 04/10] fix: batched items in POS --- .../pos_invoice_merge_log.py | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py index c8f14220c155..78a20e8cb4c1 100644 --- a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py +++ b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py @@ -83,19 +83,17 @@ def on_submit(self): pos_invoice_docs = [ frappe.get_cached_doc("POS Invoice", d.pos_invoice) for d in self.pos_invoices ] + batched_invoices = self.get_batched_invoices(pos_invoice_docs) - returns = [d for d in pos_invoice_docs if d.get("is_return") == 1] - sales = [d for d in pos_invoice_docs if d.get("is_return") == 0] + for invoice in batched_invoices: + sales_invoice, credit_note = "", "" + if not invoice[0].get("is_return"): + sales_invoice = self.process_merging_into_sales_invoice(invoice) + else: + credit_note = self.process_merging_into_credit_note(invoice) - sales_invoice, credit_note = "", "" - if returns: - credit_note = self.process_merging_into_credit_note(returns) - - if sales: - sales_invoice = self.process_merging_into_sales_invoice(sales) - - self.save() # save consolidated_sales_invoice & consolidated_credit_note ref in merge log - self.update_pos_invoices(pos_invoice_docs, sales_invoice, credit_note) + self.save() # save consolidated_sales_invoice & consolidated_credit_note ref in merge log + self.update_pos_invoices(pos_invoice_docs, sales_invoice, credit_note) def on_cancel(self): pos_invoice_docs = [ @@ -273,6 +271,21 @@ def cancel_linked_invoices(self): si.flags.ignore_validate = True si.cancel() + def get_batched_invoices(self, pos_invoice_docs): + grouped_batch = [] + current_batch = [] + for item in pos_invoice_docs: + if not current_batch: + current_batch.append(item) + elif current_batch[-1].get("is_return") != item.get("is_return"): + grouped_batch.append(current_batch) + current_batch = [item] + else: + current_batch.append(item) + + grouped_batch.append(current_batch) + return grouped_batch + def update_item_wise_tax_detail(consolidate_tax_row, tax_row): consolidated_tax_detail = json.loads(consolidate_tax_row.item_wise_tax_detail) From dbc000d6551859db9999c13ca944ae90e676d573 Mon Sep 17 00:00:00 2001 From: Ritvik Sardana Date: Sat, 5 Aug 2023 11:23:07 +0530 Subject: [PATCH 05/10] fix: batched items method giving wrong quantity, so changed it back to previous way --- .../doctype/pos_invoice/pos_invoice.py | 8 +++---- .../pos_invoice_merge_log.py | 23 ++++++++++--------- .../serial_and_batch_bundle.py | 4 +--- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index ac39877f88c4..89a96118ec43 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -276,10 +276,10 @@ def validate_payment_amount(self): if self.is_return and entry.amount > 0: frappe.throw(_("Row #{0} (Payment Table): Amount must be negative").format(entry.idx)) - # if self.is_return: - # invoice_total = self.rounded_total or self.grand_total - # if total_amount_in_payments and total_amount_in_payments < invoice_total: - # frappe.throw(_("Total payments amount can't be greater than {}").format(-invoice_total)) + if self.is_return: + invoice_total = self.rounded_total or self.grand_total + if total_amount_in_payments and total_amount_in_payments < invoice_total: + frappe.throw(_("Total payments amount can't be greater than {}").format(-invoice_total)) def validate_loyalty_transaction(self): if self.redeem_loyalty_points and ( diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py index 78a20e8cb4c1..4f46aa153a7f 100644 --- a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py +++ b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py @@ -83,17 +83,19 @@ def on_submit(self): pos_invoice_docs = [ frappe.get_cached_doc("POS Invoice", d.pos_invoice) for d in self.pos_invoices ] - batched_invoices = self.get_batched_invoices(pos_invoice_docs) - for invoice in batched_invoices: - sales_invoice, credit_note = "", "" - if not invoice[0].get("is_return"): - sales_invoice = self.process_merging_into_sales_invoice(invoice) - else: - credit_note = self.process_merging_into_credit_note(invoice) + returns = [d for d in pos_invoice_docs if d.get("is_return") == 1] + sales = [d for d in pos_invoice_docs if d.get("is_return") == 0] + + sales_invoice, credit_note = "", "" + if returns: + credit_note = self.process_merging_into_credit_note(returns) - self.save() # save consolidated_sales_invoice & consolidated_credit_note ref in merge log - self.update_pos_invoices(pos_invoice_docs, sales_invoice, credit_note) + if sales: + sales_invoice = self.process_merging_into_sales_invoice(sales) + + self.save() # save consolidated_sales_invoice & consolidated_credit_note ref in merge log + self.update_pos_invoices(pos_invoice_docs, sales_invoice, credit_note) def on_cancel(self): pos_invoice_docs = [ @@ -395,8 +397,7 @@ def split_invoices(invoices): for d in invoices if d.is_return and d.return_against ] - print(pos_return_docs, invoices, _invoices, sep="-") - # breakpoint() + for pos_invoice in pos_return_docs: for item in pos_invoice.items: if not item.serial_no and not item.serial_and_batch_bundle: diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index fcf2bce43474..1f90c5bf7a53 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -1215,7 +1215,6 @@ def get_reserved_serial_nos_for_pos(kwargs): for d in get_serial_batch_ledgers(kwargs.item_code, docstatus=1, name=ids): ignore_serial_nos.append(d.serial_no) - # Will be deprecated in v16 returned_serial_nos = [] for pos_invoice in pos_invoices: if pos_invoice.serial_no: @@ -1244,8 +1243,7 @@ def get_reserved_serial_nos_for_pos(kwargs): ) ) # Counter is used to create a hashmap of serial nos, which contains count of each serial no - # ignore serial nos inlcudes serial nos which are sold and returned - # so we need to subtract returned serial nos from ignore serial nos after creating a counter of each + # so we subtract returned serial nos from ignore serial nos after creating a counter of each to get the items which we need to ignore(which are sold) ignore_serial_nos_counter = Counter(ignore_serial_nos) returned_serial_nos_counter = Counter(returned_serial_nos) From 526f1d18fb0ca06f1e729227e41db6232095d07d Mon Sep 17 00:00:00 2001 From: Ritvik Sardana Date: Thu, 10 Aug 2023 17:35:12 +0530 Subject: [PATCH 06/10] fix: added test for runtime effect --- .../pos_closing_entry/pos_closing_entry.js | 1 + .../pos_closing_entry/pos_closing_entry.json | 3 +- .../test_pos_closing_entry.py | 48 +++++++++++++++++++ .../pos_invoice_merge_log.py | 15 ------ 4 files changed, 51 insertions(+), 16 deletions(-) diff --git a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js index a6c0102a7f91..8eed57338c6c 100644 --- a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js +++ b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js @@ -185,6 +185,7 @@ function refresh_payments(d, frm) { } if (payment) { payment.expected_amount += flt(p.amount); + payment.closing_amount = payment.expected_amount; payment.difference = payment.closing_amount - payment.expected_amount; } else { frm.add_child("payment_reconciliation", { diff --git a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.json b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.json index 9d15e6cf357a..a98a24c463a9 100644 --- a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.json +++ b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.json @@ -221,6 +221,7 @@ "read_only": 1 }, { + "default": "Now", "fieldname": "posting_time", "fieldtype": "Time", "label": "Posting Time", @@ -235,7 +236,7 @@ "link_fieldname": "pos_closing_entry" } ], - "modified": "2022-08-01 11:37:14.991228", + "modified": "2023-08-10 16:25:49.322697", "modified_by": "Administrator", "module": "Accounts", "name": "POS Closing Entry", diff --git a/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py index 1deb3c52ac6a..d2eba1e97762 100644 --- a/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py +++ b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py @@ -8,9 +8,11 @@ from erpnext.accounts.doctype.pos_closing_entry.pos_closing_entry import ( make_closing_entry_from_opening, ) +from erpnext.accounts.doctype.pos_invoice.pos_invoice import make_sales_return from erpnext.accounts.doctype.pos_invoice.test_pos_invoice import create_pos_invoice from erpnext.accounts.doctype.pos_opening_entry.test_pos_opening_entry import create_opening_entry from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile +from erpnext.selling.page.point_of_sale.point_of_sale import get_items from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry @@ -67,6 +69,36 @@ def test_pos_closing_without_item_code(self): self.assertTrue(pcv_doc.name) + def test_pos_qty_for_item(self): + """ + Test if quantity is calculated correctly for an item in POS Closing Entry + """ + test_user, pos_profile = init_user_and_profile() + opening_entry = create_opening_entry(pos_profile, test_user.name) + + test_item_qty = get_test_item_qty(pos_profile) + + pos_inv1 = create_pos_invoice(rate=3500, do_not_submit=1) + pos_inv1.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3500}) + pos_inv1.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_inv2.submit() + + # make return entry of pos_inv2 + pos_return = make_sales_return(pos_inv2.name) + pos_return.paid_amount = pos_return.grand_total + pos_return.save() + pos_return.submit() + + pcv_doc = make_closing_entry_from_opening(opening_entry) + pcv_doc.submit() + + opening_entry = create_opening_entry(pos_profile, test_user.name) + test_item_qty_after_sales = get_test_item_qty(pos_profile) + self.assertEqual(test_item_qty_after_sales, test_item_qty - 1) + def test_cancelling_of_pos_closing_entry(self): test_user, pos_profile = init_user_and_profile() opening_entry = create_opening_entry(pos_profile, test_user.name) @@ -123,3 +155,19 @@ def init_user_and_profile(**args): pos_profile.save() return test_user, pos_profile + + +def get_test_item_qty(pos_profile): + test_item_pos = get_items( + start=0, + page_length=40, + price_list="Standard Selling", + pos_profile=pos_profile.name, + search_term="_Test Item", + item_group="All Item Groups", + ) + + test_item_qty = [item for item in test_item_pos["items"] if item["item_code"] == "_Test Item"][0][ + "actual_qty" + ] + return test_item_qty diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py index 4f46aa153a7f..3a684d4bba45 100644 --- a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py +++ b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py @@ -273,21 +273,6 @@ def cancel_linked_invoices(self): si.flags.ignore_validate = True si.cancel() - def get_batched_invoices(self, pos_invoice_docs): - grouped_batch = [] - current_batch = [] - for item in pos_invoice_docs: - if not current_batch: - current_batch.append(item) - elif current_batch[-1].get("is_return") != item.get("is_return"): - grouped_batch.append(current_batch) - current_batch = [item] - else: - current_batch.append(item) - - grouped_batch.append(current_batch) - return grouped_batch - def update_item_wise_tax_detail(consolidate_tax_row, tax_row): consolidated_tax_detail = json.loads(consolidate_tax_row.item_wise_tax_detail) From f6c055cca9ed489151ae526531ff8b4b8ba5fe5f Mon Sep 17 00:00:00 2001 From: Ritvik Sardana Date: Thu, 10 Aug 2023 18:15:23 +0530 Subject: [PATCH 07/10] fix: now time set in closing POS --- erpnext/selling/page/point_of_sale/pos_controller.js | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/selling/page/point_of_sale/pos_controller.js b/erpnext/selling/page/point_of_sale/pos_controller.js index 720d142ca073..db6255a4bee4 100644 --- a/erpnext/selling/page/point_of_sale/pos_controller.js +++ b/erpnext/selling/page/point_of_sale/pos_controller.js @@ -225,6 +225,7 @@ erpnext.PointOfSale.Controller = class { voucher.pos_opening_entry = this.pos_opening; voucher.period_end_date = frappe.datetime.now_datetime(); voucher.posting_date = frappe.datetime.now_date(); + voucher.posting_time = frappe.datetime.now_time(); frappe.set_route('Form', 'POS Closing Entry', voucher.name); } From 68df3f9729940b2f241379e85e20ac9fb8f182ec Mon Sep 17 00:00:00 2001 From: Ritvik Sardana Date: Mon, 14 Aug 2023 11:44:47 +0530 Subject: [PATCH 08/10] fix: get_items call improved --- .../doctype/pos_closing_entry/test_pos_closing_entry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py index d2eba1e97762..c551fdc5904a 100644 --- a/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py +++ b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py @@ -160,7 +160,7 @@ def init_user_and_profile(**args): def get_test_item_qty(pos_profile): test_item_pos = get_items( start=0, - page_length=40, + page_length=5, price_list="Standard Selling", pos_profile=pos_profile.name, search_term="_Test Item", From d4cc9daca1ac4ebe56828434181936f30e579c13 Mon Sep 17 00:00:00 2001 From: Ritvik Sardana Date: Mon, 14 Aug 2023 11:52:49 +0530 Subject: [PATCH 09/10] chore: code clean up --- .../doctype/pos_closing_entry/test_pos_closing_entry.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py index c551fdc5904a..93ba90ad9f99 100644 --- a/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py +++ b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py @@ -167,7 +167,7 @@ def get_test_item_qty(pos_profile): item_group="All Item Groups", ) - test_item_qty = [item for item in test_item_pos["items"] if item["item_code"] == "_Test Item"][0][ - "actual_qty" - ] + test_item_qty = [item for item in test_item_pos["items"] if item["item_code"] == "_Test Item"][ + 0 + ].get("actual_qty") return test_item_qty From 0d95fc0f20900b0af52d331602a646428225321f Mon Sep 17 00:00:00 2001 From: Ritvik Sardana Date: Wed, 16 Aug 2023 11:41:24 +0530 Subject: [PATCH 10/10] fix: test_serial_no_case_1 test case works --- .../doctype/pos_invoice_merge_log/pos_invoice_merge_log.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py index 3a684d4bba45..b587ce603f42 100644 --- a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py +++ b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py @@ -389,7 +389,7 @@ def split_invoices(invoices): continue return_against_is_added = any( - d for d in invoices if d.pos_invoice == pos_invoice.return_against + d for d in _invoices if d.pos_invoice == pos_invoice.return_against ) if return_against_is_added: break