fix: Invoice against partially returned DN/PR
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index 90d1d0a..cd69dd4 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -396,19 +396,7 @@
return invoiced_qty_map
-def get_returned_qty_map_against_so(sales_orders):
- """returns a map: {so_detail: returned_qty}"""
- returned_qty_map = {}
-
- for name, returned_qty in frappe.get_all('Sales Order Item', fields = ["name", "returned_qty"],
- filters = {'parent': ('in', sales_orders), 'docstatus': 1}, as_list=1):
- if not returned_qty_map.get(name):
- returned_qty_map[name] = 0
- returned_qty_map[name] += returned_qty
-
- return returned_qty_map
-
-def get_returned_qty_map_against_dn(delivery_note):
+def get_returned_qty_map(delivery_note):
"""returns a map: {so_detail: returned_qty}"""
returned_qty_map = frappe._dict(frappe.db.sql("""select dn_item.item_code, sum(abs(dn_item.qty)) as qty
from `tabDelivery Note Item` dn_item, `tabDelivery Note` dn
@@ -425,8 +413,7 @@
def make_sales_invoice(source_name, target_doc=None):
doc = frappe.get_doc('Delivery Note', source_name)
sales_orders = [d.against_sales_order for d in doc.items]
- returned_qty_map_against_so = get_returned_qty_map_against_so(sales_orders)
- returned_qty_map_against_dn = get_returned_qty_map_against_dn(source_name)
+ returned_qty_map = get_returned_qty_map(source_name)
invoiced_qty_map = get_invoiced_qty_map(source_name)
def set_missing_values(source, target):
@@ -447,17 +434,16 @@
def update_item(source_doc, target_doc, source_parent):
target_doc.qty, returned_qty = get_pending_qty(source_doc)
- if not source_doc.so_detail:
- returned_qty_map_against_dn[source_doc.item_code] = returned_qty
+ returned_qty_map[source_doc.item_code] = returned_qty
if source_doc.serial_no and source_parent.per_billed > 0:
target_doc.serial_no = get_delivery_note_serial_no(source_doc.item_code,
target_doc.qty, source_parent.name)
def get_pending_qty(item_row):
- pending_qty = item_row.qty - invoiced_qty_map.get(item_row.name, 0) - returned_qty_map_against_so.get(item_row.so_detail, 0)
- returned_qty = flt(returned_qty_map_against_dn.get(item_row.item_code, 0))
- if not item_row.so_detail:
+ pending_qty = item_row.qty - invoiced_qty_map.get(item_row.name, 0)
+ returned_qty = flt(returned_qty_map.get(item_row.item_code, 0))
+ if returned_qty:
if returned_qty >= pending_qty:
pending_qty = 0
returned_qty -= pending_qty
diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
index 5c03121..bc95c96 100644
--- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
@@ -655,7 +655,7 @@
si = make_sales_invoice(dn.name)
self.assertEquals(si.items[0].qty, 1)
- def test_make_sales_invoice_from_dn_with_returned_qty_against_dn(self):
+ def test_make_sales_invoice_from_dn_with_returned_qty_duplicate_items(self):
from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice
dn = create_delivery_note(qty=8, do_not_submit=True)
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index e3877fb..71cf1da 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -407,10 +407,7 @@
def make_purchase_invoice(source_name, target_doc=None):
from frappe.model.mapper import get_mapped_doc
doc = frappe.get_doc('Purchase Receipt', source_name)
- purchase_orders = [d.purchase_order for d in doc.items]
- returned_qty_map_against_po = get_returned_qty_map_against_po(purchase_orders)
- returned_qty_map_against_pr = get_returned_qty_map_against_pr(source_name)
-
+ returned_qty_map = get_returned_qty_map(source_name)
invoiced_qty_map = get_invoiced_qty_map(source_name)
def set_missing_values(source, target):
@@ -424,14 +421,12 @@
def update_item(source_doc, target_doc, source_parent):
target_doc.qty, returned_qty = get_pending_qty(source_doc)
- if not source_doc.purchase_order_item:
- returned_qty_map_against_pr[source_doc.item_code] = returned_qty
+ returned_qty_map[source_doc.item_code] = returned_qty
def get_pending_qty(item_row):
- pending_qty = item_row.qty - invoiced_qty_map.get(item_row.name, 0) \
- - returned_qty_map_against_po.get(item_row.purchase_order_item, 0)
- returned_qty = flt(returned_qty_map_against_pr.get(item_row.item_code, 0))
- if not item_row.purchase_order_item:
+ pending_qty = item_row.qty - invoiced_qty_map.get(item_row.name, 0)
+ returned_qty = flt(returned_qty_map.get(item_row.item_code, 0))
+ if returned_qty:
if returned_qty >= pending_qty:
pending_qty = 0
returned_qty -= pending_qty
@@ -484,19 +479,7 @@
return invoiced_qty_map
-def get_returned_qty_map_against_po(purchase_orders):
- """returns a map: {so_detail: returned_qty}"""
- returned_qty_map = {}
-
- for name, returned_qty in frappe.get_all('Purchase Order Item', fields = ["name", "returned_qty"],
- filters = {'parent': ('in', purchase_orders), 'docstatus': 1}, as_list=1):
- if not returned_qty_map.get(name):
- returned_qty_map[name] = 0
- returned_qty_map[name] += returned_qty
-
- return returned_qty_map
-
-def get_returned_qty_map_against_pr(purchase_receipt):
+def get_returned_qty_map(purchase_receipt):
"""returns a map: {so_detail: returned_qty}"""
returned_qty_map = frappe._dict(frappe.db.sql("""select pr_item.item_code, sum(abs(pr_item.qty)) as qty
from `tabPurchase Receipt Item` pr_item, `tabPurchase Receipt` pr
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index c5ae838..d124ae4 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -418,7 +418,7 @@
pi = make_purchase_invoice(pr.name)
self.assertEquals(pi.items[0].qty, 3)
- def test_make_purchase_invoice_from_dn_with_returned_qty_against_dn(self):
+ def test_make_purchase_invoice_from_pr_with_returned_qty_duplicate_items(self):
pr1 = make_purchase_receipt(qty=8, do_not_submit=True)
pr1.append("items", {
"item_code": "_Test Item",