Skip to content

Commit

Permalink
feat: option to add raw materials manually against operation
Browse files Browse the repository at this point in the history
  • Loading branch information
rohitwaghchaure committed Jan 27, 2024
1 parent 8916651 commit 83cdc6f
Show file tree
Hide file tree
Showing 27 changed files with 664 additions and 159 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -930,7 +930,7 @@
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2023-11-24 14:24:41.298416",
"modified": "2024-01-16 14:24:41.298416",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order Item",
Expand Down
84 changes: 83 additions & 1 deletion erpnext/manufacturing/doctype/bom/bom.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ frappe.ui.form.on("BOM", {
'item': row.finished_good,
'is_active': 1,
'docstatus': 1,
'make_finished_good_against_job_card': 0
'track_semi_finished_goods': 0
}
};
});
Expand Down Expand Up @@ -822,3 +822,85 @@ function trigger_process_loss_qty_prompt(frm, cdt, cdn, item_code) {
__("Set Quantity")
);
}


frappe.ui.form.on("BOM Operation", {
add_raw_materials(frm, cdt, cdn) {
let row = locals[cdt][cdn];
frm.events._prompt_for_raw_materials(frm, row);
}
});

frappe.ui.form.on("BOM", {
_prompt_for_raw_materials(frm, row) {
let fields = frm.events.get_fields_for_prompt(frm, row);
frm._bom_rm_dialog = new frappe.ui.Dialog({
title: __("Add Raw Materials"),
fields: fields,
primary_action_label: __("Add"),
primary_action: () => {
let values = frm._bom_rm_dialog.get_values();
if (values) {
frm.events._add_raw_materials(frm, values);
frm._bom_rm_dialog.hide();
}
}
});

frm._bom_rm_dialog.show();
},

get_fields_for_prompt(frm, row) {
return [
{ label: __("Raw Materials"), fieldname: "items", fieldtype: "Table", reqd: 1,
fields: [
{
label: __("Item"),
fieldname: "item_code",
fieldtype: "Link",
options: "Item",
reqd: 1,
in_list_view: 1,
change() {
let doc = this.doc;
doc.qty = 1.0;
this.grid.set_value("qty", 1.0, doc);
},
get_query () {
return {
filters: {
"name": ["!=", row.finished_good]
}
}
}
},
{
label: __("Qty"),
fieldname: "qty",
default: 1.0,
fieldtype: "Float",
reqd: 1,
in_list_view: 1
},
]
},
{
fieldname: "operation_row_id",
fieldtype: "Data",
hidden: 1,
default: row.idx
}
]
},

_add_raw_materials(frm, values) {
frm.call({
method: "add_raw_materials",
doc: frm.doc,
args: {
operation_row_id: values.operation_row_id,
items: values.items
}
})
},
});
24 changes: 13 additions & 11 deletions erpnext/manufacturing/doctype/bom/bom.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"conversion_rate",
"operations_section_section",
"with_operations",
"make_finished_good_against_job_card",
"track_semi_finished_goods",
"column_break_23",
"transfer_material_against",
"routing",
Expand Down Expand Up @@ -62,8 +62,8 @@
"base_total_cost",
"more_info_tab",
"item_name",
"description",
"column_break_27",
"description",
"has_variants",
"quality_inspection_section_break",
"inspection_required",
Expand Down Expand Up @@ -214,7 +214,7 @@
},
{
"default": "Work Order",
"depends_on": "eval: doc.with_operations === 1 && doc.make_finished_good_against_job_card === 0",
"depends_on": "eval: doc.with_operations === 1 && doc.track_semi_finished_goods === 0",
"fieldname": "transfer_material_against",
"fieldtype": "Select",
"label": "Transfer Material Against",
Expand Down Expand Up @@ -409,8 +409,8 @@
{
"depends_on": "eval:!doc.__islocal",
"fieldname": "section_break0",
"fieldtype": "Section Break",
"label": "Materials Required (Exploded)"
"fieldtype": "Tab Break",
"label": "Exploded Items"
},
{
"fieldname": "exploded_items",
Expand Down Expand Up @@ -617,15 +617,17 @@
"no_copy": 1,
"options": "BOM Creator",
"print_hide": 1,
"read_only": 1
"read_only": 1,
"search_index": 1
},
{
"fieldname": "bom_creator_item",
"fieldtype": "Data",
"label": "BOM Creator Item",
"no_copy": 1,
"print_hide": 1,
"read_only": 1
"read_only": 1,
"search_index": 1
},
{
"fieldname": "column_break_oxbz",
Expand All @@ -634,10 +636,10 @@
{
"default": "0",
"depends_on": "with_operations",
"description": "User can consume the raw materials, Add Semi Finished Goods / Final Finished Good against the Operation using Job Cards",
"fieldname": "make_finished_good_against_job_card",
"description": "Users can consume raw materials and add semi-finished goods or final finished goods against the operation using job cards.",
"fieldname": "track_semi_finished_goods",
"fieldtype": "Check",
"label": "Make Finished Good Against Job Card"
"label": "Track Semi Finished Goods"
},
{
"fieldname": "column_break_joxb",
Expand All @@ -661,7 +663,7 @@
"image_field": "image",
"is_submittable": 1,
"links": [],
"modified": "2023-12-27 19:34:08.159312",
"modified": "2024-01-26 17:28:56.864689",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "BOM",
Expand Down
30 changes: 24 additions & 6 deletions erpnext/manufacturing/doctype/bom/bom.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from frappe import _
from frappe.core.doctype.version.version import get_diff
from frappe.model.mapper import get_mapped_doc
from frappe.utils import cint, cstr, flt, today
from frappe.utils import cint, cstr, flt, parse_json, today
from frappe.website.website_generator import WebsiteGenerator

import erpnext
Expand Down Expand Up @@ -128,6 +128,8 @@ class BOM(WebsiteGenerator):
company: DF.Link
conversion_rate: DF.Float
currency: DF.Link
default_source_warehouse: DF.Link | None
default_target_warehouse: DF.Link | None
description: DF.SmallText | None
exploded_items: DF.Table[BOMExplosionItem]
fg_based_operating_cost: DF.Check
Expand All @@ -139,6 +141,7 @@ class BOM(WebsiteGenerator):
item: DF.Link
item_name: DF.Data | None
items: DF.Table[BOMItem]
track_semi_finished_goods: DF.Check
operating_cost: DF.Currency
operating_cost_per_bom_quantity: DF.Currency
operations: DF.Table[BOMOperation]
Expand Down Expand Up @@ -548,8 +551,8 @@ def clear_operations(self):
if not self.with_operations:
self.set("operations", [])

if not self.with_operations and self.make_finished_good_against_job_card:
self.make_finished_good_against_job_card = 0
if not self.with_operations and self.track_semi_finished_goods:
self.track_semi_finished_goods = 0

def clear_inspection(self):
if not self.inspection_required:
Expand Down Expand Up @@ -653,13 +656,29 @@ def _throw_error(bom_name):
_throw_error(self.name)

def set_materials_based_on_operation_bom(self):
if not self.make_finished_good_against_job_card:
if not self.track_semi_finished_goods:
return

for row in self.get("operations"):
if row.bom_no and row.finished_good:
self.add_materials_from_bom(row.finished_good, row.bom_no, row.idx, qty=row.finished_good_qty)

@frappe.whitelist()
def add_raw_materials(self, operation_row_id, items):
if isinstance(items, str):
items = parse_json(items)

for row in items:
row = parse_json(row)

row.update(get_item_details(row.get("item_code")))
row.operation_row_id = operation_row_id
row.idx = None
row.name = None
self.append("items", row)

self.save()

@frappe.whitelist()
def add_materials_from_bom(self, finished_good, bom_no, operation_row_id, qty=None):
if not frappe.db.exists("BOM", {"item": finished_good, "name": bom_no, "docstatus": 1}):
Expand Down Expand Up @@ -1131,7 +1150,7 @@ def get_bom_items_as_dict(
item_dict = {}

group_by_cond = "group by item_code, stock_uom"
if frappe.get_cached_value("BOM", bom, "make_finished_good_against_job_card"):
if frappe.get_cached_value("BOM", bom, "track_semi_finished_goods"):
fetch_exploded = 0
group_by_cond = "group by item_code, operation_row_id, stock_uom"

Expand Down Expand Up @@ -1226,7 +1245,6 @@ def get_bom_items_as_dict(
if not item_details.get(d[1]) or (company_in_record and company != company_in_record):
item_dict[item][d[1]] = frappe.get_cached_value("Company", company, d[2]) if d[2] else None

print(item_dict)
return item_dict


Expand Down
74 changes: 66 additions & 8 deletions erpnext/manufacturing/doctype/bom_creator/bom_creator.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,29 +97,65 @@ frappe.ui.form.on("BOM Creator", {
onchange: (r) => {
let track_operations = dialog.get_value("track_operations");
if (r.type === "input" && !track_operations) {
dialog.set_value("make_finished_good_against_job_card", 0);
dialog.set_value("track_semi_finished_goods", 0);
}
}
},
{ fieldtype: "Column Break" },
{
label: __("Make Finished Good Against Job Card"),
label: __("Track Semi Finished Goods"),
fieldtype: "Check",
fieldname: "make_finished_good_against_job_card",
fieldname: "track_semi_finished_goods",
depends_on: "eval:doc.track_operations"
},
{ fieldtype: "Column Break" },
{ fieldtype: "Section Break", label: __("Final Product Operation"), depends_on: "eval:doc.track_semi_finished_goods" },
{
label: __("Final Operation"),
label: __("Operation"),
fieldtype: "Link",
fieldname: "final_operation",
fieldname: "operation",
options: "Operation",
default: "Assembly",
mandatory_depends_on: "eval:doc.make_finished_good_against_job_card",
depends_on: "eval:doc.make_finished_good_against_job_card"
mandatory_depends_on: "eval:doc.track_semi_finished_goods",
depends_on: "eval:doc.track_semi_finished_goods"
},
{
label: __("Operation Time (in mins)"),
fieldtype: "Float",
fieldname: "operation_time",
mandatory_depends_on: "eval:doc.track_semi_finished_goods",
depends_on: "eval:doc.track_semi_finished_goods"
},
{ fieldtype: "Column Break" },
{
label: __("Workstation Type"),
fieldtype: "Link",
fieldname: "workstation_type",
options: "Workstation",
depends_on: "eval:doc.track_semi_finished_goods"
},
{
label: __("Workstation"),
fieldtype: "Link",
fieldname: "workstation",
options: "Workstation",
depends_on: "eval:doc.track_semi_finished_goods",
get_query() {
let workstation_type = dialog.get_value("workstation_type");

if (workstation_type) {
return {
filters: {
workstation_type: dialog.get_value("workstation_type")
}
}
}
}
},
],
primary_action_label: __("Create"),
primary_action: (values) => {
frm.events.validate_dialog_values(frm, values);

values.doctype = frm.doc.doctype;
frappe.db
.insert(values)
Expand All @@ -133,6 +169,18 @@ frappe.ui.form.on("BOM Creator", {
dialog.show();
},

validate_dialog_values(frm, values) {
if (values.track_semi_finished_goods) {
if (values.final_operation_time <= 0) {
frappe.throw(__("Operation Time must be greater than 0"));
}

if (!values.final_operation_workstation && !values.final_operation_workstation_type) {
frappe.throw(__("Either Workstation or Workstation Type is mandatory"));
}
}
},

set_queries(frm) {
frm.set_query("bom_no", "items", function(doc, cdt, cdn) {
let item = frappe.get_doc(cdt, cdn);
Expand All @@ -152,6 +200,16 @@ frappe.ui.form.on("BOM Creator", {
query: "erpnext.controllers.queries.item_query",
}
});

frm.set_query("workstation", (doc) => {
if (doc.workstation_type) {
return {
filters: {
workstation_type: doc.workstation_type
}
}
}
})
},

refresh(frm) {
Expand Down
Loading

0 comments on commit 83cdc6f

Please sign in to comment.