mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-27 17:04:47 +00:00
feat: pending qty in job card
This commit is contained in:
@@ -77,6 +77,30 @@ frappe.ui.form.on("Job Card", {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
pending_qty(frm) {
|
||||||
|
if (frm.doc.total_completed_qty <= 0.0) {
|
||||||
|
frm.doc.pending_qty = 0.0;
|
||||||
|
refresh_field("pending_qty");
|
||||||
|
frappe.throw(__("Please complete the job first before entering Pending Quantity"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frm.doc.pending_qty < 0) {
|
||||||
|
frappe.throw(__("Pending Quantity cannot be less than 0"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let remaining_qty = flt(frm.doc.for_quantity) - flt(frm.doc.total_completed_qty);
|
||||||
|
|
||||||
|
if (remaining_qty < frm.doc.pending_qty) {
|
||||||
|
frm.doc.pending_qty = 0.0;
|
||||||
|
refresh_field("pending_qty");
|
||||||
|
frappe.throw(__("Pending Quantity cannot be greater than {0}", [remaining_qty]));
|
||||||
|
}
|
||||||
|
|
||||||
|
let process_loss_qty = flt(remaining_qty) - flt(frm.doc.pending_qty);
|
||||||
|
frm.doc.process_loss_qty = process_loss_qty >= 0 ? process_loss_qty : 0;
|
||||||
|
refresh_field("process_loss_qty");
|
||||||
|
},
|
||||||
|
|
||||||
set_company_filters(frm, fieldname) {
|
set_company_filters(frm, fieldname) {
|
||||||
frm.set_query(fieldname, () => {
|
frm.set_query(fieldname, () => {
|
||||||
return {
|
return {
|
||||||
@@ -148,6 +172,10 @@ frappe.ui.form.on("Job Card", {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (frm.doc.docstatus > 0) {
|
||||||
|
frm.set_df_property("pending_qty", "read_only", 1);
|
||||||
|
}
|
||||||
|
|
||||||
let has_stock_entry = frm.doc.__onload && frm.doc.__onload.has_stock_entry ? true : false;
|
let has_stock_entry = frm.doc.__onload && frm.doc.__onload.has_stock_entry ? true : false;
|
||||||
|
|
||||||
frm.toggle_enable("for_quantity", !has_stock_entry);
|
frm.toggle_enable("for_quantity", !has_stock_entry);
|
||||||
@@ -212,12 +240,14 @@ frappe.ui.form.on("Job Card", {
|
|||||||
!has_items?.length)
|
!has_items?.length)
|
||||||
) {
|
) {
|
||||||
let last_row = {};
|
let last_row = {};
|
||||||
if (frm.doc.sub_operations?.length && frm.doc.time_logs?.length) {
|
if ((frm.doc.sub_operations?.length || frm.doc.pending_qty > 0) && frm.doc.time_logs?.length) {
|
||||||
last_row = get_last_row(frm.doc.time_logs);
|
last_row = get_last_row(frm.doc.time_logs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(!frm.doc.time_logs?.length || (frm.doc.sub_operations?.length && last_row?.to_time)) &&
|
(!frm.doc.time_logs?.length ||
|
||||||
|
(flt(frm.doc.pending_qty) > 0.0 && last_row?.to_time) ||
|
||||||
|
(frm.doc.sub_operations?.length && last_row?.to_time)) &&
|
||||||
!frm.doc.is_paused
|
!frm.doc.is_paused
|
||||||
) {
|
) {
|
||||||
frm.add_custom_button(__("Start Job"), () => {
|
frm.add_custom_button(__("Start Job"), () => {
|
||||||
@@ -312,13 +342,18 @@ frappe.ui.form.on("Job Card", {
|
|||||||
},
|
},
|
||||||
|
|
||||||
complete_job_card(frm) {
|
complete_job_card(frm) {
|
||||||
|
let pending_qty = frm.doc.for_quantity - frm.doc.total_completed_qty;
|
||||||
|
if (frm.doc.pending_qty > 0) {
|
||||||
|
pending_qty = frm.doc.pending_qty;
|
||||||
|
}
|
||||||
|
|
||||||
let fields = [
|
let fields = [
|
||||||
{
|
{
|
||||||
fieldtype: "Float",
|
fieldtype: "Float",
|
||||||
label: __("Qty to Manufacture"),
|
label: __("Qty to Manufacture"),
|
||||||
fieldname: "for_quantity",
|
fieldname: "for_quantity",
|
||||||
reqd: 1,
|
reqd: 1,
|
||||||
default: frm.doc.for_quantity,
|
default: pending_qty,
|
||||||
change() {
|
change() {
|
||||||
let doc = frm.job_completion_dialog;
|
let doc = frm.job_completion_dialog;
|
||||||
|
|
||||||
@@ -331,12 +366,29 @@ frappe.ui.form.on("Job Card", {
|
|||||||
label: __("Completed Quantity"),
|
label: __("Completed Quantity"),
|
||||||
fieldname: "completed_qty",
|
fieldname: "completed_qty",
|
||||||
reqd: 1,
|
reqd: 1,
|
||||||
default: frm.doc.for_quantity - frm.doc.total_completed_qty,
|
default: pending_qty,
|
||||||
change() {
|
change() {
|
||||||
let doc = frm.job_completion_dialog;
|
let doc = frm.job_completion_dialog;
|
||||||
|
|
||||||
let process_loss_qty = doc.get_value("for_quantity") - doc.get_value("completed_qty");
|
let pending_qty = doc.get_value("for_quantity") - doc.get_value("completed_qty");
|
||||||
if (process_loss_qty > 0 && process_loss_qty != doc.get_value("process_loss_qty")) {
|
if (pending_qty > 0 && pending_qty != doc.get_value("pending_qty")) {
|
||||||
|
doc.set_value("pending_qty", pending_qty);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldtype: "Float",
|
||||||
|
label: __("Pending Quantity"),
|
||||||
|
fieldname: "pending_qty",
|
||||||
|
default: 0.0,
|
||||||
|
change() {
|
||||||
|
let doc = frm.job_completion_dialog;
|
||||||
|
|
||||||
|
let process_loss_qty =
|
||||||
|
doc.get_value("for_quantity") -
|
||||||
|
doc.get_value("completed_qty") -
|
||||||
|
doc.get_value("pending_qty");
|
||||||
|
if (process_loss_qty >= 0 && process_loss_qty != doc.get_value("process_loss_qty")) {
|
||||||
doc.set_value("process_loss_qty", process_loss_qty);
|
doc.set_value("process_loss_qty", process_loss_qty);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -348,8 +400,13 @@ frappe.ui.form.on("Job Card", {
|
|||||||
onchange() {
|
onchange() {
|
||||||
let doc = frm.job_completion_dialog;
|
let doc = frm.job_completion_dialog;
|
||||||
|
|
||||||
let completed_qty = doc.get_value("for_quantity") - doc.get_value("process_loss_qty");
|
let pending_qty =
|
||||||
doc.set_value("completed_qty", completed_qty);
|
doc.get_value("for_quantity") -
|
||||||
|
doc.get_value("completed_qty") -
|
||||||
|
doc.get_value("process_loss_qty");
|
||||||
|
if (pending_qty >= 0 && pending_qty != doc.get_value("pending_qty")) {
|
||||||
|
doc.set_value("pending_qty", pending_qty);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -405,6 +462,8 @@ frappe.ui.form.on("Job Card", {
|
|||||||
args: {
|
args: {
|
||||||
qty: data.completed_qty,
|
qty: data.completed_qty,
|
||||||
for_quantity: data.for_quantity,
|
for_quantity: data.for_quantity,
|
||||||
|
pending_qty: data.pending_qty,
|
||||||
|
process_loss_qty: data.process_loss_qty,
|
||||||
end_time: data.end_time,
|
end_time: data.end_time,
|
||||||
sub_operation: data.sub_operation,
|
sub_operation: data.sub_operation,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -9,23 +9,26 @@
|
|||||||
"field_order": [
|
"field_order": [
|
||||||
"company",
|
"company",
|
||||||
"naming_series",
|
"naming_series",
|
||||||
"work_order",
|
"production_item",
|
||||||
"employee",
|
"employee",
|
||||||
"column_break_4",
|
"column_break_4",
|
||||||
"posting_date",
|
"posting_date",
|
||||||
"project",
|
"work_order",
|
||||||
"bom_no",
|
"bom_no",
|
||||||
"is_subcontracted",
|
|
||||||
"semi_finished_good__finished_good_section",
|
"semi_finished_good__finished_good_section",
|
||||||
"finished_good",
|
"finished_good",
|
||||||
"production_item",
|
|
||||||
"semi_fg_bom",
|
|
||||||
"total_completed_qty",
|
|
||||||
"column_break_mcnb",
|
"column_break_mcnb",
|
||||||
|
"semi_fg_bom",
|
||||||
|
"section_break_folk",
|
||||||
"for_quantity",
|
"for_quantity",
|
||||||
"transferred_qty",
|
"pending_qty",
|
||||||
"manufactured_qty",
|
"column_break_cyjw",
|
||||||
"process_loss_qty",
|
"process_loss_qty",
|
||||||
|
"total_completed_qty",
|
||||||
|
"section_break_wpjf",
|
||||||
|
"transferred_qty",
|
||||||
|
"column_break_lgte",
|
||||||
|
"manufactured_qty",
|
||||||
"production_section",
|
"production_section",
|
||||||
"operation",
|
"operation",
|
||||||
"source_warehouse",
|
"source_warehouse",
|
||||||
@@ -72,8 +75,10 @@
|
|||||||
"item_name",
|
"item_name",
|
||||||
"requested_qty",
|
"requested_qty",
|
||||||
"is_paused",
|
"is_paused",
|
||||||
|
"is_subcontracted",
|
||||||
"track_semi_finished_goods",
|
"track_semi_finished_goods",
|
||||||
"column_break_20",
|
"column_break_20",
|
||||||
|
"project",
|
||||||
"remarks",
|
"remarks",
|
||||||
"section_break_dfoc",
|
"section_break_dfoc",
|
||||||
"status",
|
"status",
|
||||||
@@ -626,12 +631,35 @@
|
|||||||
"fieldname": "secondary_items_section",
|
"fieldname": "secondary_items_section",
|
||||||
"fieldtype": "Tab Break",
|
"fieldtype": "Tab Break",
|
||||||
"label": "Secondary Items"
|
"label": "Secondary Items"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "section_break_folk",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"hide_border": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_cyjw",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 1,
|
||||||
|
"fieldname": "pending_qty",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": "Pending Qty"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "section_break_wpjf",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_lgte",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"grid_page_length": 50,
|
"grid_page_length": 50,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2026-05-12 12:17:17.750857",
|
"modified": "2026-05-20 14:05:46.205365",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Job Card",
|
"name": "Job Card",
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ class JobCard(Document):
|
|||||||
operation_id: DF.Data | None
|
operation_id: DF.Data | None
|
||||||
operation_row_id: DF.Int
|
operation_row_id: DF.Int
|
||||||
operation_row_number: DF.Literal[None]
|
operation_row_number: DF.Literal[None]
|
||||||
|
pending_qty: DF.Float
|
||||||
posting_date: DF.Date | None
|
posting_date: DF.Date | None
|
||||||
process_loss_qty: DF.Float
|
process_loss_qty: DF.Float
|
||||||
production_item: DF.Link | None
|
production_item: DF.Link | None
|
||||||
@@ -882,7 +883,9 @@ class JobCard(Document):
|
|||||||
|
|
||||||
precision = self.precision("total_completed_qty")
|
precision = self.precision("total_completed_qty")
|
||||||
total_completed_qty = flt(
|
total_completed_qty = flt(
|
||||||
flt(self.total_completed_qty, precision) + flt(self.process_loss_qty, precision)
|
flt(self.total_completed_qty, precision)
|
||||||
|
+ flt(self.process_loss_qty, precision)
|
||||||
|
+ flt(self.pending_qty, precision)
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.for_quantity and flt(total_completed_qty, precision) != flt(self.for_quantity, precision):
|
if self.for_quantity and flt(total_completed_qty, precision) != flt(self.for_quantity, precision):
|
||||||
@@ -929,8 +932,10 @@ class JobCard(Document):
|
|||||||
|
|
||||||
self.process_loss_qty = 0.0
|
self.process_loss_qty = 0.0
|
||||||
if self.total_completed_qty and self.for_quantity > self.total_completed_qty:
|
if self.total_completed_qty and self.for_quantity > self.total_completed_qty:
|
||||||
self.process_loss_qty = flt(self.for_quantity, precision) - flt(
|
self.process_loss_qty = (
|
||||||
self.total_completed_qty, precision
|
flt(self.for_quantity, precision)
|
||||||
|
- flt(self.total_completed_qty, precision)
|
||||||
|
- flt(self.pending_qty, precision)
|
||||||
)
|
)
|
||||||
|
|
||||||
def update_work_order(self):
|
def update_work_order(self):
|
||||||
@@ -944,13 +949,14 @@ class JobCard(Document):
|
|||||||
):
|
):
|
||||||
return
|
return
|
||||||
|
|
||||||
for_quantity, time_in_mins, process_loss_qty = 0, 0, 0
|
for_quantity, time_in_mins, process_loss_qty, pending_qty = 0, 0, 0, 0
|
||||||
|
|
||||||
data = self.get_current_operation_data()
|
data = self.get_current_operation_data()
|
||||||
if data and len(data) > 0:
|
if data and len(data) > 0:
|
||||||
for_quantity = flt(data[0].completed_qty)
|
for_quantity = flt(data[0].completed_qty)
|
||||||
time_in_mins = flt(data[0].time_in_mins)
|
time_in_mins = flt(data[0].time_in_mins)
|
||||||
process_loss_qty = flt(data[0].process_loss_qty)
|
process_loss_qty = flt(data[0].process_loss_qty)
|
||||||
|
pending_qty = flt(data[0].pending_qty)
|
||||||
|
|
||||||
wo = frappe.get_doc("Work Order", self.work_order)
|
wo = frappe.get_doc("Work Order", self.work_order)
|
||||||
|
|
||||||
@@ -958,8 +964,8 @@ class JobCard(Document):
|
|||||||
self.update_corrective_in_work_order(wo)
|
self.update_corrective_in_work_order(wo)
|
||||||
|
|
||||||
elif self.operation_id:
|
elif self.operation_id:
|
||||||
self.validate_produced_quantity(for_quantity, process_loss_qty, wo)
|
self.validate_produced_quantity(for_quantity, process_loss_qty, pending_qty, wo)
|
||||||
self.update_work_order_data(for_quantity, process_loss_qty, time_in_mins, wo)
|
self.update_work_order_data(for_quantity, process_loss_qty, pending_qty, time_in_mins, wo)
|
||||||
|
|
||||||
def update_semi_finished_good_details(self):
|
def update_semi_finished_good_details(self):
|
||||||
if self.operation_id:
|
if self.operation_id:
|
||||||
@@ -988,11 +994,11 @@ class JobCard(Document):
|
|||||||
wo.flags.ignore_validate_update_after_submit = True
|
wo.flags.ignore_validate_update_after_submit = True
|
||||||
wo.save()
|
wo.save()
|
||||||
|
|
||||||
def validate_produced_quantity(self, for_quantity, process_loss_qty, wo):
|
def validate_produced_quantity(self, for_quantity, process_loss_qty, pending_qty, wo):
|
||||||
if self.docstatus < 2:
|
if self.docstatus < 2:
|
||||||
return
|
return
|
||||||
|
|
||||||
if wo.produced_qty > for_quantity + process_loss_qty:
|
if wo.produced_qty > for_quantity + process_loss_qty + pending_qty:
|
||||||
first_part_msg = _(
|
first_part_msg = _(
|
||||||
"The {0} {1} is used to calculate the valuation cost for the finished good {2}."
|
"The {0} {1} is used to calculate the valuation cost for the finished good {2}."
|
||||||
).format(frappe.bold(_("Job Card")), frappe.bold(self.name), frappe.bold(self.production_item))
|
).format(frappe.bold(_("Job Card")), frappe.bold(self.name), frappe.bold(self.production_item))
|
||||||
@@ -1005,7 +1011,7 @@ class JobCard(Document):
|
|||||||
_("{0} {1}").format(first_part_msg, second_part_msg), JobCardCancelError, title=_("Error")
|
_("{0} {1}").format(first_part_msg, second_part_msg), JobCardCancelError, title=_("Error")
|
||||||
)
|
)
|
||||||
|
|
||||||
def update_work_order_data(self, for_quantity, process_loss_qty, time_in_mins, wo):
|
def update_work_order_data(self, for_quantity, process_loss_qty, pending_qty, time_in_mins, wo):
|
||||||
workstation_hour_rate = frappe.get_value("Workstation", self.workstation, "hour_rate")
|
workstation_hour_rate = frappe.get_value("Workstation", self.workstation, "hour_rate")
|
||||||
jc = frappe.qb.DocType("Job Card")
|
jc = frappe.qb.DocType("Job Card")
|
||||||
jctl = frappe.qb.DocType("Job Card Time Log")
|
jctl = frappe.qb.DocType("Job Card Time Log")
|
||||||
@@ -1027,6 +1033,7 @@ class JobCard(Document):
|
|||||||
if data.get("name") == self.operation_id:
|
if data.get("name") == self.operation_id:
|
||||||
data.completed_qty = for_quantity
|
data.completed_qty = for_quantity
|
||||||
data.process_loss_qty = process_loss_qty
|
data.process_loss_qty = process_loss_qty
|
||||||
|
data.pending_qty = pending_qty
|
||||||
data.actual_operation_time = time_in_mins
|
data.actual_operation_time = time_in_mins
|
||||||
data.actual_start_time = time_data[0].start_time if time_data else None
|
data.actual_start_time = time_data[0].start_time if time_data else None
|
||||||
data.actual_end_time = time_data[0].end_time if time_data else None
|
data.actual_end_time = time_data[0].end_time if time_data else None
|
||||||
@@ -1052,6 +1059,7 @@ class JobCard(Document):
|
|||||||
{"SUM": "total_time_in_mins", "as": "time_in_mins"},
|
{"SUM": "total_time_in_mins", "as": "time_in_mins"},
|
||||||
{"SUM": "total_completed_qty", "as": "completed_qty"},
|
{"SUM": "total_completed_qty", "as": "completed_qty"},
|
||||||
{"SUM": "process_loss_qty", "as": "process_loss_qty"},
|
{"SUM": "process_loss_qty", "as": "process_loss_qty"},
|
||||||
|
{"SUM": "pending_qty", "as": "pending_qty"},
|
||||||
],
|
],
|
||||||
filters={
|
filters={
|
||||||
"docstatus": 1,
|
"docstatus": 1,
|
||||||
@@ -1446,10 +1454,10 @@ class JobCard(Document):
|
|||||||
if isinstance(kwargs, dict):
|
if isinstance(kwargs, dict):
|
||||||
kwargs = frappe._dict(kwargs)
|
kwargs = frappe._dict(kwargs)
|
||||||
|
|
||||||
if kwargs.end_time:
|
self.pending_qty = flt(kwargs.pending_qty)
|
||||||
if kwargs.for_quantity:
|
self.process_loss_qty = flt(kwargs.process_loss_qty)
|
||||||
self.for_quantity = kwargs.for_quantity
|
|
||||||
|
|
||||||
|
if kwargs.end_time:
|
||||||
self.add_time_logs(
|
self.add_time_logs(
|
||||||
to_time=kwargs.end_time,
|
to_time=kwargs.end_time,
|
||||||
completed_qty=kwargs.qty,
|
completed_qty=kwargs.qty,
|
||||||
|
|||||||
@@ -721,6 +721,7 @@ class TestJobCard(ERPNextTestSuite):
|
|||||||
)
|
)
|
||||||
|
|
||||||
jc.time_logs[0].completed_qty = 8
|
jc.time_logs[0].completed_qty = 8
|
||||||
|
jc.pending_qty = 0.0
|
||||||
jc.save()
|
jc.save()
|
||||||
jc.submit()
|
jc.submit()
|
||||||
|
|
||||||
|
|||||||
@@ -167,18 +167,19 @@ class WorkOrder(Document):
|
|||||||
self.set_onload("backflush_raw_materials_based_on", based_on)
|
self.set_onload("backflush_raw_materials_based_on", based_on)
|
||||||
|
|
||||||
def show_create_job_card_button(self):
|
def show_create_job_card_button(self):
|
||||||
operation_details = frappe._dict(
|
jc_doctype = frappe.qb.DocType("Job Card")
|
||||||
frappe.get_all(
|
query = (
|
||||||
"Job Card",
|
frappe.qb.from_(jc_doctype)
|
||||||
fields=["operation", {"SUM": "for_quantity"}],
|
.select(jc_doctype.operation_id, Sum(jc_doctype.for_quantity - IfNull(jc_doctype.pending_qty, 0)))
|
||||||
filters={"docstatus": ("<", 2), "work_order": self.name},
|
.where((jc_doctype.docstatus < 2) & (jc_doctype.work_order == self.name))
|
||||||
as_list=1,
|
.groupby(jc_doctype.operation_id)
|
||||||
group_by="operation_id",
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
operation_details = query.run(as_list=1)
|
||||||
|
operation_details = frappe._dict(operation_details)
|
||||||
|
|
||||||
for d in self.operations:
|
for d in self.operations:
|
||||||
job_card_qty = self.qty - flt(operation_details.get(d.operation))
|
job_card_qty = self.qty - flt(operation_details.get(d.name))
|
||||||
if job_card_qty > 0:
|
if job_card_qty > 0:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"actions": [],
|
"actions": [],
|
||||||
|
"allow_bulk_edit": 1,
|
||||||
"creation": "2025-04-09 12:12:19.824560",
|
"creation": "2025-04-09 12:12:19.824560",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
@@ -10,6 +11,7 @@
|
|||||||
"status",
|
"status",
|
||||||
"completed_qty",
|
"completed_qty",
|
||||||
"process_loss_qty",
|
"process_loss_qty",
|
||||||
|
"pending_qty",
|
||||||
"column_break_4",
|
"column_break_4",
|
||||||
"bom",
|
"bom",
|
||||||
"workstation_type",
|
"workstation_type",
|
||||||
@@ -301,13 +303,20 @@
|
|||||||
"fieldname": "quality_inspection_required",
|
"fieldname": "quality_inspection_required",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Quality Inspection Required"
|
"label": "Quality Inspection Required"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "pending_qty",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": "Pending Qty",
|
||||||
|
"no_copy": 1,
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"grid_page_length": 50,
|
"grid_page_length": 50,
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2026-03-30 17:20:08.874381",
|
"modified": "2026-05-20 13:01:21.827200",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Work Order Operation",
|
"name": "Work Order Operation",
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class WorkOrderOperation(Document):
|
|||||||
parent: DF.Data
|
parent: DF.Data
|
||||||
parentfield: DF.Data
|
parentfield: DF.Data
|
||||||
parenttype: DF.Data
|
parenttype: DF.Data
|
||||||
|
pending_qty: DF.Float
|
||||||
planned_end_time: DF.Datetime | None
|
planned_end_time: DF.Datetime | None
|
||||||
planned_operating_cost: DF.Currency
|
planned_operating_cost: DF.Currency
|
||||||
planned_start_time: DF.Datetime | None
|
planned_start_time: DF.Datetime | None
|
||||||
|
|||||||
Reference in New Issue
Block a user