fix: Manufacturing UX, added calendar view for job card
This commit is contained in:
parent
36b60dbbef
commit
8ab8376975
@ -6,7 +6,6 @@ frappe.provide("erpnext.bom");
|
|||||||
frappe.ui.form.on("BOM", {
|
frappe.ui.form.on("BOM", {
|
||||||
setup: function(frm) {
|
setup: function(frm) {
|
||||||
frm.custom_make_buttons = {
|
frm.custom_make_buttons = {
|
||||||
'BOM': 'Duplicate BOM',
|
|
||||||
'Work Order': 'Work Order',
|
'Work Order': 'Work Order',
|
||||||
'Quality Inspection': 'Quality Inspection'
|
'Quality Inspection': 'Quality Inspection'
|
||||||
};
|
};
|
||||||
@ -91,10 +90,6 @@ frappe.ui.form.on("BOM", {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(frm.doc.docstatus!=0) {
|
if(frm.doc.docstatus!=0) {
|
||||||
frm.add_custom_button(__("Duplicate BOM"), function() {
|
|
||||||
frm.copy_doc();
|
|
||||||
}, __("Create"));
|
|
||||||
|
|
||||||
frm.add_custom_button(__("Work Order"), function() {
|
frm.add_custom_button(__("Work Order"), function() {
|
||||||
frm.trigger("make_work_order");
|
frm.trigger("make_work_order");
|
||||||
}, __("Create"));
|
}, __("Create"));
|
||||||
|
@ -25,5 +25,5 @@ def get_data():
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
'disable_create_buttons': ["Item", "Purchase Order", "Purchase Receipt",
|
'disable_create_buttons': ["Item", "Purchase Order", "Purchase Receipt",
|
||||||
"Purchase Invoice", "Job Card", "Stock Entry"]
|
"Purchase Invoice", "Job Card", "Stock Entry", "BOM"]
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
|
|
||||||
frappe.ui.form.on('Job Card', {
|
frappe.ui.form.on('Job Card', {
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
|
frappe.flags.pause_job = 0;
|
||||||
|
frappe.flags.resume_job = 0;
|
||||||
|
|
||||||
if(!frm.doc.__islocal && frm.doc.items && frm.doc.items.length) {
|
if(!frm.doc.__islocal && frm.doc.items && frm.doc.items.length) {
|
||||||
if (frm.doc.for_quantity != frm.doc.transferred_qty) {
|
if (frm.doc.for_quantity != frm.doc.transferred_qty) {
|
||||||
frm.add_custom_button(__("Material Request"), () => {
|
frm.add_custom_button(__("Material Request"), () => {
|
||||||
@ -13,35 +16,89 @@ frappe.ui.form.on('Job Card', {
|
|||||||
if (frm.doc.for_quantity != frm.doc.transferred_qty) {
|
if (frm.doc.for_quantity != frm.doc.transferred_qty) {
|
||||||
frm.add_custom_button(__("Material Transfer"), () => {
|
frm.add_custom_button(__("Material Transfer"), () => {
|
||||||
frm.trigger("make_stock_entry");
|
frm.trigger("make_stock_entry");
|
||||||
});
|
}).addClass("btn-primary");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frm.doc.docstatus == 0) {
|
if (frm.doc.docstatus == 0 && frm.doc.for_quantity > frm.doc.total_completed_qty
|
||||||
|
&& (!frm.doc.items.length || frm.doc.for_quantity == frm.doc.transferred_qty)) {
|
||||||
|
frm.trigger("prepare_timer_buttons");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
prepare_timer_buttons: function(frm) {
|
||||||
frm.trigger("make_dashboard");
|
frm.trigger("make_dashboard");
|
||||||
|
|
||||||
if (!frm.doc.job_started) {
|
if (!frm.doc.job_started) {
|
||||||
frm.add_custom_button(__("Start Job"), () => {
|
frm.add_custom_button(__("Start"), () => {
|
||||||
|
if (!frm.doc.employee) {
|
||||||
|
frappe.prompt({fieldtype: 'Link', label: __('Employee'), options: "Employee",
|
||||||
|
fieldname: 'employee'}, d => {
|
||||||
|
if (d.employee) {
|
||||||
|
frm.set_value("employee", d.employee);
|
||||||
|
}
|
||||||
|
|
||||||
|
frm.events.start_job(frm);
|
||||||
|
}, __("Enter Value"), __("Start"));
|
||||||
|
} else {
|
||||||
|
frm.events.start_job(frm);
|
||||||
|
}
|
||||||
|
}).addClass("btn-primary");
|
||||||
|
} else if (frm.doc.status == "On Hold") {
|
||||||
|
frm.add_custom_button(__("Resume"), () => {
|
||||||
|
frappe.flags.resume_job = 1;
|
||||||
|
frm.events.start_job(frm);
|
||||||
|
}).addClass("btn-primary");
|
||||||
|
} else {
|
||||||
|
frm.add_custom_button(__("Pause"), () => {
|
||||||
|
frappe.flags.pause_job = 1;
|
||||||
|
frm.set_value("status", "On Hold");
|
||||||
|
frm.events.complete_job(frm);
|
||||||
|
});
|
||||||
|
|
||||||
|
frm.add_custom_button(__("Complete"), () => {
|
||||||
|
let completed_time = frappe.datetime.now_datetime();
|
||||||
|
frm.trigger("hide_timer");
|
||||||
|
|
||||||
|
frappe.prompt({fieldtype: 'Float', label: __('Completed Quantity'),
|
||||||
|
fieldname: 'qty', reqd: 1, default: frm.doc.for_quantity}, data => {
|
||||||
|
frm.events.complete_job(frm, completed_time, data.qty);
|
||||||
|
}, __("Enter Value"), __("Complete"));
|
||||||
|
}).addClass("btn-primary");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
start_job: function(frm) {
|
||||||
let row = frappe.model.add_child(frm.doc, 'Job Card Time Log', 'time_logs');
|
let row = frappe.model.add_child(frm.doc, 'Job Card Time Log', 'time_logs');
|
||||||
row.from_time = frappe.datetime.now_datetime();
|
row.from_time = frappe.datetime.now_datetime();
|
||||||
frm.set_value('job_started', 1);
|
frm.set_value('job_started', 1);
|
||||||
frm.set_value('started_time' , row.from_time);
|
frm.set_value('started_time' , row.from_time);
|
||||||
|
frm.set_value("status", "Work In Progress");
|
||||||
|
|
||||||
|
if (!frappe.flags.resume_job) {
|
||||||
|
frm.set_value('current_time' , 0);
|
||||||
|
}
|
||||||
|
|
||||||
frm.save();
|
frm.save();
|
||||||
});
|
},
|
||||||
} else {
|
|
||||||
frm.add_custom_button(__("Complete Job"), () => {
|
complete_job: function(frm, completed_time, completed_qty) {
|
||||||
let completed_time = frappe.datetime.now_datetime();
|
|
||||||
frm.doc.time_logs.forEach(d => {
|
frm.doc.time_logs.forEach(d => {
|
||||||
if (d.from_time && !d.to_time) {
|
if (d.from_time && !d.to_time) {
|
||||||
d.to_time = completed_time;
|
d.to_time = completed_time || frappe.datetime.now_datetime();
|
||||||
|
d.completed_qty = completed_qty || 0;
|
||||||
|
|
||||||
|
if(frappe.flags.pause_job) {
|
||||||
|
let currentIncrement = moment(d.to_time).diff(moment(d.from_time),"seconds") || 0;
|
||||||
|
frm.set_value('current_time' , currentIncrement + (frm.doc.current_time || 0));
|
||||||
|
} else {
|
||||||
frm.set_value('started_time' , '');
|
frm.set_value('started_time' , '');
|
||||||
frm.set_value('job_started', 0);
|
frm.set_value('job_started', 0);
|
||||||
|
frm.set_value('current_time' , 0);
|
||||||
|
}
|
||||||
|
|
||||||
frm.save();
|
frm.save();
|
||||||
}
|
}
|
||||||
})
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
make_dashboard: function(frm) {
|
make_dashboard: function(frm) {
|
||||||
@ -50,7 +107,8 @@ frappe.ui.form.on('Job Card', {
|
|||||||
|
|
||||||
frm.dashboard.refresh();
|
frm.dashboard.refresh();
|
||||||
const timer = `
|
const timer = `
|
||||||
<div class="stopwatch" style="font-weight:bold">
|
<div class="stopwatch" style="font-weight:bold;margin:0px 13px 0px 2px;
|
||||||
|
color:#545454;font-size:18px;display:inline-block;vertical-align:text-bottom;>
|
||||||
<span class="hours">00</span>
|
<span class="hours">00</span>
|
||||||
<span class="colon">:</span>
|
<span class="colon">:</span>
|
||||||
<span class="minutes">00</span>
|
<span class="minutes">00</span>
|
||||||
@ -58,11 +116,16 @@ frappe.ui.form.on('Job Card', {
|
|||||||
<span class="seconds">00</span>
|
<span class="seconds">00</span>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
var section = frm.dashboard.add_section(timer);
|
var section = frm.toolbar.page.add_inner_message(timer);
|
||||||
|
|
||||||
if (frm.doc.started_time) {
|
let currentIncrement = frm.doc.current_time || 0;
|
||||||
let currentIncrement = moment(frappe.datetime.now_datetime()).diff(moment(frm.doc.started_time),"seconds");
|
if (frm.doc.started_time || frm.doc.current_time) {
|
||||||
|
if (frm.doc.status == "On Hold") {
|
||||||
|
updateStopwatch(currentIncrement);
|
||||||
|
} else {
|
||||||
|
currentIncrement += moment(frappe.datetime.now_datetime()).diff(moment(frm.doc.started_time),"seconds");
|
||||||
initialiseTimer();
|
initialiseTimer();
|
||||||
|
}
|
||||||
|
|
||||||
function initialiseTimer() {
|
function initialiseTimer() {
|
||||||
const interval = setInterval(function() {
|
const interval = setInterval(function() {
|
||||||
@ -88,6 +151,10 @@ frappe.ui.form.on('Job Card', {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
hide_timer: function(frm) {
|
||||||
|
frm.toolbar.page.inner_toolbar.find(".stopwatch").remove();
|
||||||
|
},
|
||||||
|
|
||||||
for_quantity: function(frm) {
|
for_quantity: function(frm) {
|
||||||
frm.doc.items = [];
|
frm.doc.items = [];
|
||||||
frm.call({
|
frm.call({
|
||||||
@ -117,5 +184,22 @@ frappe.ui.form.on('Job Card', {
|
|||||||
|
|
||||||
timer: function(frm) {
|
timer: function(frm) {
|
||||||
return `<button> Start </button>`
|
return `<button> Start </button>`
|
||||||
|
},
|
||||||
|
|
||||||
|
set_total_completed_qty: function(frm) {
|
||||||
|
frm.doc.total_completed_qty = 0;
|
||||||
|
frm.doc.time_logs.forEach(d => {
|
||||||
|
if (d.completed_qty) {
|
||||||
|
frm.doc.total_completed_qty += d.completed_qty;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
refresh_field("total_completed_qty");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
frappe.ui.form.on('Job Card Time Log', {
|
||||||
|
completed_qty: function(frm) {
|
||||||
|
frm.events.set_total_completed_qty(frm);
|
||||||
|
}
|
||||||
|
})
|
@ -13,10 +13,18 @@
|
|||||||
"column_break_4",
|
"column_break_4",
|
||||||
"posting_date",
|
"posting_date",
|
||||||
"company",
|
"company",
|
||||||
|
"remarks",
|
||||||
|
"production_section",
|
||||||
|
"production_item",
|
||||||
|
"item_name",
|
||||||
"for_quantity",
|
"for_quantity",
|
||||||
"wip_warehouse",
|
"wip_warehouse",
|
||||||
"timing_detail",
|
"column_break_12",
|
||||||
"employee",
|
"employee",
|
||||||
|
"employee_name",
|
||||||
|
"status",
|
||||||
|
"project",
|
||||||
|
"timing_detail",
|
||||||
"time_logs",
|
"time_logs",
|
||||||
"section_break_13",
|
"section_break_13",
|
||||||
"total_completed_qty",
|
"total_completed_qty",
|
||||||
@ -28,12 +36,11 @@
|
|||||||
"operation_id",
|
"operation_id",
|
||||||
"transferred_qty",
|
"transferred_qty",
|
||||||
"requested_qty",
|
"requested_qty",
|
||||||
"project",
|
|
||||||
"remarks",
|
|
||||||
"column_break_20",
|
"column_break_20",
|
||||||
"status",
|
"barcode",
|
||||||
"job_started",
|
"job_started",
|
||||||
"started_time",
|
"started_time",
|
||||||
|
"current_time",
|
||||||
"amended_from"
|
"amended_from"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
@ -41,13 +48,14 @@
|
|||||||
"fieldname": "work_order",
|
"fieldname": "work_order",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 1,
|
||||||
"label": "Work Order",
|
"label": "Work Order",
|
||||||
"options": "Work Order",
|
"options": "Work Order",
|
||||||
"read_only": 1,
|
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 1
|
"search_index": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"fetch_from": "work_order.bom_no",
|
||||||
"fieldname": "bom_no",
|
"fieldname": "bom_no",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "BOM No",
|
"label": "BOM No",
|
||||||
@ -91,7 +99,7 @@
|
|||||||
"fieldname": "for_quantity",
|
"fieldname": "for_quantity",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "For Quantity",
|
"label": "Qty To Manufacture",
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -109,6 +117,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "employee",
|
"fieldname": "employee",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
|
"in_standard_filter": 1,
|
||||||
"label": "Employee",
|
"label": "Employee",
|
||||||
"options": "Employee"
|
"options": "Employee"
|
||||||
},
|
},
|
||||||
@ -198,7 +207,7 @@
|
|||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"label": "Status",
|
"label": "Status",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "Open\nWork In Progress\nMaterial Transferred\nSubmitted\nCancelled\nCompleted",
|
"options": "Open\nWork In Progress\nMaterial Transferred\nOn Hold\nSubmitted\nCancelled\nCompleted",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -236,10 +245,52 @@
|
|||||||
"label": "Naming Series",
|
"label": "Naming Series",
|
||||||
"options": "PO-JOB.#####",
|
"options": "PO-JOB.#####",
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "employee.employee_name",
|
||||||
|
"fieldname": "employee_name",
|
||||||
|
"fieldtype": "Read Only",
|
||||||
|
"label": "Employee Name"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "production_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Production"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_12",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "work_order.production_item",
|
||||||
|
"fieldname": "production_item",
|
||||||
|
"fieldtype": "Read Only",
|
||||||
|
"label": "Production Item"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "barcode",
|
||||||
|
"fieldtype": "Barcode",
|
||||||
|
"label": "Barcode",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "work_order.item_name",
|
||||||
|
"fieldname": "item_name",
|
||||||
|
"fieldtype": "Read Only",
|
||||||
|
"label": "Item Name"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "current_time",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"hidden": 1,
|
||||||
|
"label": "Current Time",
|
||||||
|
"no_copy": 1,
|
||||||
|
"print_hide": 1,
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"modified": "2019-10-30 01:49:19.606178",
|
"modified": "2019-12-03 13:08:57.926201",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Job Card",
|
"name": "Job Card",
|
||||||
|
@ -194,8 +194,9 @@ class JobCard(Document):
|
|||||||
if self.total_completed_qty <= 0.0:
|
if self.total_completed_qty <= 0.0:
|
||||||
frappe.throw(_("Total completed qty must be greater than zero"))
|
frappe.throw(_("Total completed qty must be greater than zero"))
|
||||||
|
|
||||||
if self.total_completed_qty > self.for_quantity:
|
if self.total_completed_qty != self.for_quantity:
|
||||||
frappe.throw(_("Total completed qty can not be greater than for quantity"))
|
frappe.throw(_("The total completed qty({0}) must be equal to qty to manufacture({1})"
|
||||||
|
.format(frappe.bold(self.total_completed_qty),frappe.bold(self.for_quantity))))
|
||||||
|
|
||||||
def update_work_order(self):
|
def update_work_order(self):
|
||||||
if not self.work_order:
|
if not self.work_order:
|
||||||
@ -271,6 +272,8 @@ class JobCard(Document):
|
|||||||
self.set_status(update_status)
|
self.set_status(update_status)
|
||||||
|
|
||||||
def set_status(self, update_status=False):
|
def set_status(self, update_status=False):
|
||||||
|
if self.status == "On Hold": return
|
||||||
|
|
||||||
self.status = {
|
self.status = {
|
||||||
0: "Open",
|
0: "Open",
|
||||||
1: "Submitted",
|
1: "Submitted",
|
||||||
@ -329,6 +332,7 @@ def make_stock_entry(source_name, target_doc=None):
|
|||||||
target.fg_completed_qty = source.get('for_quantity', 0) - source.get('transferred_qty', 0)
|
target.fg_completed_qty = source.get('for_quantity', 0) - source.get('transferred_qty', 0)
|
||||||
target.calculate_rate_and_amount()
|
target.calculate_rate_and_amount()
|
||||||
target.set_missing_values()
|
target.set_missing_values()
|
||||||
|
target.set_stock_entry_type()
|
||||||
|
|
||||||
doclist = get_mapped_doc("Job Card", source_name, {
|
doclist = get_mapped_doc("Job Card", source_name, {
|
||||||
"Job Card": {
|
"Job Card": {
|
||||||
@ -353,3 +357,45 @@ def make_stock_entry(source_name, target_doc=None):
|
|||||||
|
|
||||||
def time_diff_in_minutes(string_ed_date, string_st_date):
|
def time_diff_in_minutes(string_ed_date, string_st_date):
|
||||||
return time_diff(string_ed_date, string_st_date).total_seconds() / 60
|
return time_diff(string_ed_date, string_st_date).total_seconds() / 60
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_job_details(start, end, filters=None):
|
||||||
|
events = []
|
||||||
|
|
||||||
|
event_color = {
|
||||||
|
"Completed": "#cdf5a6",
|
||||||
|
"Material Transferred": "#ffdd9e",
|
||||||
|
"Work In Progress": "#D3D3D3"
|
||||||
|
}
|
||||||
|
|
||||||
|
from frappe.desk.reportview import get_filters_cond
|
||||||
|
conditions = get_filters_cond("Job Card", filters, [])
|
||||||
|
|
||||||
|
job_cards = frappe.db.sql(""" SELECT `tabJob Card`.name, `tabJob Card`.work_order,
|
||||||
|
`tabJob Card`.employee_name, `tabJob Card`.status, ifnull(`tabJob Card`.remarks, ''),
|
||||||
|
min(`tabJob Card Time Log`.from_time) as from_time,
|
||||||
|
max(`tabJob Card Time Log`.to_time) as to_time
|
||||||
|
FROM `tabJob Card` , `tabJob Card Time Log`
|
||||||
|
WHERE
|
||||||
|
`tabJob Card`.name = `tabJob Card Time Log`.parent {0}
|
||||||
|
group by `tabJob Card`.name""".format(conditions), as_dict=1)
|
||||||
|
|
||||||
|
for d in job_cards:
|
||||||
|
subject_data = []
|
||||||
|
for field in ["name", "work_order", "remarks", "employee_name"]:
|
||||||
|
if not d.get(field): continue
|
||||||
|
|
||||||
|
subject_data.append(d.get(field))
|
||||||
|
|
||||||
|
color = event_color.get(d.status)
|
||||||
|
job_card_data = {
|
||||||
|
'from_time': d.from_time,
|
||||||
|
'to_time': d.to_time,
|
||||||
|
'name': d.name,
|
||||||
|
'subject': '\n'.join(subject_data),
|
||||||
|
'color': color if color else "#89bcde"
|
||||||
|
}
|
||||||
|
|
||||||
|
events.append(job_card_data)
|
||||||
|
|
||||||
|
return events
|
||||||
|
21
erpnext/manufacturing/doctype/job_card/job_card_calendar.js
Normal file
21
erpnext/manufacturing/doctype/job_card/job_card_calendar.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
frappe.views.calendar["Job Card"] = {
|
||||||
|
field_map: {
|
||||||
|
"start": "from_time",
|
||||||
|
"end": "to_time",
|
||||||
|
"id": "name",
|
||||||
|
"title": "subject",
|
||||||
|
"color": "color",
|
||||||
|
"allDay": "allDay",
|
||||||
|
"progress": "progress"
|
||||||
|
},
|
||||||
|
gantt: true,
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"fieldname": "employee",
|
||||||
|
"options": "Employee",
|
||||||
|
"label": __("Employee")
|
||||||
|
}
|
||||||
|
],
|
||||||
|
get_events_method: "erpnext.manufacturing.doctype.job_card.job_card.get_job_details"
|
||||||
|
};
|
@ -1,208 +1,57 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
|
||||||
"allow_events_in_timeline": 0,
|
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 0,
|
|
||||||
"allow_rename": 0,
|
|
||||||
"beta": 0,
|
|
||||||
"creation": "2019-03-08 23:56:43.187569",
|
"creation": "2019-03-08 23:56:43.187569",
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "",
|
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"from_time",
|
||||||
|
"to_time",
|
||||||
|
"column_break_2",
|
||||||
|
"time_in_mins",
|
||||||
|
"completed_qty"
|
||||||
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "from_time",
|
"fieldname": "from_time",
|
||||||
"fieldtype": "Datetime",
|
"fieldtype": "Datetime",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
"label": "From Time"
|
||||||
"label": "From Time",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "to_time",
|
"fieldname": "to_time",
|
||||||
"fieldtype": "Datetime",
|
"fieldtype": "Datetime",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
"label": "To Time"
|
||||||
"label": "To Time",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "column_break_2",
|
"fieldname": "column_break_2",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break"
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "time_in_mins",
|
"fieldname": "time_in_mins",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Time In Mins",
|
"label": "Time In Mins",
|
||||||
"length": 0,
|
"read_only": 1
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 1,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"default": "0",
|
"default": "0",
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "completed_qty",
|
"fieldname": "completed_qty",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Completed Qty",
|
"label": "Completed Qty",
|
||||||
"length": 0,
|
"reqd": 1
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
|
||||||
"hide_heading": 0,
|
|
||||||
"hide_toolbar": 0,
|
|
||||||
"idx": 0,
|
|
||||||
"image_view": 0,
|
|
||||||
"in_create": 0,
|
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 0,
|
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"modified": "2019-12-03 12:56:02.285448",
|
||||||
"modified": "2019-03-10 17:08:46.504910",
|
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Job Card Time Log",
|
"name": "Job Card Time Log",
|
||||||
"name_case": "",
|
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0,
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "ASC",
|
"sort_order": "ASC",
|
||||||
"track_changes": 1,
|
"track_changes": 1
|
||||||
"track_seen": 0,
|
|
||||||
"track_views": 0
|
|
||||||
}
|
}
|
@ -71,12 +71,13 @@ frappe.ui.form.on('Production Plan', {
|
|||||||
}, __('Create'));
|
}, __('Create'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frm.page.set_inner_btn_group_as_primary(__('Create'));
|
||||||
frm.trigger("material_requirement");
|
frm.trigger("material_requirement");
|
||||||
|
|
||||||
const projected_qty_formula = ` <table class="table table-bordered" style="background-color: #f9f9f9;">
|
const projected_qty_formula = ` <table class="table table-bordered" style="background-color: #f9f9f9;">
|
||||||
<tr><td style="padding-left:25px">
|
<tr><td style="padding-left:25px">
|
||||||
<div>
|
<div>
|
||||||
<h3>
|
<h3 style="text-decoration: underline;">
|
||||||
<a href = "https://erpnext.com/docs/user/manual/en/stock/projected-quantity">
|
<a href = "https://erpnext.com/docs/user/manual/en/stock/projected-quantity">
|
||||||
${__("Projected Quantity Formula")}
|
${__("Projected Quantity Formula")}
|
||||||
</a>
|
</a>
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -6,7 +6,7 @@ def get_data():
|
|||||||
'fieldname': 'production_plan',
|
'fieldname': 'production_plan',
|
||||||
'transactions': [
|
'transactions': [
|
||||||
{
|
{
|
||||||
'label': _('Related'),
|
'label': _('Transactions'),
|
||||||
'items': ['Work Order', 'Material Request']
|
'items': ['Work Order', 'Material Request']
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -6,6 +6,7 @@ frappe.ui.form.on("Work Order", {
|
|||||||
frm.custom_make_buttons = {
|
frm.custom_make_buttons = {
|
||||||
'Stock Entry': 'Start',
|
'Stock Entry': 'Start',
|
||||||
'Pick List': 'Create Pick List',
|
'Pick List': 'Create Pick List',
|
||||||
|
'Job Card': 'Create Job Card'
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set query for warehouses
|
// Set query for warehouses
|
||||||
@ -131,7 +132,8 @@ frappe.ui.form.on("Work Order", {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (frm.doc.docstatus===1) {
|
if (frm.doc.docstatus===1) {
|
||||||
frm.trigger('show_progress');
|
frm.trigger('show_progress_for_items');
|
||||||
|
frm.trigger('show_progress_for_operations');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frm.doc.docstatus === 1
|
if (frm.doc.docstatus === 1
|
||||||
@ -179,89 +181,72 @@ frappe.ui.form.on("Work Order", {
|
|||||||
|
|
||||||
make_job_card: function(frm) {
|
make_job_card: function(frm) {
|
||||||
let qty = 0;
|
let qty = 0;
|
||||||
const fields = [{
|
let operations_data = [];
|
||||||
fieldtype: "Link",
|
|
||||||
fieldname: "operation",
|
|
||||||
options: "Operation",
|
|
||||||
label: __("Operation"),
|
|
||||||
get_query: () => {
|
|
||||||
const filter_workstation = frm.doc.operations.filter(d => {
|
|
||||||
if (d.status != "Completed") {
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
const dialog = frappe.prompt({fieldname: 'operations', fieldtype: 'Table', label: __('Operations'),
|
||||||
filters: {
|
fields: [
|
||||||
name: ["in", (filter_workstation || []).map(d => d.operation)]
|
{
|
||||||
}
|
fieldtype:'Link',
|
||||||
};
|
fieldname:'operation',
|
||||||
|
label: __('Operation'),
|
||||||
|
read_only:1,
|
||||||
|
in_list_view:1
|
||||||
},
|
},
|
||||||
reqd: true
|
{
|
||||||
}, {
|
fieldtype:'Link',
|
||||||
fieldtype: "Link",
|
fieldname:'workstation',
|
||||||
fieldname: "workstation",
|
label: __('Workstation'),
|
||||||
options: "Workstation",
|
read_only:1,
|
||||||
label: __("Workstation"),
|
in_list_view:1
|
||||||
get_query: () => {
|
|
||||||
const operation = dialog.get_value("operation");
|
|
||||||
const filter_workstation = frm.doc.operations.filter(d => {
|
|
||||||
if (d.operation == operation) {
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
filters: {
|
|
||||||
name: ["in", (filter_workstation || []).map(d => d.workstation)]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
onchange: () => {
|
{
|
||||||
const operation = dialog.get_value("operation");
|
fieldtype:'Data',
|
||||||
const workstation = dialog.get_value("workstation");
|
fieldname:'name',
|
||||||
if (operation && workstation) {
|
label: __('Operation Id')
|
||||||
const row = frm.doc.operations.filter(d => d.operation == operation && d.workstation == workstation)[0];
|
|
||||||
qty = frm.doc.qty - row.completed_qty;
|
|
||||||
|
|
||||||
if (qty > 0) {
|
|
||||||
dialog.set_value("qty", qty);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
reqd: true
|
{
|
||||||
}, {
|
fieldtype:'Float',
|
||||||
fieldtype: "Float",
|
fieldname:'pending_qty',
|
||||||
fieldname: "qty",
|
label: __('Pending Qty'),
|
||||||
label: __("For Quantity"),
|
},
|
||||||
reqd: true
|
{
|
||||||
}];
|
fieldtype:'Float',
|
||||||
|
fieldname:'qty',
|
||||||
const dialog = frappe.prompt(fields, function(data) {
|
label: __('Quantity to Manufacture'),
|
||||||
if (data.qty > qty) {
|
read_only:0,
|
||||||
frappe.throw(__("For Quantity must be less than quantity {0}", [qty]));
|
in_list_view:1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
data: operations_data,
|
||||||
|
in_place_edit: true,
|
||||||
|
get_data: function() {
|
||||||
|
return operations_data;
|
||||||
}
|
}
|
||||||
|
}, function(data) {
|
||||||
if (data.qty <= 0) {
|
|
||||||
frappe.throw(__("For Quantity must be greater than zero"));
|
|
||||||
}
|
|
||||||
|
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "erpnext.manufacturing.doctype.work_order.work_order.make_job_card",
|
method: "erpnext.manufacturing.doctype.work_order.work_order.make_job_card",
|
||||||
args: {
|
args: {
|
||||||
work_order: frm.doc.name,
|
work_order: frm.doc.name,
|
||||||
operation: data.operation,
|
operations: data.operations,
|
||||||
workstation: data.workstation,
|
|
||||||
qty: data.qty
|
|
||||||
},
|
|
||||||
callback: function(r){
|
|
||||||
if (r.message) {
|
|
||||||
var doc = frappe.model.sync(r.message)[0];
|
|
||||||
frappe.set_route("Form", doc.doctype, doc.name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, __("For Job Card"));
|
}, __("Job Card"), __("Create"));
|
||||||
|
|
||||||
|
var pending_qty = 0;
|
||||||
|
frm.doc.operations.forEach(data => {
|
||||||
|
if(data.completed_qty != frm.doc.qty) {
|
||||||
|
pending_qty = frm.doc.qty - flt(data.completed_qty);
|
||||||
|
|
||||||
|
dialog.fields_dict.operations.df.data.push({
|
||||||
|
'name': data.name,
|
||||||
|
'operation': data.operation,
|
||||||
|
'workstation': data.workstation,
|
||||||
|
'qty': pending_qty,
|
||||||
|
'pending_qty': pending_qty,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dialog.fields_dict.operations.grid.refresh();
|
||||||
},
|
},
|
||||||
|
|
||||||
make_bom: function(frm) {
|
make_bom: function(frm) {
|
||||||
@ -277,7 +262,7 @@ frappe.ui.form.on("Work Order", {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
show_progress: function(frm) {
|
show_progress_for_items: function(frm) {
|
||||||
var bars = [];
|
var bars = [];
|
||||||
var message = '';
|
var message = '';
|
||||||
var added_min = false;
|
var added_min = false;
|
||||||
@ -311,6 +296,44 @@ frappe.ui.form.on("Work Order", {
|
|||||||
frm.dashboard.add_progress(__('Status'), bars, message);
|
frm.dashboard.add_progress(__('Status'), bars, message);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
show_progress_for_operations: function(frm) {
|
||||||
|
if (frm.doc.operations && frm.doc.operations.length) {
|
||||||
|
|
||||||
|
let progress_class = {
|
||||||
|
"Work in Progress": "progress-bar-warning",
|
||||||
|
"Completed": "progress-bar-success"
|
||||||
|
};
|
||||||
|
|
||||||
|
let bars = [];
|
||||||
|
let message = '';
|
||||||
|
let title = '';
|
||||||
|
let status_wise_oprtation_data = {};
|
||||||
|
let total_completed_qty = frm.doc.qty * frm.doc.operations.length;
|
||||||
|
|
||||||
|
frm.doc.operations.forEach(d => {
|
||||||
|
if (!status_wise_oprtation_data[d.status]) {
|
||||||
|
status_wise_oprtation_data[d.status] = [d.completed_qty, d.operation];
|
||||||
|
} else {
|
||||||
|
status_wise_oprtation_data[d.status][0] += d.completed_qty;
|
||||||
|
status_wise_oprtation_data[d.status][1] += ', ' + d.operation;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let key in status_wise_oprtation_data) {
|
||||||
|
title = __("{0} Operations: {1}", [key, status_wise_oprtation_data[key][1].bold()]);
|
||||||
|
bars.push({
|
||||||
|
'title': title,
|
||||||
|
'width': status_wise_oprtation_data[key][0] / total_completed_qty * 100 + '%',
|
||||||
|
'progress_class': progress_class[key]
|
||||||
|
});
|
||||||
|
|
||||||
|
message += title + '. ';
|
||||||
|
}
|
||||||
|
|
||||||
|
frm.dashboard.add_progress(__('Status'), bars, message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
production_item: function(frm) {
|
production_item: function(frm) {
|
||||||
if (frm.doc.production_item) {
|
if (frm.doc.production_item) {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"actions": [],
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"autoname": "naming_series:",
|
"autoname": "naming_series:",
|
||||||
"creation": "2013-01-10 16:34:16",
|
"creation": "2013-01-10 16:34:16",
|
||||||
@ -468,7 +469,8 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"image_field": "image",
|
"image_field": "image",
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"modified": "2019-08-28 12:29:35.315239",
|
"links": [],
|
||||||
|
"modified": "2019-12-04 11:20:04.695123",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Work Order",
|
"name": "Work Order",
|
||||||
|
@ -6,7 +6,7 @@ import frappe
|
|||||||
import json
|
import json
|
||||||
import math
|
import math
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import flt, get_datetime, getdate, date_diff, cint, nowdate
|
from frappe.utils import flt, get_datetime, getdate, date_diff, cint, nowdate, get_link_to_form
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from erpnext.manufacturing.doctype.bom.bom import validate_bom_no, get_bom_items_as_dict
|
from erpnext.manufacturing.doctype.bom.bom import validate_bom_no, get_bom_items_as_dict
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
@ -755,21 +755,41 @@ def query_sales_order(production_item):
|
|||||||
return out
|
return out
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_job_card(work_order, operation, workstation, qty=0):
|
def make_job_card(work_order, operations):
|
||||||
|
if isinstance(operations, string_types):
|
||||||
|
operations = json.loads(operations)
|
||||||
|
|
||||||
work_order = frappe.get_doc('Work Order', work_order)
|
work_order = frappe.get_doc('Work Order', work_order)
|
||||||
row = get_work_order_operation_data(work_order, operation, workstation)
|
for row in operations:
|
||||||
if row:
|
validate_operation_data(row)
|
||||||
return create_job_card(work_order, row, qty)
|
create_job_card(work_order, row, row.get("qty"), auto_create=True)
|
||||||
|
|
||||||
|
def validate_operation_data(row):
|
||||||
|
if row.get("qty") <= 0:
|
||||||
|
frappe.throw(_("Quantity to Manufacture can not be zero for the operation {0}")
|
||||||
|
.format(
|
||||||
|
frappe.bold(row.get("operation"))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if row.get("qty") > row.get("pending_qty"):
|
||||||
|
frappe.throw(_("For operation {0}: Quantity ({1}) can not be greter than pending quantity({2})")
|
||||||
|
.format(
|
||||||
|
frappe.bold(row.get("operation")),
|
||||||
|
frappe.bold(row.get("qty")),
|
||||||
|
frappe.bold(row.get("pending_qty"))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def create_job_card(work_order, row, qty=0, enable_capacity_planning=False, auto_create=False):
|
def create_job_card(work_order, row, qty=0, enable_capacity_planning=False, auto_create=False):
|
||||||
doc = frappe.new_doc("Job Card")
|
doc = frappe.new_doc("Job Card")
|
||||||
doc.update({
|
doc.update({
|
||||||
'work_order': work_order.name,
|
'work_order': work_order.name,
|
||||||
'operation': row.operation,
|
'operation': row.get("operation"),
|
||||||
'workstation': row.workstation,
|
'workstation': row.get("workstation"),
|
||||||
'posting_date': nowdate(),
|
'posting_date': nowdate(),
|
||||||
'for_quantity': qty or work_order.get('qty', 0),
|
'for_quantity': qty or work_order.get('qty', 0),
|
||||||
'operation_id': row.name,
|
'operation_id': row.get("name"),
|
||||||
'bom_no': work_order.bom_no,
|
'bom_no': work_order.bom_no,
|
||||||
'project': work_order.project,
|
'project': work_order.project,
|
||||||
'company': work_order.company,
|
'company': work_order.company,
|
||||||
@ -785,7 +805,7 @@ def create_job_card(work_order, row, qty=0, enable_capacity_planning=False, auto
|
|||||||
doc.schedule_time_logs(row)
|
doc.schedule_time_logs(row)
|
||||||
|
|
||||||
doc.insert()
|
doc.insert()
|
||||||
frappe.msgprint(_("Job card {0} created").format(doc.name))
|
frappe.msgprint(_("Job card {0} created").format(get_link_to_form("Job Card", doc.name)))
|
||||||
|
|
||||||
return doc
|
return doc
|
||||||
|
|
||||||
|
@ -2,11 +2,13 @@
|
|||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.views.calendar["Work Order"] = {
|
frappe.views.calendar["Work Order"] = {
|
||||||
|
fields: ["planned_start_date", "planned_end_date", "status", "produced_qty", "qty", "name", "name"],
|
||||||
field_map: {
|
field_map: {
|
||||||
"start": "planned_start_date",
|
"start": "planned_start_date",
|
||||||
"end": "planned_end_date",
|
"end": "planned_end_date",
|
||||||
"id": "name",
|
"id": "name",
|
||||||
"title": "name",
|
"title": "name",
|
||||||
|
"status": "status",
|
||||||
"allDay": "allDay",
|
"allDay": "allDay",
|
||||||
"progress": function(data) {
|
"progress": function(data) {
|
||||||
return flt(data.produced_qty) / data.qty * 100;
|
return flt(data.produced_qty) / data.qty * 100;
|
||||||
|
@ -6,7 +6,8 @@ def get_data():
|
|||||||
'fieldname': 'work_order',
|
'fieldname': 'work_order',
|
||||||
'transactions': [
|
'transactions': [
|
||||||
{
|
{
|
||||||
'items': ['Pick List', 'Stock Entry', 'Job Card']
|
'label': _('Transactions'),
|
||||||
|
'items': ['Stock Entry', 'Job Card', 'Pick List']
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"actions": [],
|
||||||
"creation": "2014-10-16 14:35:41.950175",
|
"creation": "2014-10-16 14:35:41.950175",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
@ -68,6 +69,7 @@
|
|||||||
"description": "Operation completed for how many finished goods?",
|
"description": "Operation completed for how many finished goods?",
|
||||||
"fieldname": "completed_qty",
|
"fieldname": "completed_qty",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
|
"in_list_view": 1,
|
||||||
"label": "Completed Qty",
|
"label": "Completed Qty",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
@ -188,8 +190,9 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2019-07-16 23:01:07.720337",
|
"links": [],
|
||||||
"modified_by": "govindsmenokee@gmail.com",
|
"modified": "2019-12-03 19:24:29.594189",
|
||||||
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Work Order Operation",
|
"name": "Work Order Operation",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
|
@ -13,5 +13,7 @@ def get_data():
|
|||||||
'label': _('Transaction'),
|
'label': _('Transaction'),
|
||||||
'items': ['Work Order', 'Job Card', 'Timesheet']
|
'items': ['Work Order', 'Job Card', 'Timesheet']
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
'disable_create_buttons': ['BOM', 'Routing', 'Operation',
|
||||||
|
'Work Order', 'Job Card', 'Timesheet']
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user