feat: SCR return

This commit is contained in:
Sagar Sharma 2022-05-18 22:42:25 +05:30
parent 323bdf85ce
commit e9b28452e4
3 changed files with 91 additions and 18 deletions

View File

@ -77,7 +77,7 @@ def validate_returned_items(doc):
if doc.doctype != "Purchase Invoice":
select_fields += ",serial_no, batch_no"
if doc.doctype in ["Purchase Invoice", "Purchase Receipt"]:
if doc.doctype in ["Purchase Invoice", "Purchase Receipt", "Subcontracting Receipt"]:
select_fields += ",rejected_qty, received_qty"
for d in frappe.db.sql(
@ -161,7 +161,7 @@ def validate_returned_items(doc):
def validate_quantity(doc, args, ref, valid_items, already_returned_items):
fields = ["stock_qty"]
if doc.doctype in ["Purchase Receipt", "Purchase Invoice"]:
if doc.doctype in ["Purchase Receipt", "Purchase Invoice", "Subcontracting Receipt"]:
fields.extend(["received_qty", "rejected_qty"])
already_returned_data = already_returned_items.get(args.item_code) or {}
@ -224,7 +224,7 @@ def get_ref_item_dict(valid_items, ref_item_row):
if ref_item_row.get("rate", 0) > item_dict["rate"]:
item_dict["rate"] = ref_item_row.get("rate", 0)
if ref_item_row.parenttype in ["Purchase Invoice", "Purchase Receipt"]:
if ref_item_row.parenttype in ["Purchase Invoice", "Purchase Receipt", "Subcontracting Receipt"]:
item_dict["received_qty"] += ref_item_row.received_qty
item_dict["rejected_qty"] += ref_item_row.rejected_qty
@ -239,7 +239,7 @@ def get_ref_item_dict(valid_items, ref_item_row):
def get_already_returned_items(doc):
column = "child.item_code, sum(abs(child.qty)) as qty, sum(abs(child.stock_qty)) as stock_qty"
if doc.doctype in ["Purchase Invoice", "Purchase Receipt"]:
if doc.doctype in ["Purchase Invoice", "Purchase Receipt", "Subcontracting Receipt"]:
column += """, sum(abs(child.rejected_qty) * child.conversion_factor) as rejected_qty,
sum(abs(child.received_qty) * child.conversion_factor) as received_qty"""
@ -281,17 +281,21 @@ def get_returned_qty_map_for_row(return_against, party, row_name, doctype):
child_doctype = doctype + " Item"
reference_field = "dn_detail" if doctype == "Delivery Note" else frappe.scrub(child_doctype)
if doctype in ("Purchase Receipt", "Purchase Invoice"):
if doctype in ("Purchase Receipt", "Purchase Invoice", "Subcontracting Receipt"):
party_type = "supplier"
else:
party_type = "customer"
fields = [
"sum(abs(`tab{0}`.qty)) as qty".format(child_doctype),
"sum(abs(`tab{0}`.stock_qty)) as stock_qty".format(child_doctype),
]
if doctype in ("Purchase Receipt", "Purchase Invoice"):
if doctype != "Subcontracting Receipt":
fields += [
"sum(abs(`tab{0}`.stock_qty)) as stock_qty".format(child_doctype),
]
if doctype in ("Purchase Receipt", "Purchase Invoice", "Subcontracting Receipt"):
fields += [
"sum(abs(`tab{0}`.rejected_qty)) as rejected_qty".format(child_doctype),
"sum(abs(`tab{0}`.received_qty)) as received_qty".format(child_doctype),
@ -397,7 +401,7 @@ def make_return_doc(doctype, source_name, target_doc=None):
if serial_nos:
target_doc.serial_no = "\n".join(serial_nos)
if doctype == "Purchase Receipt":
if doctype in ["Purchase Receipt", "Subcontracting Receipt"]:
returned_qty_map = get_returned_qty_map_for_row(
source_parent.name, source_parent.supplier, source_doc.name, doctype
)
@ -409,15 +413,24 @@ def make_return_doc(doctype, source_name, target_doc=None):
)
target_doc.qty = -1 * flt(source_doc.qty - (returned_qty_map.get("qty") or 0))
target_doc.stock_qty = -1 * flt(source_doc.stock_qty - (returned_qty_map.get("stock_qty") or 0))
target_doc.received_stock_qty = -1 * flt(
source_doc.received_stock_qty - (returned_qty_map.get("received_stock_qty") or 0)
)
if hasattr(target_doc, "stock_qty"):
target_doc.stock_qty = -1 * flt(
source_doc.stock_qty - (returned_qty_map.get("stock_qty") or 0)
)
target_doc.received_stock_qty = -1 * flt(
source_doc.received_stock_qty - (returned_qty_map.get("received_stock_qty") or 0)
)
target_doc.purchase_order = source_doc.purchase_order
target_doc.purchase_order_item = source_doc.purchase_order_item
target_doc.rejected_warehouse = source_doc.rejected_warehouse
target_doc.purchase_receipt_item = source_doc.name
if doctype == "Subcontracting Receipt":
target_doc.subcontracting_order = source_doc.subcontracting_order
target_doc.subcontracting_order_item = source_doc.subcontracting_order_item
target_doc.rejected_warehouse = source_doc.rejected_warehouse
target_doc.subcontracting_receipt_item = source_doc.name
else:
target_doc.purchase_order = source_doc.purchase_order
target_doc.purchase_order_item = source_doc.purchase_order_item
target_doc.rejected_warehouse = source_doc.rejected_warehouse
target_doc.purchase_receipt_item = source_doc.name
elif doctype == "Purchase Invoice":
returned_qty_map = get_returned_qty_map_for_row(
@ -529,7 +542,7 @@ def get_rate_for_return(
item_row,
)
if voucher_type in ("Purchase Receipt", "Purchase Invoice"):
if voucher_type in ("Purchase Receipt", "Purchase Invoice", "Subcontracting Receipt"):
select_field = "incoming_rate"
else:
select_field = "abs(stock_value_difference / actual_qty)"
@ -564,6 +577,7 @@ def get_return_against_item_fields(voucher_type):
"Purchase Invoice": "purchase_invoice_item",
"Delivery Note": "dn_detail",
"Sales Invoice": "sales_invoice_item",
"Subcontracting Receipt": "subcontracting_receipt_item",
}
return return_against_item_fields[voucher_type]

View File

@ -76,7 +76,7 @@ frappe.ui.form.on('Subcontracting Receipt', {
}, __("View"));
}
if (!frm.doc.is_return && frm.doc.docstatus == 1) {
if (!frm.doc.is_return && frm.doc.docstatus == 1 && frm.doc.per_returned < 100) {
frm.add_custom_button('Subcontract Return', function () {
frappe.model.open_mapped_doc({
method: 'erpnext.subcontracting.doctype.subcontracting_receipt.subcontracting_receipt.make_subcontract_return',

View File

@ -21,6 +21,7 @@ from erpnext.controllers.tests.test_subcontracting_controller import (
set_backflush_based_on,
)
from erpnext.stock.doctype.item.test_item import make_item
from erpnext.controllers.sales_and_purchase_return import make_return_doc
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
from erpnext.subcontracting.doctype.subcontracting_order.subcontracting_order import make_subcontracting_receipt
@ -272,6 +273,64 @@ class TestSubcontractingReceipt(FrappeTestCase):
for row in scr.supplied_items:
self.assertEqual(transferred_batch.get(row.batch_no), row.consumed_qty)
def test_subcontracting_order_partial_return(self):
sco = get_subcontracting_order()
rm_items = get_rm_items(sco.supplied_items)
itemwise_details = make_stock_in_entry(rm_items=rm_items)
make_stock_transfer_entry(
sco_no=sco.name,
rm_items=rm_items,
itemwise_details=copy.deepcopy(itemwise_details),
)
scr1 = make_subcontracting_receipt(sco.name)
scr1.save()
scr1.submit()
scr1_return = make_return_subcontracting_receipt(scr_name=scr1.name, qty=-3)
scr1.load_from_db()
self.assertEqual(scr1_return.status, "Return")
self.assertEqual(scr1.items[0].returned_qty, 3)
scr2_return = make_return_subcontracting_receipt(scr_name=scr1.name, qty=-7)
scr1.load_from_db()
self.assertEqual(scr2_return.status, "Return")
self.assertEqual(scr1.status, "Return Issued")
self.assertEqual(scr1.items[0].returned_qty, 10)
def test_subcontracting_order_over_return(self):
sco = get_subcontracting_order()
rm_items = get_rm_items(sco.supplied_items)
itemwise_details = make_stock_in_entry(rm_items=rm_items)
make_stock_transfer_entry(
sco_no=sco.name,
rm_items=rm_items,
itemwise_details=copy.deepcopy(itemwise_details),
)
scr1 = make_subcontracting_receipt(sco.name)
scr1.save()
scr1.submit()
from erpnext.controllers.status_updater import OverAllowanceError
args = frappe._dict(scr_name=scr1.name, qty=-15)
self.assertRaises(OverAllowanceError, make_return_subcontracting_receipt, **args)
def make_return_subcontracting_receipt(**args):
args = frappe._dict(args)
return_doc = make_return_doc("Subcontracting Receipt", args.scr_name)
return_doc.supplier_warehouse = args.supplier_warehouse or args.warehouse or "_Test Warehouse 1 - _TC"
if args.qty:
for item in return_doc.items:
item.qty = args.qty
if not args.do_not_save:
return_doc.save()
if not args.do_not_submit:
return_doc.submit()
return_doc.load_from_db()
return return_doc
def get_items(**args):
args = frappe._dict(args)