fix: Status updater fixes in PO and SO and test coverage for return (#17491)
* fix: Status updator fixes in sales and purchase cycle * fix: Test cases for return in so and po * fix: Resolve conflicts
This commit is contained in:
parent
9da57d79b5
commit
0ae1c293d3
@ -100,6 +100,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.validate_fixed_asset()
|
self.validate_fixed_asset()
|
||||||
self.create_remarks()
|
self.create_remarks()
|
||||||
self.set_status()
|
self.set_status()
|
||||||
|
self.validate_purchase_receipt_if_update_stock()
|
||||||
validate_inter_company_party(self.doctype, self.supplier, self.company, self.inter_company_invoice_reference)
|
validate_inter_company_party(self.doctype, self.supplier, self.company, self.inter_company_invoice_reference)
|
||||||
|
|
||||||
def validate_release_date(self):
|
def validate_release_date(self):
|
||||||
@ -284,7 +285,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
|
|
||||||
def update_status_updater_args(self):
|
def update_status_updater_args(self):
|
||||||
if cint(self.update_stock):
|
if cint(self.update_stock):
|
||||||
self.status_updater.extend([{
|
self.status_updater.append({
|
||||||
'source_dt': 'Purchase Invoice Item',
|
'source_dt': 'Purchase Invoice Item',
|
||||||
'target_dt': 'Purchase Order Item',
|
'target_dt': 'Purchase Order Item',
|
||||||
'join_field': 'po_detail',
|
'join_field': 'po_detail',
|
||||||
@ -292,28 +293,29 @@ class PurchaseInvoice(BuyingController):
|
|||||||
'target_parent_dt': 'Purchase Order',
|
'target_parent_dt': 'Purchase Order',
|
||||||
'target_parent_field': 'per_received',
|
'target_parent_field': 'per_received',
|
||||||
'target_ref_field': 'qty',
|
'target_ref_field': 'qty',
|
||||||
'source_field': 'qty',
|
'source_field': 'received_qty',
|
||||||
|
'second_source_dt': 'Purchase Receipt Item',
|
||||||
|
'second_source_field': 'received_qty',
|
||||||
|
'second_join_field': 'purchase_order_item',
|
||||||
'percent_join_field':'purchase_order',
|
'percent_join_field':'purchase_order',
|
||||||
# 'percent_join_field': 'prevdoc_docname',
|
|
||||||
'overflow_type': 'receipt',
|
'overflow_type': 'receipt',
|
||||||
'extra_cond': """ and exists(select name from `tabPurchase Invoice`
|
'extra_cond': """ and exists(select name from `tabPurchase Invoice`
|
||||||
where name=`tabPurchase Invoice Item`.parent and update_stock = 1)"""
|
where name=`tabPurchase Invoice Item`.parent and update_stock = 1)"""
|
||||||
},
|
})
|
||||||
{
|
if cint(self.is_return):
|
||||||
'source_dt': 'Purchase Invoice Item',
|
self.status_updater.append({
|
||||||
'target_dt': 'Purchase Order Item',
|
'source_dt': 'Purchase Invoice Item',
|
||||||
'join_field': 'po_detail',
|
'target_dt': 'Purchase Order Item',
|
||||||
'target_field': 'returned_qty',
|
'join_field': 'po_detail',
|
||||||
'target_parent_dt': 'Purchase Order',
|
'target_field': 'returned_qty',
|
||||||
# 'target_parent_field': 'per_received',
|
'source_field': '-1 * qty',
|
||||||
# 'target_ref_field': 'qty',
|
'second_source_dt': 'Purchase Receipt Item',
|
||||||
'source_field': '-1 * qty',
|
'second_source_field': '-1 * qty',
|
||||||
# 'percent_join_field': 'prevdoc_docname',
|
'second_join_field': 'purchase_order_item',
|
||||||
# 'overflow_type': 'receipt',
|
'overflow_type': 'receipt',
|
||||||
'extra_cond': """ and exists (select name from `tabPurchase Invoice`
|
'extra_cond': """ and exists (select name from `tabPurchase Invoice`
|
||||||
where name=`tabPurchase Invoice Item`.parent and update_stock=1 and is_return=1)"""
|
where name=`tabPurchase Invoice Item`.parent and update_stock=1 and is_return=1)"""
|
||||||
}
|
})
|
||||||
])
|
|
||||||
|
|
||||||
def validate_purchase_receipt_if_update_stock(self):
|
def validate_purchase_receipt_if_update_stock(self):
|
||||||
if self.update_stock:
|
if self.update_stock:
|
||||||
@ -327,13 +329,13 @@ class PurchaseInvoice(BuyingController):
|
|||||||
|
|
||||||
self.check_prev_docstatus()
|
self.check_prev_docstatus()
|
||||||
self.update_status_updater_args()
|
self.update_status_updater_args()
|
||||||
|
self.update_prevdoc_status()
|
||||||
|
|
||||||
frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype,
|
frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype,
|
||||||
self.company, self.base_grand_total)
|
self.company, self.base_grand_total)
|
||||||
|
|
||||||
if not self.is_return:
|
if not self.is_return:
|
||||||
self.update_against_document_in_jv()
|
self.update_against_document_in_jv()
|
||||||
self.update_prevdoc_status()
|
|
||||||
self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
|
self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
|
||||||
self.update_billing_status_in_pr()
|
self.update_billing_status_in_pr()
|
||||||
|
|
||||||
@ -763,9 +765,9 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.check_on_hold_or_closed_status()
|
self.check_on_hold_or_closed_status()
|
||||||
|
|
||||||
self.update_status_updater_args()
|
self.update_status_updater_args()
|
||||||
|
self.update_prevdoc_status()
|
||||||
|
|
||||||
if not self.is_return:
|
if not self.is_return:
|
||||||
self.update_prevdoc_status()
|
|
||||||
self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
|
self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
|
||||||
self.update_billing_status_in_pr()
|
self.update_billing_status_in_pr()
|
||||||
|
|
||||||
|
@ -254,7 +254,7 @@ class SalesInvoice(SellingController):
|
|||||||
|
|
||||||
def update_status_updater_args(self):
|
def update_status_updater_args(self):
|
||||||
if cint(self.update_stock):
|
if cint(self.update_stock):
|
||||||
self.status_updater.extend([{
|
self.status_updater.append({
|
||||||
'source_dt':'Sales Invoice Item',
|
'source_dt':'Sales Invoice Item',
|
||||||
'target_dt':'Sales Order Item',
|
'target_dt':'Sales Order Item',
|
||||||
'target_parent_dt':'Sales Order',
|
'target_parent_dt':'Sales Order',
|
||||||
@ -272,21 +272,20 @@ class SalesInvoice(SellingController):
|
|||||||
'overflow_type': 'delivery',
|
'overflow_type': 'delivery',
|
||||||
'extra_cond': """ and exists(select name from `tabSales Invoice`
|
'extra_cond': """ and exists(select name from `tabSales Invoice`
|
||||||
where name=`tabSales Invoice Item`.parent and update_stock = 1)"""
|
where name=`tabSales Invoice Item`.parent and update_stock = 1)"""
|
||||||
},
|
})
|
||||||
{
|
if cint(self.is_return):
|
||||||
'source_dt': 'Sales Invoice Item',
|
self.status_updater.append({
|
||||||
'target_dt': 'Sales Order Item',
|
'source_dt': 'Sales Invoice Item',
|
||||||
'join_field': 'so_detail',
|
'target_dt': 'Sales Order Item',
|
||||||
'target_field': 'returned_qty',
|
'join_field': 'so_detail',
|
||||||
'target_parent_dt': 'Sales Order',
|
'target_field': 'returned_qty',
|
||||||
# 'target_parent_field': 'per_delivered',
|
'target_parent_dt': 'Sales Order',
|
||||||
# 'target_ref_field': 'qty',
|
'source_field': '-1 * qty',
|
||||||
'source_field': '-1 * qty',
|
'second_source_dt': 'Delivery Note Item',
|
||||||
# 'percent_join_field': 'sales_order',
|
'second_source_field': '-1 * qty',
|
||||||
# 'overflow_type': 'delivery',
|
'second_join_field': 'so_detail',
|
||||||
'extra_cond': """ and exists (select name from `tabSales Invoice` where name=`tabSales Invoice Item`.parent and update_stock=1 and is_return=1)"""
|
'extra_cond': """ and exists (select name from `tabSales Invoice` where name=`tabSales Invoice Item`.parent and update_stock=1 and is_return=1)"""
|
||||||
}
|
})
|
||||||
])
|
|
||||||
|
|
||||||
def check_credit_limit(self):
|
def check_credit_limit(self):
|
||||||
from erpnext.selling.doctype.customer.customer import check_credit_limit
|
from erpnext.selling.doctype.customer.customer import check_credit_limit
|
||||||
|
@ -108,6 +108,69 @@ class TestPurchaseOrder(unittest.TestCase):
|
|||||||
self.assertEqual(po.get("items")[0].amount, 1400)
|
self.assertEqual(po.get("items")[0].amount, 1400)
|
||||||
self.assertEqual(get_ordered_qty(), existing_ordered_qty + 3)
|
self.assertEqual(get_ordered_qty(), existing_ordered_qty + 3)
|
||||||
|
|
||||||
|
def test_update_qty(self):
|
||||||
|
po = create_purchase_order()
|
||||||
|
|
||||||
|
make_pr_against_po(po.name, 6)
|
||||||
|
|
||||||
|
po.load_from_db()
|
||||||
|
self.assertEqual(po.get("items")[0].received_qty, 6)
|
||||||
|
|
||||||
|
# Check received_qty after make_purchase_invoice without update_stock checked
|
||||||
|
pi1 = make_purchase_invoice(po.name)
|
||||||
|
pi1.get("items")[0].qty = 6
|
||||||
|
pi1.insert()
|
||||||
|
pi1.submit()
|
||||||
|
|
||||||
|
po.load_from_db()
|
||||||
|
self.assertEqual(po.get("items")[0].received_qty, 6)
|
||||||
|
|
||||||
|
# Check received_qty after make_purchase_invoice with update_stock checked
|
||||||
|
pi2 = make_purchase_invoice(po.name)
|
||||||
|
pi2.set("update_stock", 1)
|
||||||
|
pi2.get("items")[0].qty = 3
|
||||||
|
pi2.insert()
|
||||||
|
pi2.submit()
|
||||||
|
|
||||||
|
po.load_from_db()
|
||||||
|
self.assertEqual(po.get("items")[0].received_qty, 9)
|
||||||
|
|
||||||
|
def test_return_against_purchase_order(self):
|
||||||
|
po = create_purchase_order()
|
||||||
|
|
||||||
|
pr = make_pr_against_po(po.name, 6)
|
||||||
|
|
||||||
|
po.load_from_db()
|
||||||
|
self.assertEqual(po.get("items")[0].received_qty, 6)
|
||||||
|
|
||||||
|
pi2 = make_purchase_invoice(po.name)
|
||||||
|
pi2.set("update_stock", 1)
|
||||||
|
pi2.get("items")[0].qty = 3
|
||||||
|
pi2.insert()
|
||||||
|
pi2.submit()
|
||||||
|
|
||||||
|
po.load_from_db()
|
||||||
|
self.assertEqual(po.get("items")[0].received_qty, 9)
|
||||||
|
|
||||||
|
# Make return purchase receipt, purchase invoice and check quantity
|
||||||
|
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt \
|
||||||
|
import make_purchase_receipt as make_purchase_receipt_return
|
||||||
|
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice \
|
||||||
|
import make_purchase_invoice as make_purchase_invoice_return
|
||||||
|
|
||||||
|
pr1 = make_purchase_receipt_return(is_return=1, return_against=pr.name, qty=-3, do_not_submit=True)
|
||||||
|
pr1.items[0].purchase_order = po.name
|
||||||
|
pr1.items[0].purchase_order_item = po.items[0].name
|
||||||
|
pr1.submit()
|
||||||
|
|
||||||
|
pi1= make_purchase_invoice_return(is_return=1, return_against=pi2.name, qty=-1, update_stock=1, do_not_submit=True)
|
||||||
|
pi1.items[0].purchase_order = po.name
|
||||||
|
pi1.items[0].po_detail = po.items[0].name
|
||||||
|
pi1.submit()
|
||||||
|
|
||||||
|
|
||||||
|
po.load_from_db()
|
||||||
|
self.assertEqual(po.get("items")[0].received_qty, 5)
|
||||||
|
|
||||||
def test_make_purchase_invoice(self):
|
def test_make_purchase_invoice(self):
|
||||||
po = create_purchase_order(do_not_submit=True)
|
po = create_purchase_order(do_not_submit=True)
|
||||||
@ -510,6 +573,13 @@ class TestPurchaseOrder(unittest.TestCase):
|
|||||||
frappe.db.set_value("Accounts Settings", "Accounts Settings",
|
frappe.db.set_value("Accounts Settings", "Accounts Settings",
|
||||||
"unlink_advance_payment_on_cancelation_of_order", 0)
|
"unlink_advance_payment_on_cancelation_of_order", 0)
|
||||||
|
|
||||||
|
def make_pr_against_po(po, received_qty=0):
|
||||||
|
pr = make_purchase_receipt(po)
|
||||||
|
pr.get("items")[0].qty = received_qty or 5
|
||||||
|
pr.insert()
|
||||||
|
pr.submit()
|
||||||
|
return pr
|
||||||
|
|
||||||
def make_subcontracted_item(item_code):
|
def make_subcontracted_item(item_code):
|
||||||
from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
|
from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
|
||||||
|
|
||||||
|
@ -124,6 +124,44 @@ class TestSalesOrder(unittest.TestCase):
|
|||||||
so.load_from_db()
|
so.load_from_db()
|
||||||
self.assertEqual(so.get("items")[0].delivered_qty, 9)
|
self.assertEqual(so.get("items")[0].delivered_qty, 9)
|
||||||
|
|
||||||
|
def test_return_against_sales_order(self):
|
||||||
|
so = make_sales_order()
|
||||||
|
|
||||||
|
dn = create_dn_against_so(so.name, 6)
|
||||||
|
|
||||||
|
so.load_from_db()
|
||||||
|
self.assertEqual(so.get("items")[0].delivered_qty, 6)
|
||||||
|
|
||||||
|
# Check delivered_qty after make_sales_invoice with update_stock checked
|
||||||
|
si2 = make_sales_invoice(so.name)
|
||||||
|
si2.set("update_stock", 1)
|
||||||
|
si2.get("items")[0].qty = 3
|
||||||
|
si2.insert()
|
||||||
|
si2.submit()
|
||||||
|
|
||||||
|
so.load_from_db()
|
||||||
|
|
||||||
|
self.assertEqual(so.get("items")[0].delivered_qty, 9)
|
||||||
|
|
||||||
|
# Make return deliver note, sales invoice and check quantity
|
||||||
|
from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
|
||||||
|
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||||
|
|
||||||
|
dn1 = create_delivery_note(is_return=1, return_against=dn.name, qty=-3, do_not_submit=True)
|
||||||
|
dn1.items[0].against_sales_order = so.name
|
||||||
|
dn1.items[0].so_detail = so.items[0].name
|
||||||
|
dn1.submit()
|
||||||
|
|
||||||
|
si1 = create_sales_invoice(is_return=1, return_against=si2.name, qty=-1, update_stock=1, do_not_submit=True)
|
||||||
|
si1.items[0].sales_order = so.name
|
||||||
|
si1.items[0].so_detail = so.items[0].name
|
||||||
|
si1.submit()
|
||||||
|
|
||||||
|
|
||||||
|
so.load_from_db()
|
||||||
|
self.assertEqual(so.get("items")[0].delivered_qty, 5)
|
||||||
|
|
||||||
|
|
||||||
def test_reserved_qty_for_partial_delivery(self):
|
def test_reserved_qty_for_partial_delivery(self):
|
||||||
make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100)
|
make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100)
|
||||||
existing_reserved_qty = get_reserved_qty()
|
existing_reserved_qty = get_reserved_qty()
|
||||||
|
@ -52,16 +52,20 @@ class DeliveryNote(SellingController):
|
|||||||
'percent_join_field': 'against_sales_invoice',
|
'percent_join_field': 'against_sales_invoice',
|
||||||
'overflow_type': 'delivery',
|
'overflow_type': 'delivery',
|
||||||
'no_tolerance': 1
|
'no_tolerance': 1
|
||||||
},
|
|
||||||
{
|
|
||||||
'source_dt': 'Delivery Note Item',
|
|
||||||
'target_dt': 'Sales Order Item',
|
|
||||||
'join_field': 'so_detail',
|
|
||||||
'target_field': 'returned_qty',
|
|
||||||
'target_parent_dt': 'Sales Order',
|
|
||||||
'source_field': '-1 * qty',
|
|
||||||
'extra_cond': """ and exists (select name from `tabDelivery Note` where name=`tabDelivery Note Item`.parent and is_return=1)"""
|
|
||||||
}]
|
}]
|
||||||
|
if cint(self.is_return):
|
||||||
|
self.status_updater.append({
|
||||||
|
'source_dt': 'Delivery Note Item',
|
||||||
|
'target_dt': 'Sales Order Item',
|
||||||
|
'join_field': 'so_detail',
|
||||||
|
'target_field': 'returned_qty',
|
||||||
|
'target_parent_dt': 'Sales Order',
|
||||||
|
'source_field': '-1 * qty',
|
||||||
|
'second_source_dt': 'Sales Invoice Item',
|
||||||
|
'second_source_field': '-1 * qty',
|
||||||
|
'second_join_field': 'so_detail',
|
||||||
|
'extra_cond': """ and exists (select name from `tabDelivery Note` where name=`tabDelivery Note Item`.parent and is_return=1)"""
|
||||||
|
})
|
||||||
|
|
||||||
def before_print(self):
|
def before_print(self):
|
||||||
def toggle_print_hide(meta, fieldname):
|
def toggle_print_hide(meta, fieldname):
|
||||||
|
@ -24,14 +24,17 @@ class PurchaseReceipt(BuyingController):
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(PurchaseReceipt, self).__init__(*args, **kwargs)
|
super(PurchaseReceipt, self).__init__(*args, **kwargs)
|
||||||
self.status_updater = [{
|
self.status_updater = [{
|
||||||
'source_dt': 'Purchase Receipt Item',
|
|
||||||
'target_dt': 'Purchase Order Item',
|
'target_dt': 'Purchase Order Item',
|
||||||
'join_field': 'purchase_order_item',
|
'join_field': 'purchase_order_item',
|
||||||
'target_field': 'received_qty',
|
'target_field': 'received_qty',
|
||||||
'target_parent_dt': 'Purchase Order',
|
'target_parent_dt': 'Purchase Order',
|
||||||
'target_parent_field': 'per_received',
|
'target_parent_field': 'per_received',
|
||||||
'target_ref_field': 'qty',
|
'target_ref_field': 'qty',
|
||||||
'source_field': 'qty',
|
'source_dt': 'Purchase Receipt Item',
|
||||||
|
'source_field': 'received_qty',
|
||||||
|
'second_source_dt': 'Purchase Invoice Item',
|
||||||
|
'second_source_field': 'received_qty',
|
||||||
|
'second_join_field': 'po_detail',
|
||||||
'percent_join_field': 'purchase_order',
|
'percent_join_field': 'purchase_order',
|
||||||
'overflow_type': 'receipt'
|
'overflow_type': 'receipt'
|
||||||
},
|
},
|
||||||
@ -58,6 +61,18 @@ class PurchaseReceipt(BuyingController):
|
|||||||
# 'overflow_type': 'receipt',
|
# 'overflow_type': 'receipt',
|
||||||
'extra_cond': """ and exists (select name from `tabPurchase Receipt` where name=`tabPurchase Receipt Item`.parent and is_return=1)"""
|
'extra_cond': """ and exists (select name from `tabPurchase Receipt` where name=`tabPurchase Receipt Item`.parent and is_return=1)"""
|
||||||
}]
|
}]
|
||||||
|
if cint(self.is_return):
|
||||||
|
self.status_updater.append({
|
||||||
|
'source_dt': 'Purchase Receipt Item',
|
||||||
|
'target_dt': 'Purchase Order Item',
|
||||||
|
'join_field': 'purchase_order_item',
|
||||||
|
'target_field': 'returned_qty',
|
||||||
|
'source_field': '-1 * qty',
|
||||||
|
'second_source_dt': 'Purchase Invoice Item',
|
||||||
|
'second_source_field': '-1 * qty',
|
||||||
|
'second_join_field': 'po_detail',
|
||||||
|
'extra_cond': """ and exists (select name from `tabPurchase Receipt` where name=`tabPurchase Receipt Item`.parent and is_return=1)"""
|
||||||
|
})
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_posting_time()
|
self.validate_posting_time()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user