fix: rounding issue of required qty in subcontracting order (#43810)
* fix: rounding issue of required qty in subcontracting order * fix: uom issue in test case * fix: test case
This commit is contained in:
@@ -561,11 +561,11 @@ class SubcontractingController(StockController):
|
|||||||
use_serial_batch_fields = frappe.db.get_single_value("Stock Settings", "use_serial_batch_fields")
|
use_serial_batch_fields = frappe.db.get_single_value("Stock Settings", "use_serial_batch_fields")
|
||||||
|
|
||||||
if self.doctype == self.subcontract_data.order_doctype:
|
if self.doctype == self.subcontract_data.order_doctype:
|
||||||
rm_obj.required_qty = qty
|
rm_obj.required_qty = flt(qty, rm_obj.precision("required_qty"))
|
||||||
rm_obj.amount = rm_obj.required_qty * rm_obj.rate
|
rm_obj.amount = flt(rm_obj.required_qty * rm_obj.rate, rm_obj.precision("amount"))
|
||||||
else:
|
else:
|
||||||
rm_obj.consumed_qty = qty
|
rm_obj.consumed_qty = flt(qty, rm_obj.precision("consumed_qty"))
|
||||||
rm_obj.required_qty = bom_item.required_qty or qty
|
rm_obj.required_qty = flt(bom_item.required_qty or qty, rm_obj.precision("required_qty"))
|
||||||
rm_obj.serial_and_batch_bundle = None
|
rm_obj.serial_and_batch_bundle = None
|
||||||
setattr(
|
setattr(
|
||||||
rm_obj, self.subcontract_data.order_field, item_row.get(self.subcontract_data.order_field)
|
rm_obj, self.subcontract_data.order_field, item_row.get(self.subcontract_data.order_field)
|
||||||
@@ -664,8 +664,8 @@ class SubcontractingController(StockController):
|
|||||||
self.__set_serial_nos(item_row, rm_obj)
|
self.__set_serial_nos(item_row, rm_obj)
|
||||||
|
|
||||||
def __set_consumed_qty(self, rm_obj, consumed_qty, required_qty=0):
|
def __set_consumed_qty(self, rm_obj, consumed_qty, required_qty=0):
|
||||||
rm_obj.required_qty = required_qty
|
rm_obj.required_qty = flt(required_qty, rm_obj.precision("required_qty"))
|
||||||
rm_obj.consumed_qty = consumed_qty
|
rm_obj.consumed_qty = flt(consumed_qty, rm_obj.precision("consumed_qty"))
|
||||||
|
|
||||||
def __set_serial_nos(self, item_row, rm_obj):
|
def __set_serial_nos(self, item_row, rm_obj):
|
||||||
key = (rm_obj.rm_item_code, item_row.item_code, item_row.get(self.subcontract_data.order_field))
|
key = (rm_obj.rm_item_code, item_row.item_code, item_row.get(self.subcontract_data.order_field))
|
||||||
|
|||||||
@@ -1234,6 +1234,7 @@ def make_subcontracted_items():
|
|||||||
"Subcontracted Item SA6": {},
|
"Subcontracted Item SA6": {},
|
||||||
"Subcontracted Item SA7": {},
|
"Subcontracted Item SA7": {},
|
||||||
"Subcontracted Item SA8": {},
|
"Subcontracted Item SA8": {},
|
||||||
|
"Subcontracted Item SA9": {"stock_uom": "Litre"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for item, properties in sub_contracted_items.items():
|
for item, properties in sub_contracted_items.items():
|
||||||
@@ -1254,6 +1255,7 @@ def make_raw_materials():
|
|||||||
"Subcontracted SRM Item 4": {"has_serial_no": 1, "serial_no_series": "SRII.####"},
|
"Subcontracted SRM Item 4": {"has_serial_no": 1, "serial_no_series": "SRII.####"},
|
||||||
"Subcontracted SRM Item 5": {"has_serial_no": 1, "serial_no_series": "SRIID.####"},
|
"Subcontracted SRM Item 5": {"has_serial_no": 1, "serial_no_series": "SRIID.####"},
|
||||||
"Subcontracted SRM Item 8": {},
|
"Subcontracted SRM Item 8": {},
|
||||||
|
"Subcontracted SRM Item 9": {"stock_uom": "Litre"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for item, properties in raw_materials.items():
|
for item, properties in raw_materials.items():
|
||||||
@@ -1280,6 +1282,7 @@ def make_service_items():
|
|||||||
"Subcontracted Service Item 6": {},
|
"Subcontracted Service Item 6": {},
|
||||||
"Subcontracted Service Item 7": {},
|
"Subcontracted Service Item 7": {},
|
||||||
"Subcontracted Service Item 8": {},
|
"Subcontracted Service Item 8": {},
|
||||||
|
"Subcontracted Service Item 9": {},
|
||||||
}
|
}
|
||||||
|
|
||||||
for item, properties in service_items.items():
|
for item, properties in service_items.items():
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
import unittest
|
|
||||||
|
|
||||||
import frappe
|
|
||||||
from frappe.tests import IntegrationTestCase
|
|
||||||
|
|
||||||
from erpnext.tests.utils import ReportFilters, ReportName, execute_script_report
|
|
||||||
|
|
||||||
DEFAULT_FILTERS = {
|
|
||||||
"company": "_Test Company",
|
|
||||||
"from_date": "2010-01-01",
|
|
||||||
"to_date": "2030-01-01",
|
|
||||||
"warehouse": "_Test Warehouse - _TC",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
REPORT_FILTER_TEST_CASES: list[tuple[ReportName, ReportFilters]] = [
|
|
||||||
("BOM Explorer", {"bom": frappe.get_last_doc("BOM").name}),
|
|
||||||
("BOM Operations Time", {}),
|
|
||||||
("BOM Stock Calculated", {"bom": frappe.get_last_doc("BOM").name, "qty_to_make": 2}),
|
|
||||||
("BOM Stock Report", {"bom": frappe.get_last_doc("BOM").name, "qty_to_produce": 2}),
|
|
||||||
("Cost of Poor Quality Report", {"item": "_Test Item", "serial_no": "00"}),
|
|
||||||
("Downtime Analysis", {}),
|
|
||||||
(
|
|
||||||
"Exponential Smoothing Forecasting",
|
|
||||||
{
|
|
||||||
"based_on_document": "Sales Order",
|
|
||||||
"based_on_field": "Qty",
|
|
||||||
"no_of_years": 3,
|
|
||||||
"periodicity": "Yearly",
|
|
||||||
"smoothing_constant": 0.3,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
("Job Card Summary", {"fiscal_year": "2021-2022"}),
|
|
||||||
("Production Analytics", {"range": "Monthly"}),
|
|
||||||
("Quality Inspection Summary", {}),
|
|
||||||
("Process Loss Report", {}),
|
|
||||||
("Work Order Stock Report", {}),
|
|
||||||
("Work Order Summary", {"fiscal_year": "2021-2022", "age": 0}),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
if frappe.db.a_row_exists("Production Plan"):
|
|
||||||
REPORT_FILTER_TEST_CASES.append(
|
|
||||||
("Production Plan Summary", {"production_plan": frappe.get_last_doc("Production Plan").name})
|
|
||||||
)
|
|
||||||
|
|
||||||
OPTIONAL_FILTERS = {
|
|
||||||
"warehouse": "_Test Warehouse - _TC",
|
|
||||||
"item": "_Test Item",
|
|
||||||
"item_group": "_Test Item Group",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class TestManufacturingReports(IntegrationTestCase):
|
|
||||||
def test_execute_all_manufacturing_reports(self):
|
|
||||||
"""Test that all script report in manufacturing modules are executable with supported filters"""
|
|
||||||
for report, filter in REPORT_FILTER_TEST_CASES:
|
|
||||||
with self.subTest(report=report):
|
|
||||||
execute_script_report(
|
|
||||||
report_name=report,
|
|
||||||
module="Manufacturing",
|
|
||||||
filters=filter,
|
|
||||||
default_filters=DEFAULT_FILTERS,
|
|
||||||
optional_filters=OPTIONAL_FILTERS if filter.get("_optional") else None,
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ from erpnext.controllers.tests.test_subcontracting_controller import (
|
|||||||
make_subcontracted_items,
|
make_subcontracted_items,
|
||||||
set_backflush_based_on,
|
set_backflush_based_on,
|
||||||
)
|
)
|
||||||
|
from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
|
||||||
from erpnext.stock.doctype.item.test_item import make_item
|
from erpnext.stock.doctype.item.test_item import make_item
|
||||||
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.subcontracting.doctype.subcontracting_order.subcontracting_order import (
|
from erpnext.subcontracting.doctype.subcontracting_order.subcontracting_order import (
|
||||||
@@ -692,6 +693,28 @@ class TestSubcontractingOrder(IntegrationTestCase):
|
|||||||
|
|
||||||
self.assertEqual(requested_qty, new_requested_qty)
|
self.assertEqual(requested_qty, new_requested_qty)
|
||||||
|
|
||||||
|
def test_subcontracting_order_rm_required_items_for_precision(self):
|
||||||
|
item_code = "Subcontracted Item SA9"
|
||||||
|
raw_materials = ["Subcontracted SRM Item 9"]
|
||||||
|
if not frappe.db.exists("BOM", {"item": item_code}):
|
||||||
|
make_bom(item=item_code, raw_materials=raw_materials, rate=100, rm_qty=1.04)
|
||||||
|
|
||||||
|
service_items = [
|
||||||
|
{
|
||||||
|
"warehouse": "_Test Warehouse - _TC",
|
||||||
|
"item_code": "Subcontracted Service Item 9",
|
||||||
|
"qty": 1, # 202.0656,
|
||||||
|
"rate": 100,
|
||||||
|
"fg_item": "Subcontracted Item SA9",
|
||||||
|
"fg_item_qty": 202.0656,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
sco = get_subcontracting_order(service_items=service_items)
|
||||||
|
sco.reload()
|
||||||
|
|
||||||
|
self.assertEqual(sco.supplied_items[0].required_qty, 210.149)
|
||||||
|
|
||||||
|
|
||||||
def create_subcontracting_order(**args):
|
def create_subcontracting_order(**args):
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
|
|||||||
Reference in New Issue
Block a user