mirror of
https://github.com/frappe/erpnext.git
synced 2026-09-14 01:20:41 +00:00
refactor(manufacturing): rename secondary item valuation type to "% of Component Cost" (backport #59021) (#59022)
Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
This commit is contained in:
@@ -1026,7 +1026,7 @@ frappe.tour["BOM"] = [
|
|||||||
frappe.ui.form.on("BOM Secondary Item", {
|
frappe.ui.form.on("BOM Secondary Item", {
|
||||||
valuation_type(frm, cdt, cdn) {
|
valuation_type(frm, cdt, cdn) {
|
||||||
const row = locals[cdt][cdn];
|
const row = locals[cdt][cdn];
|
||||||
if (row.valuation_type !== "% of FG Cost") {
|
if (row.valuation_type !== "% of Component Cost") {
|
||||||
frappe.model.set_value(cdt, cdn, "cost_allocation_per", 0);
|
frappe.model.set_value(cdt, cdn, "cost_allocation_per", 0);
|
||||||
}
|
}
|
||||||
if (row.valuation_type === "Valuation Rate") {
|
if (row.valuation_type === "Valuation Rate") {
|
||||||
|
|||||||
@@ -1092,7 +1092,7 @@ class BOM(WebsiteGenerator):
|
|||||||
|
|
||||||
def calculate_secondary_items_costs(self, save=False):
|
def calculate_secondary_items_costs(self, save=False):
|
||||||
"""Valuation Rate and Manual rows carry their own cost, deducted from the raw
|
"""Valuation Rate and Manual rows carry their own cost, deducted from the raw
|
||||||
material cost; the % of FG Cost rows split the remainder by their percentage."""
|
material cost; the % of Component Cost rows split the remainder by their percentage."""
|
||||||
total_sm_cost = 0
|
total_sm_cost = 0
|
||||||
base_total_sm_cost = 0
|
base_total_sm_cost = 0
|
||||||
precision = self.precision("raw_material_cost")
|
precision = self.precision("raw_material_cost")
|
||||||
|
|||||||
@@ -462,7 +462,7 @@ class TestBOM(ERPNextTestSuite):
|
|||||||
"secondary_item_type": "Additional Finished Good",
|
"secondary_item_type": "Additional Finished Good",
|
||||||
"qty": 1,
|
"qty": 1,
|
||||||
"cost_allocation_per": 10,
|
"cost_allocation_per": 10,
|
||||||
"valuation_type": "% of FG Cost",
|
"valuation_type": "% of Component Cost",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -497,7 +497,7 @@ class TestBOM(ERPNextTestSuite):
|
|||||||
"secondary_item_type": "Scrap",
|
"secondary_item_type": "Scrap",
|
||||||
"qty": 1,
|
"qty": 1,
|
||||||
"cost_allocation_per": 10,
|
"cost_allocation_per": 10,
|
||||||
"valuation_type": "% of FG Cost",
|
"valuation_type": "% of Component Cost",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
self.assertRaises(frappe.ValidationError, bom_doc.save)
|
self.assertRaises(frappe.ValidationError, bom_doc.save)
|
||||||
@@ -570,7 +570,7 @@ class TestBOM(ERPNextTestSuite):
|
|||||||
"secondary_item_type": "By-Product",
|
"secondary_item_type": "By-Product",
|
||||||
"qty": 1,
|
"qty": 1,
|
||||||
"cost_allocation_per": 10,
|
"cost_allocation_per": 10,
|
||||||
"valuation_type": "% of FG Cost",
|
"valuation_type": "% of Component Cost",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
bom_doc.save()
|
bom_doc.save()
|
||||||
|
|||||||
@@ -138,7 +138,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
"depends_on": "eval:doc.valuation_type == '% of FG Cost'",
|
"depends_on": "eval:doc.valuation_type == '% of Component Cost'",
|
||||||
"fieldname": "cost_allocation_per",
|
"fieldname": "cost_allocation_per",
|
||||||
"fieldtype": "Percent",
|
"fieldtype": "Percent",
|
||||||
"label": "Cost Allocation %",
|
"label": "Cost Allocation %",
|
||||||
@@ -178,11 +178,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "Valuation Rate",
|
"default": "Valuation Rate",
|
||||||
"description": "Valuation Rate and Manual value this item on its own and deduct that cost from the raw material cost, like the pre-v16 scrap items. % of FG Cost allocates a percentage of the remaining raw material cost.",
|
"description": "Valuation Rate and Manual value this item on its own and deduct that cost from the raw material cost, like the pre-v16 scrap items. % of Component Cost allocates a percentage of the remaining raw material cost.",
|
||||||
"fieldname": "valuation_type",
|
"fieldname": "valuation_type",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"label": "Valuation Type",
|
"label": "Valuation Type",
|
||||||
"options": "Valuation Rate\n% of FG Cost\nManual",
|
"options": "Valuation Rate\n% of Component Cost\nManual",
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"show_description_on_click": 1
|
"show_description_on_click": 1
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class BOMSecondaryItem(Document):
|
|||||||
stock_qty: DF.Float
|
stock_qty: DF.Float
|
||||||
stock_uom: DF.Link | None
|
stock_uom: DF.Link | None
|
||||||
uom: DF.Link
|
uom: DF.Link
|
||||||
valuation_type: DF.Literal["Valuation Rate", "% of FG Cost", "Manual"]
|
valuation_type: DF.Literal["Valuation Rate", "% of Component Cost", "Manual"]
|
||||||
# end: auto-generated types
|
# end: auto-generated types
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -1303,7 +1303,7 @@ class TestJobCard(ERPNextTestSuite):
|
|||||||
"qty": 1,
|
"qty": 1,
|
||||||
"process_loss_per": 10,
|
"process_loss_per": 10,
|
||||||
"cost_allocation_per": 5,
|
"cost_allocation_per": 5,
|
||||||
"valuation_type": "% of FG Cost",
|
"valuation_type": "% of Component Cost",
|
||||||
"secondary_item_type": "Scrap",
|
"secondary_item_type": "Scrap",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -2645,7 +2645,7 @@ class TestJobCard(ERPNextTestSuite):
|
|||||||
"secondary_item_type": "Scrap",
|
"secondary_item_type": "Scrap",
|
||||||
"qty": 1,
|
"qty": 1,
|
||||||
"cost_allocation_per": cost_allocation_per,
|
"cost_allocation_per": cost_allocation_per,
|
||||||
"valuation_type": "% of FG Cost" if cost_allocation_per else "Valuation Rate",
|
"valuation_type": "% of Component Cost" if cost_allocation_per else "Valuation Rate",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
bom_doc.save()
|
bom_doc.save()
|
||||||
@@ -2701,7 +2701,7 @@ class TestJobCard(ERPNextTestSuite):
|
|||||||
self.assertEqual(rows[bom_links[0]].qty, 2)
|
self.assertEqual(rows[bom_links[0]].qty, 2)
|
||||||
self.assertEqual(rows[bom_links[0]].valuation_type, "Valuation Rate")
|
self.assertEqual(rows[bom_links[0]].valuation_type, "Valuation Rate")
|
||||||
self.assertEqual(rows[bom_links[1]].qty, 3)
|
self.assertEqual(rows[bom_links[1]].qty, 3)
|
||||||
self.assertEqual(rows[bom_links[1]].valuation_type, "% of FG Cost")
|
self.assertEqual(rows[bom_links[1]].valuation_type, "% of Component Cost")
|
||||||
|
|
||||||
@ERPNextTestSuite.change_settings(
|
@ERPNextTestSuite.change_settings(
|
||||||
"Manufacturing Settings", {"overproduction_percentage_for_work_order": 100}
|
"Manufacturing Settings", {"overproduction_percentage_for_work_order": 100}
|
||||||
|
|||||||
@@ -4023,7 +4023,7 @@ def make_bom(**args):
|
|||||||
"stock_uom": item_doc.stock_uom,
|
"stock_uom": item_doc.stock_uom,
|
||||||
"qty": args.scrap_qty or 1,
|
"qty": args.scrap_qty or 1,
|
||||||
"cost_allocation_per": args.scrap_cost_allocation_per or 10,
|
"cost_allocation_per": args.scrap_cost_allocation_per or 10,
|
||||||
"valuation_type": "% of FG Cost",
|
"valuation_type": "% of Component Cost",
|
||||||
"process_loss_per": args.scrap_process_loss_per or 10,
|
"process_loss_per": args.scrap_process_loss_per or 10,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4789,7 +4789,7 @@ class TestWorkOrder(ERPNextTestSuite):
|
|||||||
"item_name": scrap_item,
|
"item_name": scrap_item,
|
||||||
"qty": 3,
|
"qty": 3,
|
||||||
"cost_allocation_per": 25,
|
"cost_allocation_per": 25,
|
||||||
"valuation_type": "% of FG Cost",
|
"valuation_type": "% of Component Cost",
|
||||||
"process_loss_per": 0,
|
"process_loss_per": 0,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -4838,7 +4838,7 @@ class TestWorkOrder(ERPNextTestSuite):
|
|||||||
"item_name": scrap_item,
|
"item_name": scrap_item,
|
||||||
"qty": 3,
|
"qty": 3,
|
||||||
"cost_allocation_per": 25,
|
"cost_allocation_per": 25,
|
||||||
"valuation_type": "% of FG Cost",
|
"valuation_type": "% of Component Cost",
|
||||||
"process_loss_per": 0,
|
"process_loss_per": 0,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -507,3 +507,4 @@ erpnext.patches.v16_0.append_fieldname_to_pos_search_fields
|
|||||||
erpnext.patches.v16_0.set_secondary_item_valuation_type
|
erpnext.patches.v16_0.set_secondary_item_valuation_type
|
||||||
erpnext.patches.v16_0.add_transaction_roles_to_sms_settings
|
erpnext.patches.v16_0.add_transaction_roles_to_sms_settings
|
||||||
erpnext.patches.v16_0.recalculate_holiday_list_totals
|
erpnext.patches.v16_0.recalculate_holiday_list_totals
|
||||||
|
erpnext.patches.v16_0.rename_component_cost_valuation_type
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
DOCTYPES = ("BOM Secondary Item", "Stock Entry Detail", "Subcontracting Receipt Item")
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
"""Rename the `% of FG Cost` valuation type: the percentage is of the component cost."""
|
||||||
|
for doctype in DOCTYPES:
|
||||||
|
frappe.db.set_value(
|
||||||
|
doctype,
|
||||||
|
{"valuation_type": "% of FG Cost"},
|
||||||
|
"valuation_type",
|
||||||
|
"% of Component Cost",
|
||||||
|
update_modified=False,
|
||||||
|
)
|
||||||
@@ -310,7 +310,7 @@ frappe.ui.form.on("Stock Entry", {
|
|||||||
frm.trigger("toggle_warehouse_fields");
|
frm.trigger("toggle_warehouse_fields");
|
||||||
|
|
||||||
// only BOM-less rows are editable, and they cannot allocate a BOM percentage;
|
// only BOM-less rows are editable, and they cannot allocate a BOM percentage;
|
||||||
// read-only rows from a BOM still display their stored % of FG Cost
|
// read-only rows from a BOM still display their stored % of Component Cost
|
||||||
frm.fields_dict.items.grid.update_docfield_property("valuation_type", "options", [
|
frm.fields_dict.items.grid.update_docfield_property("valuation_type", "options", [
|
||||||
"Valuation Rate",
|
"Valuation Rate",
|
||||||
"Manual",
|
"Manual",
|
||||||
|
|||||||
@@ -1656,7 +1656,7 @@ class StockEntry(StockController, SubcontractingInwardController):
|
|||||||
def set_bomless_secondary_valuation_types(self):
|
def set_bomless_secondary_valuation_types(self):
|
||||||
"""Secondary rows without a BOM link choose their own costing: valuation rate or manual.
|
"""Secondary rows without a BOM link choose their own costing: valuation rate or manual.
|
||||||
|
|
||||||
There is no percentage to allocate without a BOM row, so % of FG Cost is rejected."""
|
There is no percentage to allocate without a BOM row, so % of Component Cost is rejected."""
|
||||||
for d in self.get("items"):
|
for d in self.get("items"):
|
||||||
if d.bom_secondary_item:
|
if d.bom_secondary_item:
|
||||||
continue
|
continue
|
||||||
@@ -1667,10 +1667,10 @@ class StockEntry(StockController, SubcontractingInwardController):
|
|||||||
d.set_basic_rate_manually = 0
|
d.set_basic_rate_manually = 0
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if d.valuation_type == "% of FG Cost":
|
if d.valuation_type == "% of Component Cost":
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_(
|
_(
|
||||||
"Row #{0}: % of FG Cost needs a BOM secondary item. Choose Valuation Rate or Manual for {1}."
|
"Row #{0}: % of Component Cost needs a BOM secondary item. Choose Valuation Rate or Manual for {1}."
|
||||||
).format(d.idx, frappe.bold(d.item_code))
|
).format(d.idx, frappe.bold(d.item_code))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1124,7 +1124,7 @@ class TestStockEntry(ERPNextTestSuite):
|
|||||||
"secondary_item_type": "By-Product",
|
"secondary_item_type": "By-Product",
|
||||||
"qty": 1,
|
"qty": 1,
|
||||||
"cost_allocation_per": 10,
|
"cost_allocation_per": 10,
|
||||||
"valuation_type": "% of FG Cost",
|
"valuation_type": "% of Component Cost",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
bom_doc.save()
|
bom_doc.save()
|
||||||
@@ -1208,7 +1208,7 @@ class TestStockEntry(ERPNextTestSuite):
|
|||||||
"secondary_item_type": "By-Product",
|
"secondary_item_type": "By-Product",
|
||||||
"qty": 1,
|
"qty": 1,
|
||||||
"cost_allocation_per": 10,
|
"cost_allocation_per": 10,
|
||||||
"valuation_type": "% of FG Cost",
|
"valuation_type": "% of Component Cost",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
bom_doc.save()
|
bom_doc.save()
|
||||||
@@ -1422,7 +1422,7 @@ class TestStockEntry(ERPNextTestSuite):
|
|||||||
self.assertEqual(fg_row.basic_amount, 830)
|
self.assertEqual(fg_row.basic_amount, 830)
|
||||||
|
|
||||||
# there is no percentage to allocate without a BOM row
|
# there is no percentage to allocate without a BOM row
|
||||||
manual_row.valuation_type = "% of FG Cost"
|
manual_row.valuation_type = "% of Component Cost"
|
||||||
self.assertRaises(frappe.ValidationError, entry.save)
|
self.assertRaises(frappe.ValidationError, entry.save)
|
||||||
|
|
||||||
def test_valuation_rate_lookup_without_voucher_no(self):
|
def test_valuation_rate_lookup_without_voucher_no(self):
|
||||||
@@ -3348,7 +3348,7 @@ class TestStockEntry(ERPNextTestSuite):
|
|||||||
"qty": 5,
|
"qty": 5,
|
||||||
"cost_allocation_per": 25,
|
"cost_allocation_per": 25,
|
||||||
"process_loss_per": 0,
|
"process_loss_per": 0,
|
||||||
"valuation_type": "% of FG Cost",
|
"valuation_type": "% of Component Cost",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
bom.insert()
|
bom.insert()
|
||||||
@@ -3410,7 +3410,7 @@ class TestStockEntry(ERPNextTestSuite):
|
|||||||
"qty": 5,
|
"qty": 5,
|
||||||
"cost_allocation_per": 0,
|
"cost_allocation_per": 0,
|
||||||
"process_loss_per": 0,
|
"process_loss_per": 0,
|
||||||
"valuation_type": "% of FG Cost",
|
"valuation_type": "% of Component Cost",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
bom.insert()
|
bom.insert()
|
||||||
@@ -3497,7 +3497,7 @@ class TestStockEntry(ERPNextTestSuite):
|
|||||||
"qty": 5,
|
"qty": 5,
|
||||||
"cost_allocation_per": 25,
|
"cost_allocation_per": 25,
|
||||||
"process_loss_per": 0,
|
"process_loss_per": 0,
|
||||||
"valuation_type": "% of FG Cost",
|
"valuation_type": "% of Component Cost",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
bom.insert()
|
bom.insert()
|
||||||
|
|||||||
@@ -682,7 +682,7 @@
|
|||||||
"fieldname": "valuation_type",
|
"fieldname": "valuation_type",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"label": "Valuation Type",
|
"label": "Valuation Type",
|
||||||
"options": "\nValuation Rate\n% of FG Cost\nManual",
|
"options": "\nValuation Rate\n% of Component Cost\nManual",
|
||||||
"read_only_depends_on": "eval:!doc.secondary_item_type || doc.bom_secondary_item"
|
"read_only_depends_on": "eval:!doc.secondary_item_type || doc.bom_secondary_item"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ class StockEntryDetail(Document):
|
|||||||
transferred_qty: DF.Float
|
transferred_qty: DF.Float
|
||||||
secondary_item_type: DF.Literal["", "Co-Product", "By-Product", "Scrap", "Additional Finished Good"]
|
secondary_item_type: DF.Literal["", "Co-Product", "By-Product", "Scrap", "Additional Finished Good"]
|
||||||
uom: DF.Link
|
uom: DF.Link
|
||||||
valuation_type: DF.Literal["", "Valuation Rate", "% of FG Cost", "Manual"]
|
valuation_type: DF.Literal["", "Valuation Rate", "% of Component Cost", "Manual"]
|
||||||
use_serial_batch_fields: DF.Check
|
use_serial_batch_fields: DF.Check
|
||||||
valuation_rate: DF.Currency
|
valuation_rate: DF.Currency
|
||||||
# end: auto-generated types
|
# end: auto-generated types
|
||||||
|
|||||||
@@ -1216,7 +1216,7 @@ class TestSubcontractingReceipt(ERPNextTestSuite):
|
|||||||
"item_code": percentage_item,
|
"item_code": percentage_item,
|
||||||
"secondary_item_type": "Co-Product",
|
"secondary_item_type": "Co-Product",
|
||||||
"stock_qty": 1,
|
"stock_qty": 1,
|
||||||
"valuation_type": "% of FG Cost",
|
"valuation_type": "% of Component Cost",
|
||||||
"cost_allocation_per": 10,
|
"cost_allocation_per": 10,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -623,7 +623,7 @@
|
|||||||
"fieldname": "valuation_type",
|
"fieldname": "valuation_type",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"label": "Valuation Type",
|
"label": "Valuation Type",
|
||||||
"options": "\nValuation Rate\n% of FG Cost\nManual",
|
"options": "\nValuation Rate\n% of Component Cost\nManual",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ class SubcontractingReceiptItem(Document):
|
|||||||
subcontracting_receipt_item: DF.Data | None
|
subcontracting_receipt_item: DF.Data | None
|
||||||
secondary_item_type: DF.Literal["", "Co-Product", "By-Product", "Scrap", "Additional Finished Good"]
|
secondary_item_type: DF.Literal["", "Co-Product", "By-Product", "Scrap", "Additional Finished Good"]
|
||||||
use_serial_batch_fields: DF.Check
|
use_serial_batch_fields: DF.Check
|
||||||
valuation_type: DF.Literal["", "Valuation Rate", "% of FG Cost", "Manual"]
|
valuation_type: DF.Literal["", "Valuation Rate", "% of Component Cost", "Manual"]
|
||||||
warehouse: DF.Link | None
|
warehouse: DF.Link | None
|
||||||
# end: auto-generated types
|
# end: auto-generated types
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user