mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-04 14:08:29 +00:00
refactor: remove old subcontracting flow (#54717)
This commit is contained in:
@@ -680,10 +680,6 @@ frappe.ui.form.on("Purchase Invoice", {
|
||||
},
|
||||
|
||||
is_subcontracted: function (frm) {
|
||||
if (frm.doc.is_old_subcontracting_flow) {
|
||||
erpnext.buying.get_default_bom(frm);
|
||||
}
|
||||
|
||||
frm.toggle_reqd("supplier_warehouse", frm.doc.is_subcontracted);
|
||||
},
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"actions": [],
|
||||
"allow_bulk_edit": 1,
|
||||
"allow_import": 1,
|
||||
"autoname": "naming_series:",
|
||||
"creation": "2013-05-21 16:16:39",
|
||||
@@ -206,7 +207,6 @@
|
||||
"sender",
|
||||
"column_break_147",
|
||||
"inter_company_invoice_reference",
|
||||
"is_old_subcontracting_flow",
|
||||
"remarks",
|
||||
"connections_tab"
|
||||
],
|
||||
@@ -1456,14 +1456,6 @@
|
||||
"label": "Subscription",
|
||||
"options": "Subscription"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "is_old_subcontracting_flow",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"label": "Is Old Subcontracting Flow",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "payments_tab",
|
||||
"fieldtype": "Tab Break",
|
||||
@@ -1703,7 +1695,7 @@
|
||||
"idx": 204,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2026-03-30 12:16:40.157755",
|
||||
"modified": "2026-05-04 10:10:11.717131",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice",
|
||||
|
||||
@@ -129,7 +129,6 @@ class PurchaseInvoice(BuyingController):
|
||||
incoterm: DF.Link | None
|
||||
inter_company_invoice_reference: DF.Link | None
|
||||
is_internal_supplier: DF.Check
|
||||
is_old_subcontracting_flow: DF.Check
|
||||
is_opening: DF.Literal["No", "Yes"]
|
||||
is_paid: DF.Check
|
||||
is_return: DF.Check
|
||||
@@ -778,9 +777,6 @@ class PurchaseInvoice(BuyingController):
|
||||
self.make_bundle_using_old_serial_batch_fields()
|
||||
self.update_stock_ledger()
|
||||
|
||||
if self.is_old_subcontracting_flow:
|
||||
self.set_consumed_qty_in_subcontract_order()
|
||||
|
||||
# this sequence because outstanding may get -negative
|
||||
self.make_gl_entries()
|
||||
|
||||
@@ -1706,9 +1702,6 @@ class PurchaseInvoice(BuyingController):
|
||||
self.update_stock_ledger()
|
||||
self.delete_auto_created_batches()
|
||||
|
||||
if self.is_old_subcontracting_flow:
|
||||
self.set_consumed_qty_in_subcontract_order()
|
||||
|
||||
self.make_gl_entries_on_cancel()
|
||||
|
||||
if self.update_stock == 1:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"actions": [],
|
||||
"allow_bulk_edit": 1,
|
||||
"autoname": "hash",
|
||||
"creation": "2013-05-22 12:43:10",
|
||||
"doctype": "DocType",
|
||||
@@ -99,7 +100,6 @@
|
||||
"service_end_date",
|
||||
"reference",
|
||||
"item_tax_rate",
|
||||
"bom",
|
||||
"include_exploded_items",
|
||||
"purchase_invoice_item",
|
||||
"col_break6",
|
||||
@@ -645,15 +645,6 @@
|
||||
"read_only": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:parent.is_old_subcontracting_flow",
|
||||
"fieldname": "bom",
|
||||
"fieldtype": "Link",
|
||||
"label": "BOM",
|
||||
"options": "BOM",
|
||||
"read_only": 1,
|
||||
"read_only_depends_on": "eval:!parent.is_old_subcontracting_flow"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:parent.is_subcontracted",
|
||||
@@ -1007,7 +998,7 @@
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2026-04-07 15:40:45.687554",
|
||||
"modified": "2026-05-04 10:48:54.535480",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice Item",
|
||||
|
||||
@@ -26,7 +26,6 @@ class PurchaseInvoiceItem(Document):
|
||||
base_rate: DF.Currency
|
||||
base_rate_with_margin: DF.Currency
|
||||
batch_no: DF.Link | None
|
||||
bom: DF.Link | None
|
||||
brand: DF.Link | None
|
||||
conversion_factor: DF.Float
|
||||
cost_center: DF.Link | None
|
||||
|
||||
@@ -12,18 +12,6 @@ erpnext.buying.setup_buying_controller();
|
||||
|
||||
frappe.ui.form.on("Purchase Order", {
|
||||
setup: function (frm) {
|
||||
if (frm.doc.is_old_subcontracting_flow) {
|
||||
frm.set_query("reserve_warehouse", "supplied_items", function () {
|
||||
return {
|
||||
filters: {
|
||||
company: frm.doc.company,
|
||||
name: ["!=", frm.doc.supplier_warehouse],
|
||||
is_group: 0,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
frm.set_indicator_formatter("item_code", function (doc) {
|
||||
let color;
|
||||
if (!doc.qty && frm.doc.has_unit_price_items) {
|
||||
@@ -72,18 +60,6 @@ frappe.ui.form.on("Purchase Order", {
|
||||
},
|
||||
|
||||
refresh: function (frm) {
|
||||
if (frm.doc.is_old_subcontracting_flow) {
|
||||
frm.trigger("get_materials_from_supplier");
|
||||
|
||||
$("a.grey-link").each(function () {
|
||||
var id = $(this).children(":first-child").attr("data-label");
|
||||
if (id == "Duplicate") {
|
||||
$(this).remove();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (frm.doc.docstatus == 0) {
|
||||
erpnext.set_unit_price_items_note(frm);
|
||||
}
|
||||
@@ -179,7 +155,7 @@ frappe.ui.form.on("Purchase Order Item", {
|
||||
},
|
||||
|
||||
item_code: async function (frm, cdt, cdn) {
|
||||
if (frm.doc.is_subcontracted && !frm.doc.is_old_subcontracting_flow) {
|
||||
if (frm.doc.is_subcontracted) {
|
||||
var row = locals[cdt][cdn];
|
||||
|
||||
if (row.item_code && !row.fg_item) {
|
||||
@@ -227,7 +203,7 @@ frappe.ui.form.on("Purchase Order Item", {
|
||||
},
|
||||
|
||||
fg_item: async function (frm, cdt, cdn) {
|
||||
if (frm.doc.is_subcontracted && !frm.doc.is_old_subcontracting_flow) {
|
||||
if (frm.doc.is_subcontracted) {
|
||||
var row = locals[cdt][cdn];
|
||||
|
||||
if (row.fg_item) {
|
||||
@@ -248,7 +224,7 @@ frappe.ui.form.on("Purchase Order Item", {
|
||||
},
|
||||
|
||||
qty: async function (frm, cdt, cdn) {
|
||||
if (frm.doc.is_subcontracted && !frm.doc.is_old_subcontracting_flow) {
|
||||
if (frm.doc.is_subcontracted) {
|
||||
var row = locals[cdt][cdn];
|
||||
|
||||
if (row.fg_item) {
|
||||
@@ -383,26 +359,14 @@ erpnext.buying.PurchaseOrderController = class PurchaseOrderController extends (
|
||||
__("Create")
|
||||
);
|
||||
if (doc.is_subcontracted) {
|
||||
if (doc.is_old_subcontracting_flow) {
|
||||
if (me.has_unsupplied_items()) {
|
||||
this.frm.add_custom_button(
|
||||
__("Material to Supplier"),
|
||||
function () {
|
||||
me.make_stock_entry();
|
||||
},
|
||||
__("Transfer")
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (!doc.items.every((item) => item.qty == item.subcontracted_qty)) {
|
||||
this.frm.add_custom_button(
|
||||
__("Subcontracting Order"),
|
||||
() => {
|
||||
me.make_subcontracting_order();
|
||||
},
|
||||
__("Create")
|
||||
);
|
||||
}
|
||||
if (!doc.items.every((item) => item.qty == item.subcontracted_qty)) {
|
||||
this.frm.add_custom_button(
|
||||
__("Subcontracting Order"),
|
||||
() => {
|
||||
me.make_subcontracting_order();
|
||||
},
|
||||
__("Create")
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -748,20 +712,6 @@ cur_frm.cscript.update_status = function (label, status) {
|
||||
});
|
||||
};
|
||||
|
||||
if (cur_frm.doc.is_old_subcontracting_flow) {
|
||||
cur_frm.fields_dict["items"].grid.get_field("bom").get_query = function (doc, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
return {
|
||||
filters: [
|
||||
["BOM", "item", "=", d.item_code],
|
||||
["BOM", "is_active", "=", "1"],
|
||||
["BOM", "docstatus", "=", "1"],
|
||||
["BOM", "company", "=", doc.company],
|
||||
],
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function set_schedule_date(frm) {
|
||||
if (frm.doc.schedule_date) {
|
||||
erpnext.utils.copy_value_in_all_rows(
|
||||
@@ -775,9 +725,3 @@ function set_schedule_date(frm) {
|
||||
}
|
||||
|
||||
frappe.provide("erpnext.buying");
|
||||
|
||||
frappe.ui.form.on("Purchase Order", "is_subcontracted", function (frm) {
|
||||
if (frm.doc.is_old_subcontracting_flow) {
|
||||
erpnext.buying.get_default_bom(frm);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"actions": [],
|
||||
"allow_auto_repeat": 1,
|
||||
"allow_bulk_edit": 1,
|
||||
"allow_import": 1,
|
||||
"autoname": "naming_series:",
|
||||
"creation": "2013-05-21 16:16:39",
|
||||
@@ -164,7 +165,6 @@
|
||||
"mps",
|
||||
"is_internal_supplier",
|
||||
"inter_company_order_reference",
|
||||
"is_old_subcontracting_flow",
|
||||
"connections_tab"
|
||||
],
|
||||
"fields": [
|
||||
@@ -516,23 +516,6 @@
|
||||
"options": "Pricing Rule Detail",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"collapsible_depends_on": "supplied_items",
|
||||
"fieldname": "raw_material_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Raw Materials Supplied"
|
||||
},
|
||||
{
|
||||
"fieldname": "supplied_items",
|
||||
"fieldtype": "Table",
|
||||
"label": "Supplied Items",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "po_raw_material_details",
|
||||
"oldfieldtype": "Table",
|
||||
"options": "Purchase Order Item Supplied",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "sb_last_purchase",
|
||||
"fieldtype": "Section Break"
|
||||
@@ -1142,14 +1125,6 @@
|
||||
"label": "Project",
|
||||
"options": "Project"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "is_old_subcontracting_flow",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"label": "Is Old Subcontracting Flow",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "is_internal_supplier",
|
||||
"fieldname": "set_from_warehouse",
|
||||
@@ -1330,7 +1305,7 @@
|
||||
"idx": 105,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2026-03-30 12:17:43.342204",
|
||||
"modified": "2026-05-04 10:10:22.608381",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order",
|
||||
|
||||
@@ -49,9 +49,6 @@ class PurchaseOrder(BuyingController):
|
||||
PurchaseTaxesandCharges,
|
||||
)
|
||||
from erpnext.buying.doctype.purchase_order_item.purchase_order_item import PurchaseOrderItem
|
||||
from erpnext.buying.doctype.purchase_order_item_supplied.purchase_order_item_supplied import (
|
||||
PurchaseOrderItemSupplied,
|
||||
)
|
||||
|
||||
additional_discount_percentage: DF.Float
|
||||
address_display: DF.TextEditor | None
|
||||
@@ -100,7 +97,6 @@ class PurchaseOrder(BuyingController):
|
||||
incoterm: DF.Link | None
|
||||
inter_company_order_reference: DF.Link | None
|
||||
is_internal_supplier: DF.Check
|
||||
is_old_subcontracting_flow: DF.Check
|
||||
is_subcontracted: DF.Check
|
||||
item_wise_tax_details: DF.Table[ItemWiseTaxDetail]
|
||||
items: DF.Table[PurchaseOrderItem]
|
||||
@@ -147,7 +143,6 @@ class PurchaseOrder(BuyingController):
|
||||
"Closed",
|
||||
"Delivered",
|
||||
]
|
||||
supplied_items: DF.Table[PurchaseOrderItemSupplied]
|
||||
supplier: DF.Link
|
||||
supplier_address: DF.Link | None
|
||||
supplier_group: DF.Link | None
|
||||
@@ -210,14 +205,9 @@ class PurchaseOrder(BuyingController):
|
||||
self.validate_uom_is_integer("stock_uom", "stock_qty")
|
||||
|
||||
self.validate_with_previous_doc()
|
||||
self.validate_for_subcontracting()
|
||||
self.validate_minimum_order_qty()
|
||||
validate_against_blanket_order(self)
|
||||
|
||||
if self.is_old_subcontracting_flow:
|
||||
self.validate_bom_for_subcontracting_items()
|
||||
self.create_raw_materials_supplied()
|
||||
|
||||
self.validate_fg_item_for_subcontracting()
|
||||
self.set_received_qty_for_drop_ship_items()
|
||||
|
||||
@@ -328,40 +318,30 @@ class PurchaseOrder(BuyingController):
|
||||
).format(item_code, qty, itemwise_min_order_qty.get(item_code))
|
||||
)
|
||||
|
||||
def validate_bom_for_subcontracting_items(self):
|
||||
for item in self.items:
|
||||
if not item.bom:
|
||||
frappe.throw(
|
||||
_("Row #{0}: BOM is not specified for subcontracting item {0}").format(
|
||||
item.idx, item.item_code
|
||||
)
|
||||
)
|
||||
|
||||
def validate_fg_item_for_subcontracting(self):
|
||||
if self.is_subcontracted:
|
||||
if not self.is_old_subcontracting_flow:
|
||||
for item in self.items:
|
||||
if not item.fg_item:
|
||||
for item in self.items:
|
||||
if not item.fg_item:
|
||||
frappe.throw(
|
||||
_("Row #{0}: Finished Good Item is not specified for service item {1}").format(
|
||||
item.idx, item.item_code
|
||||
)
|
||||
)
|
||||
else:
|
||||
if not frappe.get_value("Item", item.fg_item, "is_sub_contracted_item"):
|
||||
frappe.throw(
|
||||
_("Row #{0}: Finished Good Item is not specified for service item {1}").format(
|
||||
item.idx, item.item_code
|
||||
_("Row #{0}: Finished Good Item {1} must be a sub-contracted item").format(
|
||||
item.idx, item.fg_item
|
||||
)
|
||||
)
|
||||
else:
|
||||
if not frappe.get_value("Item", item.fg_item, "is_sub_contracted_item"):
|
||||
frappe.throw(
|
||||
_("Row #{0}: Finished Good Item {1} must be a sub-contracted item").format(
|
||||
item.idx, item.fg_item
|
||||
)
|
||||
elif not item.bom and not frappe.get_value("Item", item.fg_item, "default_bom"):
|
||||
frappe.throw(
|
||||
_("Row #{0}: Default BOM not found for FG Item {1}").format(
|
||||
item.idx, item.fg_item
|
||||
)
|
||||
elif not item.bom and not frappe.get_value("Item", item.fg_item, "default_bom"):
|
||||
frappe.throw(
|
||||
_("Row #{0}: Default BOM not found for FG Item {1}").format(
|
||||
item.idx, item.fg_item
|
||||
)
|
||||
)
|
||||
if not item.fg_item_qty:
|
||||
frappe.throw(_("Row #{0}: Finished Good Item Qty can not be zero").format(item.idx))
|
||||
)
|
||||
if not item.fg_item_qty:
|
||||
frappe.throw(_("Row #{0}: Finished Good Item Qty can not be zero").format(item.idx))
|
||||
else:
|
||||
for item in self.items:
|
||||
item.set("fg_item", None)
|
||||
@@ -442,7 +422,6 @@ class PurchaseOrder(BuyingController):
|
||||
self.set_status(update=True, status=status)
|
||||
self.update_requested_qty()
|
||||
self.update_ordered_qty()
|
||||
self.update_reserved_qty_for_subcontract()
|
||||
self.update_subcontracting_order_status()
|
||||
self.update_blanket_order()
|
||||
self.notify_update()
|
||||
@@ -458,12 +437,11 @@ class PurchaseOrder(BuyingController):
|
||||
self.update_status_updater_if_from_pp()
|
||||
|
||||
self.update_prevdoc_status()
|
||||
if not self.is_subcontracted or self.is_old_subcontracting_flow:
|
||||
if not self.is_subcontracted:
|
||||
self.update_requested_qty()
|
||||
|
||||
self.update_ordered_qty()
|
||||
self.validate_budget()
|
||||
self.update_reserved_qty_for_subcontract()
|
||||
|
||||
frappe.get_cached_doc("Authorization Control").validate_approving_authority(
|
||||
self.doctype, self.company, self.base_grand_total
|
||||
@@ -495,7 +473,6 @@ class PurchaseOrder(BuyingController):
|
||||
if self.has_drop_ship_item():
|
||||
self.update_delivered_qty_in_sales_order()
|
||||
|
||||
self.update_reserved_qty_for_subcontract()
|
||||
self.check_on_hold_or_closed_status()
|
||||
|
||||
self.db_set("status", "Cancelled")
|
||||
@@ -504,7 +481,7 @@ class PurchaseOrder(BuyingController):
|
||||
|
||||
# Must be called after updating ordered qty in Material Request
|
||||
# bin uses Material Request Items to recalculate & update
|
||||
if not self.is_subcontracted or self.is_old_subcontracting_flow:
|
||||
if not self.is_subcontracted:
|
||||
self.update_requested_qty()
|
||||
|
||||
self.update_ordered_qty()
|
||||
@@ -581,13 +558,6 @@ class PurchaseOrder(BuyingController):
|
||||
if item.delivered_by_supplier == 1:
|
||||
item.received_qty = item.qty
|
||||
|
||||
def update_reserved_qty_for_subcontract(self):
|
||||
if self.is_old_subcontracting_flow:
|
||||
for d in self.supplied_items:
|
||||
if d.rm_item_code:
|
||||
stock_bin = get_bin(d.rm_item_code, d.reserve_warehouse)
|
||||
stock_bin.update_reserved_qty_for_sub_contracting(subcontract_doctype="Purchase Order")
|
||||
|
||||
def update_receiving_percentage(self):
|
||||
total_qty, received_qty = 0.0, 0.0
|
||||
for item in self.items:
|
||||
@@ -599,7 +569,7 @@ class PurchaseOrder(BuyingController):
|
||||
self.db_set("per_received", 0, update_modified=False)
|
||||
|
||||
def set_service_items_for_finished_goods(self):
|
||||
if not self.is_subcontracted or self.is_old_subcontracting_flow:
|
||||
if not self.is_subcontracted:
|
||||
return
|
||||
|
||||
finished_goods_without_service_item = {
|
||||
@@ -620,7 +590,7 @@ class PurchaseOrder(BuyingController):
|
||||
def can_update_items(self) -> bool:
|
||||
result = True
|
||||
|
||||
if self.is_subcontracted and not self.is_old_subcontracting_flow:
|
||||
if self.is_subcontracted:
|
||||
if frappe.db.exists(
|
||||
"Subcontracting Order", {"purchase_order": self.name, "docstatus": ["!=", 2]}
|
||||
):
|
||||
@@ -644,7 +614,7 @@ class PurchaseOrder(BuyingController):
|
||||
)
|
||||
|
||||
def auto_create_subcontracting_order(self):
|
||||
if self.is_subcontracted and not self.is_old_subcontracting_flow:
|
||||
if self.is_subcontracted:
|
||||
if frappe.db.get_single_value("Buying Settings", "auto_create_subcontracting_order"):
|
||||
make_subcontracting_order(self.name, save=True, notify=True)
|
||||
|
||||
@@ -653,7 +623,7 @@ class PurchaseOrder(BuyingController):
|
||||
update_subcontracting_order_status as update_sco_status,
|
||||
)
|
||||
|
||||
if self.is_subcontracted and not self.is_old_subcontracting_flow:
|
||||
if self.is_subcontracted:
|
||||
sco = frappe.db.get_value("Subcontracting Order", {"purchase_order": self.name, "docstatus": 1})
|
||||
|
||||
if sco:
|
||||
|
||||
@@ -1593,11 +1593,6 @@ def create_purchase_order(**args):
|
||||
po.set_missing_values()
|
||||
po.insert()
|
||||
if not args.do_not_submit:
|
||||
if po.is_subcontracted:
|
||||
supp_items = po.get("supplied_items")
|
||||
for d in supp_items:
|
||||
if not d.reserve_warehouse:
|
||||
d.reserve_warehouse = args.warehouse or "_Test Warehouse - _TC"
|
||||
po.submit()
|
||||
|
||||
return po
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"actions": [],
|
||||
"allow_bulk_edit": 1,
|
||||
"autoname": "hash",
|
||||
"creation": "2024-12-09 12:54:24.652161",
|
||||
"doctype": "DocType",
|
||||
@@ -94,7 +95,6 @@
|
||||
"manufacturer_part_no",
|
||||
"column_break_14",
|
||||
"bom",
|
||||
"include_exploded_items",
|
||||
"item_weight_details",
|
||||
"weight_per_unit",
|
||||
"total_weight",
|
||||
@@ -588,22 +588,12 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:parent.is_old_subcontracting_flow",
|
||||
"fieldname": "bom",
|
||||
"fieldtype": "Link",
|
||||
"label": "BOM",
|
||||
"options": "BOM",
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"read_only_depends_on": "eval:!parent.is_old_subcontracting_flow"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:parent.is_old_subcontracting_flow",
|
||||
"fieldname": "include_exploded_items",
|
||||
"fieldtype": "Check",
|
||||
"label": "Include Exploded Items",
|
||||
"print_hide": 1
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_56",
|
||||
@@ -870,20 +860,20 @@
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:parent.is_subcontracted && !parent.is_old_subcontracting_flow",
|
||||
"depends_on": "eval:parent.is_subcontracted",
|
||||
"fieldname": "fg_item",
|
||||
"fieldtype": "Link",
|
||||
"label": "Finished Good",
|
||||
"mandatory_depends_on": "eval:parent.is_subcontracted && !parent.is_old_subcontracting_flow",
|
||||
"mandatory_depends_on": "eval:parent.is_subcontracted",
|
||||
"options": "Item"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"depends_on": "eval:parent.is_subcontracted && !parent.is_old_subcontracting_flow",
|
||||
"depends_on": "eval:parent.is_subcontracted",
|
||||
"fieldname": "fg_item_qty",
|
||||
"fieldtype": "Float",
|
||||
"label": "Finished Good Qty",
|
||||
"mandatory_depends_on": "eval:parent.is_subcontracted && !parent.is_old_subcontracting_flow",
|
||||
"mandatory_depends_on": "eval:parent.is_subcontracted",
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
@@ -935,7 +925,7 @@
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"default": "0",
|
||||
"depends_on": "eval:parent.is_subcontracted && !parent.is_old_subcontracting_flow",
|
||||
"depends_on": "eval:parent.is_subcontracted",
|
||||
"fieldname": "subcontracted_qty",
|
||||
"fieldtype": "Float",
|
||||
"label": "Subcontracted Quantity",
|
||||
@@ -950,7 +940,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-11-30 16:51:57.761673",
|
||||
"modified": "2026-05-04 10:51:05.183490",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order Item",
|
||||
|
||||
@@ -27,7 +27,6 @@ class PurchaseOrderItem(Document):
|
||||
billed_amt: DF.Currency
|
||||
blanket_order: DF.Link | None
|
||||
blanket_order_rate: DF.Currency
|
||||
bom: DF.Link | None
|
||||
brand: DF.Link | None
|
||||
company_total_stock: DF.Float
|
||||
conversion_factor: DF.Float
|
||||
@@ -43,7 +42,6 @@ class PurchaseOrderItem(Document):
|
||||
fg_item_qty: DF.Float
|
||||
from_warehouse: DF.Link | None
|
||||
image: DF.Attach | None
|
||||
include_exploded_items: DF.Check
|
||||
is_fixed_asset: DF.Check
|
||||
is_free_item: DF.Check
|
||||
item_code: DF.Link
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Raw material (if any) supplied along with Purchase Order.
|
||||
@@ -1,195 +0,0 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2013-02-22 01:27:42",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"main_item_code",
|
||||
"rm_item_code",
|
||||
"column_break_3",
|
||||
"stock_uom",
|
||||
"reserve_warehouse",
|
||||
"conversion_factor",
|
||||
"column_break_6",
|
||||
"bom_detail_no",
|
||||
"reference_name",
|
||||
"section_break2",
|
||||
"rate",
|
||||
"col_break2",
|
||||
"amount",
|
||||
"section_break1",
|
||||
"required_qty",
|
||||
"supplied_qty",
|
||||
"col_break1",
|
||||
"consumed_qty",
|
||||
"returned_qty",
|
||||
"total_supplied_qty"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "main_item_code",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Item Code",
|
||||
"oldfieldname": "main_item_code",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "Item",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "rm_item_code",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Raw Material Item Code",
|
||||
"oldfieldname": "rm_item_code",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "Item",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "required_qty",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Required Qty",
|
||||
"oldfieldname": "required_qty",
|
||||
"oldfieldtype": "Currency",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "rate",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Rate",
|
||||
"oldfieldname": "rate",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency"
|
||||
},
|
||||
{
|
||||
"fieldname": "amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Amount",
|
||||
"oldfieldname": "amount",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_6",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "bom_detail_no",
|
||||
"fieldtype": "Data",
|
||||
"label": "BOM Detail No",
|
||||
"oldfieldname": "bom_detail_no",
|
||||
"oldfieldtype": "Data",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "reference_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "Reference Name",
|
||||
"oldfieldname": "reference_name",
|
||||
"oldfieldtype": "Data",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "conversion_factor",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 1,
|
||||
"label": "Conversion Factor",
|
||||
"oldfieldname": "conversion_factor",
|
||||
"oldfieldtype": "Currency",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "stock_uom",
|
||||
"fieldtype": "Link",
|
||||
"label": "Stock Uom",
|
||||
"oldfieldname": "stock_uom",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "UOM",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "reserve_warehouse",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Reserve Warehouse",
|
||||
"options": "Warehouse"
|
||||
},
|
||||
{
|
||||
"fieldname": "supplied_qty",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Supplied Qty",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break1",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "col_break1",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break2",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "col_break2",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "consumed_qty",
|
||||
"fieldtype": "Float",
|
||||
"label": "Consumed Qty",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "returned_qty",
|
||||
"fieldtype": "Float",
|
||||
"label": "Returned Qty",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "total_supplied_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 1,
|
||||
"label": "Total Supplied Qty",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break"
|
||||
}
|
||||
],
|
||||
"hide_toolbar": 1,
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:10:25.280016",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order Item Supplied",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "creation",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class PurchaseOrderItemSupplied(Document):
|
||||
# begin: auto-generated types
|
||||
# This code is auto-generated. Do not modify anything in this block.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from frappe.types import DF
|
||||
|
||||
amount: DF.Currency
|
||||
bom_detail_no: DF.Data | None
|
||||
consumed_qty: DF.Float
|
||||
conversion_factor: DF.Float
|
||||
main_item_code: DF.Link | None
|
||||
parent: DF.Data
|
||||
parentfield: DF.Data
|
||||
parenttype: DF.Data
|
||||
rate: DF.Currency
|
||||
reference_name: DF.Data | None
|
||||
required_qty: DF.Float
|
||||
reserve_warehouse: DF.Link | None
|
||||
returned_qty: DF.Float
|
||||
rm_item_code: DF.Link | None
|
||||
stock_uom: DF.Link | None
|
||||
supplied_qty: DF.Float
|
||||
total_supplied_qty: DF.Float
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
@@ -25,13 +25,6 @@ frappe.query_reports["Subcontract Order Summary"] = {
|
||||
default: frappe.datetime.get_today(),
|
||||
reqd: 1,
|
||||
},
|
||||
{
|
||||
label: __("Order Type"),
|
||||
fieldname: "order_type",
|
||||
fieldtype: "Select",
|
||||
options: ["Purchase Order", "Subcontracting Order"],
|
||||
default: "Subcontracting Order",
|
||||
},
|
||||
{
|
||||
label: __("Subcontract Order"),
|
||||
fieldname: "name",
|
||||
|
||||
@@ -28,37 +28,34 @@ def get_data(report_filters):
|
||||
|
||||
def get_subcontracted_orders(report_filters):
|
||||
fields = [
|
||||
f"`tab{report_filters.order_type} Item`.`parent` as order_id",
|
||||
f"`tab{report_filters.order_type} Item`.`item_code`",
|
||||
f"`tab{report_filters.order_type} Item`.`item_name`",
|
||||
f"`tab{report_filters.order_type} Item`.`qty`",
|
||||
f"`tab{report_filters.order_type} Item`.`name`",
|
||||
f"`tab{report_filters.order_type} Item`.`received_qty`",
|
||||
f"`tab{report_filters.order_type}`.`status`",
|
||||
"`tabSubcontracting Order Item`.`parent` as order_id",
|
||||
"`tabSubcontracting Order Item`.`item_code`",
|
||||
"`tabSubcontracting Order Item`.`item_name`",
|
||||
"`tabSubcontracting Order Item`.`qty`",
|
||||
"`tabSubcontracting Order Item`.`name`",
|
||||
"`tabSubcontracting Order Item`.`received_qty`",
|
||||
"`tabSubcontracting Order`.`status`",
|
||||
]
|
||||
|
||||
filters = get_filters(report_filters)
|
||||
|
||||
return frappe.get_all(report_filters.order_type, fields=fields, filters=filters) or []
|
||||
return frappe.get_all("Subcontracting Order", fields=fields, filters=filters) or []
|
||||
|
||||
|
||||
def get_filters(report_filters):
|
||||
filters = [
|
||||
[report_filters.order_type, "docstatus", "=", 1],
|
||||
["Subcontracting Order", "docstatus", "=", 1],
|
||||
[
|
||||
report_filters.order_type,
|
||||
"Subcontracting Order",
|
||||
"transaction_date",
|
||||
"between",
|
||||
(report_filters.from_date, report_filters.to_date),
|
||||
],
|
||||
]
|
||||
|
||||
if report_filters.order_type == "Purchase Order":
|
||||
filters.append(["Purchase Order", "is_old_subcontracting_flow", "=", 1])
|
||||
|
||||
for field in ["name", "company"]:
|
||||
if report_filters.get(field):
|
||||
filters.append([report_filters.order_type, field, "=", report_filters.get(field)])
|
||||
filters.append(["Subcontracting Order", field, "=", report_filters.get(field)])
|
||||
|
||||
return filters
|
||||
|
||||
@@ -82,12 +79,7 @@ def get_supplied_items(orders, report_filters):
|
||||
filters = {"parent": ("in", [d.order_id for d in orders]), "docstatus": 1}
|
||||
|
||||
supplied_items = {}
|
||||
supplied_items_table = (
|
||||
"Purchase Order Item Supplied"
|
||||
if report_filters.order_type == "Purchase Order"
|
||||
else "Subcontracting Order Supplied Item"
|
||||
)
|
||||
for row in frappe.get_all(supplied_items_table, fields=fields, filters=filters):
|
||||
for row in frappe.get_all("Subcontracting Order Supplied Item", fields=fields, filters=filters):
|
||||
new_key = (row.parent, row.reference_name, row.main_item_code)
|
||||
|
||||
supplied_items.setdefault(new_key, []).append(row)
|
||||
@@ -128,7 +120,7 @@ def get_columns(filters):
|
||||
"label": _("Subcontract Order"),
|
||||
"fieldname": "order_id",
|
||||
"fieldtype": "Link",
|
||||
"options": filters.order_type,
|
||||
"options": "Subcontracting Order",
|
||||
"width": 100,
|
||||
},
|
||||
{"label": _("Status"), "fieldname": "status", "fieldtype": "Data", "width": 80},
|
||||
|
||||
@@ -3,13 +3,6 @@
|
||||
|
||||
frappe.query_reports["Subcontracted Item To Be Received"] = {
|
||||
filters: [
|
||||
{
|
||||
label: __("Order Type"),
|
||||
fieldname: "order_type",
|
||||
fieldtype: "Select",
|
||||
options: ["Purchase Order", "Subcontracting Order"],
|
||||
default: "Subcontracting Order",
|
||||
},
|
||||
{
|
||||
fieldname: "supplier",
|
||||
label: __("Supplier"),
|
||||
|
||||
@@ -22,7 +22,6 @@ def get_columns(filters):
|
||||
"label": _("Subcontract Order"),
|
||||
"fieldtype": "Link",
|
||||
"fieldname": "subcontract_order",
|
||||
"options": filters.order_type,
|
||||
"width": 150,
|
||||
},
|
||||
{"label": _("Date"), "fieldtype": "Date", "fieldname": "date", "hidden": 1, "width": 150},
|
||||
@@ -59,7 +58,7 @@ def get_columns(filters):
|
||||
def get_data(data, filters):
|
||||
orders = get_subcontract_orders(filters)
|
||||
orders_name = [order.name for order in orders]
|
||||
subcontracted_items = get_subcontract_order_supplied_item(filters.order_type, orders_name)
|
||||
subcontracted_items = get_subcontract_order_supplied_item("Subcontracting Order", orders_name)
|
||||
for item in subcontracted_items:
|
||||
for order in orders:
|
||||
if order.name == item.parent and item.received_qty < item.qty:
|
||||
@@ -84,11 +83,8 @@ def get_subcontract_orders(filters):
|
||||
["docstatus", "=", 1],
|
||||
]
|
||||
|
||||
if filters.order_type == "Purchase Order":
|
||||
record_filters.append(["is_old_subcontracting_flow", "=", 1])
|
||||
|
||||
return frappe.get_all(
|
||||
filters.order_type, filters=record_filters, fields=["name", "transaction_date", "supplier"]
|
||||
"Subcontracting Order", filters=record_filters, fields=["name", "transaction_date", "supplier"]
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -3,13 +3,6 @@
|
||||
|
||||
frappe.query_reports["Subcontracted Raw Materials To Be Transferred"] = {
|
||||
filters: [
|
||||
{
|
||||
label: __("Order Type"),
|
||||
fieldname: "order_type",
|
||||
fieldtype: "Select",
|
||||
options: ["Purchase Order", "Subcontracting Order"],
|
||||
default: "Subcontracting Order",
|
||||
},
|
||||
{
|
||||
fieldname: "supplier",
|
||||
label: __("Supplier"),
|
||||
|
||||
@@ -22,7 +22,6 @@ def get_columns(filters):
|
||||
"label": _("Subcontract Order"),
|
||||
"fieldtype": "Link",
|
||||
"fieldname": "subcontract_order",
|
||||
"options": filters.order_type,
|
||||
"width": 200,
|
||||
},
|
||||
{"label": _("Date"), "fieldtype": "Date", "fieldname": "date", "width": 150},
|
||||
@@ -61,25 +60,18 @@ def get_data(filters):
|
||||
|
||||
|
||||
def get_order_items_to_supply(filters):
|
||||
supplied_items_table = (
|
||||
"Purchase Order Item Supplied"
|
||||
if filters.order_type == "Purchase Order"
|
||||
else "Subcontracting Order Supplied Item"
|
||||
)
|
||||
supplied_items_table = "Subcontracting Order Supplied Item"
|
||||
|
||||
record_filters = [
|
||||
[filters.order_type, "per_received", "<", "100"],
|
||||
[filters.order_type, "supplier", "=", filters.supplier],
|
||||
[filters.order_type, "transaction_date", "<=", filters.to_date],
|
||||
[filters.order_type, "transaction_date", ">=", filters.from_date],
|
||||
[filters.order_type, "docstatus", "=", 1],
|
||||
["Subcontracting Order", "per_received", "<", "100"],
|
||||
["Subcontracting Order", "supplier", "=", filters.supplier],
|
||||
["Subcontracting Order", "transaction_date", "<=", filters.to_date],
|
||||
["Subcontracting Order", "transaction_date", ">=", filters.from_date],
|
||||
["Subcontracting Order", "docstatus", "=", 1],
|
||||
]
|
||||
|
||||
if filters.order_type == "Purchase Order":
|
||||
record_filters.append([filters.order_type, "is_old_subcontracting_flow", "=", 1])
|
||||
|
||||
return frappe.db.get_all(
|
||||
filters.order_type,
|
||||
"Subcontracting Order",
|
||||
fields=[
|
||||
"name as subcontract_order",
|
||||
"transaction_date as date",
|
||||
|
||||
@@ -4171,11 +4171,7 @@ def update_child_qty_rate(
|
||||
if flt(child_item.get("qty")) != flt(d.get("qty")):
|
||||
any_qty_changed = True
|
||||
|
||||
if (
|
||||
parent.doctype in ["Sales Order", "Purchase Order"]
|
||||
and parent.is_subcontracted
|
||||
and not parent.get("is_old_subcontracting_flow")
|
||||
):
|
||||
if parent.doctype in ["Sales Order", "Purchase Order"] and parent.is_subcontracted:
|
||||
validate_fg_item_for_subcontracting(d, new_child_flag)
|
||||
child_item.fg_item_qty = flt(d["fg_item_qty"])
|
||||
|
||||
@@ -4246,18 +4242,12 @@ def update_child_qty_rate(
|
||||
parent.update_receiving_percentage()
|
||||
|
||||
if parent.is_subcontracted:
|
||||
if parent.is_old_subcontracting_flow:
|
||||
if should_update_supplied_items(parent):
|
||||
parent.update_reserved_qty_for_subcontract()
|
||||
parent.create_raw_materials_supplied()
|
||||
parent.save()
|
||||
else:
|
||||
if not parent.can_update_items():
|
||||
frappe.throw(
|
||||
_(
|
||||
"Items cannot be updated as Subcontracting Order is created against the Purchase Order {0}."
|
||||
).format(frappe.bold(parent.name))
|
||||
)
|
||||
if not parent.can_update_items():
|
||||
frappe.throw(
|
||||
_(
|
||||
"Items cannot be updated as Subcontracting Order is created against the Purchase Order {0}."
|
||||
).format(frappe.bold(parent.name))
|
||||
)
|
||||
elif parent_doctype == "Sales Order": # Sales Order
|
||||
if parent.is_subcontracted and not parent.can_update_items():
|
||||
frappe.throw(
|
||||
|
||||
@@ -59,11 +59,6 @@ class BuyingController(SubcontractingController):
|
||||
self.validate_rejected_warehouse()
|
||||
self.validate_accepted_rejected_qty()
|
||||
validate_for_items(self)
|
||||
|
||||
# sub-contracting
|
||||
self.validate_for_subcontracting()
|
||||
if self.get("is_old_subcontracting_flow"):
|
||||
self.create_raw_materials_supplied()
|
||||
self.set_landed_cost_voucher_amount()
|
||||
|
||||
if self.doctype in ("Purchase Receipt", "Purchase Invoice"):
|
||||
@@ -488,21 +483,12 @@ class BuyingController(SubcontractingController):
|
||||
if not qty_in_stock_uom and item.get("rejected_qty"):
|
||||
qty_in_stock_uom = flt(item.rejected_qty * item.conversion_factor)
|
||||
|
||||
if self.get("is_old_subcontracting_flow"):
|
||||
item.rm_supp_cost = self.get_supplied_items_cost(item.name, reset_outgoing_rate)
|
||||
item.valuation_rate = (
|
||||
net_rate
|
||||
+ item.item_tax_amount
|
||||
+ item.rm_supp_cost
|
||||
+ flt(item.landed_cost_voucher_amount)
|
||||
) / qty_in_stock_uom
|
||||
else:
|
||||
item.valuation_rate = (
|
||||
net_rate
|
||||
+ item.item_tax_amount
|
||||
+ flt(item.landed_cost_voucher_amount)
|
||||
+ flt(item.get("amount_difference_with_purchase_invoice"))
|
||||
) / qty_in_stock_uom
|
||||
item.valuation_rate = (
|
||||
net_rate
|
||||
+ item.item_tax_amount
|
||||
+ flt(item.landed_cost_voucher_amount)
|
||||
+ flt(item.get("amount_difference_with_purchase_invoice"))
|
||||
) / qty_in_stock_uom
|
||||
else:
|
||||
item.valuation_rate = 0.0
|
||||
|
||||
@@ -642,36 +628,6 @@ class BuyingController(SubcontractingController):
|
||||
* (d.conversion_factor or 1)
|
||||
)
|
||||
|
||||
def validate_for_subcontracting(self):
|
||||
if self.is_subcontracted and self.get("is_old_subcontracting_flow"):
|
||||
if self.doctype in ["Purchase Receipt", "Purchase Invoice"] and not self.supplier_warehouse:
|
||||
frappe.throw(
|
||||
_("{field_label} is mandatory for sub-contracted {doctype}.").format(
|
||||
field_label=_(self.meta.get_label("supplier_warehouse")), doctype=_(self.doctype)
|
||||
)
|
||||
)
|
||||
|
||||
for item in self.get("items"):
|
||||
if item in self.sub_contracted_items and not item.bom:
|
||||
frappe.throw(
|
||||
_("Please select BOM in BOM field for Item {item_code}.").format(
|
||||
item_code=frappe.bold(item.item_code)
|
||||
)
|
||||
)
|
||||
if self.doctype != "Purchase Order":
|
||||
return
|
||||
for row in self.get("supplied_items"):
|
||||
if not row.reserve_warehouse:
|
||||
frappe.throw(
|
||||
_(
|
||||
"Reserved Warehouse is mandatory for the Item {item_code} in Raw Materials supplied."
|
||||
).format(item_code=frappe.bold(row.rm_item_code))
|
||||
)
|
||||
else:
|
||||
for item in self.get("items"):
|
||||
if item.get("bom"):
|
||||
item.bom = None
|
||||
|
||||
def set_qty_as_per_stock_uom(self):
|
||||
allow_to_edit_stock_qty = frappe.get_single_value(
|
||||
"Stock Settings", "allow_to_edit_stock_uom_qty_for_purchase"
|
||||
@@ -885,9 +841,6 @@ class BuyingController(SubcontractingController):
|
||||
)
|
||||
)
|
||||
|
||||
if self.get("is_old_subcontracting_flow"):
|
||||
self.make_sl_entries_for_supplier_warehouse(sl_entries)
|
||||
|
||||
self.make_sl_entries(
|
||||
sl_entries,
|
||||
allow_negative_stock=allow_negative_stock,
|
||||
@@ -943,8 +896,6 @@ class BuyingController(SubcontractingController):
|
||||
)
|
||||
|
||||
po_obj.update_ordered_qty(po_item_rows)
|
||||
if self.get("is_old_subcontracting_flow"):
|
||||
po_obj.update_reserved_qty_for_subcontract()
|
||||
|
||||
def on_submit(self):
|
||||
if self.get("is_return"):
|
||||
@@ -1213,10 +1164,7 @@ class BuyingController(SubcontractingController):
|
||||
if self.doctype == "Material Request":
|
||||
return
|
||||
|
||||
if self.get("is_old_subcontracting_flow"):
|
||||
validate_item_type(self, "is_sub_contracted_item", "subcontracted")
|
||||
else:
|
||||
validate_item_type(self, "is_purchase_item", "purchase")
|
||||
validate_item_type(self, "is_purchase_item", "purchase")
|
||||
|
||||
|
||||
def get_asset_item_details(asset_items):
|
||||
|
||||
@@ -26,17 +26,7 @@ from erpnext.stock.utils import get_incoming_rate
|
||||
class SubcontractingController(StockController):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
if self.get("is_old_subcontracting_flow"):
|
||||
self.subcontract_data = frappe._dict(
|
||||
{
|
||||
"order_doctype": "Purchase Order",
|
||||
"order_field": "purchase_order",
|
||||
"rm_detail_field": "po_detail",
|
||||
"receipt_supplied_items_field": "Purchase Receipt Item Supplied",
|
||||
"order_supplied_items_field": "Purchase Order Item Supplied",
|
||||
}
|
||||
)
|
||||
elif self.doctype == "Subcontracting Inward Order":
|
||||
if self.doctype == "Subcontracting Inward Order":
|
||||
self.subcontract_data = frappe._dict(
|
||||
{
|
||||
"order_doctype": "Subcontracting Inward Order",
|
||||
@@ -541,11 +531,7 @@ class SubcontractingController(StockController):
|
||||
self.__set_alternative_item_details(row)
|
||||
|
||||
self.__transferred_items = copy.deepcopy(self.available_materials)
|
||||
if self.get("is_old_subcontracting_flow"):
|
||||
for doctype in ["Purchase Receipt", "Purchase Invoice"]:
|
||||
self.__update_consumed_materials(doctype)
|
||||
else:
|
||||
self.__update_consumed_materials("Subcontracting Receipt")
|
||||
self.__update_consumed_materials("Subcontracting Receipt")
|
||||
|
||||
def __remove_changed_rows(self):
|
||||
if not self.__changed_name:
|
||||
@@ -1136,24 +1122,17 @@ class SubcontractingController(StockController):
|
||||
|
||||
def set_consumed_qty_in_subcontract_order(self):
|
||||
# Update consumed qty back in the subcontract order
|
||||
if self.doctype in ["Subcontracting Order", "Subcontracting Receipt"] or self.get(
|
||||
"is_old_subcontracting_flow"
|
||||
):
|
||||
if self.doctype in ["Subcontracting Order", "Subcontracting Receipt"]:
|
||||
self.__get_subcontract_orders()
|
||||
itemwise_consumed_qty = defaultdict(float)
|
||||
if self.get("is_old_subcontracting_flow"):
|
||||
doctypes = ["Purchase Receipt", "Purchase Invoice"]
|
||||
else:
|
||||
doctypes = ["Subcontracting Receipt"]
|
||||
|
||||
for doctype in doctypes:
|
||||
consumed_items, receipt_items = self.__update_consumed_materials(
|
||||
doctype, return_consumed_items=True
|
||||
)
|
||||
consumed_items, receipt_items = self.__update_consumed_materials(
|
||||
"Subcontracting Receipt", return_consumed_items=True
|
||||
)
|
||||
|
||||
for row in consumed_items:
|
||||
key = (row.rm_item_code, row.main_item_code, receipt_items.get(row.reference_name))
|
||||
itemwise_consumed_qty[key] += row.consumed_qty
|
||||
for row in consumed_items:
|
||||
key = (row.rm_item_code, row.main_item_code, receipt_items.get(row.reference_name))
|
||||
itemwise_consumed_qty[key] += row.consumed_qty
|
||||
|
||||
self.__update_consumed_qty_in_subcontract_order(itemwise_consumed_qty)
|
||||
|
||||
@@ -1236,32 +1215,10 @@ class SubcontractingController(StockController):
|
||||
via_landed_cost_voucher=via_landed_cost_voucher,
|
||||
)
|
||||
|
||||
def get_supplied_items_cost(self, item_row_id, reset_outgoing_rate=True):
|
||||
def get_supplied_items_cost(self, item_row_id):
|
||||
supplied_items_cost = 0.0
|
||||
for item in self.get("supplied_items"):
|
||||
if item.reference_name == item_row_id:
|
||||
if (
|
||||
self.get("is_old_subcontracting_flow")
|
||||
and reset_outgoing_rate
|
||||
and frappe.get_cached_value("Item", item.rm_item_code, "is_stock_item")
|
||||
):
|
||||
rate = get_incoming_rate(
|
||||
{
|
||||
"item_code": item.rm_item_code,
|
||||
"warehouse": self.supplier_warehouse,
|
||||
"posting_date": self.posting_date,
|
||||
"posting_time": self.posting_time,
|
||||
"qty": -1 * item.consumed_qty,
|
||||
"voucher_detail_no": item.name,
|
||||
"serial_and_batch_bundle": item.get("serial_and_batch_bundle"),
|
||||
"serial_no": item.get("serial_no"),
|
||||
"batch_no": item.get("batch_no"),
|
||||
}
|
||||
)
|
||||
|
||||
if rate > 0:
|
||||
item.rate = rate
|
||||
|
||||
item.amount = flt(flt(item.consumed_qty) * flt(item.rate), item.precision("amount"))
|
||||
supplied_items_cost += item.amount
|
||||
|
||||
|
||||
@@ -92,11 +92,7 @@ erpnext.buying = {
|
||||
this.frm.set_query("item_code", "items", function () {
|
||||
if (me.frm.doc.is_subcontracted) {
|
||||
var filters = { supplier: me.frm.doc.supplier };
|
||||
if (me.frm.doc.is_old_subcontracting_flow) {
|
||||
filters["is_sub_contracted_item"] = 1;
|
||||
} else {
|
||||
filters["is_stock_item"] = 0;
|
||||
}
|
||||
filters["is_stock_item"] = 0;
|
||||
|
||||
return {
|
||||
query: "erpnext.controllers.queries.item_query",
|
||||
|
||||
@@ -806,7 +806,6 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
|
||||
item_tax_template: item.item_tax_template,
|
||||
child_doctype: item.doctype,
|
||||
child_docname: item.name,
|
||||
is_old_subcontracting_flow: me.frm.doc.is_old_subcontracting_flow,
|
||||
use_serial_batch_fields: item.use_serial_batch_fields,
|
||||
serial_and_batch_bundle: item.serial_and_batch_bundle,
|
||||
},
|
||||
|
||||
@@ -744,11 +744,7 @@ erpnext.utils.update_child_items = function (opts) {
|
||||
}
|
||||
} else if (frm.doc.doctype == "Purchase Order") {
|
||||
if (frm.doc.is_subcontracted) {
|
||||
if (frm.doc.is_old_subcontracting_flow) {
|
||||
filters = { is_sub_contracted_item: 1 };
|
||||
} else {
|
||||
filters = { is_stock_item: 0 };
|
||||
}
|
||||
filters = { is_stock_item: 0 };
|
||||
} else {
|
||||
filters = { is_purchase_item: 1 };
|
||||
}
|
||||
@@ -791,7 +787,6 @@ erpnext.utils.update_child_items = function (opts) {
|
||||
pos_profile: cint(frm.doc.is_pos) ? frm.doc.pos_profile : "",
|
||||
tax_category: frm.doc.tax_category,
|
||||
child_doctype: frm.doc.doctype + " Item",
|
||||
is_old_subcontracting_flow: frm.doc.is_old_subcontracting_flow,
|
||||
},
|
||||
},
|
||||
callback: function (r) {
|
||||
@@ -904,11 +899,7 @@ erpnext.utils.update_child_items = function (opts) {
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
["Purchase Order", "Sales Order"].includes(frm.doc.doctype) &&
|
||||
frm.doc.is_subcontracted &&
|
||||
!frm.doc.is_old_subcontracting_flow
|
||||
) {
|
||||
if (["Purchase Order", "Sales Order"].includes(frm.doc.doctype) && frm.doc.is_subcontracted) {
|
||||
fields.push(
|
||||
{
|
||||
fieldtype: "Link",
|
||||
|
||||
@@ -145,11 +145,7 @@ class Bin(Document):
|
||||
# reserved qty
|
||||
|
||||
subcontract_order = frappe.qb.DocType(subcontract_doctype)
|
||||
supplied_item = frappe.qb.DocType(
|
||||
"Purchase Order Item Supplied"
|
||||
if subcontract_doctype == "Purchase Order"
|
||||
else "Subcontracting Order Supplied Item"
|
||||
)
|
||||
supplied_item = frappe.qb.DocType("Subcontracting Order Supplied Item")
|
||||
|
||||
conditions = (
|
||||
(supplied_item.rm_item_code == self.item_code)
|
||||
@@ -157,11 +153,7 @@ class Bin(Document):
|
||||
& (subcontract_order.per_received < 100)
|
||||
& (supplied_item.reserve_warehouse == self.warehouse)
|
||||
& (
|
||||
(
|
||||
(subcontract_order.is_old_subcontracting_flow == 1)
|
||||
& (subcontract_order.status != "Closed")
|
||||
& (subcontract_order.docstatus == 1)
|
||||
)
|
||||
((subcontract_order.status != "Closed") & (subcontract_order.docstatus == 1))
|
||||
if subcontract_doctype == "Purchase Order"
|
||||
else (subcontract_order.docstatus == 1)
|
||||
)
|
||||
@@ -193,7 +185,6 @@ class Bin(Document):
|
||||
(
|
||||
(Coalesce(se.purchase_order, "") != "")
|
||||
& (subcontract_order.name == se.purchase_order)
|
||||
& (subcontract_order.is_old_subcontracting_flow == 1)
|
||||
& (subcontract_order.status != "Closed")
|
||||
)
|
||||
if subcontract_doctype == "Purchase Order"
|
||||
|
||||
@@ -278,8 +278,6 @@ erpnext.stock.PurchaseReceiptController = class PurchaseReceiptController extend
|
||||
if (this.frm.doc.docstatus == 1 && this.frm.doc.status === "Closed" && this.frm.has_perm("submit")) {
|
||||
cur_frm.add_custom_button(__("Reopen"), this.reopen_purchase_receipt, __("Status"));
|
||||
}
|
||||
|
||||
this.frm.toggle_reqd("supplier_warehouse", this.frm.doc.is_old_subcontracting_flow);
|
||||
}
|
||||
|
||||
make_purchase_invoice() {
|
||||
@@ -420,14 +418,6 @@ cur_frm.fields_dict["items"].grid.get_field("bom").get_query = function (doc, cd
|
||||
|
||||
frappe.provide("erpnext.buying");
|
||||
|
||||
frappe.ui.form.on("Purchase Receipt", "is_subcontracted", function (frm) {
|
||||
if (frm.doc.is_old_subcontracting_flow) {
|
||||
erpnext.buying.get_default_bom(frm);
|
||||
}
|
||||
|
||||
frm.toggle_reqd("supplier_warehouse", frm.doc.is_old_subcontracting_flow);
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Purchase Receipt Item", {
|
||||
item_code: function (frm, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"actions": [],
|
||||
"allow_auto_repeat": 1,
|
||||
"allow_bulk_edit": 1,
|
||||
"allow_import": 1,
|
||||
"autoname": "naming_series:",
|
||||
"creation": "2026-04-06 14:10:33.384946",
|
||||
@@ -155,7 +156,6 @@
|
||||
"remarks",
|
||||
"range",
|
||||
"amended_from",
|
||||
"is_old_subcontracting_flow",
|
||||
"other_details",
|
||||
"connections_tab"
|
||||
],
|
||||
@@ -1151,14 +1151,6 @@
|
||||
"fieldname": "dimension_col_break",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "is_old_subcontracting_flow",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"label": "Is Old Subcontracting Flow",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "address_and_contact_tab",
|
||||
"fieldtype": "Tab Break",
|
||||
@@ -1306,7 +1298,7 @@
|
||||
"idx": 261,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2026-04-06 14:11:29.630333",
|
||||
"modified": "2026-05-04 10:19:44.638858",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Purchase Receipt",
|
||||
|
||||
@@ -88,7 +88,6 @@ class PurchaseReceipt(BuyingController):
|
||||
instructions: DF.SmallText | None
|
||||
inter_company_reference: DF.Link | None
|
||||
is_internal_supplier: DF.Check
|
||||
is_old_subcontracting_flow: DF.Check
|
||||
is_return: DF.Check
|
||||
is_subcontracted: DF.Check
|
||||
item_wise_tax_details: DF.Table[ItemWiseTaxDetail]
|
||||
@@ -149,6 +148,7 @@ class PurchaseReceipt(BuyingController):
|
||||
taxes_and_charges_deducted: DF.Currency
|
||||
tc_name: DF.Link | None
|
||||
terms: DF.TextEditor | None
|
||||
title: DF.Data | None
|
||||
total: DF.Currency
|
||||
total_net_weight: DF.Float
|
||||
total_qty: DF.Float
|
||||
|
||||
@@ -106,9 +106,6 @@
|
||||
"rejected_serial_no",
|
||||
"column_break_tolu",
|
||||
"batch_no",
|
||||
"subcontract_bom_section",
|
||||
"include_exploded_items",
|
||||
"bom",
|
||||
"item_weight_details",
|
||||
"weight_per_unit",
|
||||
"total_weight",
|
||||
@@ -635,26 +632,6 @@
|
||||
"no_copy": 1,
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:parent.is_old_subcontracting_flow",
|
||||
"fieldname": "bom",
|
||||
"fieldtype": "Link",
|
||||
"label": "BOM",
|
||||
"no_copy": 1,
|
||||
"options": "BOM",
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"read_only_depends_on": "eval:!parent.is_old_subcontracting_flow"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:parent.is_subcontracted",
|
||||
"fieldname": "include_exploded_items",
|
||||
"fieldtype": "Check",
|
||||
"label": "Include Exploded Items",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "billed_amt",
|
||||
"fieldtype": "Currency",
|
||||
@@ -1015,12 +992,6 @@
|
||||
"print_hide": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:parent.is_old_subcontracting_flow",
|
||||
"fieldname": "subcontract_bom_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Subcontract BOM"
|
||||
},
|
||||
{
|
||||
"fieldname": "serial_no",
|
||||
"fieldtype": "Text",
|
||||
@@ -1149,7 +1120,7 @@
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2026-04-29 16:01:34.154697",
|
||||
"modified": "2026-05-04 10:52:43.188507",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Purchase Receipt Item",
|
||||
|
||||
@@ -28,7 +28,6 @@ class PurchaseReceiptItem(Document):
|
||||
base_rate_with_margin: DF.Currency
|
||||
batch_no: DF.Link | None
|
||||
billed_amt: DF.Currency
|
||||
bom: DF.Link | None
|
||||
brand: DF.Link | None
|
||||
conversion_factor: DF.Float
|
||||
cost_center: DF.Link | None
|
||||
@@ -41,7 +40,6 @@ class PurchaseReceiptItem(Document):
|
||||
from_warehouse: DF.Link | None
|
||||
has_item_scanned: DF.Check
|
||||
image: DF.Attach | None
|
||||
include_exploded_items: DF.Check
|
||||
is_fixed_asset: DF.Check
|
||||
is_free_item: DF.Check
|
||||
item_code: DF.Link
|
||||
|
||||
@@ -1200,16 +1200,6 @@ erpnext.stock.StockEntry = class StockEntry extends erpnext.stock.StockControlle
|
||||
return erpnext.queries.item({ is_stock_item: 1 });
|
||||
};
|
||||
|
||||
this.frm.set_query("purchase_order", function () {
|
||||
return {
|
||||
filters: {
|
||||
docstatus: 1,
|
||||
is_old_subcontracting_flow: 1,
|
||||
company: me.frm.doc.company,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
this.frm.set_query("subcontracting_order", function () {
|
||||
return {
|
||||
filters: {
|
||||
|
||||
@@ -128,7 +128,6 @@ class StockEntry(StockController, SubcontractingInwardController):
|
||||
process_loss_percentage: DF.Percent
|
||||
process_loss_qty: DF.Float
|
||||
project: DF.Link | None
|
||||
purchase_order: DF.Link | None
|
||||
purchase_receipt_no: DF.Link | None
|
||||
purpose: DF.Literal[
|
||||
"Material Issue",
|
||||
@@ -173,16 +172,7 @@ class StockEntry(StockController, SubcontractingInwardController):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
if self.purchase_order:
|
||||
self.subcontract_data = frappe._dict(
|
||||
{
|
||||
"order_doctype": "Purchase Order",
|
||||
"order_field": "purchase_order",
|
||||
"rm_detail_field": "po_detail",
|
||||
"order_supplied_items_field": "Purchase Order Item Supplied",
|
||||
}
|
||||
)
|
||||
elif self.subcontracting_inward_order:
|
||||
if self.subcontracting_inward_order:
|
||||
self.subcontract_data = frappe._dict(
|
||||
{
|
||||
"order_doctype": "Subcontracting Inward Order",
|
||||
@@ -253,7 +243,6 @@ class StockEntry(StockController, SubcontractingInwardController):
|
||||
self.validate_source_stock_entry()
|
||||
self.validate_bom()
|
||||
self.set_process_loss_qty()
|
||||
self.validate_purchase_order()
|
||||
self.validate_company_in_accounting_dimension()
|
||||
|
||||
if self.purpose in ("Manufacture", "Repack"):
|
||||
@@ -1696,19 +1685,6 @@ class StockEntry(StockController, SubcontractingInwardController):
|
||||
item_code = d.original_item or d.item_code
|
||||
validate_bom_no(item_code, d.bom_no)
|
||||
|
||||
def validate_purchase_order(self):
|
||||
if self.purpose == "Send to Subcontractor" and self.get("purchase_order"):
|
||||
is_old_subcontracting_flow = frappe.db.get_value(
|
||||
"Purchase Order", self.purchase_order, "is_old_subcontracting_flow"
|
||||
)
|
||||
|
||||
if not is_old_subcontracting_flow:
|
||||
frappe.throw(
|
||||
_("Please select Subcontracting Order instead of Purchase Order {0}").format(
|
||||
self.purchase_order
|
||||
)
|
||||
)
|
||||
|
||||
def validate_closed_subcontracting_order(self):
|
||||
order = self.get("subcontracting_order") or self.get("subcontracting_inward_order")
|
||||
if order:
|
||||
|
||||
@@ -346,13 +346,8 @@ def validate_item_details(ctx: ItemDetailsCtx, item):
|
||||
throw(_(msg), title=_("Template Item Selected"))
|
||||
|
||||
elif ctx.doctype != "Material Request":
|
||||
if ctx.is_subcontracted:
|
||||
if ctx.is_old_subcontracting_flow:
|
||||
if item.is_sub_contracted_item != 1:
|
||||
throw(_("Item {0} must be a Sub-contracted Item").format(item.name))
|
||||
else:
|
||||
if item.is_stock_item:
|
||||
throw(_("Item {0} must be a Non-Stock Item").format(item.name))
|
||||
if ctx.is_subcontracted and item.is_stock_item:
|
||||
throw(_("Item {0} must be a Non-Stock Item").format(item.name))
|
||||
|
||||
|
||||
def get_basic_details(ctx: ItemDetailsCtx, item, overwrite_warehouse=True) -> ItemDetails:
|
||||
|
||||
@@ -55,7 +55,6 @@ frappe.ui.form.on("Subcontracting Order", {
|
||||
filters: {
|
||||
docstatus: 1,
|
||||
is_subcontracted: 1,
|
||||
is_old_subcontracting_flow: 0,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
@@ -138,9 +138,6 @@ class SubcontractingOrder(SubcontractingController):
|
||||
if not po.is_subcontracted:
|
||||
frappe.throw(_("Please select a valid Purchase Order that is configured for Subcontracting."))
|
||||
|
||||
if po.is_old_subcontracting_flow:
|
||||
frappe.throw(_("Please select a valid Purchase Order that has Service Items."))
|
||||
|
||||
if po.docstatus != 1:
|
||||
msg = f"Please submit Purchase Order {po.name} before proceeding."
|
||||
frappe.throw(_(msg))
|
||||
|
||||
@@ -1076,7 +1076,6 @@ def make_purchase_receipt(
|
||||
"subcontracting_receipt": source_doc.name,
|
||||
"supplier_warehouse": source_doc.supplier_warehouse,
|
||||
"is_subcontracted": 1,
|
||||
"is_old_subcontracting_flow": 0,
|
||||
"currency": frappe.get_cached_value("Company", target.company, "default_currency"),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -343,7 +343,6 @@ class TransactionBase(StatusUpdater):
|
||||
"item_tax_template": item.get("item_tax_template"),
|
||||
"child_doctype": item.get("doctype"),
|
||||
"child_docname": item.get("name"),
|
||||
"is_old_subcontracting_flow": self.get("is_old_subcontracting_flow"),
|
||||
}
|
||||
),
|
||||
self,
|
||||
|
||||
Reference in New Issue
Block a user