fix: incorrectly billed amount in the purchase receipt

(cherry picked from commit a5271fdb2e)

# Conflicts:
#	erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
This commit is contained in:
Rohit Waghchaure
2025-03-03 13:38:38 +05:30
committed by Mergify
parent 1a8bf0cf3d
commit ca94ad3a24
2 changed files with 137 additions and 1 deletions

View File

@@ -865,15 +865,19 @@ def get_billed_amount_against_po(po_items):
if not po_items:
return {}
purchase_invoice = frappe.qb.DocType("Purchase Invoice")
purchase_invoice_item = frappe.qb.DocType("Purchase Invoice Item")
query = (
frappe.qb.from_(purchase_invoice_item)
.inner_join(purchase_invoice)
.on(purchase_invoice_item.parent == purchase_invoice.name)
.select(fn.Sum(purchase_invoice_item.amount).as_("billed_amt"), purchase_invoice_item.po_detail)
.where(
(purchase_invoice_item.po_detail.isin(po_items))
& (purchase_invoice_item.docstatus == 1)
& (purchase_invoice.docstatus == 1)
& (purchase_invoice_item.pr_detail.isnull())
& (purchase_invoice.update_stock == 0)
)
.groupby(purchase_invoice_item.po_detail)
).run(as_dict=1)

View File

@@ -2731,6 +2731,138 @@ class TestPurchaseReceipt(FrappeTestCase):
self.assertEqual(return_pr.per_billed, 100)
self.assertEqual(return_pr.status, "Completed")
<<<<<<< HEAD
=======
def test_do_not_allow_to_inward_same_serial_no_multiple_times(self):
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
frappe.db.set_single_value("Stock Settings", "allow_existing_serial_no", 0)
item_code = make_item(
"Test Do Not Allow INWD Item 123", {"has_serial_no": 1, "serial_no_series": "SN-TDAISN-.#####"}
).name
pr = make_purchase_receipt(item_code=item_code, qty=1, rate=100, use_serial_batch_fields=1)
serial_no = get_serial_nos_from_bundle(pr.items[0].serial_and_batch_bundle)[0]
status = frappe.db.get_value("Serial No", serial_no, "status")
self.assertTrue(status == "Active")
make_stock_entry(
item_code=item_code,
source=pr.items[0].warehouse,
qty=1,
serial_no=serial_no,
use_serial_batch_fields=1,
)
status = frappe.db.get_value("Serial No", serial_no, "status")
self.assertFalse(status == "Active")
pr = make_purchase_receipt(
item_code=item_code, qty=1, rate=100, use_serial_batch_fields=1, do_not_submit=1
)
pr.items[0].serial_no = serial_no
pr.save()
self.assertRaises(frappe.exceptions.ValidationError, pr.submit)
frappe.db.set_single_value("Stock Settings", "allow_existing_serial_no", 1)
def test_seral_no_return_validation(self):
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import (
make_purchase_return,
)
sn_item_code = make_item(
"Test Serial No for Validation", {"has_serial_no": 1, "serial_no_series": "SN-TSNFVAL-.#####"}
).name
pr1 = make_purchase_receipt(item_code=sn_item_code, qty=5, rate=100, use_serial_batch_fields=1)
pr1_serial_nos = get_serial_nos_from_bundle(pr1.items[0].serial_and_batch_bundle)
serial_no_pr = make_purchase_receipt(
item_code=sn_item_code, qty=5, rate=100, use_serial_batch_fields=1
)
serial_no_pr_serial_nos = get_serial_nos_from_bundle(serial_no_pr.items[0].serial_and_batch_bundle)
sn_return = make_purchase_return(serial_no_pr.name)
sn_return.items[0].qty = -1
sn_return.items[0].received_qty = -1
sn_return.items[0].serial_no = pr1_serial_nos[0]
sn_return.save()
self.assertRaises(frappe.ValidationError, sn_return.submit)
sn_return = make_purchase_return(serial_no_pr.name)
sn_return.items[0].qty = -1
sn_return.items[0].received_qty = -1
sn_return.items[0].serial_no = serial_no_pr_serial_nos[0]
sn_return.save()
sn_return.submit()
def test_batch_no_return_validation(self):
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import (
make_purchase_return,
)
batch_item_code = make_item(
"Test Batch No for Validation",
{"has_batch_no": 1, "batch_number_series": "BT-TSNFVAL-.#####", "create_new_batch": 1},
).name
pr1 = make_purchase_receipt(item_code=batch_item_code, qty=5, rate=100, use_serial_batch_fields=1)
batch_no = get_batch_from_bundle(pr1.items[0].serial_and_batch_bundle)
batch_no_pr = make_purchase_receipt(
item_code=batch_item_code, qty=5, rate=100, use_serial_batch_fields=1
)
original_batch_no = get_batch_from_bundle(batch_no_pr.items[0].serial_and_batch_bundle)
batch_return = make_purchase_return(batch_no_pr.name)
batch_return.items[0].qty = -1
batch_return.items[0].received_qty = -1
batch_return.items[0].batch_no = batch_no
batch_return.save()
self.assertRaises(frappe.ValidationError, batch_return.submit)
batch_return = make_purchase_return(batch_no_pr.name)
batch_return.items[0].qty = -1
batch_return.items[0].received_qty = -1
batch_return.items[0].batch_no = original_batch_no
batch_return.save()
batch_return.submit()
def test_pr_status_based_on_invoices_with_update_stock(self):
from erpnext.buying.doctype.purchase_order.purchase_order import (
make_purchase_invoice as _make_purchase_invoice,
)
from erpnext.buying.doctype.purchase_order.purchase_order import (
make_purchase_receipt as _make_purchase_receipt,
)
from erpnext.buying.doctype.purchase_order.test_purchase_order import (
create_pr_against_po,
create_purchase_order,
)
item_code = "Test Item for PR Status Based on Invoices"
create_item(item_code)
po = create_purchase_order(item_code=item_code, qty=10)
pi = _make_purchase_invoice(po.name)
pi.update_stock = 1
pi.items[0].qty = 5
pi.submit()
po.reload()
self.assertEqual(po.per_billed, 50)
pr = _make_purchase_receipt(po.name)
self.assertEqual(pr.items[0].qty, 5)
pr.submit()
pr.reload()
self.assertEqual(pr.status, "To Bill")
>>>>>>> a5271fdb2e (fix: incorrectly billed amount in the purchase receipt)
def prepare_data_for_internal_transfer():
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier