mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-19 13:09:17 +00:00
Merge pull request #35138 from s-aga-r/FIX-ISS-23-24-00368
fix: recalculate costs in SCR while reposting
This commit is contained in:
@@ -741,7 +741,7 @@ class SubcontractingController(StockController):
|
|||||||
sco_doc = frappe.get_doc("Subcontracting Order", sco)
|
sco_doc = frappe.get_doc("Subcontracting Order", sco)
|
||||||
sco_doc.update_status()
|
sco_doc.update_status()
|
||||||
|
|
||||||
def set_missing_values_in_additional_costs(self):
|
def calculate_additional_costs(self):
|
||||||
self.total_additional_costs = sum(flt(item.amount) for item in self.get("additional_costs"))
|
self.total_additional_costs = sum(flt(item.amount) for item in self.get("additional_costs"))
|
||||||
|
|
||||||
if self.total_additional_costs:
|
if self.total_additional_costs:
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class TestSubcontractingController(FrappeTestCase):
|
|||||||
sco.remove_empty_rows()
|
sco.remove_empty_rows()
|
||||||
self.assertEqual((len_before - 1), len(sco.service_items))
|
self.assertEqual((len_before - 1), len(sco.service_items))
|
||||||
|
|
||||||
def test_set_missing_values_in_additional_costs(self):
|
def test_calculate_additional_costs(self):
|
||||||
sco = get_subcontracting_order(do_not_submit=1)
|
sco = get_subcontracting_order(do_not_submit=1)
|
||||||
|
|
||||||
rate_without_additional_cost = sco.items[0].rate
|
rate_without_additional_cost = sco.items[0].rate
|
||||||
|
|||||||
@@ -781,13 +781,21 @@ class update_entries_after(object):
|
|||||||
d.db_update()
|
d.db_update()
|
||||||
|
|
||||||
def update_rate_on_subcontracting_receipt(self, sle, outgoing_rate):
|
def update_rate_on_subcontracting_receipt(self, sle, outgoing_rate):
|
||||||
if frappe.db.exists(sle.voucher_type + " Item", sle.voucher_detail_no):
|
if frappe.db.exists("Subcontracting Receipt Item", sle.voucher_detail_no):
|
||||||
frappe.db.set_value(sle.voucher_type + " Item", sle.voucher_detail_no, "rate", outgoing_rate)
|
frappe.db.set_value("Subcontracting Receipt Item", sle.voucher_detail_no, "rate", outgoing_rate)
|
||||||
else:
|
else:
|
||||||
frappe.db.set_value(
|
frappe.db.set_value(
|
||||||
"Subcontracting Receipt Supplied Item", sle.voucher_detail_no, "rate", outgoing_rate
|
"Subcontracting Receipt Supplied Item",
|
||||||
|
sle.voucher_detail_no,
|
||||||
|
{"rate": outgoing_rate, "amount": abs(sle.actual_qty) * outgoing_rate},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
scr = frappe.get_doc("Subcontracting Receipt", sle.voucher_no, for_update=True)
|
||||||
|
scr.calculate_items_qty_and_amount()
|
||||||
|
scr.db_update()
|
||||||
|
for d in scr.items:
|
||||||
|
d.db_update()
|
||||||
|
|
||||||
def get_serialized_values(self, sle):
|
def get_serialized_values(self, sle):
|
||||||
incoming_rate = flt(sle.incoming_rate)
|
incoming_rate = flt(sle.incoming_rate)
|
||||||
actual_qty = flt(sle.actual_qty)
|
actual_qty = flt(sle.actual_qty)
|
||||||
|
|||||||
@@ -77,22 +77,22 @@ class SubcontractingOrder(SubcontractingController):
|
|||||||
frappe.throw(_(msg))
|
frappe.throw(_(msg))
|
||||||
|
|
||||||
def set_missing_values(self):
|
def set_missing_values(self):
|
||||||
self.set_missing_values_in_additional_costs()
|
self.calculate_additional_costs()
|
||||||
self.set_missing_values_in_service_items()
|
self.calculate_service_costs()
|
||||||
self.set_missing_values_in_supplied_items()
|
self.calculate_supplied_items_qty_and_amount()
|
||||||
self.set_missing_values_in_items()
|
self.calculate_items_qty_and_amount()
|
||||||
|
|
||||||
def set_missing_values_in_service_items(self):
|
def calculate_service_costs(self):
|
||||||
for idx, item in enumerate(self.get("service_items")):
|
for idx, item in enumerate(self.get("service_items")):
|
||||||
self.items[idx].service_cost_per_qty = item.amount / self.items[idx].qty
|
self.items[idx].service_cost_per_qty = item.amount / self.items[idx].qty
|
||||||
|
|
||||||
def set_missing_values_in_supplied_items(self):
|
def calculate_supplied_items_qty_and_amount(self):
|
||||||
for item in self.get("items"):
|
for item in self.get("items"):
|
||||||
bom = frappe.get_doc("BOM", item.bom)
|
bom = frappe.get_doc("BOM", item.bom)
|
||||||
rm_cost = sum(flt(rm_item.amount) for rm_item in bom.items)
|
rm_cost = sum(flt(rm_item.amount) for rm_item in bom.items)
|
||||||
item.rm_cost_per_qty = rm_cost / flt(bom.quantity)
|
item.rm_cost_per_qty = rm_cost / flt(bom.quantity)
|
||||||
|
|
||||||
def set_missing_values_in_items(self):
|
def calculate_items_qty_and_amount(self):
|
||||||
total_qty = total = 0
|
total_qty = total = 0
|
||||||
for item in self.items:
|
for item in self.items:
|
||||||
item.rate = item.rm_cost_per_qty + item.service_cost_per_qty + flt(item.additional_cost_per_qty)
|
item.rate = item.rm_cost_per_qty + item.service_cost_per_qty + flt(item.additional_cost_per_qty)
|
||||||
|
|||||||
@@ -113,9 +113,9 @@ class SubcontractingReceipt(SubcontractingController):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def set_missing_values(self):
|
def set_missing_values(self):
|
||||||
self.set_missing_values_in_additional_costs()
|
self.calculate_additional_costs()
|
||||||
self.set_missing_values_in_supplied_items()
|
self.calculate_supplied_items_qty_and_amount()
|
||||||
self.set_missing_values_in_items()
|
self.calculate_items_qty_and_amount()
|
||||||
|
|
||||||
def set_available_qty_for_consumption(self):
|
def set_available_qty_for_consumption(self):
|
||||||
supplied_items_details = {}
|
supplied_items_details = {}
|
||||||
@@ -147,13 +147,13 @@ class SubcontractingReceipt(SubcontractingController):
|
|||||||
item.rm_item_code, 0
|
item.rm_item_code, 0
|
||||||
)
|
)
|
||||||
|
|
||||||
def set_missing_values_in_supplied_items(self):
|
def calculate_supplied_items_qty_and_amount(self):
|
||||||
for item in self.get("supplied_items") or []:
|
for item in self.get("supplied_items") or []:
|
||||||
item.amount = item.rate * item.consumed_qty
|
item.amount = item.rate * item.consumed_qty
|
||||||
|
|
||||||
self.set_available_qty_for_consumption()
|
self.set_available_qty_for_consumption()
|
||||||
|
|
||||||
def set_missing_values_in_items(self):
|
def calculate_items_qty_and_amount(self):
|
||||||
rm_supp_cost = {}
|
rm_supp_cost = {}
|
||||||
for item in self.get("supplied_items") or []:
|
for item in self.get("supplied_items") or []:
|
||||||
if item.reference_name in rm_supp_cost:
|
if item.reference_name in rm_supp_cost:
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import copy
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.tests.utils import FrappeTestCase
|
from frappe.tests.utils import FrappeTestCase
|
||||||
from frappe.utils import cint, flt
|
from frappe.utils import add_days, cint, cstr, flt, today
|
||||||
|
|
||||||
import erpnext
|
import erpnext
|
||||||
from erpnext.accounts.doctype.account.test_account import get_inventory_account
|
from erpnext.accounts.doctype.account.test_account import get_inventory_account
|
||||||
@@ -26,6 +26,9 @@ from erpnext.controllers.tests.test_subcontracting_controller import (
|
|||||||
from erpnext.stock.doctype.item.test_item import make_item
|
from erpnext.stock.doctype.item.test_item import make_item
|
||||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import get_gl_entries
|
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import get_gl_entries
|
||||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
|
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
|
||||||
|
from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import (
|
||||||
|
create_stock_reconciliation,
|
||||||
|
)
|
||||||
from erpnext.subcontracting.doctype.subcontracting_order.subcontracting_order import (
|
from erpnext.subcontracting.doctype.subcontracting_order.subcontracting_order import (
|
||||||
make_subcontracting_receipt,
|
make_subcontracting_receipt,
|
||||||
)
|
)
|
||||||
@@ -528,6 +531,69 @@ class TestSubcontractingReceipt(FrappeTestCase):
|
|||||||
# consumed_qty should be (accepted_qty * qty_consumed_per_unit) = (6 * 1) = 6
|
# consumed_qty should be (accepted_qty * qty_consumed_per_unit) = (6 * 1) = 6
|
||||||
self.assertEqual(scr.supplied_items[0].consumed_qty, 6)
|
self.assertEqual(scr.supplied_items[0].consumed_qty, 6)
|
||||||
|
|
||||||
|
def test_supplied_items_cost_after_reposting(self):
|
||||||
|
# Set Backflush Based On as "BOM"
|
||||||
|
set_backflush_based_on("BOM")
|
||||||
|
|
||||||
|
# Create Material Receipt for RM's
|
||||||
|
make_stock_entry(
|
||||||
|
item_code="_Test Item",
|
||||||
|
qty=100,
|
||||||
|
target="_Test Warehouse 1 - _TC",
|
||||||
|
basic_rate=100,
|
||||||
|
posting_date=add_days(today(), -2),
|
||||||
|
)
|
||||||
|
make_stock_entry(
|
||||||
|
item_code="_Test Item Home Desktop 100",
|
||||||
|
qty=100,
|
||||||
|
target="_Test Warehouse 1 - _TC",
|
||||||
|
basic_rate=100,
|
||||||
|
)
|
||||||
|
|
||||||
|
service_items = [
|
||||||
|
{
|
||||||
|
"warehouse": "_Test Warehouse - _TC",
|
||||||
|
"item_code": "Subcontracted Service Item 1",
|
||||||
|
"qty": 10,
|
||||||
|
"rate": 100,
|
||||||
|
"fg_item": "_Test FG Item",
|
||||||
|
"fg_item_qty": 10,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
# Create Subcontracting Order
|
||||||
|
sco = get_subcontracting_order(service_items=service_items)
|
||||||
|
|
||||||
|
# Transfer RM's
|
||||||
|
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),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create Subcontracting Receipt
|
||||||
|
scr = make_subcontracting_receipt(sco.name)
|
||||||
|
scr.save()
|
||||||
|
scr.submit()
|
||||||
|
|
||||||
|
# Create Backdated Stock Reconciliation
|
||||||
|
sr = create_stock_reconciliation(
|
||||||
|
item_code=rm_items[0].get("item_code"),
|
||||||
|
warehouse="_Test Warehouse 1 - _TC",
|
||||||
|
qty=100,
|
||||||
|
rate=50,
|
||||||
|
posting_date=add_days(today(), -1),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Cost should be updated in Subcontracting Receipt after reposting
|
||||||
|
prev_cost = scr.supplied_items[0].rate
|
||||||
|
scr.load_from_db()
|
||||||
|
self.assertNotEqual(scr.supplied_items[0].rate, prev_cost)
|
||||||
|
self.assertEqual(scr.supplied_items[0].rate, sr.items[0].valuation_rate)
|
||||||
|
|
||||||
|
|
||||||
def make_return_subcontracting_receipt(**args):
|
def make_return_subcontracting_receipt(**args):
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
|
|||||||
Reference in New Issue
Block a user