Production module cleanup
This commit is contained in:
parent
65032af912
commit
c5d6bcbb8f
68
erpnext/patches/jan_mar_2012/production_cleanup.py
Normal file
68
erpnext/patches/jan_mar_2012/production_cleanup.py
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
def execute():
|
||||||
|
import webnotes
|
||||||
|
from webnotes.modules.module_manager import reload_doc
|
||||||
|
from webnotes.model import delete_doc
|
||||||
|
sql = webnotes.conn.sql
|
||||||
|
|
||||||
|
# Production Planning Tool
|
||||||
|
#---------------------------------------------------------------
|
||||||
|
delete_doc('DocType', 'PP Detail')
|
||||||
|
delete_doc('DocType', 'PP SO Detail')
|
||||||
|
delete_doc('DocType', 'Production Planning Tool')
|
||||||
|
|
||||||
|
reload_doc('production', 'doctype', 'production_planning_tool')
|
||||||
|
reload_doc('production', 'doctype', 'pp_detail')
|
||||||
|
reload_doc('production', 'doctype', 'pp_so_detail')
|
||||||
|
|
||||||
|
# Production Order
|
||||||
|
#---------------------------------------------------------------
|
||||||
|
|
||||||
|
reload_doc('production', 'doctype', 'production_order')
|
||||||
|
|
||||||
|
sql("""delete from `tabDocField` where parent = 'Production Order'
|
||||||
|
and (label in ('Material Transfer', 'Backflush', 'Stop Production Order', 'Unstop Production Order')
|
||||||
|
or fieldname = 'transaction_date')
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
# Bill Of Materials
|
||||||
|
#---------------------------------------------------------------
|
||||||
|
reload_doc('production', 'doctype', 'bill_of_materials')
|
||||||
|
relaod_doc('production', 'doctype', 'bom_material')
|
||||||
|
relaod_doc('production', 'doctype', 'bom_operation')
|
||||||
|
relaod_doc('production', 'doctype', 'flat_bom_detail')
|
||||||
|
|
||||||
|
#copy values
|
||||||
|
sql("""update `tabBill Of Materials` set rm_cost_as_per = 'Valuation Rate',
|
||||||
|
raw_material_cost = dir_mat_as_per_mar, total_cost = cost_as_per_mar, costing_date = cost_as_on""")
|
||||||
|
|
||||||
|
sql("update `tabBOM Material` set rate = moving_avg_rate, amount = amount_as_per_mar")
|
||||||
|
|
||||||
|
sql("update `tabFlat Bom Detail` set rate = moving_average_rate, amount = amount_as_per_mar")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# delete depricated flds from bom
|
||||||
|
sql(""" delete from `tabDocField` where parent = 'Bill Of Materials'
|
||||||
|
and (
|
||||||
|
label in ('TreeView1', 'Set as Default BOM', 'Activate BOM', 'Inactivate BOM')
|
||||||
|
or fieldname in ('cost_as_per_mar', 'cost_as_per_lpr', 'cost_as_per_sr', 'cost_as_on',
|
||||||
|
'dir_mat_as_per_mar', 'dir_mat_as_per_lpr', 'dir_mat_as_per_sr')
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
|
||||||
|
# delete depricated flds from bom operation
|
||||||
|
sql("delete from `tabDocField` where parent = 'BOM Operation' and fieldname in ('details', 'workstation_capacity')")
|
||||||
|
|
||||||
|
# delete depricated flds from bom material
|
||||||
|
sql("""delete from `tabDocField` where parent = 'BOM Material'
|
||||||
|
and fieldname in ('dir_mat_as_per_mar', 'dir_mat_as_per_sr', 'dir_mat_as_per_lpr', 'operating_cost', 'value_as_per_mar',
|
||||||
|
'value_as_per_sr', 'value_as_per_lpr', 'moving_avg_rate', 'standard_rate', 'last_purchase_rate', 'amount_as_per_sr',
|
||||||
|
'amount_as_per_lpr', 'amount_as_per_mar')
|
||||||
|
""")
|
||||||
|
|
||||||
|
# delete depricated flds from flat bom
|
||||||
|
sql("""delete from tabDocField where parent = 'Flat BOM Detail'
|
||||||
|
and fieldname in ('moving_avg_rate', 'standard_rate', 'last_purchase_rate', 'amount_as_per_mar',
|
||||||
|
'amount_as_per_sr', 'amount_as_per_lpr', 'flat_bom_no', 'bom_mat_no', 'is_pro_applicable')
|
||||||
|
""")
|
||||||
@ -1,123 +1,143 @@
|
|||||||
//$import(Production Tips Common)
|
|
||||||
|
|
||||||
// ONLOAD
|
|
||||||
cur_frm.cscript.onload = function(doc,cdt,cdn){
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// On REFRESH
|
// On REFRESH
|
||||||
cur_frm.cscript.refresh = function(doc,cdt,cdn){
|
cur_frm.cscript.refresh = function(doc,dt,dn){
|
||||||
|
if(!doc.__islocal) {
|
||||||
|
set_field_permlevel('item',1);
|
||||||
|
unhide_field('Update Cost as on today');
|
||||||
// Hide - Un Hide Buttons
|
} else {
|
||||||
if (!doc.is_default && doc.__islocal!=1) unhide_field('Set as Default BOM');
|
hide_field('Update Cost as on today');
|
||||||
else hide_field('Set as Default BOM');
|
}
|
||||||
if (doc.is_default && doc.__islocal!=1) unhide_field('Unset as Default BOM');
|
|
||||||
else hide_field('Unset as Default BOM');
|
|
||||||
|
|
||||||
if(doc.__islocal!=1){
|
|
||||||
set_field_permlevel('item',1);
|
|
||||||
}
|
|
||||||
if (flt(doc.docstatus) == 1){
|
|
||||||
if (doc.is_active == 'Yes') { unhide_field('Inactivate BOM'); hide_field('Activate BOM');}
|
|
||||||
else { hide_field('Inactivate BOM'); unhide_field('Activate BOM');}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Triggers
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
cur_frm.cscript.item = function(doc, dt, dn) {
|
||||||
|
if (doc.item) {
|
||||||
|
get_server_fields('get_item_detail',doc.item,'',doc,dt,dn,1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cur_frm.cscript.workstation = function(doc,dt,dn) {
|
||||||
|
var d = locals[dt][dn];
|
||||||
|
if (d.workstation) {
|
||||||
|
var callback = function(r, rt) {
|
||||||
|
calculate_op_cost(doc, dt, dn);
|
||||||
|
calculate_total(doc);
|
||||||
|
}
|
||||||
|
get_server_fields('get_workstation_details',d.workstation,'bom_operations',doc,dt,dn,1, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cur_frm.cscript.hour_rate = function(doc, dt, dn) {
|
||||||
|
calculate_op_cost(doc, dt, dn);
|
||||||
|
calculate_total(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cur_frm.cscript.time_in_mins = cur_frm.cscript.hour_rate;
|
||||||
|
|
||||||
|
|
||||||
|
cur_frm.cscript.item_code = function(doc,dt,dn) {
|
||||||
|
get_bom_material_detail(doc, dt, dn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cur_frm.cscript.bom_no = function(doc,dt,dn) {
|
||||||
|
get_bom_material_detail(doc, dt, dn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var get_bom_material_detail= function(doc,dt,dn) {
|
||||||
|
var d = locals[dt][dn];
|
||||||
|
var callback = function(doc, dt, dn) {
|
||||||
|
calculate_rm_cost(doc, dt, dn);
|
||||||
|
calculate_total(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
var bom_no = (d.bom_no!=null) ? d.bom_no:''
|
||||||
|
if (d.item_code) {
|
||||||
|
arg = {'item_code': d.item_code, 'bom_no': bom_no, 'qty': d.qty};
|
||||||
|
get_server_fields('get_bom_material_detail', JSON.stringify(arg), 'bom_materials', doc, dt, dn, 1, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cur_frm.cscript.qty = function(doc, dt, dn) {
|
||||||
|
calculate_rm_cost(doc, dt, dn);
|
||||||
|
calculate_total(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cur_frm.cscript.rate = cur_frm.cscript.qty;
|
||||||
|
|
||||||
|
|
||||||
|
cur_frm.cscript.is_default = function(doc, dt, dn) {
|
||||||
|
if (doc.docstatus == 1)
|
||||||
|
$c_obj(make_doclist(dt, dn), 'manage_default_bom', '', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cur_frm.cscript.is_active = function(doc, dt, dn) {
|
||||||
|
if (!doc.__islocal)
|
||||||
|
$c_obj(make_doclist(dt, dn), 'manage_active_bom', '', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Calculate Operating Cost
|
||||||
|
var calculate_op_cost = function(doc, dt, dn) {
|
||||||
|
var op = getchildren('BOM Operation', doc.name, 'bom_operations');
|
||||||
|
total_op_cost = 0;
|
||||||
|
for(var i=0;i<op.length;i++) {
|
||||||
|
op_cost = flt(op[i].hour_rate) * flt(op[i].time_in_mins) / 60;
|
||||||
|
set_multiple('BOM Operation',op[i].name, {'operating_cost': op_cost}, 'bom_operations');
|
||||||
|
total_op_cost += op_cost;
|
||||||
|
}
|
||||||
|
doc.operating_cost = total_op_cost;
|
||||||
|
refresh_field('operating_cost');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Calculate Raw Material Cost
|
||||||
|
var calculate_rm_cost = function(doc, dt, dn) {
|
||||||
|
var rm = getchildren('BOM Material', doc.name, 'bom_materials');
|
||||||
|
total_rm_cost = 0;
|
||||||
|
for(var i=0;i<rm.length;i++) {
|
||||||
|
amt = flt(rm[i].rate) * flt(rm[i].qty);
|
||||||
|
set_multiple('BOM Material',rm[i].name, {'amount': amt}, 'bom_materials');
|
||||||
|
set_multiple('BOM Material',rm[i].name, {'qty_consumed_per_unit': flt(rm[i].qty)/flt(doc.quantity)}, 'bom_materials');
|
||||||
|
total_rm_cost += amt;
|
||||||
|
}
|
||||||
|
doc.raw_material_cost = total_rm_cost;
|
||||||
|
refresh_field('raw_material_cost');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Calculate Total Cost
|
||||||
|
var calculate_total = function(doc) {
|
||||||
|
doc.total_cost = flt(doc.raw_material_cost) + flt(doc.operating_cost);
|
||||||
|
refresh_field('total_cost');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Get Query
|
||||||
|
//-----------------------------------------------------------------------------------------------------
|
||||||
cur_frm.fields_dict['item'].get_query = function(doc) {
|
cur_frm.fields_dict['item'].get_query = function(doc) {
|
||||||
return 'SELECT DISTINCT `tabItem`.`name`, `tabItem`.description FROM `tabItem` WHERE (IFNULL(`tabItem`.`end_of_life`,"") = "" OR `tabItem`.`end_of_life` = "0000-00-00" OR `tabItem`.`end_of_life` > NOW()) AND `tabItem`.`%(key)s` like "%s" ORDER BY `tabItem`.`name` LIMIT 50';
|
return 'SELECT DISTINCT `tabItem`.`name`, `tabItem`.description FROM `tabItem` WHERE (IFNULL(`tabItem`.`end_of_life`,"") = "" OR `tabItem`.`end_of_life` = "0000-00-00" OR `tabItem`.`end_of_life` > NOW()) AND `tabItem`.`%(key)s` like "%s" ORDER BY `tabItem`.`name` LIMIT 50';
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------- Get project name --------------------------
|
cur_frm.fields_dict['project_name'].get_query = function(doc, dt, dn) {
|
||||||
cur_frm.fields_dict['project_name'].get_query = function(doc, cdt, cdn) {
|
return 'SELECT `tabProject`.name FROM `tabProject` WHERE `tabProject`.status = "Open" AND `tabProject`.name LIKE "%s" ORDER BY `tabProject`.name ASC LIMIT 50';
|
||||||
return 'SELECT `tabProject`.name FROM `tabProject` WHERE `tabProject`.status = "Open" AND `tabProject`.name LIKE "%s" ORDER BY `tabProject`.name ASC LIMIT 50';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_frm.fields_dict['bom_materials'].grid.get_field('item_code').get_query = function(doc) {
|
cur_frm.fields_dict['bom_materials'].grid.get_field('item_code').get_query = function(doc) {
|
||||||
return 'SELECT DISTINCT `tabItem`.`name`, `tabItem`.description FROM `tabItem` WHERE (IFNULL(`tabItem`.`end_of_life`,"") = "" OR `tabItem`.`end_of_life` = "0000-00-00" OR `tabItem`.`end_of_life` > NOW()) AND `tabItem`.`%(key)s` like "%s" ORDER BY `tabItem`.`name` LIMIT 50';
|
return 'SELECT DISTINCT `tabItem`.`name`, `tabItem`.description FROM `tabItem` WHERE (IFNULL(`tabItem`.`end_of_life`,"") = "" OR `tabItem`.`end_of_life` = "0000-00-00" OR `tabItem`.`end_of_life` > NOW()) AND `tabItem`.`%(key)s` like "%s" ORDER BY `tabItem`.`name` LIMIT 50';
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_frm.fields_dict['bom_materials'].grid.get_field('bom_no').get_query = function(doc) {
|
cur_frm.fields_dict['bom_materials'].grid.get_field('bom_no').get_query = function(doc) {
|
||||||
var d = locals[this.doctype][this.docname];
|
var d = locals[this.doctype][this.docname];
|
||||||
return 'SELECT DISTINCT `tabBill Of Materials`.`name`, `tabBill Of Materials`.`remarks` FROM `tabBill Of Materials` WHERE `tabBill Of Materials`.`item` = "' + d.item_code + '" AND `tabBill Of Materials`.`name` like "%s" ORDER BY `tabBill Of Materials`.`name` LIMIT 50';
|
return 'SELECT DISTINCT `tabBill Of Materials`.`name`, `tabBill Of Materials`.`remarks` FROM `tabBill Of Materials` WHERE `tabBill Of Materials`.`item` = "' + d.item_code + '" AND `tabBill Of Materials`.`is_active` = "Yes" AND `tabBill Of Materials`.docstatus = 1 AND `tabBill Of Materials`.`name` like "%s" ORDER BY `tabBill Of Materials`.`name` LIMIT 50';
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_frm.cscript.item = function(doc, cdt, cdn) {
|
|
||||||
if (doc.item) {
|
|
||||||
get_server_fields('get_item_detail',doc.item,'',doc,cdt,cdn,1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.cscript.workstation = function(doc,cdt,cdn) {
|
|
||||||
var d = locals[cdt][cdn];
|
|
||||||
if (d.workstation) {
|
|
||||||
get_server_fields('get_workstation_details',d.workstation,'bom_operations',doc,cdt,cdn,1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.cscript.item_code =function(doc,cdt,cdn) {
|
|
||||||
var d = locals[cdt][cdn];
|
|
||||||
if (d.item_code) {
|
|
||||||
arg = "{'item_code' : '" + d.item_code + "', 'bom_no' : ''}";
|
|
||||||
get_server_fields('get_bom_material_detail',arg,'bom_materials',doc,cdt,cdn,1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.cscript.bom_no = function(doc,cdt,cdn) {
|
|
||||||
var d = locals[cdt][cdn];
|
|
||||||
if (d.item_code && d.bom_no) {
|
|
||||||
arg = "{'item_code' : '" + d.item_code + "', 'bom_no' : '" + d.bom_no + "'}";
|
|
||||||
get_server_fields('get_bom_material_detail',arg,'bom_materials',doc,cdt,cdn,1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.cscript['Set as Default BOM'] = function(doc,cdt,cdn) {
|
|
||||||
var check = confirm("Do you Really want to Set BOM " + doc.name + " as default for Item " + doc.item);
|
|
||||||
if (check) {
|
|
||||||
$c('runserverobj', args={'method':'set_as_default_bom', 'docs': compress_doclist([doc])}, function(r,rt) {
|
|
||||||
refresh_field('is_default');
|
|
||||||
hide_field('Set as Default BOM');unhide_field('Unset as Default BOM');
|
|
||||||
refresh_field('Set as Default BOM');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.cscript['Unset as Default BOM'] = function(doc,cdt,cdn) {
|
|
||||||
var check = confirm("Do you Really want to Unset BOM " + doc.name + " as default for Item " + doc.item);
|
|
||||||
if (check) {
|
|
||||||
$c('runserverobj', args={'method':'unset_as_default_bom', 'docs': compress_doclist([doc])}, function(r,rt) {
|
|
||||||
refresh_field('is_default');
|
|
||||||
hide_field('Unset as Default BOM');unhide_field('Set as Default BOM');
|
|
||||||
refresh_field('Unset as Default BOM');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.cscript['Activate BOM'] = function(doc,cdt,cdn) {
|
|
||||||
var check = confirm("DO YOU REALLY WANT TO ACTIVATE BOM : " + doc.name);
|
|
||||||
|
|
||||||
if (check) {
|
|
||||||
$c('runserverobj', args={'method':'activate_inactivate_bom', 'arg': 'Activate', 'docs': compress_doclist(make_doclist(doc.doctype, doc.name))}, function(r,rt) {
|
|
||||||
cur_frm.refresh();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.cscript['Test Flat BOM'] = function(doc,cdt,cdn) {
|
|
||||||
|
|
||||||
$c('runserverobj', args={'method':'get_current_flat_bom_items', 'docs': compress_doclist(make_doclist(doc.doctype, doc.name))}, function(r,rt) {
|
|
||||||
cur_frm.refresh();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.cscript['Inactivate BOM'] = function(doc,cdt,cdn) {
|
|
||||||
var check = confirm("DO YOU REALLY WANT TO INACTIVATE BOM : " + doc.name);
|
|
||||||
|
|
||||||
if (check) {
|
|
||||||
$c('runserverobj', args={'method':'activate_inactivate_bom', 'arg': 'Inactivate', 'docs': compress_doclist(make_doclist(doc.doctype, doc.name))}, function(r,rt) {
|
|
||||||
cur_frm.refresh();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,547 +1,397 @@
|
|||||||
# Please edit this list and import only required elements
|
|
||||||
import webnotes
|
import webnotes
|
||||||
|
from webnotes.utils import cint, cstr, flt, get_defaults, getdate, now, nowdate
|
||||||
from webnotes.utils import add_days, add_months, add_years, cint, cstr, date_diff, default_fields, flt, fmt_money, formatdate, generate_hash, getTraceback, get_defaults, get_first_day, get_last_day, getdate, has_common, month_name, now, nowdate, replace_newlines, sendmail, set_default, str_esc_quote, user_format, validate_email_add
|
from webnotes.model.doc import Document, addchild, getchildren, make_autoname
|
||||||
from webnotes.model import db_exists
|
from webnotes.model.doclist import getlist
|
||||||
from webnotes.model.doc import Document, addchild, removechild, getchildren, make_autoname, SuperDocType
|
from webnotes.model.code import get_obj
|
||||||
from webnotes.model.doclist import getlist, copy_doclist
|
from webnotes import msgprint, errprint
|
||||||
from webnotes.model.code import get_obj, get_server_obj, run_server_obj, updatedb, check_syntax
|
|
||||||
from webnotes import session, form, is_testing, msgprint, errprint
|
|
||||||
|
|
||||||
set = webnotes.conn.set
|
set = webnotes.conn.set
|
||||||
sql = webnotes.conn.sql
|
sql = webnotes.conn.sql
|
||||||
get_value = webnotes.conn.get_value
|
get_value = webnotes.conn.get_value
|
||||||
in_transaction = webnotes.conn.in_transaction
|
|
||||||
convert_to_lists = webnotes.conn.convert_to_lists
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
class DocType:
|
class DocType:
|
||||||
def __init__(self, doc, doclist=[]):
|
def __init__(self, doc, doclist=[]):
|
||||||
self.doc = doc
|
self.doc = doc
|
||||||
self.doclist = doclist
|
self.doclist = doclist
|
||||||
|
|
||||||
def autoname(self):
|
def autoname(self):
|
||||||
last_name = sql("select max(name) from `tabBill Of Materials` where name like 'BOM/%s/%%'" % self.doc.item)
|
last_name = sql("select max(name) from `tabBill Of Materials` where name like 'BOM/%s/%%'" % self.doc.item)
|
||||||
if last_name:
|
if last_name:
|
||||||
idx = cint(cstr(last_name[0][0]).split('/')[-1]) + 1
|
idx = cint(cstr(last_name[0][0]).split('/')[-1]) + 1
|
||||||
else:
|
else:
|
||||||
idx = 1
|
idx = 1
|
||||||
self.doc.name = 'BOM/' + self.doc.item + ('/%.3i' % idx)
|
self.doc.name = 'BOM/' + self.doc.item + ('/%.3i' % idx)
|
||||||
|
|
||||||
#----------- Client Trigger function ----------
|
|
||||||
def get_item_detail(self, item_code):
|
def get_item_det(self, item_code):
|
||||||
item = sql("select description, stock_uom from `tabItem` where (ifnull(end_of_life,'')='' or end_of_life = '0000-00-00' or end_of_life > now()) and name = %s",item_code , as_dict =1)
|
item = sql("""select name, is_asset_item, is_purchase_item, docstatus, is_sub_contracted_item,
|
||||||
ret={
|
description, stock_uom, default_bom, last_purchase_rate, standard_rate, is_manufactured_item from `tabItem`
|
||||||
'description' : item and item[0]['description'] or '',
|
where item_code = %s""", item_code, as_dict = 1)
|
||||||
'uom' : item and item[0]['stock_uom'] or ''
|
|
||||||
}
|
return item
|
||||||
return ret
|
|
||||||
|
|
||||||
def get_workstation_details(self,workstation):
|
def get_item_detail(self, item_code):
|
||||||
ws = sql("select hour_rate, capacity from `tabWorkstation` where name = %s",workstation , as_dict = 1)
|
""" Get stock uom and description for finished good item"""
|
||||||
ret = {
|
|
||||||
'hour_rate' : ws and flt(ws[0]['hour_rate']) or '',
|
item = self.get_item_det(item_code)
|
||||||
'workstation_capacity' : ws and flt(ws[0]['capacity']) or ''
|
ret={
|
||||||
}
|
'description' : item and item[0]['description'] or '',
|
||||||
return ret
|
'uom' : item and item[0]['stock_uom'] or ''
|
||||||
|
}
|
||||||
def get_bom_material_detail(self, arg):
|
return ret
|
||||||
arg = eval(arg)
|
|
||||||
if arg['item_code'] and arg['item_code'] == self.doc.item:
|
|
||||||
msgprint(" Item_code: "+arg['item_code']+" in materials tab cannot be same as main Item in BOM := " +cstr(self.doc.name))
|
|
||||||
raise Exception
|
def get_workstation_details(self,workstation):
|
||||||
if arg['item_code']:
|
""" Fetch hour rate from workstation master"""
|
||||||
item = sql("select is_asset_item, is_purchase_item, docstatus, is_sub_contracted_item, description, stock_uom, default_bom from `tabItem` where item_code = %s", (arg['item_code']), as_dict = 1)
|
|
||||||
|
ws = sql("select hour_rate from `tabWorkstation` where name = %s",workstation , as_dict = 1)
|
||||||
# Check for Asset Item
|
ret = {
|
||||||
if item and item[0]['is_asset_item'] == 'Yes':
|
'hour_rate' : ws and flt(ws[0]['hour_rate']) or '',
|
||||||
msgprint("Sorry!!! Item " + arg['item_code'] + " is an Asset of the company. Entered in BOM := " + cstr(self.doc.name))
|
}
|
||||||
raise Exception
|
return ret
|
||||||
|
|
||||||
if item and item[0]['docstatus'] == 2:
|
|
||||||
msgprint("Item %s does not exist in system" % cstr(args['item_code']))
|
|
||||||
|
def validate_rm_item(self, item):
|
||||||
ret_item = {
|
""" Validate raw material items"""
|
||||||
'description' : item and item[0]['description'] or '',
|
|
||||||
'stock_uom' : item and item[0]['stock_uom'] or '',
|
if item[0]['name'] == self.doc.item:
|
||||||
'bom_no' : item and item[0]['default_bom'] or ''
|
msgprint(" Item_code: "+item[0]['name']+" in materials tab cannot be same as FG Item in BOM := " +cstr(self.doc.name), raise_exception=1)
|
||||||
}
|
|
||||||
|
if item and item[0]['is_asset_item'] == 'Yes':
|
||||||
# Check for Purchase Item
|
msgprint("Sorry!!! Item " + item[0]['name'] + " is an Asset of the company. Entered in BOM => " + cstr(self.doc.name), raise_exception = 1)
|
||||||
if item and (item[0]['is_purchase_item'] == 'Yes' or item[0]['is_sub_contracted_item'] == 'Yes'):
|
|
||||||
ret_item['moving_avg_rate'], ret_item['last_purchase_rate'], ret_item['standard_rate'] = self.get_mar_lpr_sr(arg['item_code'], mar = 1, lpr = 1, sr = 1)
|
if not item or item[0]['docstatus'] == 2:
|
||||||
ret_item['operating_cost'], ret_item['dir_mat_as_per_mar'], ret_item['dir_mat_as_per_lpr'], ret_item['dir_mat_as_per_sr'] = 0, 0, 0, 0
|
msgprint("Item %s does not exist in system" % item[0]['item_code'], raise_exception = 1)
|
||||||
ret_item['value_as_per_mar'], ret_item['value_as_per_lpr'], ret_item['value_as_per_sr'] = 0, 0, 0
|
|
||||||
ret_item['amount_as_per_mar'], ret_item['amount_as_per_lpr'], ret_item['amount_as_per_sr'] = 0, 0, 0
|
|
||||||
|
|
||||||
if arg['bom_no'] or not ret_item['bom_no'] =='':
|
def get_bom_material_detail(self, arg):
|
||||||
if arg['bom_no']:
|
""" Get raw material details like uom, desc and rate"""
|
||||||
bom = sql("select name, dir_mat_as_per_mar,dir_mat_as_per_lpr,dir_mat_as_per_sr, operating_cost, quantity from `tabBill Of Materials` where is_active = 'Yes' and name = %s", (arg['bom_no']), as_dict=1)
|
|
||||||
else:
|
arg = eval(arg)
|
||||||
# get recent direct material cost, operating_cost, cost from Default BOM of Item
|
item = self.get_item_det(arg['item_code'])
|
||||||
bom = sql("select name, dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr, operating_cost, quantity from `tabBill Of Materials` where is_active = 'Yes' and name = %s", (ret_item['bom_no']), as_dict=1)
|
|
||||||
|
self.validate_rm_item(item)
|
||||||
# get recent direct material cost, operating_cost, cost from Entered BOM of Item
|
|
||||||
ret_item['bom_no'] = bom and bom[0]['name'] or ''
|
arg['bom_no'] = arg['bom_no'] or item and cstr(item[0]['default_bom']) or ''
|
||||||
|
arg.update(item[0])
|
||||||
if bom and bom[0]['name']:
|
|
||||||
ret_bom = {
|
rate = self.get_rm_rate(arg)
|
||||||
'dir_mat_as_per_mar' : flt(bom[0]['dir_mat_as_per_mar']) / flt(bom[0]['quantity']) or 0.00,
|
|
||||||
'dir_mat_as_per_lpr' : flt(bom[0]['dir_mat_as_per_lpr']) / flt(bom[0]['quantity']) or 0.00,
|
ret_item = {
|
||||||
'dir_mat_as_per_sr' : flt(bom[0]['dir_mat_as_per_sr']) / flt(bom[0]['quantity']) or 0.00,
|
'description' : item and arg['description'] or '',
|
||||||
'operating_cost' : flt(bom[0]['operating_cost']) / flt(bom[0]['quantity']) or 0.00,
|
'stock_uom' : item and arg['stock_uom'] or '',
|
||||||
'value_as_per_mar' : ((flt(bom[0]['dir_mat_as_per_mar']) + flt(bom[0]['operating_cost'])) / flt(bom[0]['quantity'])) or 0.00,
|
'bom_no' : arg['bom_no'],
|
||||||
'value_as_per_lpr' : ((flt(bom[0]['dir_mat_as_per_lpr']) + flt(bom[0]['operating_cost'])) / flt(bom[0]['quantity'])) or 0.00,
|
'rate' : rate
|
||||||
'value_as_per_sr' : ((flt(bom[0]['dir_mat_as_per_sr']) + flt(bom[0]['operating_cost'])) / flt(bom[0]['quantity'])) or 0.00,
|
}
|
||||||
'amount_as_per_mar' : 0,
|
return ret_item
|
||||||
'amount_as_per_lpr' : 0,
|
|
||||||
'amount_as_per_sr' : 0
|
|
||||||
}
|
|
||||||
ret_item.update(ret_bom)
|
def get_rm_rate(self, arg):
|
||||||
if item and item[0]['is_sub_contracted_item'] != 'Yes':
|
""" Get raw material rate as per selected method, if bom exists takes bom cost """
|
||||||
ret_bom_rates = {
|
|
||||||
'moving_avg_rate' : 0,
|
if arg['bom_no']:
|
||||||
'last_purchase_rate' : 0,
|
bom = sql("""select name, total_cost/quantity as unit_cost from `tabBill Of Materials`
|
||||||
'standard_rate' : 0
|
where is_active = 'Yes' and name = %s""", arg['bom_no'], as_dict=1)
|
||||||
}
|
rate = bom and bom[0]['unit_cost'] or 0
|
||||||
ret_item.update(ret_bom_rates)
|
elif arg and (arg['is_purchase_item'] == 'Yes' or arg['is_sub_contracted_item'] == 'Yes'):
|
||||||
return ret_item
|
if self.doc.rm_cost_as_per == 'Valuation Rate':
|
||||||
|
rate = self.get_valuation_rate(arg)
|
||||||
def set_as_default_bom(self):
|
elif self.doc.rm_cost_as_per == 'Last Purchase Rate':
|
||||||
# set Is Default as 1
|
rate = arg['last_purchase_rate']
|
||||||
set(self.doc,'is_default', flt(1))
|
elif self.doc.rm_cost_as_per == 'Standard Rate':
|
||||||
|
rate = arg['standard_rate']
|
||||||
# get previous default bom from Item Master
|
|
||||||
prev_def_bom = sql("select default_bom from `tabItem` where name = %s", self.doc.item,as_dict = 1)
|
return rate
|
||||||
|
|
||||||
if prev_def_bom[0]['default_bom'] and prev_def_bom[0]['default_bom'] != self.doc.name:
|
|
||||||
# update Is Default as 0 in Previous Default BOM
|
|
||||||
msgprint(cstr(prev_def_bom[0]['default_bom']) + "is no longer Default BOM for item" + cstr(self.doc.item))
|
def get_valuation_rate(self, arg):
|
||||||
sql("update `tabBill Of Materials` set is_default = 0 where name = '%s'" % (prev_def_bom[0]['default_bom']))
|
""" Get average valuation rate of relevant warehouses
|
||||||
|
as per valuation method (MAR/FIFO)
|
||||||
# update current BOM as default bom in Item Master
|
as on costing date
|
||||||
sql("update `tabItem` set default_bom = '%s' where name = '%s'" % (self.doc.name,self.doc.item))
|
"""
|
||||||
msgprint(cstr(self.doc.name) + "has been set as Default BOM for Item "+cstr(self.doc.item))
|
|
||||||
|
dt = self.doc.costing_date or nowdate()
|
||||||
def unset_as_default_bom(self):
|
time = self.doc.costing_date == nowdate() and now().split()[1] or '23:59'
|
||||||
# set Is Default as 1
|
warehouse = sql("select warehouse from `tabBin` where item_code = %s", arg['item_code'])
|
||||||
set(self.doc,'is_default', flt(0))
|
rate = []
|
||||||
|
for wh in warehouse:
|
||||||
# update current BOM as default bom in Item Master
|
r = get_obj('Valuation Control').get_incoming_rate(dt, time, arg['item_code'], wh[0], qty = arg.get('qty', 0))
|
||||||
sql("update `tabItem` set default_bom = null where name = '%s'" % (self.doc.item))
|
if r:
|
||||||
msgprint(cstr(self.doc.name) + "has been unset as Default BOM for Item "+cstr(self.doc.item))
|
rate.append(r)
|
||||||
|
|
||||||
def check_active_parent_boms(self):
|
return rate and flt(sum(rate))/len(rate) or 0
|
||||||
act_pbom = sql("select distinct t1.parent from `tabBOM Material` t1, `tabBill Of Materials` t2 where t1.bom_no ='%s' and t2.name = t1.parent and t2.is_active = 'Yes' and t2.docstatus = 1 and t1.docstatus =1 " % self.doc.name )
|
|
||||||
if act_pbom and act_pbom[0][0]:
|
|
||||||
msgprint("Sorry cannot Inactivate as BOM %s is child of one or many other active parent BOMs" % self.doc.name)
|
|
||||||
raise Exception
|
def manage_default_bom(self):
|
||||||
|
""" Uncheck others if current one is selected as default, update default bom in item master"""
|
||||||
def activate_inactivate_bom(self, action):
|
|
||||||
if cstr(action) == 'Activate':
|
if self.doc.is_default and self.doc.is_active == 'Yes':
|
||||||
self.validate()
|
sql("update `tabBill Of Materials` set is_default = 0 where name != %s", self.doc.name)
|
||||||
set(self.doc, 'is_active', 'Yes')
|
|
||||||
elif cstr(action) == 'Inactivate':
|
# update default bom in Item Master
|
||||||
self.check_active_parent_boms()
|
sql("update `tabItem` set default_bom = %s where name = %s", (self.doc.name, self.doc.item))
|
||||||
set(self.doc, 'is_active', 'No')
|
else:
|
||||||
|
sql("update `tabItem` set default_bom = '' where name = %s and default_bom = %s", (self.doc.item, self.doc.name))
|
||||||
#------ On Validation Of Document ----------
|
|
||||||
def validate_main_item(self):
|
|
||||||
item = sql("select is_manufactured_item, is_sub_contracted_item from `tabItem` where name = %s and (ifnull(end_of_life,'')='' or end_of_life = '0000-00-00' or end_of_life > now())", self.doc.item, as_dict = 1)
|
|
||||||
|
def manage_active_bom(self):
|
||||||
if not item:
|
""" Manage active/inactive """
|
||||||
msgprint("Item %s do not exists in the system. Entered in BOM := %s" % (cstr(self.doc.item), cstr(self.doc.name)))
|
if self.doc.is_active == 'Yes':
|
||||||
raise Exception
|
self.validate()
|
||||||
|
else:
|
||||||
elif not item[0]['is_manufactured_item'] == 'Yes' and not item[0]['is_sub_contracted_item'] == 'Yes':
|
self.check_active_parent_boms()
|
||||||
msgprint("Sorry cannot make Bill Of Materials for Item %s. As it is not a manufactured / sub-contracted item. Entered in BOM := %s " % (cstr(self.doc.item), cstr(self.doc.name)))
|
|
||||||
raise Exception
|
|
||||||
|
|
||||||
# validate operations
|
def check_active_parent_boms(self):
|
||||||
#------------------------------------------------------
|
""" Check parent BOM before making it inactive """
|
||||||
def validate_operations(self,o,validate = "0"):
|
act_pbom = sql("""select distinct t1.parent from `tabBOM Material` t1, `tabBill Of Materials` t2
|
||||||
if not o.operation_no:
|
where t1.bom_no =%s and t2.name = t1.parent and t2.is_active = 'Yes'
|
||||||
msgprint("Please Enter Operation No at Row " + cstr(o.idx)+" in BOM := " +cstr(self.doc.name))
|
and t2.docstatus = 1 and t1.docstatus =1 """, self.doc.name)
|
||||||
raise Exception
|
if act_pbom and act_pbom[0][0]:
|
||||||
|
msgprint("""Sorry cannot inactivate as BOM: %s is child
|
||||||
if not o.workstation:
|
of one or many other active parent BOMs""" % self.doc.name, raise_exception=1)
|
||||||
msgprint("Please Enter Workstation for Operation No. " + cstr(o.operation_no) + " in BOM NO. " + self.doc.name)
|
|
||||||
raise Exception
|
|
||||||
|
|
||||||
if not o.time_in_mins:
|
def calculate_cost(self):
|
||||||
msgprint("Please Enter Operation Time of Operation No. " + cstr(o.operation_no) + " in BOM NO. " + self.doc.name)
|
"""Calculate bom totals"""
|
||||||
raise Exception
|
self.doc.costing_date = nowdate()
|
||||||
|
self.calculate_op_cost()
|
||||||
# Operation No should not repeat.
|
self.calculate_rm_cost()
|
||||||
if o.operation_no in self.op:
|
self.doc.total_cost = self.doc.raw_material_cost + self.doc.operating_cost
|
||||||
msgprint("Operation No " + cstr(o.operation_no) + "is repeated in Operations Table of BOM NO. " + self.doc.name)
|
self.doc.modified = now()
|
||||||
raise Exception
|
self.doc.save()
|
||||||
|
|
||||||
# add operation in op list
|
self.update_flat_bom_engine(is_submit = self.doc.docstatus)
|
||||||
self.op.append(cstr(o.operation_no))
|
|
||||||
|
|
||||||
# Validate materials
|
|
||||||
#-------------------------------------------------
|
|
||||||
|
def calculate_op_cost(self):
|
||||||
def validate_materials(self,m):
|
"""Update workstation rate and calculates totals"""
|
||||||
|
total_op_cost = 0
|
||||||
# check for operation no
|
for d in getlist(self.doclist, 'bom_operations'):
|
||||||
if not self.op:
|
hour_rate = sql("select hour_rate from `tabWorkstation` where name = %s", d.workstation)
|
||||||
msgprint("Please Enter Operations in operation table of BOM NO. " + self.doc.name)
|
d.hour_rate = hour_rate and flt(hour_rate[0][0]) or 0
|
||||||
raise Exception
|
d.operating_cost = flt(d.hour_rate) * flt(d.time_in_mins) / 60
|
||||||
|
total_op_cost += d.operating_cost
|
||||||
# check if operation no not in op list
|
self.doc.operating_cost = total_op_cost
|
||||||
if m.operation_no not in self.op:
|
|
||||||
msgprint("Operation no "+ cstr(m.operation_no) + " for item code " + cstr(m.item_code) +" is not present in BOM Operations of BOM NO. " + self.doc.name)
|
|
||||||
raise Exception
|
|
||||||
|
def calculate_rm_cost(self):
|
||||||
if not m.item_code:
|
"""Fetch RM rate as per today's valuation rate and calculate totals"""
|
||||||
msgprint("Please Enter Item Code at Row " + cstr(m.idx) + "of BOM Material in BOM NO. " + self.doc.name)
|
total_rm_cost = 0
|
||||||
raise Exception
|
for d in getlist(self.doclist, 'bom_materials'):
|
||||||
|
if self.doc.rm_cost_as_per == 'Valuation Rate':
|
||||||
item = sql("select is_manufactured_item, is_sub_contracted_item from`tabItem` where item_code = %s and (ifnull(end_of_life,'')='' or end_of_life = '0000-00-00' or end_of_life > now())", m.item_code, as_dict = 1)
|
arg = {'item_code': d.item_code, 'qty': d.qty, 'bom_no': d.bom_no}
|
||||||
if not item:
|
ret = self.get_bom_material_detail(cstr(arg))
|
||||||
msgprint("Item %s is not present in Item Master." % m.item_code)
|
for k in ret:
|
||||||
raise Exception
|
d.fields[k] = ret[k]
|
||||||
|
|
||||||
if item[0]['is_manufactured_item'] == 'Yes' or item[0]['is_sub_contracted_item'] == 'Yes':
|
d.amount = flt(d.rate) * flt(d.qty)
|
||||||
bom = sql("select name, is_active, docstatus from `tabBill Of Materials` where item = %s", m.item_code, as_dict =1)
|
total_rm_cost += d.amount
|
||||||
if bom and bom[0]['name']:
|
self.doc.raw_material_cost = total_rm_cost
|
||||||
if not m.bom_no:
|
|
||||||
msgprint("Please Enter BOM No for Item " + cstr(m.item_code) + " in Materials at Row No. " + cstr(m.idx) + " in BOM NO. " + self.doc.name)
|
|
||||||
raise Exception
|
|
||||||
else:
|
def validate_main_item(self):
|
||||||
match = 0
|
""" Validate main FG item"""
|
||||||
for b in bom:
|
item = self.get_item_det(self.doc.item)
|
||||||
if cstr(m.bom_no) == cstr(b['name']):
|
if not item:
|
||||||
if b['is_active'] != 'Yes':
|
msgprint("Item %s does not exists in the system or expired." % self.doc.item, raise_exception = 1)
|
||||||
msgprint("BOM %s NOT ACTIVE BOM. Entered in BOM := %s at row no := %s" % (cstr(m.bom_no), cstr(self.doc.name), m.idx))
|
|
||||||
raise Exception
|
elif item[0]['is_manufactured_item'] != 'Yes' and item[0]['is_sub_contracted_item'] != 'Yes':
|
||||||
|
msgprint("""As Item: %s is not a manufactured / sub-contracted item,
|
||||||
#if flt(b['docstatus']) != 1:
|
you can not make BOM for it""" % self.doc.item, raise_exception = 1)
|
||||||
# msgprint("BOM %s is NOT SUBMITTED."% cstr(m.bom_no))
|
|
||||||
# raise Exception
|
|
||||||
|
|
||||||
match = 1
|
def validate_operations(self):
|
||||||
if not match:
|
""" Check duplicate operation no"""
|
||||||
msgprint("Item %s does not belongs to Bill Of Material %s or Bill Of Material %s is NOT ACTIVE BOM. Entered in BOM := %s at row no := %s" % (cstr(m.item_code),cstr(m.bom_no), cstr(m.bom_no), self.doc.name, m.idx))
|
self.op = []
|
||||||
raise Exception
|
for d in getlist(self.doclist, 'bom_operations'):
|
||||||
|
if cstr(d.operation_no) in self.op:
|
||||||
if not item[0]['is_manufactured_item'] == 'Yes' and not item[0]['is_sub_contracted_item']== 'Yes':
|
msgprint("Operation no: %s is repeated in Operations Table"% d.operation_no, raise_exception=1)
|
||||||
if m.bom_no:
|
else:
|
||||||
msgprint("As in Item Master of Item %s Is Manufactured Item / Is Sub-Contracted Item is not 'Yes' hence there should be no BOM.In BOm := %s at row no := %s" % (m.item_code, cstr(self.doc.name), m.idx))
|
# add operation in op list
|
||||||
raise Exception
|
self.op.append(cstr(d.operation_no))
|
||||||
|
|
||||||
if not m.qty or m.qty <= 0:
|
|
||||||
msgprint("Please Enter Qty value greater than 0(Zero) at Row " + cstr(m.idx) + " in BOM NO. " + self.doc.name)
|
|
||||||
raise Exception
|
def validate_materials(self):
|
||||||
|
""" Validate raw material entries """
|
||||||
if m.scrap and m.scrap < 0:
|
check_list = []
|
||||||
msgprint("Please Enter Scrap value Greater than 0(Zero) at Row " + cstr(m.idx) + " in BOM NO. " + self.doc.name)
|
for m in getlist(self.doclist, 'bom_materials'):
|
||||||
raise Exception
|
# check if operation no not in op table
|
||||||
|
if m.operation_no not in self.op:
|
||||||
# Calculate Cost
|
msgprint("""Operation no: %s against item: %s at row no: %s is not present
|
||||||
#-----------------------------------------------
|
at Operations table"""% (m.operation_no, m.item_code, m.idx), raise_exception = 1)
|
||||||
|
|
||||||
def calculate_cost(self, validate = 0):
|
item = self.get_item_det(m.item_code)
|
||||||
self.op, op_cost, dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr, count_mat = [], 0.0, 0.0,0.0,0.0, 0
|
if item[0]['is_manufactured_item'] == 'Yes' or item[0]['is_sub_contracted_item'] == 'Yes':
|
||||||
# -------- Calculate Cost Of BOM -------------
|
if not m.bom_no:
|
||||||
# --- calculate operating cost from BOM Operations ----
|
msgprint("Please enter BOM No aginst item: %s at row no: %s"% (m.item_code, m.idx), raise_exception=1)
|
||||||
for o in getlist(self.doclist, 'bom_operations'):
|
else:
|
||||||
# --- Validation for enteries in BOM Operations ----
|
self.validate_bom_no(m.item_code, m.bom_no, m.idx)
|
||||||
if validate:
|
|
||||||
self.validate_operations(o)
|
elif m.bom_no:
|
||||||
|
msgprint("""As Item %s is not a manufactured / sub-contracted item,
|
||||||
o.operating_cost = flt(flt(o.time_in_mins)/60) * flt(o.hour_rate)
|
you can enter BOM against it (Row No: %s)."""% (m.item_code, m.idx), raise_excepiton = 1)
|
||||||
if validate != 1:
|
|
||||||
o.save()
|
if flt(m.qty) <= 0:
|
||||||
msgprint('Operation saved')
|
msgprint("Please enter qty against raw material: %s at row no: %s"% (m.item_code, m.idx), raise_exception = 1)
|
||||||
|
|
||||||
op_cost = flt(op_cost) + flt(o.operating_cost)
|
self.check_if_item_repeated(m.item_code, m.operation_no, check_list)
|
||||||
|
|
||||||
# --- calculate operating cost and direct material cost from BOM Material ---
|
|
||||||
for m in getlist(self.doclist, 'bom_materials'):
|
|
||||||
# --- Validation for enteries in BOM Material --- '''
|
def validate_bom_no(self, item, bom_no, idx):
|
||||||
count_mat = count_mat + 1
|
"""Validate BOM No of sub-contracted items"""
|
||||||
if validate:
|
bom = sql("""select name from `tabBill Of Materials` where name = %s and item = %s
|
||||||
self.validate_materials(m)
|
and ifnull(is_active, 'No') = 'Yes' and docstatus < 2 """, (bom_no, item), as_dict =1)
|
||||||
|
if not bom:
|
||||||
if m.bom_no:
|
msgprint("""Incorrect BOM No: %s against item: %s at row no: %s.
|
||||||
# add operating cost of child boms
|
It may be inactive or cancelled or for some other item."""% (bom_no, item, idx), raise_exception = 1)
|
||||||
op_cost += flt(m.operating_cost)
|
|
||||||
|
|
||||||
# update dir_mat, op_cost, value from child bom
|
|
||||||
self.update_childs_dir_op_value(m, child_bom_cost = 1)
|
def check_if_item_repeated(self, item, op, check_list):
|
||||||
|
if [cstr(item), cstr(op)] in check_list:
|
||||||
# check for is_sub_contracted_item
|
msgprint("Item %s has been entered twice against same operation" % d.item_code, raise_exception = 1)
|
||||||
item = sql("select is_sub_contracted_item from `tabItem` where name = '%s'" % m.item_code, as_dict =1)
|
else:
|
||||||
if item and item[0]['is_sub_contracted_item'] == 'Yes':
|
check_list.append([cstr(item), cstr(op)])
|
||||||
# update recent mar,lpr,sr
|
|
||||||
self.update_mar_lpr_sr(m, mar =1, lpr =1, sr =1)
|
|
||||||
# calculate amount for sub contracted item
|
|
||||||
self.calculate_amount( m, has_bom = 1, is_sub_cont = 1)
|
#----- Document on Save function------
|
||||||
# calculate Direct Material
|
def validate(self):
|
||||||
dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr = self.calculate_dir_mat(m, dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr, has_bom = 1, is_sub_cont =1)
|
self.validate_main_item()
|
||||||
else:
|
self.validate_operations()
|
||||||
# update mar,lpr,sr as 0
|
self.validate_materials()
|
||||||
self.update_mar_lpr_sr( m, mar = 0, lpr = 0, sr = 0)
|
self.validate_operations()
|
||||||
# calculate amount
|
|
||||||
self.calculate_amount( m, has_bom = 1, is_sub_cont = 0)
|
|
||||||
# calculate Direct Material
|
|
||||||
dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr = self.calculate_dir_mat(m, dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr, has_bom = 1, is_sub_cont =0)
|
def check_recursion(self):
|
||||||
|
""" Check whether reqursion occurs in any bom"""
|
||||||
else :
|
|
||||||
# update dir_mat,op_cost, value as 0
|
check_list = [['parent', 'bom_no', 'parent'], ['bom_no', 'parent', 'child']]
|
||||||
self.update_childs_dir_op_value(m, child_bom_cost = 0)
|
for d in check_list:
|
||||||
# update recent mar,lpr,sr
|
bom_list, count = [self.doc.name], 0
|
||||||
self.update_mar_lpr_sr(m, mar =1, lpr =1, sr =1)
|
while (len(bom_list) > count ):
|
||||||
# calculate amount
|
boms = sql(" select %s from `tabBOM Material` where %s = '%s' " % (d[0], d[1], cstr(bom_list[count])))
|
||||||
self.calculate_amount(m, has_bom = 0, is_sub_cont = 0)
|
count = count + 1
|
||||||
# calculate Direct Material
|
for b in boms:
|
||||||
dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr = self.calculate_dir_mat(m, dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr, has_bom =0, is_sub_cont =0)
|
if b[0] == self.doc.name:
|
||||||
|
msgprint("""Recursion Occured => '%s' cannot be '%s' of '%s'.
|
||||||
# update qty_consumed_per_unit
|
""" % (cstr(b), cstr(d[2]), self.doc.name), raise_exception = 1)
|
||||||
m.qty_consumed_per_unit = flt(m.qty) / flt(self.doc.quantity)
|
if b[0]:
|
||||||
m.save()
|
bom_list.append(b[0])
|
||||||
#msgprint("dir_mat_as_per_mar < ==> " + cstr(dir_mat_as_per_mar) + "***" + "dir_mat_as_per_lpr < ==> " + cstr(dir_mat_as_per_lpr) + "***" + "dir_mat_as_per_sr < ==> " + cstr(dir_mat_as_per_sr) + "***")
|
|
||||||
if not count_mat:
|
|
||||||
msgprint("There should at least one Item in BOM Material. In BOM := " +cstr(self.doc.name))
|
|
||||||
raise Exception
|
def on_update(self):
|
||||||
|
if self.doc.item != cstr(self.doc.name.split('/')[1]):
|
||||||
set(self.doc, 'operating_cost' ,op_cost)
|
msgprint("Cannot change Item once the Bill Of Material is created.")
|
||||||
set(self.doc, 'cost_as_on' ,now())
|
raise Exception
|
||||||
# update dir_mat
|
self.check_recursion()
|
||||||
set(self.doc, 'dir_mat_as_per_mar' ,dir_mat_as_per_mar)
|
|
||||||
set(self.doc, 'dir_mat_as_per_lpr' ,dir_mat_as_per_lpr)
|
|
||||||
set(self.doc, 'dir_mat_as_per_sr' ,dir_mat_as_per_sr)
|
|
||||||
# update cost
|
def add_to_flat_bom_detail(self, is_submit = 0):
|
||||||
set(self.doc, 'cost_as_per_mar' ,flt(dir_mat_as_per_mar + op_cost))
|
"Add items to Flat BOM table"
|
||||||
set(self.doc, 'cost_as_per_lpr' ,flt(dir_mat_as_per_lpr + op_cost))
|
self.doc.clear_table(self.doclist, 'flat_bom_details', 1)
|
||||||
set(self.doc, 'cost_as_per_sr' ,flt(dir_mat_as_per_sr + op_cost))
|
for d in self.cur_flat_bom_items:
|
||||||
|
ch = addchild(self.doc, 'flat_bom_details', 'Flat BOM Detail', 1, self.doclist)
|
||||||
def update_childs_dir_op_value(self, m, child_bom_cost = 0):
|
for i in d.keys():
|
||||||
#msgprint("IN UPDATE CHILDS DIR OP VALUE")
|
ch.fields[i] = d[i]
|
||||||
if child_bom_cost:
|
ch.docstatus = is_submit
|
||||||
# get recent direct material cost, operating cost, cost from child bom
|
ch.save(1)
|
||||||
child_bom_cost = sql("select dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr, operating_cost, cost_as_per_mar, cost_as_per_lpr, cost_as_per_sr, quantity from `tabBill Of Materials` where name = %s", m.bom_no, as_dict = 1)
|
|
||||||
|
self.doc.save()
|
||||||
# operating_cost
|
|
||||||
m.operating_cost = child_bom_cost and flt(child_bom_cost[0]['operating_cost']) / flt(child_bom_cost[0]['quantity']) or 0.00
|
|
||||||
|
|
||||||
val_dir_dict = {'value_as_per_mar': 'cost_as_per_mar', 'dir_mat_as_per_mar': 'dir_mat_as_per_mar',
|
def get_child_flat_bom_items(self, bom_no, qty):
|
||||||
'value_as_per_lpr': 'cost_as_per_lpr', 'dir_mat_as_per_lpr': 'dir_mat_as_per_lpr',
|
""" Add all items from Flat BOM of child BOM"""
|
||||||
'value_as_per_sr' : 'cost_as_per_sr' , 'dir_mat_as_per_sr' : 'dir_mat_as_per_sr' }
|
|
||||||
for d in val_dir_dict:
|
child_fb_items = sql("""select item_code, description, stock_uom, qty, rate, amount, parent_bom, mat_detail_no, qty_consumed_per_unit
|
||||||
# Set Value and Dir MAt
|
from `tabFlat BOM Detail` where parent = '%s' and docstatus = 1""" % bom_no, as_dict = 1)
|
||||||
m.fields[d] = child_bom_cost and flt(child_bom_cost[0][val_dir_dict[d]])/flt(child_bom_cost[0]['quantity']) or 0.00
|
for d in child_fb_items:
|
||||||
|
self.cur_flat_bom_items.append({
|
||||||
def update_mar_lpr_sr(self, m, mar = 0, lpr = 0, sr = 0):
|
'item_code' : d['item_code'],
|
||||||
m.moving_avg_rate, m.last_purchase_rate, m.standard_rate = self.get_mar_lpr_sr(cstr(m.item_code), mar, lpr, sr, m.qty)
|
'description' : d['description'],
|
||||||
|
'stock_uom' : d['stock_uom'],
|
||||||
def calculate_amount(self, m, has_bom = 0, is_sub_cont = 0):
|
'qty' : flt(d['qty_consumed_per_unit'])*qty,
|
||||||
#msgprint("IN CALCULATE AMOUNT")
|
'rate' : flt(d['rate']),
|
||||||
if has_bom :
|
'amount' : flt(d['amount']),
|
||||||
m.amount_as_per_mar = flt(m.qty) * (is_sub_cont and flt(m.moving_avg_rate) or flt(m.value_as_per_mar)) * flt(1.00 + (flt(m.scrap)/100)) or 0
|
'parent_bom' : d['parent_bom'],
|
||||||
m.amount_as_per_lpr = flt(m.qty) * (is_sub_cont and (flt(m.value_as_per_lpr) + flt(m.last_purchase_rate)) or flt(m.value_as_per_lpr)) * flt(1.00 + (flt(m.scrap)/100)) or 0
|
'mat_detail_no' : d['mat_detail_no'],
|
||||||
m.amount_as_per_sr = flt(m.qty) * (is_sub_cont and (flt(m.value_as_per_sr) + flt(m.standard_rate)) or flt(m.value_as_per_mar)) * flt(1.00 + (flt(m.scrap)/100)) or 0
|
'qty_consumed_per_unit' : flt(d['qty_consumed_per_unit'])*qty/flt(self.doc.quantity)
|
||||||
|
|
||||||
else:
|
})
|
||||||
m.amount_as_per_mar = flt(m.qty) * flt(m.moving_avg_rate) * flt(1.00 + (flt(m.scrap)/100)) or 0
|
|
||||||
m.amount_as_per_lpr = flt(m.qty) * flt(m.last_purchase_rate) * flt(1.00 + (flt(m.scrap)/100)) or 0
|
|
||||||
m.amount_as_per_sr = flt(m.qty) * flt(m.standard_rate) * flt(1.00 + (flt(m.scrap)/100)) or 0
|
|
||||||
#msgprint(cstr(m.item_code))
|
|
||||||
#msgprint("amount_as_per_mar < ==> " + cstr(m.amount_as_per_mar) + "***" + "amount_as_per_lpr < ==> " + cstr(m.amount_as_per_lpr) + "***" + "amount_as_per_sr < ==> " + cstr(m.amount_as_per_sr) + "***")
|
# Get Current Flat BOM Items
|
||||||
def calculate_dir_mat(self, m, dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr, has_bom = 0, is_sub_cont =0):
|
# -----------------------------
|
||||||
#msgprint("IN CALCULATE DIR MAT")
|
def get_current_flat_bom_items(self):
|
||||||
if has_bom:
|
""" Get all raw materials including items from child bom"""
|
||||||
dir_mat_as_per_mar += flt(m.qty) * (is_sub_cont and flt(m.moving_avg_rate) or flt(m.dir_mat_as_per_mar)) * flt(1.00 + (flt(m.scrap)/100)) or 0
|
self.cur_flat_bom_items = []
|
||||||
dir_mat_as_per_lpr += flt(m.qty) * (is_sub_cont and ( flt(m.dir_mat_as_per_lpr)+ flt(m.last_purchase_rate)) or flt(m.dir_mat_as_per_lpr)) * flt(1.00 + (flt(m.scrap)/100)) or 0
|
for d in getlist(self.doclist, 'bom_materials'):
|
||||||
dir_mat_as_per_sr += flt(m.qty) * (is_sub_cont and ( flt(m.dir_mat_as_per_sr)+ flt(m.standard_rate) ) or flt(m.dir_mat_as_per_sr)) * flt(1.00 + (flt(m.scrap)/100)) or 0
|
item = {}
|
||||||
else:
|
if d.bom_no:
|
||||||
dir_mat_as_per_mar += flt(m.amount_as_per_mar)
|
item = sql("select is_sub_contracted_item from `tabItem` where name = '%s'" % d.item_code)
|
||||||
dir_mat_as_per_lpr += flt(m.amount_as_per_lpr)
|
|
||||||
dir_mat_as_per_sr += flt(m.amount_as_per_sr)
|
self.cur_flat_bom_items.append({
|
||||||
#msgprint(cstr(m.item_code))
|
'item_code' : d.item_code,
|
||||||
#msgprint("dir_mat_as_per_mar < ==> " + cstr(dir_mat_as_per_mar) + "***" + "dir_mat_as_per_lpr < ==> " + cstr(dir_mat_as_per_lpr) + "***" + "dir_mat_as_per_sr < ==> " + cstr(dir_mat_as_per_sr) + "***")
|
'description' : d.description,
|
||||||
return dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr
|
'stock_uom' : d.stock_uom,
|
||||||
|
'qty' : flt(d.qty),
|
||||||
|
'rate' : flt(d.rate),
|
||||||
# Get FIFO Rate from Stack
|
'amount' : flt(d.amount),
|
||||||
# -------------------------
|
'parent_bom' : d.parent, #item and item[0][0]=='No' and d.bom_no or d.parent,
|
||||||
def get_fifo_rate(self, fcfs_bal, qty):
|
'mat_detail_no' : d.name,
|
||||||
if qty:
|
'qty_consumed_per_unit' : flt(d.qty_consumed_per_unit)
|
||||||
fcfs_val = 0
|
})
|
||||||
withdraw = flt(qty)
|
if d.bom_no:
|
||||||
while withdraw:
|
self.get_child_flat_bom_items(d.bom_no, d.qty)
|
||||||
if not fcfs_bal:
|
|
||||||
break # nothing in store
|
|
||||||
|
|
||||||
batch = fcfs_bal[0]
|
def update_flat_bom_engine(self, is_submit = 0):
|
||||||
|
""" Update Flat BOM, following will be correct data"""
|
||||||
if batch[0] < withdraw:
|
self.get_current_flat_bom_items()
|
||||||
# not enough in current batch, clear batch
|
self.add_to_flat_bom_detail(is_submit)
|
||||||
withdraw -= batch[0]
|
|
||||||
fcfs_val += (flt(batch[0]) * flt(batch[1]))
|
|
||||||
fcfs_bal.pop(0)
|
def get_parent_bom_list(self, bom_no):
|
||||||
else:
|
p_bom = sql("select parent from `tabBOM Material` where bom_no = '%s'" % bom_no)
|
||||||
# all from current batch
|
return p_bom and [i[0] for i in p_bom] or []
|
||||||
fcfs_val += (flt(withdraw) * flt(batch[1]))
|
|
||||||
batch[0] -= withdraw
|
|
||||||
withdraw = 0
|
def on_submit(self):
|
||||||
fcfs_rate = flt(fcfs_val) / flt(qty)
|
self.manage_default_bom()
|
||||||
return fcfs_rate
|
self.update_flat_bom_engine(1)
|
||||||
else:
|
|
||||||
return fcfs_bal and fcfs_bal[0][1] or 0
|
|
||||||
|
def on_cancel(self):
|
||||||
|
# check if used in any other bom
|
||||||
# Get valuation rate
|
par = sql("""select t1.parent from `tabBOM Material` t1, `tabBill Of Materials` t2
|
||||||
# --------------------
|
where t1.parent = t2.name and t1.bom_no = %s and t1.docstatus = 1 and t2.is_active = 'Yes'""", self.doc.name)
|
||||||
def get_valuation_rate(self, item_code, qty):
|
if par:
|
||||||
# get default warehouse
|
msgprint("BOM can not be cancelled, as it is a child item in following active BOM %s"% [d[0] for d in par])
|
||||||
warehouse = sql("select default_warehouse from tabItem where name = %s", item_code)
|
raise Exception
|
||||||
warehouse = warehouse and warehouse[0][0] or ''
|
|
||||||
in_rate = 0
|
|
||||||
|
|
||||||
# get default valuation method
|
|
||||||
val_method = sql("select valuation_method from tabItem where name = %s", item_code)
|
|
||||||
val_method = val_method and val_method[0][0] or ''
|
|
||||||
if not val_method: val_method = get_defaults().has_key('valuation_method') and get_defaults()['valuation_method'] or 'FIFO'
|
|
||||||
|
|
||||||
if val_method == 'FIFO':
|
|
||||||
if warehouse:
|
|
||||||
bin_obj = get_obj('Warehouse',warehouse).get_bin(item_code)
|
|
||||||
prev_sle = bin_obj.get_prev_sle(nowdate(), (now().split(' ')[1])[:-3])
|
|
||||||
fcfs_stack = prev_sle and prev_sle['fcfs_stack'] and eval(prev_sle['fcfs_stack']) or []
|
|
||||||
else:
|
|
||||||
prev_sle = sql("select fcfs_stack from `tabStock Ledger Entry` where item_code = '%s' and posting_date <= '%s' order by posting_date DESC, posting_time DESC, name DESC limit 1" % (item_code, nowdate()))
|
|
||||||
fcfs_stack = prev_sle and (prev_sle[0][0] and eval(prev_sle[0][0]) or []) or []
|
|
||||||
in_rate = fcfs_stack and self.get_fifo_rate(fcfs_stack, qty) or 0
|
|
||||||
elif val_method == 'Moving Average':
|
|
||||||
in_rate = sql("select ifnull(sum(valuation_rate), 0)/ ifnull(count(*),1) from `tabBin` where item_code = '%s' and ifnull(ma_rate, 0) > 0" % cstr(item_code))
|
|
||||||
in_rate = in_rate and flt(in_rate[0][0]) or 0
|
|
||||||
return in_rate
|
|
||||||
|
|
||||||
|
|
||||||
# Get valuation, Last Purchase and Standard Rate
|
|
||||||
# ------------------------------------------------
|
|
||||||
def get_mar_lpr_sr(self, item_code, mar = 0, lpr = 0, sr = 0, qty = 1.00):
|
|
||||||
# get list of warehouse having
|
|
||||||
ma_rate, lpr_rate, sr_rate = 0,0,0
|
|
||||||
if mar:
|
|
||||||
# get recent moving average rate
|
|
||||||
#ma_rate = sql("select ifnull(sum(ma_rate), 0)/ ifnull(count(*),1) from `tabBin` where item_code = '%s' and ifnull(ma_rate, 0) > 0" % cstr(item_code))
|
|
||||||
#ma_rate = flt(ma_rate and ma_rate[0][0]) or 0
|
|
||||||
ma_rate = self.get_valuation_rate(item_code, qty)
|
|
||||||
|
|
||||||
# get recent last purchase rate
|
|
||||||
lpr_rate = lpr and flt(sql("select last_purchase_rate from `tabItem` where name = '%s'" % item_code)[0][0]) or 0.00
|
|
||||||
# get recent standard rate
|
|
||||||
sr_rate = sr and flt(sql("select standard_rate from `tabItem` where name = '%s'" % item_code)[0][0]) or 0.00
|
|
||||||
return ma_rate, lpr_rate, sr_rate
|
|
||||||
|
|
||||||
#checking for duplicate items i.e items that may be entered twice
|
|
||||||
def validate_duplicate_items(self):
|
|
||||||
check_list = []
|
|
||||||
for d in getlist(self.doclist, 'bom_materials'):
|
|
||||||
if cstr(d.item_code) in check_list:
|
|
||||||
msgprint("Item %s has been entered twice. In BOM %s" % (d.item_code, self.doc.name))
|
|
||||||
raise Exception
|
|
||||||
else:
|
|
||||||
check_list.append(cstr(d.item_code))
|
|
||||||
|
|
||||||
#----- Document on Save function------
|
|
||||||
def validate(self):
|
|
||||||
#msgprint(len(getlist(self.doclist, 'bom_materials')))
|
|
||||||
self.validate_main_item()
|
|
||||||
self.validate_duplicate_items()
|
|
||||||
self.calculate_cost(validate = 1)
|
|
||||||
|
|
||||||
def check_recursion(self):
|
|
||||||
check_list = [['parent', 'bom_no', 'parent'], ['bom_no', 'parent', 'child']]
|
|
||||||
for d in check_list:
|
|
||||||
bom_list, count = [self.doc.name], 0
|
|
||||||
while ( len(bom_list) > count ):
|
|
||||||
boms = sql(" select %s from `tabBOM Material` where %s = '%s' " % ( d[0], d[1], cstr(bom_list[count])))
|
|
||||||
count = count + 1
|
|
||||||
for b in boms:
|
|
||||||
if b[0] == self.doc.name:
|
|
||||||
msgprint("Recursion Occured:=> '%s' cannot be '%s' of '%s'." % ( cstr(b), cstr(d[2]), cstr(self.doc.name)))
|
|
||||||
raise Exception
|
|
||||||
if b[0]:
|
|
||||||
bom_list.append(b[0])
|
|
||||||
|
|
||||||
def on_update(self):
|
|
||||||
if self.doc.item != cstr(self.doc.name.split('/')[1]):
|
|
||||||
msgprint("Cannot change Item once the Bill Of Material is created.")
|
|
||||||
raise Exception
|
|
||||||
self.check_recursion()
|
|
||||||
|
|
||||||
|
|
||||||
# ********************************************** Submit *************************************************************
|
|
||||||
|
|
||||||
# Add Flat BOM Details
|
|
||||||
# -----------------------
|
|
||||||
def add_to_flat_bom_detail(self, is_submit = 0):
|
|
||||||
self.doc.clear_table(self.doclist, 'flat_bom_details', 1)
|
|
||||||
fb_lbl = {'item_code': 0, 'description': 1, 'qty': 2, 'stock_uom': 3, 'moving_avg_rate': 4,'amount_as_per_mar': 5, 'last_purchase_rate': 6, 'amount_as_per_lpr':7,'standard_rate':8,'amount_as_per_sr':9,'qty_consumed_per_unit': 10, 'parent_bom': 11, 'bom_mat_no': 12, 'is_pro_applicable': 13}
|
|
||||||
for d in self.cur_flat_bom_items:
|
|
||||||
fb_child = addchild(self.doc, 'flat_bom_details', 'Flat BOM Detail', 1, self.doclist)
|
|
||||||
for i in fb_lbl:
|
|
||||||
fb_child.fields[i] = d[fb_lbl[i]]
|
|
||||||
fb_child.docstatus = is_submit
|
|
||||||
fb_child.save(1)
|
|
||||||
self.doc.save()
|
|
||||||
|
|
||||||
|
|
||||||
#Get Child Flat BOM Items
|
|
||||||
#----------------------------------------
|
|
||||||
def get_child_flat_bom_items(self, item, d):
|
|
||||||
|
|
||||||
child_flat_bom_items=[]
|
|
||||||
|
|
||||||
child_flat_bom_items = sql("select fbom.item_code, fbom.description, fbom.qty_consumed_per_unit, fbom.stock_uom, fbom.moving_avg_rate, fbom.last_purchase_rate, fbom.standard_rate, '%s' as parent_bom, fbom.bom_mat_no, 'No' as is_pro_applicable from `tabFlat BOM Detail` fbom,`tabBill Of Materials` bom where fbom.parent=bom.name and fbom.parent = '%s' and fbom.is_pro_applicable = 'No' and bom.docstatus = 1" % ( d.bom_no, cstr(d.bom_no)))
|
|
||||||
self.cur_flat_bom_items.append([d.item_code, d.description, flt(d.qty), d.stock_uom, flt(d.moving_avg_rate), flt(d.amount_as_per_mar), flt(d.last_purchase_rate), flt(d.amount_as_per_lpr), flt(d.standard_rate), flt(d.amount_as_per_sr), flt(d.qty_consumed_per_unit), (item[0]['is_sub_contracted_item'] == 'Yes') and d.parent or d.bom_no, d.name, (item[0]['is_sub_contracted_item'] == 'Yes') and 'No' or 'Yes'])
|
|
||||||
return child_flat_bom_items
|
|
||||||
|
|
||||||
|
|
||||||
# Get Current Flat BOM Items
|
|
||||||
# -----------------------------
|
|
||||||
def get_current_flat_bom_items(self):
|
|
||||||
|
|
||||||
self.cur_flat_bom_items = []
|
|
||||||
|
|
||||||
cfb_lbl = {'item_code': 0, 'description': 1, 'qty_consumed_per_unit': 2, 'stock_uom': 3, 'moving_avg_rate': 4, 'last_purchase_rate': 5, 'standard_rate': 6, 'parent_bom': 7, 'bom_mat_no': 8, 'is_pro_applicable': 9}
|
|
||||||
|
|
||||||
for d in getlist(self.doclist, 'bom_materials'):
|
|
||||||
|
|
||||||
if d.bom_no:
|
|
||||||
item = sql("select is_sub_contracted_item, is_pro_applicable from `tabItem` where name = '%s'" % d.item_code, as_dict = 1)
|
|
||||||
child_flat_bom_items = self.get_child_flat_bom_items(item,d)
|
|
||||||
|
|
||||||
for c in child_flat_bom_items:
|
|
||||||
self.cur_flat_bom_items.append([c[cfb_lbl['item_code']], c[cfb_lbl['description']], flt(d.qty) * flt(c[cfb_lbl['qty_consumed_per_unit']]), c[cfb_lbl['stock_uom']], flt(c[cfb_lbl['moving_avg_rate']]), flt(d.qty) * flt(c[cfb_lbl['qty_consumed_per_unit']]) * flt(c[cfb_lbl['moving_avg_rate']]) ,flt(c[cfb_lbl['last_purchase_rate']]), flt(d.qty) * flt(c[cfb_lbl['qty_consumed_per_unit']]) * flt(c[cfb_lbl['last_purchase_rate']]), flt(c[cfb_lbl['standard_rate']]), flt(d.qty) * flt(c[cfb_lbl['qty_consumed_per_unit']]) * flt(c[cfb_lbl['standard_rate']]), flt(d.qty_consumed_per_unit) * flt(c[cfb_lbl['qty_consumed_per_unit']]), c[cfb_lbl['parent_bom']], c[cfb_lbl['bom_mat_no']], c[cfb_lbl['is_pro_applicable']]])
|
|
||||||
else:
|
|
||||||
# add purchase_items from bom material to the child_flat_bom_items
|
|
||||||
self.cur_flat_bom_items.append([d.item_code, d.description, flt(d.qty), d.stock_uom, flt(d.moving_avg_rate), flt(d.amount_as_per_mar), flt(d.last_purchase_rate), flt(d.amount_as_per_lpr), flt(d.standard_rate), flt(d.amount_as_per_sr), flt(d.qty_consumed_per_unit), d.parent, d.name, 'No' ])
|
|
||||||
|
|
||||||
# Update Flat BOM Engine
|
|
||||||
# ------------------------
|
|
||||||
def update_flat_bom_engine(self, is_submit = 0):
|
|
||||||
# following will be correct data
|
|
||||||
# get correct / updated flat bom data
|
|
||||||
self.get_current_flat_bom_items()
|
|
||||||
# insert to curr flat bom data
|
|
||||||
self.add_to_flat_bom_detail(is_submit)
|
|
||||||
|
|
||||||
|
|
||||||
# On Submit
|
|
||||||
# -----------
|
|
||||||
def on_submit(self):
|
|
||||||
self.update_flat_bom_engine(1)
|
|
||||||
|
|
||||||
|
|
||||||
def get_parent_bom_list(self, bom_no):
|
|
||||||
p_bom = sql("select parent from `tabBOM Material` where bom_no = '%s'" % bom_no)
|
|
||||||
return p_bom and [i[0] for i in p_bom] or []
|
|
||||||
|
|||||||
@ -5,14 +5,14 @@
|
|||||||
{
|
{
|
||||||
'creation': '2010-08-08 17:08:52',
|
'creation': '2010-08-08 17:08:52',
|
||||||
'docstatus': 0,
|
'docstatus': 0,
|
||||||
'modified': '2011-11-09 12:47:50',
|
'modified': '2012-01-11 14:33:04',
|
||||||
'modified_by': 'Administrator',
|
'modified_by': 'Administrator',
|
||||||
'owner': 'Administrator'
|
'owner': 'Administrator'
|
||||||
},
|
},
|
||||||
|
|
||||||
# These values are common for all DocType
|
# These values are common for all DocType
|
||||||
{
|
{
|
||||||
'_last_update': '1319016431',
|
'_last_update': '1326272478',
|
||||||
'allow_attach': 0,
|
'allow_attach': 0,
|
||||||
'allow_copy': 0,
|
'allow_copy': 0,
|
||||||
'allow_email': 0,
|
'allow_email': 0,
|
||||||
@ -32,11 +32,11 @@
|
|||||||
'name': '__common__',
|
'name': '__common__',
|
||||||
'read_only': 0,
|
'read_only': 0,
|
||||||
'search_fields': 'item',
|
'search_fields': 'item',
|
||||||
'section_style': 'Tabbed',
|
'section_style': 'Simple',
|
||||||
'server_code_error': ' ',
|
'server_code_error': ' ',
|
||||||
'show_in_menu': 0,
|
'show_in_menu': 0,
|
||||||
'subject': '%(item)s',
|
'subject': '%(item)s',
|
||||||
'version': 171
|
'version': 194
|
||||||
},
|
},
|
||||||
|
|
||||||
# These values are common for all DocField
|
# These values are common for all DocField
|
||||||
@ -131,89 +131,13 @@
|
|||||||
'write': 0
|
'write': 0
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'trash_reason',
|
|
||||||
'fieldtype': 'Small Text',
|
|
||||||
'label': 'Trash Reason',
|
|
||||||
'oldfieldname': 'trash_reason',
|
|
||||||
'oldfieldtype': 'Small Text',
|
|
||||||
'permlevel': 1
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldtype': 'HTML',
|
|
||||||
'label': 'TreeView1',
|
|
||||||
'oldfieldtype': 'HTML',
|
|
||||||
'options': '<div style=\'border: 1px solid #CCF; padding: 8px;margin-bottom: 8px;\'><div class=\'link_type\' onclick=\'loadpage("Bill of Materials"); \'>Go To BOM Tree View</div></div>',
|
|
||||||
'permlevel': 1
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldtype': 'Section Break',
|
|
||||||
'oldfieldtype': 'Section Break',
|
|
||||||
'options': 'Simple',
|
|
||||||
'permlevel': 0
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'allow_on_submit': 1,
|
|
||||||
'colour': 'White:FFF',
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldtype': 'Button',
|
|
||||||
'label': 'Set as Default BOM',
|
|
||||||
'oldfieldtype': 'Button',
|
|
||||||
'permlevel': 0,
|
|
||||||
'trigger': 'Client'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldtype': 'Column Break',
|
'fieldtype': 'Column Break',
|
||||||
'oldfieldtype': 'Column Break',
|
'oldfieldtype': 'Column Break',
|
||||||
'permlevel': 0
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'allow_on_submit': 1,
|
|
||||||
'colour': 'White:FFF',
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldtype': 'Button',
|
|
||||||
'hidden': 1,
|
|
||||||
'label': 'Activate BOM',
|
|
||||||
'oldfieldtype': 'Button',
|
|
||||||
'permlevel': 0,
|
'permlevel': 0,
|
||||||
'trigger': 'Client'
|
'width': '50%'
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'allow_on_submit': 1,
|
|
||||||
'colour': 'White:FFF',
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldtype': 'Button',
|
|
||||||
'hidden': 1,
|
|
||||||
'label': 'Inactivate BOM',
|
|
||||||
'oldfieldtype': 'Button',
|
|
||||||
'permlevel': 0,
|
|
||||||
'trigger': 'Client'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldtype': 'Section Break',
|
|
||||||
'label': 'Details',
|
|
||||||
'oldfieldtype': 'Section Break',
|
|
||||||
'permlevel': 0
|
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
@ -234,18 +158,6 @@
|
|||||||
'trigger': 'Client'
|
'trigger': 'Client'
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'description',
|
|
||||||
'fieldtype': 'Text',
|
|
||||||
'label': 'Description',
|
|
||||||
'oldfieldname': 'description',
|
|
||||||
'oldfieldtype': 'Text',
|
|
||||||
'permlevel': 0,
|
|
||||||
'width': '300px'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'colour': 'White:FFF',
|
'colour': 'White:FFF',
|
||||||
@ -272,30 +184,22 @@
|
|||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'colour': 'White:FFF',
|
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'is_active',
|
'fieldname': 'description',
|
||||||
'fieldtype': 'Select',
|
'fieldtype': 'Text',
|
||||||
'label': 'Is Active',
|
'label': 'Description',
|
||||||
'no_copy': 1,
|
'oldfieldname': 'description',
|
||||||
'oldfieldname': 'is_active',
|
'oldfieldtype': 'Text',
|
||||||
'oldfieldtype': 'Select',
|
|
||||||
'options': '\nYes\nNo',
|
|
||||||
'permlevel': 0,
|
'permlevel': 0,
|
||||||
'reqd': 1
|
'width': '300px'
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'colour': 'White:FFF',
|
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'is_default',
|
'fieldtype': 'Column Break',
|
||||||
'fieldtype': 'Check',
|
'permlevel': 0,
|
||||||
'label': 'Is Default',
|
'width': '50%'
|
||||||
'no_copy': 1,
|
|
||||||
'oldfieldname': 'is_default',
|
|
||||||
'oldfieldtype': 'Check',
|
|
||||||
'permlevel': 1
|
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
@ -313,6 +217,61 @@
|
|||||||
'trigger': 'Client'
|
'trigger': 'Client'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'allow_on_submit': 1,
|
||||||
|
'colour': 'White:FFF',
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldname': 'is_active',
|
||||||
|
'fieldtype': 'Select',
|
||||||
|
'hidden': 0,
|
||||||
|
'label': 'Is Active',
|
||||||
|
'no_copy': 1,
|
||||||
|
'oldfieldname': 'is_active',
|
||||||
|
'oldfieldtype': 'Select',
|
||||||
|
'options': '\nYes\nNo',
|
||||||
|
'permlevel': 0,
|
||||||
|
'reqd': 1
|
||||||
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'allow_on_submit': 1,
|
||||||
|
'colour': 'White:FFF',
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldname': 'is_default',
|
||||||
|
'fieldtype': 'Check',
|
||||||
|
'label': 'Is Default',
|
||||||
|
'no_copy': 1,
|
||||||
|
'oldfieldname': 'is_default',
|
||||||
|
'oldfieldtype': 'Check',
|
||||||
|
'permlevel': 0
|
||||||
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldname': 'maintained_by',
|
||||||
|
'fieldtype': 'Data',
|
||||||
|
'label': 'Maintained By',
|
||||||
|
'oldfieldname': 'maintained_by',
|
||||||
|
'oldfieldtype': 'Data',
|
||||||
|
'permlevel': 0
|
||||||
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'colour': 'White:FFF',
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldname': 'remarks',
|
||||||
|
'fieldtype': 'Text',
|
||||||
|
'label': 'Remarks',
|
||||||
|
'no_copy': 1,
|
||||||
|
'oldfieldname': 'remarks',
|
||||||
|
'oldfieldtype': 'Text',
|
||||||
|
'permlevel': 0
|
||||||
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
@ -325,7 +284,7 @@
|
|||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'colour': 'White:FFF',
|
'colour': 'White:FFF',
|
||||||
'description': 'Specify the operations performed and give a unique Operation no to your operations. Select the workstation which is nothing but machinery where this operation would be performed on raw materials. Hour rate will be fetched from the Workstation master. Operation time will be entered manually. Operating cost will be calculated once the Bill of Material is saved.',
|
'description': 'Specify the operations, operating cost and give a unique Operation no to your operations.',
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'bom_operations',
|
'fieldname': 'bom_operations',
|
||||||
'fieldtype': 'Table',
|
'fieldtype': 'Table',
|
||||||
@ -370,92 +329,55 @@
|
|||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'colour': 'White:FFF',
|
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'remarks',
|
'fieldtype': 'Column Break',
|
||||||
'fieldtype': 'Text',
|
'permlevel': 0,
|
||||||
'label': 'Remarks',
|
'width': '50%'
|
||||||
'no_copy': 1,
|
},
|
||||||
'oldfieldname': 'remarks',
|
|
||||||
'oldfieldtype': 'Text',
|
# DocField
|
||||||
|
{
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldname': 'rm_cost_as_per',
|
||||||
|
'fieldtype': 'Select',
|
||||||
|
'label': 'Consider Raw Material Cost As Per',
|
||||||
|
'options': 'Valuation Rate\nLast Purchase Rate\nStandard Rate',
|
||||||
'permlevel': 0
|
'permlevel': 0
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'cost_as_per_mar',
|
'fieldname': 'costing_date',
|
||||||
'fieldtype': 'Currency',
|
'fieldtype': 'Date',
|
||||||
'label': 'Cost As Per Valuation Rate',
|
'label': 'Costing Date',
|
||||||
'oldfieldname': 'cost_as_per_mar',
|
|
||||||
'oldfieldtype': 'Currency',
|
|
||||||
'permlevel': 1
|
'permlevel': 1
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
|
'allow_on_submit': 1,
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'cost_as_per_lpr',
|
'fieldtype': 'Button',
|
||||||
'fieldtype': 'Currency',
|
'label': 'Update Cost as on today',
|
||||||
'label': 'Cost As Per LPR',
|
'options': 'calculate_cost',
|
||||||
'oldfieldname': 'cost_as_per_lpr',
|
'permlevel': 0
|
||||||
'oldfieldtype': 'Currency',
|
|
||||||
'permlevel': 1
|
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'cost_as_per_sr',
|
'fieldtype': 'Column Break',
|
||||||
'fieldtype': 'Currency',
|
'permlevel': 0,
|
||||||
'label': 'Cost As Per SR',
|
'width': '50%'
|
||||||
'oldfieldname': 'cost_as_per_sr',
|
|
||||||
'oldfieldtype': 'Currency',
|
|
||||||
'permlevel': 1
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'colour': 'White:FFF',
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'cost_as_on',
|
|
||||||
'fieldtype': 'Data',
|
|
||||||
'label': 'Cost as on',
|
|
||||||
'oldfieldname': 'cost_as_on',
|
|
||||||
'oldfieldtype': 'Data',
|
|
||||||
'permlevel': 1
|
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'dir_mat_as_per_mar',
|
'fieldname': 'raw_material_cost',
|
||||||
'fieldtype': 'Currency',
|
'fieldtype': 'Float',
|
||||||
'label': 'Direct Material As Per Valuation',
|
'label': 'Raw Material Cost',
|
||||||
'oldfieldname': 'dir_mat_as_per_mar',
|
|
||||||
'oldfieldtype': 'Currency',
|
|
||||||
'permlevel': 1
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'dir_mat_as_per_lpr',
|
|
||||||
'fieldtype': 'Currency',
|
|
||||||
'label': 'Direct Material As Per LPR',
|
|
||||||
'oldfieldname': 'dir_mat_as_per_lpr',
|
|
||||||
'oldfieldtype': 'Currency',
|
|
||||||
'permlevel': 1
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'dir_mat_as_per_sr',
|
|
||||||
'fieldtype': 'Currency',
|
|
||||||
'label': 'Direct Material As Per SR',
|
|
||||||
'oldfieldname': 'dir_mat_as_per_sr',
|
|
||||||
'oldfieldtype': 'Currency',
|
|
||||||
'permlevel': 1
|
'permlevel': 1
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -463,22 +385,18 @@
|
|||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'operating_cost',
|
'fieldname': 'operating_cost',
|
||||||
'fieldtype': 'Currency',
|
'fieldtype': 'Float',
|
||||||
'label': 'Operating Cost',
|
'label': 'Operating Cost',
|
||||||
'oldfieldname': 'operating_cost',
|
|
||||||
'oldfieldtype': 'Currency',
|
|
||||||
'permlevel': 1
|
'permlevel': 1
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'maintained_by',
|
'fieldname': 'total_cost',
|
||||||
'fieldtype': 'Data',
|
'fieldtype': 'Float',
|
||||||
'label': 'Maintained By',
|
'label': 'Total Cost',
|
||||||
'oldfieldname': 'maintained_by',
|
'permlevel': 1
|
||||||
'oldfieldtype': 'Data',
|
|
||||||
'permlevel': 0
|
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
@ -486,19 +404,9 @@
|
|||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldtype': 'Section Break',
|
'fieldtype': 'Section Break',
|
||||||
'hidden': 1,
|
'hidden': 1,
|
||||||
'label': 'BOM Report',
|
'options': 'Simple',
|
||||||
'oldfieldtype': 'Section Break',
|
'permlevel': 0,
|
||||||
'permlevel': 0
|
'print_hide': 0
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldtype': 'Section Break',
|
|
||||||
'hidden': 0,
|
|
||||||
'label': 'Flat BOM',
|
|
||||||
'oldfieldtype': 'Section Break',
|
|
||||||
'permlevel': 0
|
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
@ -508,12 +416,25 @@
|
|||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'flat_bom_details',
|
'fieldname': 'flat_bom_details',
|
||||||
'fieldtype': 'Table',
|
'fieldtype': 'Table',
|
||||||
'hidden': 0,
|
'hidden': 1,
|
||||||
'label': 'Flat BOM Detail',
|
'label': 'Flat BOM Detail',
|
||||||
'no_copy': 1,
|
'no_copy': 1,
|
||||||
'oldfieldname': 'flat_bom_details',
|
'oldfieldname': 'flat_bom_details',
|
||||||
'oldfieldtype': 'Table',
|
'oldfieldtype': 'Table',
|
||||||
'options': 'Flat BOM Detail',
|
'options': 'Flat BOM Detail',
|
||||||
'permlevel': 0
|
'permlevel': 0,
|
||||||
|
'print_hide': 1
|
||||||
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldname': 'trash_reason',
|
||||||
|
'fieldtype': 'Small Text',
|
||||||
|
'hidden': 1,
|
||||||
|
'label': 'Trash Reason',
|
||||||
|
'oldfieldname': 'trash_reason',
|
||||||
|
'oldfieldtype': 'Small Text',
|
||||||
|
'permlevel': 1
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -18,85 +18,87 @@ convert_to_lists = webnotes.conn.convert_to_lists
|
|||||||
|
|
||||||
|
|
||||||
class DocType:
|
class DocType:
|
||||||
def __init__(self, doc, doclist):
|
def __init__(self, doc, doclist):
|
||||||
self.doc = doc
|
self.doc = doc
|
||||||
self.doclist = doclist
|
self.doclist = doclist
|
||||||
|
|
||||||
def get_item_group(self):
|
|
||||||
ret = sql("select name from `tabItem Group` ")
|
|
||||||
item_group = []
|
|
||||||
for r in ret:
|
|
||||||
item =sql("select t1.name from `tabItem` t1, `tabBill Of Materials` t2 where t2.item = t1.name and t1.item_group = '%s' " % (r[0]))
|
|
||||||
if item and item[0][0]:
|
|
||||||
item_group.append(r[0])
|
|
||||||
return '~~~'.join([r for r in item_group])
|
|
||||||
|
|
||||||
def get_item_code(self,item_group):
|
|
||||||
# here Bill Of Materials docstatus = 1 and is_active ='yes' condition is not given because some bom is under construction
|
|
||||||
# that is it is still in saved mode and they want see till where they have reach.
|
|
||||||
ret = sql("select distinct t1.name from `tabItem` t1, `tabBill Of Materials` t2 where t2.item = t1.name and t1.item_group = '%s' " % (item_group))
|
|
||||||
return '~~~'.join([r[0] for r in ret])
|
|
||||||
|
|
||||||
def get_bom_no(self,item_code):
|
|
||||||
ret = sql("select name from `tabBill Of Materials` where item = '%s' " % (item_code))
|
|
||||||
return '~~~'.join([r[0] for r in ret])
|
|
||||||
|
|
||||||
def get_operations(self,bom_no):
|
|
||||||
# reply = [ 'Operation',operation_no, opn_description,BOM NO , workstation, hour_rate, time_in_minutes, Total Direct Material, Total Operating Cost, Cost]
|
|
||||||
# reply = [ 0 , 1 , 2 ,3 , 4 , 5 , 6 , 7 , 8 ,9 , 10 , 11 ]
|
|
||||||
ret = sql("select operation_no,opn_description,workstation,hour_rate,time_in_mins from `tabBOM Operation` where parent = %s", bom_no, as_dict = 1)
|
|
||||||
cost = sql("select dir_mat_as_per_mar , operating_cost , cost_as_per_mar from `tabBill Of Materials` where name = %s", bom_no, as_dict = 1)
|
|
||||||
|
|
||||||
# Validate the BOM ENTRIES
|
|
||||||
#check = get_obj('Bill Of Materials', bom_no, with_children =1).validate()
|
|
||||||
reply = []
|
|
||||||
|
|
||||||
if ret:
|
|
||||||
for r in ret:
|
|
||||||
reply.append(['operation',cint(r['operation_no']), r['opn_description'] or '','%s'% bom_no,r['workstation'],flt(r['hour_rate']),flt(r['time_in_mins']),0,0,0])
|
|
||||||
|
|
||||||
reply[0][7]= flt(cost[0]['dir_mat_as_per_mar'])
|
|
||||||
reply[0][8]=flt(cost[0]['operating_cost'])
|
|
||||||
reply[0][9]=flt(cost[0]['cost_as_per_mar'])
|
|
||||||
return reply
|
|
||||||
|
|
||||||
def get_item_bom(self,data):
|
|
||||||
# reply = ['item_bom',item_code,description, BOM NO , qty, uom , scrap ,m_avg_r or value, 1 or 0]
|
|
||||||
# reply = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ]
|
|
||||||
data = eval(data)
|
|
||||||
reply = []
|
|
||||||
ret = sql("select item_code,description,bom_no,qty,scrap,stock_uom,value_as_per_mar,moving_avg_rate from `tabBOM Material` where parent = '%s' and operation_no = '%s'" % (data['bom_no'],data['op_no']), as_dict =1 )
|
|
||||||
|
|
||||||
for r in ret:
|
|
||||||
item = sql("select is_manufactured_item, is_sub_contracted_item from `tabItem` where name = '%s'" % r['item_code'], as_dict=1)
|
|
||||||
if not item[0]['is_manufactured_item'] == 'Yes' and not item[0]['is_sub_contracted_item'] =='Yes':
|
|
||||||
#msgprint("IS_PURCHASE")
|
|
||||||
#if item is not manufactured or it is not sub-contracted
|
|
||||||
reply.append([ 'item_bom', r['item_code'] or '', r['description'] or '', r['bom_no'] or '', flt(r['qty']) or 0, r['stock_uom'] or '', flt(r['scrap']) or 0, flt(r['moving_avg_rate']) or 0, 1])
|
|
||||||
else:
|
|
||||||
#msgprint("IS_NOT_PURCHASE")
|
|
||||||
# if it is manufactured or sub_contracted this will be considered(here item can be purchase item)
|
|
||||||
reply.append([ 'item_bom', r['item_code'] or '', r['description'] or '', r['bom_no'] or '', flt(r['qty']) or 0, r['stock_uom'] or '', flt(r['scrap']) or 0, flt(r['value_as_per_mar']) or 0, 0])
|
|
||||||
return reply
|
|
||||||
|
|
||||||
|
|
||||||
#------------- Wrapper Code --------------
|
|
||||||
# BOM TREE
|
def get_item_group(self):
|
||||||
def calculate_cost( self, bom_no):
|
ret = sql("select name from `tabItem Group` ")
|
||||||
main_bom_list = get_obj(dt = 'Production Control').traverse_bom_tree( bom_no = bom_no, qty = 1, calculate_cost = 1)
|
item_group = []
|
||||||
main_bom_list.reverse()
|
for r in ret:
|
||||||
for bom in main_bom_list:
|
item =sql("select t1.name from `tabItem` t1, `tabBill Of Materials` t2 where t2.item = t1.name and t1.item_group = '%s' " % (r[0]))
|
||||||
bom_obj = get_obj('Bill Of Materials', bom, with_children = 1)
|
if item and item[0][0]:
|
||||||
bom_obj.calculate_cost(validate = 0)
|
item_group.append(r[0])
|
||||||
bom_obj.doc.save()
|
return '~~~'.join([r for r in item_group])
|
||||||
return 'calculated'
|
|
||||||
|
|
||||||
|
|
||||||
def get_bom_tree_list(self,args):
|
|
||||||
arg = eval(args)
|
def get_item_code(self,item_group):
|
||||||
i =[]
|
""" here Bill Of Materials docstatus = 1 and is_active ='yes' condition is not given because some bom
|
||||||
for a in sql("select t1.name from `tabBill Of Materials` t1, `tabItem` t2 where t2.item_group like '%s' and t1.item like '%s'"%(arg['item_group'] +'%',arg['item_code'] + '%')):
|
is under construction that is it is still in saved mode and they want see till where they have reach.
|
||||||
if a[0] not in i:
|
"""
|
||||||
i.append(a[0])
|
ret = sql("select distinct t1.name from `tabItem` t1, `tabBill Of Materials` t2 where t2.item = t1.name and t1.item_group = '%s' " % (item_group))
|
||||||
return i
|
return '~~~'.join([r[0] for r in ret])
|
||||||
# return [s[0] for s in sql("select t1.name from `tabBill Of Materials` t1, `tabItem` t2 where t2.item_group like '%s' and t1.item like '%s' " %(arg['item_group']+'%',arg['item_code'+'%'])]
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_bom_no(self,item_code):
|
||||||
|
ret = sql("select name from `tabBill Of Materials` where item = '%s' " % (item_code))
|
||||||
|
return '~~~'.join([r[0] for r in ret])
|
||||||
|
|
||||||
|
def get_operations(self,bom_no):
|
||||||
|
ret = sql("select operation_no,opn_description,workstation,hour_rate,time_in_mins from `tabBOM Operation` where parent = %s", bom_no, as_dict = 1)
|
||||||
|
cost = sql("select dir_mat_as_per_mar , operating_cost , cost_as_per_mar from `tabBill Of Materials` where name = %s", bom_no, as_dict = 1)
|
||||||
|
|
||||||
|
# Validate the BOM ENTRIES
|
||||||
|
reply = []
|
||||||
|
|
||||||
|
if ret:
|
||||||
|
for r in ret:
|
||||||
|
reply.append(['operation',cint(r['operation_no']), r['opn_description'] or '','%s'% bom_no,r['workstation'],flt(r['hour_rate']),flt(r['time_in_mins']),0,0,0])
|
||||||
|
|
||||||
|
reply[0][7]= flt(cost[0]['dir_mat_as_per_mar'])
|
||||||
|
reply[0][8]=flt(cost[0]['operating_cost'])
|
||||||
|
reply[0][9]=flt(cost[0]['cost_as_per_mar'])
|
||||||
|
return reply
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_item_bom(self,data):
|
||||||
|
data = eval(data)
|
||||||
|
reply = []
|
||||||
|
ret = sql("select item_code,description,bom_no,qty,scrap,stock_uom,value_as_per_mar,moving_avg_rate from `tabBOM Material` where parent = '%s' and operation_no = '%s'" % (data['bom_no'],data['op_no']), as_dict =1 )
|
||||||
|
|
||||||
|
for r in ret:
|
||||||
|
item = sql("select is_manufactured_item, is_sub_contracted_item from `tabItem` where name = '%s'" % r['item_code'], as_dict=1)
|
||||||
|
if not item[0]['is_manufactured_item'] == 'Yes' and not item[0]['is_sub_contracted_item'] =='Yes':
|
||||||
|
#if item is not manufactured or it is not sub-contracted
|
||||||
|
reply.append([ 'item_bom', r['item_code'] or '', r['description'] or '', r['bom_no'] or '', flt(r['qty']) or 0, r['stock_uom'] or '', flt(r['scrap']) or 0, flt(r['moving_avg_rate']) or 0, 1])
|
||||||
|
else:
|
||||||
|
# if it is manufactured or sub_contracted this will be considered(here item can be purchase item)
|
||||||
|
reply.append([ 'item_bom', r['item_code'] or '', r['description'] or '', r['bom_no'] or '', flt(r['qty']) or 0, r['stock_uom'] or '', flt(r['scrap']) or 0, flt(r['value_as_per_mar']) or 0, 0])
|
||||||
|
return reply
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#------------- Wrapper Code --------------
|
||||||
|
def calculate_cost( self, bom_no):
|
||||||
|
main_bom_list = get_obj(dt = 'Production Control').traverse_bom_tree( bom_no = bom_no, qty = 1, calculate_cost = 1)
|
||||||
|
main_bom_list.reverse()
|
||||||
|
msgprint(main_bom_list)
|
||||||
|
for bom in main_bom_list:
|
||||||
|
bom_obj = get_obj('Bill Of Materials', bom, with_children = 1)
|
||||||
|
bom_obj.calculate_cost()
|
||||||
|
return 'calculated'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_bom_tree_list(self,args):
|
||||||
|
arg = eval(args)
|
||||||
|
i =[]
|
||||||
|
for a in sql("select t1.name from `tabBill Of Materials` t1, `tabItem` t2 where t2.item_group like '%s' and t1.item like '%s'"%(arg['item_group'] +'%',arg['item_code'] + '%')):
|
||||||
|
if a[0] not in i:
|
||||||
|
i.append(a[0])
|
||||||
|
return i
|
||||||
|
|||||||
@ -5,14 +5,15 @@
|
|||||||
{
|
{
|
||||||
'creation': '2010-08-08 17:08:53',
|
'creation': '2010-08-08 17:08:53',
|
||||||
'docstatus': 0,
|
'docstatus': 0,
|
||||||
'modified': '2010-09-20 14:06:57',
|
'modified': '2011-12-27 14:49:54',
|
||||||
'modified_by': 'umair@iwebnotes.com',
|
'modified_by': 'Administrator',
|
||||||
'owner': 'Administrator'
|
'owner': 'Administrator'
|
||||||
},
|
},
|
||||||
|
|
||||||
# These values are common for all DocType
|
# These values are common for all DocType
|
||||||
{
|
{
|
||||||
'colour': 'White:FFF',
|
'colour': 'White:FFF',
|
||||||
|
'default_print_format': 'Standard',
|
||||||
'doctype': 'DocType',
|
'doctype': 'DocType',
|
||||||
'istable': 1,
|
'istable': 1,
|
||||||
'module': 'Production',
|
'module': 'Production',
|
||||||
@ -20,7 +21,7 @@
|
|||||||
'section_style': 'Simple',
|
'section_style': 'Simple',
|
||||||
'server_code_error': ' ',
|
'server_code_error': ' ',
|
||||||
'show_in_menu': 0,
|
'show_in_menu': 0,
|
||||||
'version': 22
|
'version': 26
|
||||||
},
|
},
|
||||||
|
|
||||||
# These values are common for all DocField
|
# These values are common for all DocField
|
||||||
@ -52,7 +53,6 @@
|
|||||||
# DocPerm
|
# DocPerm
|
||||||
{
|
{
|
||||||
'doctype': 'DocPerm',
|
'doctype': 'DocPerm',
|
||||||
'idx': 1,
|
|
||||||
'permlevel': 0,
|
'permlevel': 0,
|
||||||
'write': 1
|
'write': 1
|
||||||
},
|
},
|
||||||
@ -60,7 +60,6 @@
|
|||||||
# DocPerm
|
# DocPerm
|
||||||
{
|
{
|
||||||
'doctype': 'DocPerm',
|
'doctype': 'DocPerm',
|
||||||
'idx': 2,
|
|
||||||
'permlevel': 1
|
'permlevel': 1
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -69,7 +68,6 @@
|
|||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'operation_no',
|
'fieldname': 'operation_no',
|
||||||
'fieldtype': 'Data',
|
'fieldtype': 'Data',
|
||||||
'idx': 1,
|
|
||||||
'label': 'Operation No',
|
'label': 'Operation No',
|
||||||
'oldfieldname': 'operation_no',
|
'oldfieldname': 'operation_no',
|
||||||
'oldfieldtype': 'Data',
|
'oldfieldtype': 'Data',
|
||||||
@ -82,7 +80,6 @@
|
|||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'item_code',
|
'fieldname': 'item_code',
|
||||||
'fieldtype': 'Link',
|
'fieldtype': 'Link',
|
||||||
'idx': 2,
|
|
||||||
'in_filter': 1,
|
'in_filter': 1,
|
||||||
'label': 'Item Code',
|
'label': 'Item Code',
|
||||||
'oldfieldname': 'item_code',
|
'oldfieldname': 'item_code',
|
||||||
@ -99,7 +96,6 @@
|
|||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'bom_no',
|
'fieldname': 'bom_no',
|
||||||
'fieldtype': 'Link',
|
'fieldtype': 'Link',
|
||||||
'idx': 3,
|
|
||||||
'in_filter': 1,
|
'in_filter': 1,
|
||||||
'label': 'BOM No',
|
'label': 'BOM No',
|
||||||
'oldfieldname': 'bom_no',
|
'oldfieldname': 'bom_no',
|
||||||
@ -112,51 +108,11 @@
|
|||||||
'width': '150px'
|
'width': '150px'
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'description',
|
|
||||||
'fieldtype': 'Text',
|
|
||||||
'idx': 4,
|
|
||||||
'label': 'Description',
|
|
||||||
'oldfieldname': 'description',
|
|
||||||
'oldfieldtype': 'Text',
|
|
||||||
'permlevel': 1,
|
|
||||||
'reqd': 0,
|
|
||||||
'width': '300px'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'scrap',
|
|
||||||
'fieldtype': 'Currency',
|
|
||||||
'idx': 6,
|
|
||||||
'label': 'Scrap %',
|
|
||||||
'oldfieldname': 'scrap',
|
|
||||||
'oldfieldtype': 'Currency',
|
|
||||||
'permlevel': 0
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'dir_mat_as_per_mar',
|
|
||||||
'fieldtype': 'Currency',
|
|
||||||
'idx': 8,
|
|
||||||
'label': 'Direct Material As Per Valuation Rate',
|
|
||||||
'oldfieldname': 'dir_mat_as_per_mar',
|
|
||||||
'oldfieldtype': 'Currency',
|
|
||||||
'permlevel': 1,
|
|
||||||
'width': '150px'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'qty',
|
'fieldname': 'qty',
|
||||||
'fieldtype': 'Currency',
|
'fieldtype': 'Float',
|
||||||
'idx': 9,
|
|
||||||
'label': 'Qty',
|
'label': 'Qty',
|
||||||
'oldfieldname': 'qty',
|
'oldfieldname': 'qty',
|
||||||
'oldfieldtype': 'Currency',
|
'oldfieldtype': 'Currency',
|
||||||
@ -165,48 +121,11 @@
|
|||||||
'trigger': 'Client'
|
'trigger': 'Client'
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'dir_mat_as_per_lpr',
|
|
||||||
'fieldtype': 'Currency',
|
|
||||||
'idx': 9,
|
|
||||||
'label': 'Direct Material As Per LPR',
|
|
||||||
'oldfieldname': 'dir_mat_as_per_lpr',
|
|
||||||
'oldfieldtype': 'Currency',
|
|
||||||
'permlevel': 1
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'dir_mat_as_per_sr',
|
|
||||||
'fieldtype': 'Currency',
|
|
||||||
'idx': 10,
|
|
||||||
'label': 'Direct Material As Per SR',
|
|
||||||
'oldfieldname': 'dir_mat_as_per_sr',
|
|
||||||
'oldfieldtype': 'Currency',
|
|
||||||
'permlevel': 1
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'operating_cost',
|
|
||||||
'fieldtype': 'Currency',
|
|
||||||
'idx': 11,
|
|
||||||
'label': 'Operating Cost',
|
|
||||||
'oldfieldname': 'operating_cost',
|
|
||||||
'oldfieldtype': 'Currency',
|
|
||||||
'permlevel': 1
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'stock_uom',
|
'fieldname': 'stock_uom',
|
||||||
'fieldtype': 'Data',
|
'fieldtype': 'Data',
|
||||||
'idx': 12,
|
|
||||||
'label': 'Stock UOM',
|
'label': 'Stock UOM',
|
||||||
'oldfieldname': 'stock_uom',
|
'oldfieldname': 'stock_uom',
|
||||||
'oldfieldtype': 'Data',
|
'oldfieldtype': 'Data',
|
||||||
@ -217,59 +136,18 @@
|
|||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'value_as_per_mar',
|
'fieldname': 'rate',
|
||||||
'fieldtype': 'Currency',
|
'fieldtype': 'Float',
|
||||||
'idx': 12,
|
'label': 'Rate',
|
||||||
'label': 'Value As Per Valuation Rate',
|
'permlevel': 0
|
||||||
'oldfieldname': 'value_as_per_mar',
|
|
||||||
'oldfieldtype': 'Currency',
|
|
||||||
'permlevel': 1,
|
|
||||||
'width': '150px'
|
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'value_as_per_lpr',
|
'fieldname': 'amount',
|
||||||
'fieldtype': 'Currency',
|
'fieldtype': 'Float',
|
||||||
'idx': 13,
|
'label': 'Amount',
|
||||||
'label': 'Value As Per LPR',
|
|
||||||
'oldfieldname': 'value_as_per_lpr',
|
|
||||||
'oldfieldtype': 'Currency',
|
|
||||||
'permlevel': 1
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'value_as_per_sr',
|
|
||||||
'fieldtype': 'Currency',
|
|
||||||
'idx': 14,
|
|
||||||
'label': 'Value As Per SR',
|
|
||||||
'oldfieldname': 'value_as_per_sr',
|
|
||||||
'oldfieldtype': 'Currency',
|
|
||||||
'permlevel': 1
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'moving_avg_rate',
|
|
||||||
'fieldtype': 'Currency',
|
|
||||||
'idx': 15,
|
|
||||||
'label': 'Valuation Rate',
|
|
||||||
'oldfieldname': 'moving_avg_rate',
|
|
||||||
'oldfieldtype': 'Currency',
|
|
||||||
'permlevel': 1
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'amount_as_per_mar',
|
|
||||||
'fieldtype': 'Currency',
|
|
||||||
'idx': 16,
|
|
||||||
'label': 'Amount As Per Valuation Rate',
|
|
||||||
'oldfieldname': 'amount_as_per_mar',
|
'oldfieldname': 'amount_as_per_mar',
|
||||||
'oldfieldtype': 'Currency',
|
'oldfieldtype': 'Currency',
|
||||||
'permlevel': 1,
|
'permlevel': 1,
|
||||||
@ -279,50 +157,26 @@
|
|||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'last_purchase_rate',
|
'fieldname': 'scrap',
|
||||||
'fieldtype': 'Currency',
|
'fieldtype': 'Currency',
|
||||||
'idx': 17,
|
'label': 'Scrap %',
|
||||||
'label': 'Last Purchase Rate',
|
'oldfieldname': 'scrap',
|
||||||
'oldfieldname': 'last_purchase_rate',
|
|
||||||
'oldfieldtype': 'Currency',
|
'oldfieldtype': 'Currency',
|
||||||
'permlevel': 1,
|
'permlevel': 0,
|
||||||
'width': '150px'
|
'print_hide': 1
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'amount_as_per_lpr',
|
'fieldname': 'description',
|
||||||
'fieldtype': 'Currency',
|
'fieldtype': 'Text',
|
||||||
'idx': 18,
|
'label': 'Item Description',
|
||||||
'label': 'Amount As Per LPR',
|
'oldfieldname': 'description',
|
||||||
'oldfieldname': 'amount_as_per_lpr',
|
'oldfieldtype': 'Text',
|
||||||
'oldfieldtype': 'Currency',
|
'permlevel': 0,
|
||||||
'permlevel': 1
|
'reqd': 0,
|
||||||
},
|
'width': '250px'
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'standard_rate',
|
|
||||||
'fieldtype': 'Currency',
|
|
||||||
'idx': 19,
|
|
||||||
'label': 'Standard Rate',
|
|
||||||
'oldfieldname': 'standard_rate',
|
|
||||||
'oldfieldtype': 'Currency',
|
|
||||||
'permlevel': 1
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'amount_as_per_sr',
|
|
||||||
'fieldtype': 'Currency',
|
|
||||||
'idx': 20,
|
|
||||||
'label': 'Amount As Per SR',
|
|
||||||
'oldfieldname': 'amount_as_per_sr',
|
|
||||||
'oldfieldtype': 'Currency',
|
|
||||||
'permlevel': 1
|
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
@ -330,10 +184,11 @@
|
|||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'qty_consumed_per_unit',
|
'fieldname': 'qty_consumed_per_unit',
|
||||||
'fieldtype': 'Float',
|
'fieldtype': 'Float',
|
||||||
'idx': 21,
|
'hidden': 1,
|
||||||
'label': 'Qty Consumed Per Unit',
|
'label': 'Qty Consumed Per Unit',
|
||||||
'oldfieldname': 'qty_consumed_per_unit',
|
'oldfieldname': 'qty_consumed_per_unit',
|
||||||
'oldfieldtype': 'Float',
|
'oldfieldtype': 'Float',
|
||||||
'permlevel': 1
|
'permlevel': 1,
|
||||||
|
'print_hide': 1
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -5,14 +5,15 @@
|
|||||||
{
|
{
|
||||||
'creation': '2010-08-08 17:08:53',
|
'creation': '2010-08-08 17:08:53',
|
||||||
'docstatus': 0,
|
'docstatus': 0,
|
||||||
'modified': '2010-09-20 14:06:57',
|
'modified': '2011-12-28 12:28:02',
|
||||||
'modified_by': 'umair@iwebnotes.com',
|
'modified_by': 'Administrator',
|
||||||
'owner': 'Administrator'
|
'owner': 'Administrator'
|
||||||
},
|
},
|
||||||
|
|
||||||
# These values are common for all DocType
|
# These values are common for all DocType
|
||||||
{
|
{
|
||||||
'colour': 'White:FFF',
|
'colour': 'White:FFF',
|
||||||
|
'default_print_format': 'Standard',
|
||||||
'doctype': 'DocType',
|
'doctype': 'DocType',
|
||||||
'istable': 1,
|
'istable': 1,
|
||||||
'module': 'Production',
|
'module': 'Production',
|
||||||
@ -20,7 +21,7 @@
|
|||||||
'section_style': 'Simple',
|
'section_style': 'Simple',
|
||||||
'server_code_error': ' ',
|
'server_code_error': ' ',
|
||||||
'show_in_menu': 0,
|
'show_in_menu': 0,
|
||||||
'version': 6
|
'version': 8
|
||||||
},
|
},
|
||||||
|
|
||||||
# These values are common for all DocField
|
# These values are common for all DocField
|
||||||
@ -29,7 +30,8 @@
|
|||||||
'name': '__common__',
|
'name': '__common__',
|
||||||
'parent': 'BOM Operation',
|
'parent': 'BOM Operation',
|
||||||
'parentfield': 'fields',
|
'parentfield': 'fields',
|
||||||
'parenttype': 'DocType'
|
'parenttype': 'DocType',
|
||||||
|
'permlevel': 0
|
||||||
},
|
},
|
||||||
|
|
||||||
# These values are common for all DocPerm
|
# These values are common for all DocPerm
|
||||||
@ -52,7 +54,6 @@
|
|||||||
# DocPerm
|
# DocPerm
|
||||||
{
|
{
|
||||||
'doctype': 'DocPerm',
|
'doctype': 'DocPerm',
|
||||||
'idx': 1,
|
|
||||||
'permlevel': 0,
|
'permlevel': 0,
|
||||||
'write': 1
|
'write': 1
|
||||||
},
|
},
|
||||||
@ -60,7 +61,6 @@
|
|||||||
# DocPerm
|
# DocPerm
|
||||||
{
|
{
|
||||||
'doctype': 'DocPerm',
|
'doctype': 'DocPerm',
|
||||||
'idx': 2,
|
|
||||||
'permlevel': 1
|
'permlevel': 1
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -69,11 +69,9 @@
|
|||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'operation_no',
|
'fieldname': 'operation_no',
|
||||||
'fieldtype': 'Data',
|
'fieldtype': 'Data',
|
||||||
'idx': 1,
|
|
||||||
'label': 'Operation No',
|
'label': 'Operation No',
|
||||||
'oldfieldname': 'operation_no',
|
'oldfieldname': 'operation_no',
|
||||||
'oldfieldtype': 'Data',
|
'oldfieldtype': 'Data',
|
||||||
'permlevel': 0,
|
|
||||||
'reqd': 1
|
'reqd': 1
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -82,39 +80,22 @@
|
|||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'opn_description',
|
'fieldname': 'opn_description',
|
||||||
'fieldtype': 'Text',
|
'fieldtype': 'Text',
|
||||||
'idx': 2,
|
|
||||||
'label': 'Opn Description',
|
'label': 'Opn Description',
|
||||||
'oldfieldname': 'opn_description',
|
'oldfieldname': 'opn_description',
|
||||||
'oldfieldtype': 'Text',
|
'oldfieldtype': 'Text',
|
||||||
'permlevel': 0,
|
|
||||||
'reqd': 1
|
'reqd': 1
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'details',
|
|
||||||
'fieldtype': 'Data',
|
|
||||||
'idx': 3,
|
|
||||||
'label': 'Details',
|
|
||||||
'oldfieldname': 'details',
|
|
||||||
'oldfieldtype': 'Data',
|
|
||||||
'permlevel': 0
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'workstation',
|
'fieldname': 'workstation',
|
||||||
'fieldtype': 'Link',
|
'fieldtype': 'Link',
|
||||||
'idx': 4,
|
|
||||||
'label': 'Workstation',
|
'label': 'Workstation',
|
||||||
'oldfieldname': 'workstation',
|
'oldfieldname': 'workstation',
|
||||||
'oldfieldtype': 'Link',
|
'oldfieldtype': 'Link',
|
||||||
'options': 'Workstation',
|
'options': 'Workstation',
|
||||||
'permlevel': 0,
|
'reqd': 0,
|
||||||
'reqd': 1,
|
|
||||||
'search_index': 0,
|
|
||||||
'trigger': 'Client'
|
'trigger': 'Client'
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -123,37 +104,20 @@
|
|||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'hour_rate',
|
'fieldname': 'hour_rate',
|
||||||
'fieldtype': 'Currency',
|
'fieldtype': 'Currency',
|
||||||
'idx': 5,
|
|
||||||
'label': 'Hour Rate',
|
'label': 'Hour Rate',
|
||||||
'oldfieldname': 'hour_rate',
|
'oldfieldname': 'hour_rate',
|
||||||
'oldfieldtype': 'Currency',
|
'oldfieldtype': 'Currency',
|
||||||
'permlevel': 1,
|
|
||||||
'reqd': 0
|
'reqd': 0
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'workstation_capacity',
|
|
||||||
'fieldtype': 'Currency',
|
|
||||||
'hidden': 1,
|
|
||||||
'idx': 6,
|
|
||||||
'label': 'Workstation Capacity',
|
|
||||||
'oldfieldname': 'workstation_capacity',
|
|
||||||
'oldfieldtype': 'Currency',
|
|
||||||
'permlevel': 0
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'time_in_mins',
|
'fieldname': 'time_in_mins',
|
||||||
'fieldtype': 'Currency',
|
'fieldtype': 'Currency',
|
||||||
'idx': 7,
|
|
||||||
'label': 'Operation Time (mins)',
|
'label': 'Operation Time (mins)',
|
||||||
'oldfieldname': 'time_in_mins',
|
'oldfieldname': 'time_in_mins',
|
||||||
'oldfieldtype': 'Currency',
|
'oldfieldtype': 'Currency',
|
||||||
'permlevel': 0,
|
|
||||||
'reqd': 0
|
'reqd': 0
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -163,11 +127,9 @@
|
|||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'operating_cost',
|
'fieldname': 'operating_cost',
|
||||||
'fieldtype': 'Currency',
|
'fieldtype': 'Currency',
|
||||||
'idx': 8,
|
|
||||||
'label': 'Operating Cost',
|
'label': 'Operating Cost',
|
||||||
'oldfieldname': 'operating_cost',
|
'oldfieldname': 'operating_cost',
|
||||||
'oldfieldtype': 'Currency',
|
'oldfieldtype': 'Currency',
|
||||||
'permlevel': 1,
|
|
||||||
'reqd': 0
|
'reqd': 0
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -5,7 +5,7 @@
|
|||||||
{
|
{
|
||||||
'creation': '2010-08-08 17:09:02',
|
'creation': '2010-08-08 17:09:02',
|
||||||
'docstatus': 0,
|
'docstatus': 0,
|
||||||
'modified': '2011-11-10 14:21:40',
|
'modified': '2012-01-11 14:32:31',
|
||||||
'modified_by': 'Administrator',
|
'modified_by': 'Administrator',
|
||||||
'owner': 'jai@webnotestech.com'
|
'owner': 'jai@webnotestech.com'
|
||||||
},
|
},
|
||||||
@ -23,7 +23,7 @@
|
|||||||
'section_style': 'Simple',
|
'section_style': 'Simple',
|
||||||
'server_code_error': ' ',
|
'server_code_error': ' ',
|
||||||
'show_in_menu': 0,
|
'show_in_menu': 0,
|
||||||
'version': 18
|
'version': 24
|
||||||
},
|
},
|
||||||
|
|
||||||
# These values are common for all DocField
|
# These values are common for all DocField
|
||||||
@ -64,51 +64,11 @@
|
|||||||
'width': '300px'
|
'width': '300px'
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'moving_avg_rate',
|
|
||||||
'fieldtype': 'Currency',
|
|
||||||
'label': 'Valuation Rate',
|
|
||||||
'oldfieldname': 'moving_avg_rate',
|
|
||||||
'oldfieldtype': 'Currency'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'amount_as_per_mar',
|
|
||||||
'fieldtype': 'Currency',
|
|
||||||
'label': 'Amount As Per Valuation Rate',
|
|
||||||
'oldfieldname': 'amount_as_per_mar',
|
|
||||||
'oldfieldtype': 'Currency'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'last_purchase_rate',
|
|
||||||
'fieldtype': 'Currency',
|
|
||||||
'label': 'Last Purchase Rate',
|
|
||||||
'oldfieldname': 'last_purchase_rate',
|
|
||||||
'oldfieldtype': 'Currency'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'amount_as_per_lpr',
|
|
||||||
'fieldtype': 'Currency',
|
|
||||||
'label': 'Amount As Per LPR',
|
|
||||||
'oldfieldname': 'amount_as_per_lpr',
|
|
||||||
'oldfieldtype': 'Currency'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'qty',
|
'fieldname': 'qty',
|
||||||
'fieldtype': 'Currency',
|
'fieldtype': 'Float',
|
||||||
'label': 'Qty',
|
'label': 'Qty',
|
||||||
'oldfieldname': 'qty',
|
'oldfieldname': 'qty',
|
||||||
'oldfieldtype': 'Currency'
|
'oldfieldtype': 'Currency'
|
||||||
@ -117,9 +77,9 @@
|
|||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'standard_rate',
|
'fieldname': 'rate',
|
||||||
'fieldtype': 'Currency',
|
'fieldtype': 'Float',
|
||||||
'label': 'Standard Rate',
|
'label': 'Rate',
|
||||||
'oldfieldname': 'standard_rate',
|
'oldfieldname': 'standard_rate',
|
||||||
'oldfieldtype': 'Currency'
|
'oldfieldtype': 'Currency'
|
||||||
},
|
},
|
||||||
@ -127,23 +87,13 @@
|
|||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'amount_as_per_sr',
|
'fieldname': 'amount',
|
||||||
'fieldtype': 'Currency',
|
'fieldtype': 'Float',
|
||||||
'label': 'Amount As Per SR',
|
'label': 'Amount',
|
||||||
'oldfieldname': 'amount_as_per_sr',
|
'oldfieldname': 'amount_as_per_sr',
|
||||||
'oldfieldtype': 'Currency'
|
'oldfieldtype': 'Currency'
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'qty_consumed_per_unit',
|
|
||||||
'fieldtype': 'Float',
|
|
||||||
'label': 'Qty Consumed Per Unit',
|
|
||||||
'oldfieldname': 'qty_consumed_per_unit',
|
|
||||||
'oldfieldtype': 'Float'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
@ -155,28 +105,6 @@
|
|||||||
'options': 'UOM'
|
'options': 'UOM'
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'flat_bom_no',
|
|
||||||
'fieldtype': 'Data',
|
|
||||||
'hidden': 1,
|
|
||||||
'label': 'Flat BOM No',
|
|
||||||
'oldfieldname': 'flat_bom_no',
|
|
||||||
'oldfieldtype': 'Data'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'bom_mat_no',
|
|
||||||
'fieldtype': 'Data',
|
|
||||||
'hidden': 0,
|
|
||||||
'label': 'BOM Mat No',
|
|
||||||
'oldfieldname': 'bom_mat_no',
|
|
||||||
'oldfieldtype': 'Data'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
@ -185,18 +113,26 @@
|
|||||||
'hidden': 0,
|
'hidden': 0,
|
||||||
'label': 'Parent BOM',
|
'label': 'Parent BOM',
|
||||||
'oldfieldname': 'parent_bom',
|
'oldfieldname': 'parent_bom',
|
||||||
'oldfieldtype': 'Link'
|
'oldfieldtype': 'Link',
|
||||||
|
'width': '250px'
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'is_pro_applicable',
|
'fieldname': 'mat_detail_no',
|
||||||
'fieldtype': 'Select',
|
'fieldtype': 'Data',
|
||||||
'label': 'Is PRO Applicable',
|
'hidden': 1,
|
||||||
'oldfieldname': 'is_pro_applicable',
|
'label': 'Mat Detail No'
|
||||||
'oldfieldtype': 'Select',
|
},
|
||||||
'options': '\nYes\nNo',
|
|
||||||
'reqd': 0
|
# DocField
|
||||||
|
{
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldname': 'qty_consumed_per_unit',
|
||||||
|
'fieldtype': 'Float',
|
||||||
|
'hidden': 0,
|
||||||
|
'label': 'Qty Consumed Per Unit',
|
||||||
|
'no_copy': 0
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -5,8 +5,8 @@
|
|||||||
{
|
{
|
||||||
'creation': '2010-08-08 17:09:12',
|
'creation': '2010-08-08 17:09:12',
|
||||||
'docstatus': 0,
|
'docstatus': 0,
|
||||||
'modified': '2010-09-20 14:06:57',
|
'modified': '2012-01-09 16:25:13',
|
||||||
'modified_by': 'umair@iwebnotes.com',
|
'modified_by': 'Administrator',
|
||||||
'owner': 'Administrator'
|
'owner': 'Administrator'
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -14,6 +14,7 @@
|
|||||||
{
|
{
|
||||||
'autoname': 'PPID/.#####',
|
'autoname': 'PPID/.#####',
|
||||||
'colour': 'White:FFF',
|
'colour': 'White:FFF',
|
||||||
|
'default_print_format': 'Standard',
|
||||||
'doctype': 'DocType',
|
'doctype': 'DocType',
|
||||||
'istable': 1,
|
'istable': 1,
|
||||||
'module': 'Production',
|
'module': 'Production',
|
||||||
@ -21,7 +22,7 @@
|
|||||||
'section_style': 'Simple',
|
'section_style': 'Simple',
|
||||||
'server_code_error': ' ',
|
'server_code_error': ' ',
|
||||||
'show_in_menu': 0,
|
'show_in_menu': 0,
|
||||||
'version': 21
|
'version': 27
|
||||||
},
|
},
|
||||||
|
|
||||||
# These values are common for all DocField
|
# These values are common for all DocField
|
||||||
@ -42,97 +43,28 @@
|
|||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'source_doctype',
|
'fieldname': 'sales_order',
|
||||||
'fieldtype': 'Data',
|
'fieldtype': 'Data',
|
||||||
'idx': 1,
|
'label': 'Sales Order',
|
||||||
'label': 'Against Document ',
|
|
||||||
'oldfieldname': 'source_doctype',
|
|
||||||
'oldfieldtype': 'Data',
|
|
||||||
'permlevel': 1
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'source_docname',
|
|
||||||
'fieldtype': 'Data',
|
|
||||||
'idx': 2,
|
|
||||||
'label': 'Document No',
|
|
||||||
'oldfieldname': 'source_docname',
|
'oldfieldname': 'source_docname',
|
||||||
'oldfieldtype': 'Data',
|
'oldfieldtype': 'Data',
|
||||||
'permlevel': 1
|
'permlevel': 1
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'source_detail_docname',
|
|
||||||
'fieldtype': 'Data',
|
|
||||||
'hidden': 1,
|
|
||||||
'idx': 3,
|
|
||||||
'label': 'Document Detail No',
|
|
||||||
'oldfieldname': 'source_detail_docname',
|
|
||||||
'oldfieldtype': 'Data',
|
|
||||||
'permlevel': 1
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'parent_item',
|
|
||||||
'fieldtype': 'Link',
|
|
||||||
'idx': 4,
|
|
||||||
'label': 'Parent Item',
|
|
||||||
'oldfieldname': 'parent_item',
|
|
||||||
'oldfieldtype': 'Link',
|
|
||||||
'options': 'Item',
|
|
||||||
'permlevel': 1
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'colour': 'White:FFF',
|
'colour': 'White:FFF',
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'item_code',
|
'fieldname': 'item_code',
|
||||||
'fieldtype': 'Link',
|
'fieldtype': 'Link',
|
||||||
'idx': 5,
|
|
||||||
'label': 'Item Code',
|
'label': 'Item Code',
|
||||||
'oldfieldname': 'item_code',
|
'oldfieldname': 'item_code',
|
||||||
'oldfieldtype': 'Link',
|
'oldfieldtype': 'Link',
|
||||||
'options': 'Item',
|
'options': 'Item',
|
||||||
'permlevel': 0,
|
'permlevel': 0,
|
||||||
'trigger': 'Client'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'document_date',
|
|
||||||
'fieldtype': 'Date',
|
|
||||||
'idx': 6,
|
|
||||||
'in_filter': 1,
|
|
||||||
'label': 'Document Date',
|
|
||||||
'oldfieldname': 'document_date',
|
|
||||||
'oldfieldtype': 'Date',
|
|
||||||
'permlevel': 0,
|
|
||||||
'search_index': 1,
|
|
||||||
'width': '150px'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'confirmation_date',
|
|
||||||
'fieldtype': 'Date',
|
|
||||||
'idx': 7,
|
|
||||||
'in_filter': 1,
|
|
||||||
'label': 'Confirmed Delivery Date',
|
|
||||||
'oldfieldname': 'confirmation_date',
|
|
||||||
'oldfieldtype': 'Date',
|
|
||||||
'permlevel': 0,
|
|
||||||
'reqd': 1,
|
'reqd': 1,
|
||||||
'search_index': 0,
|
'trigger': 'Client',
|
||||||
'width': '100px'
|
'width': '150px'
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
@ -140,37 +72,22 @@
|
|||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'bom_no',
|
'fieldname': 'bom_no',
|
||||||
'fieldtype': 'Link',
|
'fieldtype': 'Link',
|
||||||
'idx': 8,
|
|
||||||
'label': 'BOM No',
|
'label': 'BOM No',
|
||||||
'oldfieldname': 'bom_no',
|
'oldfieldname': 'bom_no',
|
||||||
'oldfieldtype': 'Link',
|
'oldfieldtype': 'Link',
|
||||||
'options': 'Bill Of Materials',
|
'options': 'Bill Of Materials',
|
||||||
'permlevel': 0,
|
'permlevel': 0,
|
||||||
'search_index': 0,
|
'reqd': 1,
|
||||||
'width': '100px'
|
'width': '100px'
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'description',
|
|
||||||
'fieldtype': 'Text',
|
|
||||||
'idx': 9,
|
|
||||||
'label': 'Description',
|
|
||||||
'oldfieldname': 'description',
|
|
||||||
'oldfieldtype': 'Text',
|
|
||||||
'permlevel': 1,
|
|
||||||
'width': '300px'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'default': '0.00',
|
'default': '0.00',
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'prevdoc_reqd_qty',
|
'fieldname': 'so_pending_qty',
|
||||||
'fieldtype': 'Currency',
|
'fieldtype': 'Currency',
|
||||||
'idx': 11,
|
'label': 'SO Pending Qty',
|
||||||
'label': 'Total Reqd Qty',
|
|
||||||
'oldfieldname': 'prevdoc_reqd_qty',
|
'oldfieldname': 'prevdoc_reqd_qty',
|
||||||
'oldfieldtype': 'Currency',
|
'oldfieldtype': 'Currency',
|
||||||
'permlevel': 1,
|
'permlevel': 1,
|
||||||
@ -178,72 +95,65 @@
|
|||||||
'width': '100px'
|
'width': '100px'
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'stock_uom',
|
|
||||||
'fieldtype': 'Data',
|
|
||||||
'idx': 12,
|
|
||||||
'label': 'Stock UOM',
|
|
||||||
'oldfieldname': 'stock_uom',
|
|
||||||
'oldfieldtype': 'Data',
|
|
||||||
'permlevel': 1,
|
|
||||||
'reqd': 1
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'default': '0.00',
|
'default': '0.00',
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'planned_qty',
|
'fieldname': 'planned_qty',
|
||||||
'fieldtype': 'Currency',
|
'fieldtype': 'Currency',
|
||||||
'idx': 12,
|
'label': 'Planned Qty',
|
||||||
'label': 'Planned Quantity',
|
|
||||||
'oldfieldname': 'planned_qty',
|
'oldfieldname': 'planned_qty',
|
||||||
'oldfieldtype': 'Currency',
|
'oldfieldtype': 'Currency',
|
||||||
'permlevel': 0,
|
'permlevel': 0,
|
||||||
'reqd': 1,
|
'reqd': 1,
|
||||||
'width': '180px'
|
'width': '100px'
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'default': '0.00',
|
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'produced_qty',
|
'fieldname': 'stock_uom',
|
||||||
'fieldtype': 'Currency',
|
'fieldtype': 'Data',
|
||||||
'hidden': 1,
|
'label': 'UOM',
|
||||||
'idx': 13,
|
'oldfieldname': 'stock_uom',
|
||||||
'label': 'Produced Qty',
|
'oldfieldtype': 'Data',
|
||||||
'oldfieldname': 'produced_qty',
|
|
||||||
'oldfieldtype': 'Currency',
|
|
||||||
'permlevel': 1,
|
'permlevel': 1,
|
||||||
'width': '130px'
|
'reqd': 1,
|
||||||
|
'width': '80px'
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'pro_created',
|
'fieldname': 'description',
|
||||||
'fieldtype': 'Check',
|
'fieldtype': 'Text',
|
||||||
'idx': 14,
|
'label': 'Description',
|
||||||
'label': 'PRO Created',
|
'oldfieldname': 'description',
|
||||||
'oldfieldname': 'pro_created',
|
'oldfieldtype': 'Text',
|
||||||
'oldfieldtype': 'Check',
|
'permlevel': 1,
|
||||||
|
'width': '200px'
|
||||||
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldname': 'parent_packing_item',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'label': 'Parent Packing Item',
|
||||||
|
'oldfieldname': 'parent_item',
|
||||||
|
'oldfieldtype': 'Link',
|
||||||
|
'options': 'Item',
|
||||||
'permlevel': 1
|
'permlevel': 1
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'mrp',
|
'fieldname': 'is_pro_created',
|
||||||
'fieldtype': 'Check',
|
'fieldtype': 'Check',
|
||||||
'hidden': 1,
|
'label': 'Is PRO Created',
|
||||||
'idx': 15,
|
'oldfieldname': 'pro_created',
|
||||||
'label': 'Already MRP Considered',
|
|
||||||
'oldfieldname': 'mrp',
|
|
||||||
'oldfieldtype': 'Check',
|
'oldfieldtype': 'Check',
|
||||||
'permlevel': 1,
|
'permlevel': 1
|
||||||
'width': '140px'
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -5,8 +5,8 @@
|
|||||||
{
|
{
|
||||||
'creation': '2010-08-08 17:09:13',
|
'creation': '2010-08-08 17:09:13',
|
||||||
'docstatus': 0,
|
'docstatus': 0,
|
||||||
'modified': '2010-09-20 14:06:57',
|
'modified': '2012-01-09 17:41:37',
|
||||||
'modified_by': 'umair@iwebnotes.com',
|
'modified_by': 'Administrator',
|
||||||
'owner': 'Administrator'
|
'owner': 'Administrator'
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -14,6 +14,7 @@
|
|||||||
{
|
{
|
||||||
'autoname': 'PP/.SO/.#####',
|
'autoname': 'PP/.SO/.#####',
|
||||||
'colour': 'White:FFF',
|
'colour': 'White:FFF',
|
||||||
|
'default_print_format': 'Standard',
|
||||||
'doctype': 'DocType',
|
'doctype': 'DocType',
|
||||||
'istable': 1,
|
'istable': 1,
|
||||||
'module': 'Production',
|
'module': 'Production',
|
||||||
@ -21,7 +22,7 @@
|
|||||||
'section_style': 'Simple',
|
'section_style': 'Simple',
|
||||||
'server_code_error': ' ',
|
'server_code_error': ' ',
|
||||||
'show_in_menu': 0,
|
'show_in_menu': 0,
|
||||||
'version': 2
|
'version': 5
|
||||||
},
|
},
|
||||||
|
|
||||||
# These values are common for all DocField
|
# These values are common for all DocField
|
||||||
@ -33,70 +34,31 @@
|
|||||||
'parenttype': 'DocType'
|
'parenttype': 'DocType'
|
||||||
},
|
},
|
||||||
|
|
||||||
# These values are common for all DocPerm
|
|
||||||
{
|
|
||||||
'doctype': 'DocPerm',
|
|
||||||
'name': '__common__',
|
|
||||||
'parent': 'PP SO Detail',
|
|
||||||
'parentfield': 'permissions',
|
|
||||||
'parenttype': 'DocType',
|
|
||||||
'read': 1,
|
|
||||||
'role': 'System Manager'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocType, PP SO Detail
|
# DocType, PP SO Detail
|
||||||
{
|
{
|
||||||
'doctype': 'DocType',
|
'doctype': 'DocType',
|
||||||
'name': 'PP SO Detail'
|
'name': 'PP SO Detail'
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocPerm
|
|
||||||
{
|
|
||||||
'doctype': 'DocPerm',
|
|
||||||
'idx': 1,
|
|
||||||
'permlevel': 0,
|
|
||||||
'write': 1
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocPerm
|
|
||||||
{
|
|
||||||
'doctype': 'DocPerm',
|
|
||||||
'idx': 2,
|
|
||||||
'permlevel': 1
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'prevdoc',
|
'fieldname': 'sales_order',
|
||||||
'fieldtype': 'Data',
|
'fieldtype': 'Link',
|
||||||
'idx': 1,
|
'label': 'Sales Order',
|
||||||
'label': 'Against Document',
|
|
||||||
'oldfieldname': 'prevdoc',
|
|
||||||
'oldfieldtype': 'Data',
|
|
||||||
'permlevel': 0
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'prevdoc_docname',
|
|
||||||
'fieldtype': 'Data',
|
|
||||||
'idx': 2,
|
|
||||||
'label': 'Document No',
|
|
||||||
'oldfieldname': 'prevdoc_docname',
|
'oldfieldname': 'prevdoc_docname',
|
||||||
'oldfieldtype': 'Data',
|
'oldfieldtype': 'Data',
|
||||||
'permlevel': 1,
|
'options': 'Sales Order',
|
||||||
|
'permlevel': 0,
|
||||||
'width': '150px'
|
'width': '150px'
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'document_date',
|
'fieldname': 'sales_order_date',
|
||||||
'fieldtype': 'Date',
|
'fieldtype': 'Date',
|
||||||
'idx': 3,
|
'label': 'Sales Order Date',
|
||||||
'label': 'Document Date',
|
|
||||||
'oldfieldname': 'document_date',
|
'oldfieldname': 'document_date',
|
||||||
'oldfieldtype': 'Date',
|
'oldfieldtype': 'Date',
|
||||||
'permlevel': 1,
|
'permlevel': 1,
|
||||||
@ -106,12 +68,20 @@
|
|||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'confirmation_date',
|
'fieldname': 'customer',
|
||||||
'fieldtype': 'Date',
|
'fieldtype': 'Link',
|
||||||
'idx': 5,
|
'label': 'Customer',
|
||||||
'label': 'Confirmation Date',
|
'options': 'Customer',
|
||||||
'oldfieldname': 'confirmation_date',
|
'permlevel': 1,
|
||||||
'oldfieldtype': 'Date',
|
'width': '150px'
|
||||||
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldname': 'grand_total',
|
||||||
|
'fieldtype': 'Currency',
|
||||||
|
'label': 'Grand Total',
|
||||||
'permlevel': 1,
|
'permlevel': 1,
|
||||||
'width': '100px'
|
'width': '100px'
|
||||||
},
|
},
|
||||||
@ -121,7 +91,6 @@
|
|||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'include_in_plan',
|
'fieldname': 'include_in_plan',
|
||||||
'fieldtype': 'Check',
|
'fieldtype': 'Check',
|
||||||
'idx': 6,
|
|
||||||
'label': 'Include In Plan',
|
'label': 'Include In Plan',
|
||||||
'oldfieldname': 'include_in_plan',
|
'oldfieldname': 'include_in_plan',
|
||||||
'oldfieldtype': 'Check',
|
'oldfieldtype': 'Check',
|
||||||
|
|||||||
@ -18,138 +18,82 @@ convert_to_lists = webnotes.conn.convert_to_lists
|
|||||||
|
|
||||||
|
|
||||||
class DocType:
|
class DocType:
|
||||||
def __init__( self, doc, doclist=[]):
|
def __init__( self, doc, doclist=[]):
|
||||||
self.doc = doc
|
self.doc = doc
|
||||||
self.doclist = doclist
|
self.doclist = doclist
|
||||||
# pur_items = {'item_code':req_qty}
|
self.pur_items = {}
|
||||||
self.pur_items = {}
|
self.bom_list = []
|
||||||
# bom_list = [[]]
|
self.sub_assembly_items = []
|
||||||
self.bom_list = []
|
self.item_master = {}
|
||||||
# list for sub assembly item
|
|
||||||
self.sub_assembly_items = []
|
|
||||||
# Item Master
|
|
||||||
self.item_master = {}
|
|
||||||
|
|
||||||
def traverse_bom_tree( self, bom_no, qty, ext_pur_items = 0, ext_sub_assembly_items = 0, calculate_cost = 0, maintain_item_master = 0 ):
|
def traverse_bom_tree( self, bom_no, qty, ext_pur_items = 0, ext_sub_assembly_items = 0, calculate_cost = 0, maintain_item_master = 0 ):
|
||||||
count, bom_list, qty_list = 0, [bom_no], [qty]
|
count, bom_list, qty_list = 0, [bom_no], [qty]
|
||||||
while (count < len(bom_list)):
|
while (count < len(bom_list)):
|
||||||
# get child items from BOM MAterial Table.
|
# get child items from BOM MAterial Table.
|
||||||
child_items = sql("select item_code, bom_no, qty, qty_consumed_per_unit from `tabBOM Material` where parent = %s", bom_list[count], as_dict = 1)
|
child_items = sql("select item_code, bom_no, qty, qty_consumed_per_unit from `tabBOM Material` where parent = %s", bom_list[count], as_dict = 1)
|
||||||
child_items = child_items and child_items or []
|
child_items = child_items and child_items or []
|
||||||
#msgprint(bom_list[count])
|
for item in child_items:
|
||||||
#msgprint(qty_list)
|
# Calculate qty required for FG's qty.
|
||||||
for item in child_items:
|
item['reqd_qty'] = flt(qty) * ((count == 0) and 1 or flt(qty_list[count]) )* flt(item['qty_consumed_per_unit'])
|
||||||
# Calculate qty required for FG's qty.
|
|
||||||
item['reqd_qty'] = flt(qty) * ((count == 0) and 1 or flt(qty_list[count]) )* flt(item['qty_consumed_per_unit'])
|
|
||||||
#gprint("Item Reqd : " + cstr(item['reqd_qty']))
|
|
||||||
|
|
||||||
# extracting Purchase Items
|
# extracting Purchase Items
|
||||||
if ext_pur_items and not item['bom_no']:
|
if ext_pur_items and not item['bom_no']:
|
||||||
# item exist in pur_items dict then just add qty with previous qty
|
self.pur_items[item['item_code']] = flt(self.pur_items.get(item['item_code'], 0)) + flt(item['reqd_qty'])
|
||||||
if self.pur_items.has_key(item['item_code']):
|
|
||||||
self.pur_items[item['item_code']] = flt(self.pur_items[item['item_code']]) + flt(item['reqd_qty'])
|
|
||||||
# maintain item master
|
|
||||||
#if maintain_item_master:
|
|
||||||
|
|
||||||
# else add item in pur_item dict with reqd qty.
|
# For calculate cost extracting BOM Items check for duplicate boms, this optmizes the time complexity for while loop.
|
||||||
else:
|
if calculate_cost and item['bom_no'] and (item['bom_no'] not in bom_list):
|
||||||
self.pur_items[item['item_code']] = flt(item['reqd_qty'])
|
bom_list.append(item['bom_no'])
|
||||||
# maintain item master
|
qty_list.append(item['reqd_qty'])
|
||||||
#if maintain_item_master:
|
|
||||||
|
|
||||||
# For calculate cost extracting BOM Items check for duplicate boms, this optmizes the time complexity for while loop.
|
# Here repeated bom are considered to calculate total qty of raw material required
|
||||||
if calculate_cost and item['bom_no'] and (item['bom_no'] not in bom_list):
|
if not calculate_cost and item['bom_no']:
|
||||||
bom_list.append(item['bom_no'])
|
bom_list.append(item['bom_no'])
|
||||||
qty_list.append(item['reqd_qty'])
|
qty_list.append(item['reqd_qty'])
|
||||||
|
|
||||||
# Here repeated bom are considered to calculate total qty of raw material required
|
count += 1
|
||||||
if not calculate_cost and item['bom_no']:
|
return bom_list
|
||||||
# append bom to bom_list
|
|
||||||
bom_list.append(item['bom_no'])
|
|
||||||
qty_list.append(item['reqd_qty'])
|
|
||||||
|
|
||||||
# # extracting Sub Assembly Items . Make Sure Sub Assembly Items have BOM No. in BOM MATERIAL
|
|
||||||
# if ext_sub_assembly_items:
|
|
||||||
# # If Production Order Applicable is 'Yes'
|
|
||||||
# if item['pro_applicable#'] == "Yes":
|
|
||||||
# # append item in sub_assembly_items
|
|
||||||
# self.sub_assembly_items.append([item['item_code']])
|
|
||||||
# # Remove current bom from bom_list
|
|
||||||
# bom_list.pop()
|
|
||||||
|
|
||||||
count += 1
|
|
||||||
return bom_list
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Raise Production Order
|
# Raise Production Order
|
||||||
def create_production_order(self,company, fy, pp_detail = '', pro_detail = ''):
|
def create_production_order(self,company, pp_items):
|
||||||
pro_lbl = {'production_item': 0, 'description': 1, 'qty' : 2, 'stock_uom' : 3, 'bom_no': 4, 'consider_sa_items': 5}
|
"""Create production order. Called from Production Planning Tool"""
|
||||||
|
|
||||||
default_values = { 'transaction_date' : now(),
|
default_values = {
|
||||||
'origin' : pp_detail and 'MRP' or 'Direct',
|
'posting_date' : nowdate(),
|
||||||
'wip_warehouse' : 'MB1-Stores',
|
'origin' : 'MRP',
|
||||||
'status' : 'Draft',
|
'wip_warehouse' : '',
|
||||||
'company' : company,
|
'fg_warehouse' : '',
|
||||||
'fiscal_year' : fy }
|
'status' : 'Draft',
|
||||||
|
'company' : company,
|
||||||
|
'fiscal_year' : get_defaults()['fiscal_year']
|
||||||
|
}
|
||||||
|
pro_list = []
|
||||||
|
|
||||||
pro_list, count = pp_detail and pp_detail or pro_detail, 0
|
for d in pp_items:
|
||||||
|
pro_doc = Document('Production Order')
|
||||||
|
for key in d.keys():
|
||||||
|
pro_doc.fields[key] = d[key]
|
||||||
|
|
||||||
while (count < len(pro_list)):
|
for key in default_values:
|
||||||
pro_doc = Document('Production Order')
|
pro_doc.fields[key] = default_values[key]
|
||||||
|
|
||||||
for key in pro_lbl.keys():
|
pro_doc.save(new = 1)
|
||||||
pro_doc.fields[key] = pro_list[count][pro_lbl[key]]
|
pro_list.append(pro_doc.name)
|
||||||
|
|
||||||
for key in default_values:
|
return pro_list
|
||||||
pro_doc.fields[key] = default_values[key]
|
|
||||||
|
|
||||||
pro_doc.save(new = 1)
|
|
||||||
pro_list[count] = pro_doc.name
|
|
||||||
|
|
||||||
# This was for adding raw materials in pro detail and get sa items
|
|
||||||
#sa_list = get_obj('Porduction Order', pro_doc.name, with_children = 1).get_purchase_item( get_sa_items = 1, add_child= 1)
|
|
||||||
#for sa_item in sa_list:
|
|
||||||
# pro_list.append(sa_item)
|
|
||||||
|
|
||||||
count = count + 1
|
|
||||||
return pro_list
|
|
||||||
|
|
||||||
|
|
||||||
def update_bom(self, bom_no):
|
def update_bom(self, bom_no):
|
||||||
main_bom_list = self.traverse_bom_tree(bom_no, 1)
|
main_bom_list = self.traverse_bom_tree(bom_no, 1)
|
||||||
main_bom_list.reverse()
|
main_bom_list.reverse()
|
||||||
#print('--------------')
|
# run calculate cost and get
|
||||||
msgprint(main_bom_list)
|
for bom in main_bom_list:
|
||||||
#print('--------------')
|
if bom and bom not in self.check_bom_list:
|
||||||
# run calculate cost and get
|
bom_obj = get_obj('Bill Of Materials', bom, with_children = 1)
|
||||||
for bom in main_bom_list:
|
bom_obj.doc.save()
|
||||||
if bom and bom not in self.check_bom_list:
|
bom_obj.check_recursion()
|
||||||
#print(bom)
|
bom_obj.update_flat_bom_engine()
|
||||||
bom_obj = get_obj('Bill Of Materials', bom, with_children = 1)
|
bom_obj.doc.docstatus = 1
|
||||||
#print(bom_obj.doc.fields)
|
bom_obj.doc.save()
|
||||||
bom_obj.doc.save()
|
self.check_bom_list.append(bom)
|
||||||
bom_obj.check_recursion()
|
|
||||||
bom_obj.update_flat_bom_engine()
|
|
||||||
bom_obj.doc.docstatus = 1
|
|
||||||
bom_obj.doc.save()
|
|
||||||
self.check_bom_list.append(bom)
|
|
||||||
#errprint(" " + cstr(bom) + " has been submitted successfully.")
|
|
||||||
|
|
||||||
|
|
||||||
def update_all_fg(self):
|
|
||||||
self.check_bom_list = []
|
|
||||||
#pc_obj = get_obj(dt = 'Production Control')
|
|
||||||
cn_bom = sql("select name from `tabBill Of Materials` where item not like 'CN%' and item not like 'LDR%' and item not like 'HD%' limit 1")
|
|
||||||
#cn_bom = (('BOM/A012629/001',),)
|
|
||||||
i=1
|
|
||||||
#msgprint(cn_bom)
|
|
||||||
for d in cn_bom:
|
|
||||||
if not cstr(d[0]) in self.check_bom_list:
|
|
||||||
print('Main BOM')
|
|
||||||
msgprint(d[0])
|
|
||||||
msgprint(i)
|
|
||||||
#sql("start transaction")
|
|
||||||
#self.update_bom(d[0])
|
|
||||||
#sql("commit")
|
|
||||||
i += 1
|
|
||||||
|
|||||||
@ -1,101 +1,70 @@
|
|||||||
$import(Production Tips Common)
|
|
||||||
|
|
||||||
cur_frm.cscript.onload = function(doc, cdt, cdn) {
|
cur_frm.cscript.onload = function(doc, dt, dn) {
|
||||||
|
if (!doc.posting_date) doc.transaction_date = dateutil.obj_to_str(new Date());
|
||||||
|
|
||||||
|
|
||||||
if (!doc.fiscal_year && doc.__islocal){ set_default_values(doc);}
|
|
||||||
if (!doc.transaction_date) doc.transaction_date = dateutil.obj_to_str(new Date());
|
|
||||||
if (!doc.status) doc.status = 'Draft';
|
if (!doc.status) doc.status = 'Draft';
|
||||||
cfn_set_fields(doc, cdt, cdn);
|
|
||||||
|
cfn_set_fields(doc, dt, dn);
|
||||||
|
|
||||||
if (doc.origin != "MRP"){
|
if (doc.origin != "MRP"){
|
||||||
doc.origin = "Manual";
|
doc.origin = "Manual";
|
||||||
//get_field('Production Order', 'consider_sa_items').permlevel = 0;
|
|
||||||
set_field_permlevel('production_item', 0);
|
set_field_permlevel('production_item', 0);
|
||||||
set_field_permlevel('bom_no', 0);
|
set_field_permlevel('bom_no', 0);
|
||||||
set_field_permlevel('consider_sa_items',0);
|
set_field_permlevel('consider_sa_items',0);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ================================== Refresh ==========================================
|
// ================================== Refresh ==========================================
|
||||||
cur_frm.cscript.refresh = function(doc, cdt, cdn) {
|
cur_frm.cscript.refresh = function(doc, dt, dn) {
|
||||||
|
cfn_set_fields(doc, dt, dn);
|
||||||
|
|
||||||
cfn_set_fields(doc, cdt, cdn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_frm.fields_dict['production_item'].get_query = function(doc) {
|
var cfn_set_fields = function(doc, dt, dn) {
|
||||||
return 'SELECT DISTINCT `tabItem`.`name`, `tabItem`.`description` FROM `tabItem` WHERE (IFNULL(`tabItem`.`end_of_life`,"") = "" OR `tabItem`.`end_of_life` = "0000-00-00" OR `tabItem`.`end_of_life` > NOW()) AND `tabItem`.%(key)s LIKE "%s" ORDER BY `tabItem`.`name` LIMIT 50';
|
if (doc.docstatus == 1) {
|
||||||
}
|
if (doc.status != 'Stopped' && doc.status != 'Completed')
|
||||||
|
cur_frm.add_custom_button('Stop!', cur_frm.cscript['Stop Production Order']);
|
||||||
|
else if (doc.status == 'Stopped')
|
||||||
|
cur_frm.add_custom_button('Unstop', cur_frm.cscript['Unstop Production Order']);
|
||||||
|
|
||||||
// ---------------------- Get project name --------------------------
|
|
||||||
cur_frm.fields_dict['project_name'].get_query = function(doc, cdt, cdn) {
|
|
||||||
return 'SELECT `tabProject`.name FROM `tabProject` WHERE `tabProject`.status = "Open" AND `tabProject`.name LIKE "%s" ORDER BY `tabProject`.name ASC LIMIT 50';
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.fields_dict['bom_no'].get_query = function(doc) {
|
|
||||||
if (doc.production_item){
|
|
||||||
return 'SELECT DISTINCT `tabBill Of Materials`.`name` FROM `tabBill Of Materials` WHERE `tabBill Of Materials`.`is_active` = "Yes" AND `tabBill Of Materials`.`item` = "' + cstr(doc.production_item) + '" AND`tabBill Of Materials`.%(key)s LIKE "%s" ORDER BY `tabBill Of Materials`.`name` LIMIT 50';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
alert(" Please Enter Production Item First.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.cscript.production_item = function(doc, cdt, cdn) {
|
|
||||||
get_server_fields('get_item_detail',doc.production_item,'',doc,cdt,cdn,1);
|
|
||||||
}
|
|
||||||
|
|
||||||
var cfn_set_fields = function(doc, cdt, cdn) {
|
|
||||||
hide_field('Material Transfer');
|
|
||||||
hide_field('Stop Production Order');
|
|
||||||
hide_field('Unstop Production Order')
|
|
||||||
hide_field('Backflush');
|
|
||||||
if (doc.docstatus == 1){
|
|
||||||
unhide_field('Stop Production Order');
|
|
||||||
if (doc.status == 'Submitted' || doc.status == 'Material Transferred' || doc.status == 'In Process'){
|
if (doc.status == 'Submitted' || doc.status == 'Material Transferred' || doc.status == 'In Process'){
|
||||||
unhide_field(['Material Transfer','Backflush']);
|
cur_frm.add_custom_button('Transfer Material', cur_frm.cscript['Transfer Material']);
|
||||||
}
|
cur_frm.add_custom_button('Backflush', cur_frm.cscript['Backflush']);
|
||||||
else if (doc.status == 'Stopped'){
|
|
||||||
unhide_field('Unstop Production Order');
|
|
||||||
hide_field(['Stop Production Order', 'Material Transfer', 'Backflush']);
|
|
||||||
}
|
|
||||||
else if (doc.status == 'Completed'){
|
|
||||||
hide_field(['Stop Production Order', 'Material Transfer', 'Backflush']);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ==================================================================================================
|
||||||
|
|
||||||
|
cur_frm.cscript.production_item = function(doc, dt, dn) {
|
||||||
|
get_server_fields('get_item_detail',doc.production_item,'',doc,dt,dn,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop PRODUCTION ORDER
|
// Stop PRODUCTION ORDER
|
||||||
// ==================================================================================================
|
//
|
||||||
cur_frm.cscript['Stop Production Order'] = function(doc,cdt,cdn) {
|
cur_frm.cscript['Stop Production Order'] = function() {
|
||||||
var check = confirm("DO YOU REALLY WANT TO Stop PRODUCTION ORDER : " + doc.name);
|
var doc = cur_frm.doc;
|
||||||
|
var check = confirm("Do you really want to stop production order: " + doc.name);
|
||||||
if (check) {
|
if (check) {
|
||||||
$c('runserverobj', args={'method':'update_status', 'arg': 'Stopped', 'docs': compress_doclist(make_doclist(doc.doctype, doc.name))}, function(r,rt) {
|
$c_obj(make_doclist(doc.doctype, doc.name), 'stop_unstop', 'Stopped', function(r, rt) {cur_frm.refresh();});
|
||||||
cur_frm.refresh();
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unstop PRODUCTION ORDER
|
// Unstop PRODUCTION ORDER
|
||||||
// ==================================================================================================
|
//
|
||||||
cur_frm.cscript['Unstop Production Order'] = function(doc,cdt,cdn) {
|
cur_frm.cscript['Unstop Production Order'] = function() {
|
||||||
var check = confirm("DO YOU REALLY WANT TO Unstop PRODUCTION ORDER : " + doc.name);
|
var doc = cur_frm.doc;
|
||||||
|
var check = confirm("Do really want to unstop production order: " + doc.name);
|
||||||
if (check) {
|
if (check)
|
||||||
$c('runserverobj', args={'method':'update_status', 'arg': 'Unstopped', 'docs': compress_doclist(make_doclist(doc.doctype, doc.name))}, function(r,rt) {
|
$c_obj(make_doclist(doc.doctype, doc.name), 'stop_unstop', 'Unstopped', function(r, rt) {cur_frm.refresh();});
|
||||||
cur_frm.refresh();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_frm.cscript['Material Transfer'] = function(doc,cdt,cdn) {
|
cur_frm.cscript['Transfer Material'] = function() {
|
||||||
|
var doc = cur_frm.doc;
|
||||||
cur_frm.cscript.make_se(doc, process = 'Material Transfer');
|
cur_frm.cscript.make_se(doc, process = 'Material Transfer');
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_frm.cscript['Backflush'] = function(doc,cdt,cdn) {
|
cur_frm.cscript['Backflush'] = function() {
|
||||||
|
var doc = cur_frm.doc;
|
||||||
cur_frm.cscript.make_se(doc, process = 'Backflush');
|
cur_frm.cscript.make_se(doc, process = 'Backflush');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,3 +80,23 @@ cur_frm.cscript.make_se = function(doc, process) {
|
|||||||
|
|
||||||
loaddoc('Stock Entry', se.name);
|
loaddoc('Stock Entry', se.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ==================================================================================================
|
||||||
|
cur_frm.fields_dict['production_item'].get_query = function(doc) {
|
||||||
|
return 'SELECT DISTINCT `tabItem`.`name`, `tabItem`.`description` FROM `tabItem` WHERE (IFNULL(`tabItem`.`end_of_life`,"") = "" OR `tabItem`.`end_of_life` = "0000-00-00" OR `tabItem`.`end_of_life` > NOW()) AND `tabItem`.docstatus != 2 AND `tabItem`.is_pro_applicable = "Yes" AND `tabItem`.%(key)s LIKE "%s" ORDER BY `tabItem`.`name` LIMIT 50';
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_frm.fields_dict['project_name'].get_query = function(doc, dt, dn) {
|
||||||
|
return 'SELECT `tabProject`.name FROM `tabProject` WHERE `tabProject`.status = "Open" AND `tabProject`.name LIKE "%s" ORDER BY `tabProject`.name ASC LIMIT 50';
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_frm.fields_dict['bom_no'].get_query = function(doc) {
|
||||||
|
if (doc.production_item){
|
||||||
|
return 'SELECT DISTINCT `tabBill Of Materials`.`name` FROM `tabBill Of Materials` WHERE `tabBill Of Materials`.`is_active` = "Yes" AND `tabBill Of Materials`.docstatus = 1 AND `tabBill Of Materials`.`item` = "' + cstr(doc.production_item) + '" AND`tabBill Of Materials`.%(key)s LIKE "%s" ORDER BY `tabBill Of Materials`.`name` LIMIT 50';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
alert(" Please Enter Production Item First.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,87 +18,80 @@ convert_to_lists = webnotes.conn.convert_to_lists
|
|||||||
|
|
||||||
|
|
||||||
class DocType:
|
class DocType:
|
||||||
def __init__(self, doc, doclist=[]):
|
def __init__(self, doc, doclist=[]):
|
||||||
self.doc = doc
|
self.doc = doc
|
||||||
self.doclist = doclist
|
self.doclist = doclist
|
||||||
|
|
||||||
# Autoname
|
|
||||||
def autoname(self):
|
|
||||||
p = self.doc.fiscal_year
|
|
||||||
self.doc.name = make_autoname('PRO/' + self.doc.fiscal_year[2:5]+self.doc.fiscal_year[7:9] + '/.######')
|
|
||||||
|
|
||||||
def get_item_detail(self, production_item):
|
|
||||||
item = sql("select description, stock_uom, default_bom from `tabItem` where (ifnull(end_of_life,'')='' or end_of_life = '0000-00-00' or end_of_life > now()) and name = %s", production_item, as_dict = 1 )
|
|
||||||
ret = {
|
|
||||||
'description' : item and item[0]['description'] or '',
|
|
||||||
'stock_uom' : item and item[0]['stock_uom'] or '',
|
|
||||||
'default_bom' : item and item[0]['default_bom'] or ''
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def validate(self):
|
|
||||||
if not self.doc.production_item :
|
|
||||||
msgprint("Please enter Production Item")
|
|
||||||
raise Exception
|
|
||||||
if self.doc.production_item :
|
|
||||||
item_detail = sql("select docstatus from `tabItem` where name = '%s'" % self.doc.production_item, as_dict = 1)
|
|
||||||
if not item_detail:
|
|
||||||
msgprint("Item '%s' do not exist in the system." % cstr(self.doc.production_item))
|
|
||||||
raise Exception
|
|
||||||
if item_detail[0]['docstatus'] == 2:
|
|
||||||
msgprint("Item '%s' is Trashed Item ."% self.doc.production_item)
|
|
||||||
raise Exception
|
|
||||||
if self.doc.bom_no:
|
|
||||||
bom_detail = sql("select item, is_active, docstatus from `tabBill Of Materials` where name = '%s'" % self.doc.bom_no, as_dict =1)
|
|
||||||
if not bom_detail:
|
|
||||||
msgprint("BOM No '%s' do not exist in the system." % cstr(self.doc.bom_no))
|
|
||||||
raise Exception
|
|
||||||
if cstr(bom_detail[0]['item']) != cstr(self.doc.production_item):
|
|
||||||
msgprint("The Item '%s' in BOM := '%s' do not match with Produciton Item '%s'." % (cstr(bom_detail[0]['item']), cstr(self.doc.bom_no), cstr(self.doc.production_item)))
|
|
||||||
raise Exception
|
|
||||||
if cstr(bom_detail[0]['is_active']) != 'Yes':
|
|
||||||
msgprint("BOM := '%s' is not Active BOM." % self.doc.bom_no)
|
|
||||||
raise Exception
|
|
||||||
if flt(bom_detail[0]['docstatus']) != 1:
|
|
||||||
msgprint("BOM := '%s' is not Submitted BOM." % self.doc.bom_no)
|
|
||||||
raise Exception
|
|
||||||
|
|
||||||
def update_status(self, status):
|
|
||||||
# Set Status
|
|
||||||
if status == 'Stopped':
|
|
||||||
set(self.doc, 'status', cstr(status))
|
|
||||||
else:
|
|
||||||
if flt(self.doc.qty) == flt(self.doc.produced_qty):
|
|
||||||
set(self.doc, 'status', 'Completed')
|
|
||||||
if flt(self.doc.qty) > flt(self.doc.produced_qty):
|
|
||||||
set(self.doc, 'status', 'In Process')
|
|
||||||
if flt(self.doc.produced_qty) == 0:
|
|
||||||
set(self.doc, 'status', 'Submitted')
|
|
||||||
|
|
||||||
# Update Planned Qty of Production Item
|
|
||||||
qty = (flt(self.doc.qty) - flt(self.doc.produced_qty)) * ((status == 'Stopped') and -1 or 1)
|
|
||||||
get_obj('Warehouse', self.doc.fg_warehouse).update_bin(0, 0, 0, 0, flt(qty), self.doc.production_item, now())
|
|
||||||
|
|
||||||
# Acknowledge user
|
|
||||||
msgprint(self.doc.doctype + ": " + self.doc.name + " has been %s and status has been updated as %s." % (cstr(status), cstr(self.doc.status)))
|
|
||||||
|
|
||||||
def on_submit(self):
|
|
||||||
# Set Status AS "Submitted"
|
|
||||||
set(self.doc,'status', 'Submitted')
|
|
||||||
|
|
||||||
# increase Planned Qty of Prooduction Item by Qty
|
|
||||||
get_obj('Warehouse', self.doc.fg_warehouse).update_bin(0, 0, 0, 0,flt(self.doc.qty), self.doc.production_item, now())
|
|
||||||
|
|
||||||
|
|
||||||
def on_cancel(self):
|
def autoname(self):
|
||||||
# Stock Entries Against this Production Order
|
p = self.doc.fiscal_year
|
||||||
st = sql("select name from `tabStock Entry` where production_order = '%s' and docstatus = 1" % cstr(self.doc.name))
|
self.doc.name = make_autoname('PRO/' + self.doc.fiscal_year[2:5]+self.doc.fiscal_year[7:9] + '/.######')
|
||||||
if st and st[0][0]:
|
|
||||||
msgprint("Stock Entry "+ cstr(st[0][0]) + " has already been submitted.")
|
|
||||||
raise Exception
|
|
||||||
|
|
||||||
# Set Status AS "Submitted"
|
|
||||||
set(self.doc,'status', 'Cancelled')
|
|
||||||
|
|
||||||
# decrease Planned Qty of Prooduction Item by Qty
|
def get_item_detail(self, prod_item):
|
||||||
get_obj('Warehouse', self.doc.fg_warehouse).update_bin(0, 0, 0, 0,-flt(self.doc.qty), self.doc.production_item, now())
|
item = sql("""select description, stock_uom, default_bom from `tabItem`
|
||||||
|
where (ifnull(end_of_life,'')='' or end_of_life = '0000-00-00' or end_of_life > now()) and name = %s""", prod_item, as_dict = 1 )
|
||||||
|
ret = {
|
||||||
|
'description' : item and item[0]['description'] or '',
|
||||||
|
'stock_uom' : item and item[0]['stock_uom'] or '',
|
||||||
|
'default_bom' : item and item[0]['default_bom'] or ''
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
if self.doc.production_item :
|
||||||
|
item_detail = sql("select name from `tabItem` where name = '%s' and docstatus != 2" % self.doc.production_item, as_dict = 1)
|
||||||
|
if not item_detail:
|
||||||
|
msgprint("Item '%s' does not exist or cancelled in the system." % cstr(self.doc.production_item))
|
||||||
|
raise Exception
|
||||||
|
|
||||||
|
if self.doc.bom_no:
|
||||||
|
bom = sql("""select name from `tabBill Of Materials` where name = %s and docstatus = 1
|
||||||
|
and is_active = 'Yes' and item = %s""", (self.doc.bom_no, self.doc.production_item), as_dict =1)
|
||||||
|
if not bom:
|
||||||
|
msgprint("""Incorrect BOM: %s entered.
|
||||||
|
May be BOM not exists or inactive or not submitted or for some other item.""" % cstr(self.doc.bom_no))
|
||||||
|
raise Exception
|
||||||
|
|
||||||
|
|
||||||
|
def stop_unstop(self, status):
|
||||||
|
""" Called from client side on Stop/Unstop event"""
|
||||||
|
self.update_status(status)
|
||||||
|
# Update Planned Qty of Production Item
|
||||||
|
qty = (flt(self.doc.qty) - flt(self.doc.produced_qty)) * ((status == 'Stopped') and -1 or 1)
|
||||||
|
get_obj('Warehouse', self.doc.fg_warehouse).update_bin(0, 0, 0, 0, flt(qty), self.doc.production_item, now())
|
||||||
|
msgprint("Production Order has been %s" % status)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def update_status(self, status):
|
||||||
|
if status == 'Stopped':
|
||||||
|
set(self.doc, 'status', cstr(status))
|
||||||
|
else:
|
||||||
|
if flt(self.doc.qty) == flt(self.doc.produced_qty):
|
||||||
|
set(self.doc, 'status', 'Completed')
|
||||||
|
if flt(self.doc.qty) > flt(self.doc.produced_qty):
|
||||||
|
set(self.doc, 'status', 'In Process')
|
||||||
|
if flt(self.doc.produced_qty) == 0:
|
||||||
|
set(self.doc, 'status', 'Submitted')
|
||||||
|
|
||||||
|
|
||||||
|
def on_submit(self):
|
||||||
|
set(self.doc,'status', 'Submitted')
|
||||||
|
# increase Planned Qty of Prooduction Item by Qty
|
||||||
|
get_obj('Warehouse', self.doc.fg_warehouse).update_bin(0, 0, 0, 0,flt(self.doc.qty), self.doc.production_item, now())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def on_cancel(self):
|
||||||
|
# Check whether any stock entry exists against this Production Order
|
||||||
|
st = sql("select name from `tabStock Entry` where production_order = '%s' and docstatus = 1" % cstr(self.doc.name))
|
||||||
|
if st and st[0][0]:
|
||||||
|
msgprint("""Submitted Stock Entry %s exists against this production order.
|
||||||
|
Hence can not be cancelled.""" % st[0][0])
|
||||||
|
raise Exception
|
||||||
|
|
||||||
|
set(self.doc,'status', 'Cancelled')
|
||||||
|
# decrease Planned Qty of Prooduction Item by Qty
|
||||||
|
get_obj('Warehouse', self.doc.fg_warehouse).update_bin(0, 0, 0, 0,-flt(self.doc.qty), self.doc.production_item, now())
|
||||||
|
|||||||
@ -5,15 +5,16 @@
|
|||||||
{
|
{
|
||||||
'creation': '2010-08-08 17:09:14',
|
'creation': '2010-08-08 17:09:14',
|
||||||
'docstatus': 0,
|
'docstatus': 0,
|
||||||
'modified': '2011-08-31 10:03:21',
|
'modified': '2012-01-06 13:33:25',
|
||||||
'modified_by': 'Administrator',
|
'modified_by': 'Administrator',
|
||||||
'owner': 'Administrator'
|
'owner': 'Administrator'
|
||||||
},
|
},
|
||||||
|
|
||||||
# These values are common for all DocType
|
# These values are common for all DocType
|
||||||
{
|
{
|
||||||
'_last_update': '1313485457',
|
'_last_update': '1325668998',
|
||||||
'colour': 'White:FFF',
|
'colour': 'White:FFF',
|
||||||
|
'default_print_format': 'Standard',
|
||||||
'doctype': 'DocType',
|
'doctype': 'DocType',
|
||||||
'in_create': 0,
|
'in_create': 0,
|
||||||
'module': 'Production',
|
'module': 'Production',
|
||||||
@ -21,7 +22,7 @@
|
|||||||
'section_style': 'Tabbed',
|
'section_style': 'Tabbed',
|
||||||
'server_code_error': ' ',
|
'server_code_error': ' ',
|
||||||
'show_in_menu': 0,
|
'show_in_menu': 0,
|
||||||
'version': 180
|
'version': 189
|
||||||
},
|
},
|
||||||
|
|
||||||
# These values are common for all DocField
|
# These values are common for all DocField
|
||||||
@ -95,38 +96,9 @@
|
|||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldtype': 'Section Break',
|
'fieldtype': 'Column Break',
|
||||||
'label': 'Production Order',
|
|
||||||
'oldfieldtype': 'Section Break',
|
|
||||||
'permlevel': 0
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'colour': 'White:FFF',
|
|
||||||
'description': 'The date on which current entry is made in system.',
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'transaction_date',
|
|
||||||
'fieldtype': 'Date',
|
|
||||||
'label': 'Transaction Date',
|
|
||||||
'oldfieldname': 'transaction_date',
|
|
||||||
'oldfieldtype': 'Date',
|
|
||||||
'permlevel': 0,
|
'permlevel': 0,
|
||||||
'reqd': 1
|
'width': '50%'
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'colour': 'White:FFF',
|
|
||||||
'description': 'The date on which current entry will get or has actually executed.',
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'posting_date',
|
|
||||||
'fieldtype': 'Date',
|
|
||||||
'label': 'Posting Date',
|
|
||||||
'oldfieldname': 'posting_date',
|
|
||||||
'oldfieldtype': 'Date',
|
|
||||||
'permlevel': 0,
|
|
||||||
'reqd': 1
|
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
@ -158,6 +130,17 @@
|
|||||||
'width': '300px'
|
'width': '300px'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldname': 'stock_uom',
|
||||||
|
'fieldtype': 'Data',
|
||||||
|
'label': 'Stock UOM',
|
||||||
|
'oldfieldname': 'stock_uom',
|
||||||
|
'oldfieldtype': 'Data',
|
||||||
|
'permlevel': 1
|
||||||
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'colour': 'White:FFF',
|
'colour': 'White:FFF',
|
||||||
@ -174,21 +157,6 @@
|
|||||||
'trigger': 'Client'
|
'trigger': 'Client'
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'origin',
|
|
||||||
'fieldtype': 'Select',
|
|
||||||
'in_filter': 1,
|
|
||||||
'label': 'Origin',
|
|
||||||
'no_copy': 1,
|
|
||||||
'oldfieldname': 'origin',
|
|
||||||
'oldfieldtype': 'Select',
|
|
||||||
'options': 'Manual\nMRP',
|
|
||||||
'permlevel': 1,
|
|
||||||
'reqd': 1
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'colour': 'White:FFF',
|
'colour': 'White:FFF',
|
||||||
@ -203,78 +171,6 @@
|
|||||||
'reqd': 1
|
'reqd': 1
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'description': 'Select name of the project if Production Order need to be created against any project',
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'project_name',
|
|
||||||
'fieldtype': 'Link',
|
|
||||||
'in_filter': 1,
|
|
||||||
'label': 'Project Name',
|
|
||||||
'oldfieldname': 'project_name',
|
|
||||||
'oldfieldtype': 'Link',
|
|
||||||
'options': 'Project',
|
|
||||||
'permlevel': 0,
|
|
||||||
'trigger': 'Client'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'amended_from',
|
|
||||||
'fieldtype': 'Data',
|
|
||||||
'label': 'Amended From',
|
|
||||||
'oldfieldname': 'amended_from',
|
|
||||||
'oldfieldtype': 'Data',
|
|
||||||
'permlevel': 1
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'amendment_date',
|
|
||||||
'fieldtype': 'Date',
|
|
||||||
'label': 'Amendment Date',
|
|
||||||
'oldfieldname': 'amendment_date',
|
|
||||||
'oldfieldtype': 'Date',
|
|
||||||
'permlevel': 1
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldtype': 'Column Break',
|
|
||||||
'oldfieldtype': 'Column Break',
|
|
||||||
'permlevel': 0
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'stock_uom',
|
|
||||||
'fieldtype': 'Data',
|
|
||||||
'label': 'Stock UOM',
|
|
||||||
'oldfieldname': 'stock_uom',
|
|
||||||
'oldfieldtype': 'Data',
|
|
||||||
'permlevel': 1
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'status',
|
|
||||||
'fieldtype': 'Select',
|
|
||||||
'in_filter': 1,
|
|
||||||
'label': 'Status',
|
|
||||||
'no_copy': 1,
|
|
||||||
'oldfieldname': 'status',
|
|
||||||
'oldfieldtype': 'Select',
|
|
||||||
'options': '\nDraft\nSubmitted\nStopped\nIn Process\nCompleted\nCancelled',
|
|
||||||
'permlevel': 1,
|
|
||||||
'reqd': 1,
|
|
||||||
'search_index': 1
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'colour': 'White:FFF',
|
'colour': 'White:FFF',
|
||||||
@ -307,6 +203,53 @@
|
|||||||
'reqd': 1
|
'reqd': 1
|
||||||
},
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldname': 'amended_from',
|
||||||
|
'fieldtype': 'Data',
|
||||||
|
'label': 'Amended From',
|
||||||
|
'no_copy': 1,
|
||||||
|
'oldfieldname': 'amended_from',
|
||||||
|
'oldfieldtype': 'Data',
|
||||||
|
'permlevel': 1
|
||||||
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldname': 'amendment_date',
|
||||||
|
'fieldtype': 'Date',
|
||||||
|
'label': 'Amendment Date',
|
||||||
|
'no_copy': 1,
|
||||||
|
'oldfieldname': 'amendment_date',
|
||||||
|
'oldfieldtype': 'Date',
|
||||||
|
'permlevel': 1
|
||||||
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldtype': 'Column Break',
|
||||||
|
'oldfieldtype': 'Column Break',
|
||||||
|
'permlevel': 0,
|
||||||
|
'width': '50%'
|
||||||
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'colour': 'White:FFF',
|
||||||
|
'description': 'The date on which current entry will get or has actually executed.',
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldname': 'posting_date',
|
||||||
|
'fieldtype': 'Date',
|
||||||
|
'label': 'Posting Date',
|
||||||
|
'oldfieldname': 'posting_date',
|
||||||
|
'oldfieldtype': 'Date',
|
||||||
|
'permlevel': 0,
|
||||||
|
'reqd': 1
|
||||||
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'colour': 'White:FFF',
|
'colour': 'White:FFF',
|
||||||
@ -315,7 +258,7 @@
|
|||||||
'fieldname': 'consider_sa_items',
|
'fieldname': 'consider_sa_items',
|
||||||
'fieldtype': 'Select',
|
'fieldtype': 'Select',
|
||||||
'in_filter': 1,
|
'in_filter': 1,
|
||||||
'label': 'Consider SA Items',
|
'label': 'Consider SA Items as raw material',
|
||||||
'oldfieldname': 'consider_sa_items',
|
'oldfieldname': 'consider_sa_items',
|
||||||
'oldfieldtype': 'Select',
|
'oldfieldtype': 'Select',
|
||||||
'options': '\nYes\nNo',
|
'options': '\nYes\nNo',
|
||||||
@ -323,6 +266,52 @@
|
|||||||
'reqd': 1
|
'reqd': 1
|
||||||
},
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'description': 'Select name of the project if Production Order need to be created against any project',
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldname': 'project_name',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'in_filter': 1,
|
||||||
|
'label': 'Project Name',
|
||||||
|
'oldfieldname': 'project_name',
|
||||||
|
'oldfieldtype': 'Link',
|
||||||
|
'options': 'Project',
|
||||||
|
'permlevel': 0,
|
||||||
|
'trigger': 'Client'
|
||||||
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldname': 'origin',
|
||||||
|
'fieldtype': 'Select',
|
||||||
|
'in_filter': 1,
|
||||||
|
'label': 'Origin',
|
||||||
|
'no_copy': 1,
|
||||||
|
'oldfieldname': 'origin',
|
||||||
|
'oldfieldtype': 'Select',
|
||||||
|
'options': 'Manual\nMRP',
|
||||||
|
'permlevel': 1,
|
||||||
|
'reqd': 1
|
||||||
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldname': 'status',
|
||||||
|
'fieldtype': 'Select',
|
||||||
|
'in_filter': 1,
|
||||||
|
'label': 'Status',
|
||||||
|
'no_copy': 1,
|
||||||
|
'oldfieldname': 'status',
|
||||||
|
'oldfieldtype': 'Select',
|
||||||
|
'options': '\nDraft\nSubmitted\nStopped\nIn Process\nCompleted\nCancelled',
|
||||||
|
'permlevel': 1,
|
||||||
|
'reqd': 1,
|
||||||
|
'search_index': 1
|
||||||
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'colour': 'White:FFF',
|
'colour': 'White:FFF',
|
||||||
@ -361,78 +350,5 @@
|
|||||||
'options': 'link:Fiscal Year',
|
'options': 'link:Fiscal Year',
|
||||||
'permlevel': 0,
|
'permlevel': 0,
|
||||||
'reqd': 1
|
'reqd': 1
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldtype': 'Section Break',
|
|
||||||
'label': 'Next Steps',
|
|
||||||
'oldfieldtype': 'Section Break',
|
|
||||||
'permlevel': 0
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'allow_on_submit': 1,
|
|
||||||
'colour': 'White:FFF',
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldtype': 'Button',
|
|
||||||
'label': 'Material Transfer',
|
|
||||||
'oldfieldtype': 'Button',
|
|
||||||
'permlevel': 0,
|
|
||||||
'trigger': 'Client'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldtype': 'Column Break',
|
|
||||||
'oldfieldtype': 'Column Break',
|
|
||||||
'permlevel': 0
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'allow_on_submit': 1,
|
|
||||||
'colour': 'White:FFF',
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldtype': 'Button',
|
|
||||||
'label': 'Backflush',
|
|
||||||
'oldfieldtype': 'Button',
|
|
||||||
'permlevel': 0,
|
|
||||||
'trigger': 'Client'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldtype': 'Column Break',
|
|
||||||
'oldfieldtype': 'Column Break',
|
|
||||||
'permlevel': 0
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'allow_on_submit': 1,
|
|
||||||
'colour': 'White:FFF',
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldtype': 'Button',
|
|
||||||
'label': 'Stop Production Order',
|
|
||||||
'oldfieldtype': 'Button',
|
|
||||||
'permlevel': 0,
|
|
||||||
'trigger': 'Client'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'allow_on_submit': 1,
|
|
||||||
'colour': 'White:FFF',
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldtype': 'Button',
|
|
||||||
'label': 'Unstop Production Order',
|
|
||||||
'oldfieldtype': 'Button',
|
|
||||||
'permlevel': 0,
|
|
||||||
'trigger': 'Client'
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -1,45 +1,34 @@
|
|||||||
|
|
||||||
cur_frm.cscript.onload = function(doc, cdt, cdn) {
|
|
||||||
|
|
||||||
if(!doc.fiscal_year){ set_default_values(doc);}
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.cscript.item_code = function(doc,cdt,cdn) {
|
cur_frm.cscript.item_code = function(doc,cdt,cdn) {
|
||||||
var d = locals[cdt][cdn];
|
var d = locals[cdt][cdn];
|
||||||
if (d.item_code) {
|
if (d.item_code) {
|
||||||
temp = "{'item_code':'"+(d.item_code?d.item_code:'')+"'}";
|
get_server_fields('get_item_details', d.item_code, 'pp_details', doc, cdt, cdn, 1);
|
||||||
get_server_fields('get_item_details', temp, 'pp_details', doc, cdt, cdn, 1);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cur_frm.cscript.sales_order = function(doc,cdt,cdn) {
|
||||||
|
var d = locals[cdt][cdn];
|
||||||
|
if (d.sales_order) {
|
||||||
|
get_server_fields('get_so_details', d.sales_order, 'pp_so_details', doc, cdt, cdn, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cur_frm.cscript['Download Raw Material'] = function(doc, cdt, cdn) {
|
||||||
|
var callback = function(r, rt){
|
||||||
|
if (r.message)
|
||||||
|
$c_obj_csv(make_doclist(cdt, cdn), 'download_raw_materials', '', '');
|
||||||
|
}
|
||||||
|
$c_obj(make_doclist(cdt, cdn), 'validate_data', '', callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
|
||||||
cur_frm.fields_dict['pp_details'].grid.get_field('item_code').get_query = function(doc) {
|
cur_frm.fields_dict['pp_details'].grid.get_field('item_code').get_query = function(doc) {
|
||||||
return 'SELECT DISTINCT `tabItem`.`name`,`tabItem`.`item_name` FROM `tabItem` WHERE (IFNULL(`tabItem`.`end_of_life`,"") = "" OR `tabItem`.`end_of_life`="0000-00-00" OR `tabItem`.`end_of_life` > NOW()) AND tabItem.%(key)s like "%s" ORDER BY `tabItem`.`name` LIMIT 50';
|
return 'SELECT DISTINCT `tabItem`.`name`,`tabItem`.`item_name` FROM `tabItem` WHERE (IFNULL(`tabItem`.`end_of_life`,"") = "" OR `tabItem`.`end_of_life`="0000-00-00" OR `tabItem`.`end_of_life` > NOW()) AND `tabItem`.is_pro_applicable = "Yes" AND tabItem.%(key)s like "%s" ORDER BY `tabItem`.`name` LIMIT 50';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Query for BOM NO
|
|
||||||
//-------------------------------------------------------------------------------
|
|
||||||
cur_frm.fields_dict['pp_details'].grid.get_field('bom_no').get_query = function(doc) {
|
cur_frm.fields_dict['pp_details'].grid.get_field('bom_no').get_query = function(doc) {
|
||||||
var d = locals[this.doctype][this.docname];
|
var d = locals[this.doctype][this.docname];
|
||||||
return 'SELECT DISTINCT `tabBill Of Materials`.`name` FROM `tabBill Of Materials` WHERE `tabBill Of Materials`.`item` = "' + d.item_code + '" AND `tabBill Of Materials`.`is_active` = "Yes" AND `tabBill Of Materials`.`name` like "%s" ORDER BY `tabBill Of Materials`.`name` LIMIT 50';
|
return 'SELECT DISTINCT `tabBill Of Materials`.`name` FROM `tabBill Of Materials` WHERE `tabBill Of Materials`.`item` = "' + d.item_code + '" AND `tabBill Of Materials`.`is_active` = "Yes" AND `tabBill Of Materials`.docstatus = 1 AND `tabBill Of Materials`.`name` like "%s" ORDER BY `tabBill Of Materials`.`name` LIMIT 50';
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.cscript['Clear Document Table'] = function(doc, cdt, cdn){
|
|
||||||
$c('runserverobj', args={'method':'clear_table', 'arg': 'pp_so_details', 'docs': compress_doclist(make_doclist(doc.doctype, doc.name))}, function(r,rt) {
|
|
||||||
cur_frm.refresh();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.cscript['Clear Item Table'] = function(doc, cdt, cdn){
|
|
||||||
$c('runserverobj', args={'method':'clear_table', 'arg': 'pp_details', 'docs': compress_doclist(make_doclist(doc.doctype, doc.name))}, function(r,rt) {
|
|
||||||
cur_frm.refresh();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.cscript['Download Raw Material Report'] = function(doc, cdt, cdn) {
|
|
||||||
call_back = function(r, rt){
|
|
||||||
if (r.message) {
|
|
||||||
$c_obj_csv(make_doclist(cdt, cdn), 'get_raw_materials_report', '');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$c('runserverobj', args = {'method':'validate_data','args':'','docs':compress_doclist(make_doclist(doc.doctype, doc.name))}, call_back)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,281 +1,277 @@
|
|||||||
# Please edit this list and import only required elements
|
|
||||||
import webnotes
|
import webnotes
|
||||||
|
from webnotes.utils import cint, cstr, flt, getdate, now, nowdate
|
||||||
|
from webnotes.model.doc import addchild
|
||||||
|
from webnotes.model.doclist import getlist
|
||||||
|
from webnotes.model.code import get_obj
|
||||||
|
from webnotes import msgprint, errprint
|
||||||
|
|
||||||
from webnotes.utils import add_days, add_months, add_years, cint, cstr, date_diff, default_fields, flt, fmt_money, formatdate, generate_hash, getTraceback, get_defaults, get_first_day, get_last_day, getdate, has_common, month_name, now, nowdate, replace_newlines, sendmail, set_default, str_esc_quote, user_format, validate_email_add
|
|
||||||
from webnotes.model import db_exists
|
|
||||||
from webnotes.model.doc import Document, addchild, removechild, getchildren, make_autoname, SuperDocType
|
|
||||||
from webnotes.model.doclist import getlist, copy_doclist
|
|
||||||
from webnotes.model.code import get_obj, get_server_obj, run_server_obj, updatedb, check_syntax
|
|
||||||
from webnotes import session, form, is_testing, msgprint, errprint
|
|
||||||
|
|
||||||
set = webnotes.conn.set
|
|
||||||
sql = webnotes.conn.sql
|
sql = webnotes.conn.sql
|
||||||
get_value = webnotes.conn.get_value
|
|
||||||
in_transaction = webnotes.conn.in_transaction
|
|
||||||
convert_to_lists = webnotes.conn.convert_to_lists
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
class DocType:
|
class DocType:
|
||||||
def __init__(self, doc, doclist=[]):
|
def __init__(self, doc, doclist=[]):
|
||||||
self.doc = doc
|
self.doc = doc
|
||||||
self.doclist = doclist
|
self.doclist = doclist
|
||||||
self.item_dict = {}
|
self.item_dict = {}
|
||||||
self.defaults = get_defaults()
|
|
||||||
|
|
||||||
def get_item_details(self, args):
|
def get_item_details(self, item_code):
|
||||||
args = eval(args)
|
""" Pull other item details from item master"""
|
||||||
item = sql("select description, stock_uom, default_bom from `tabItem` where name = '%s' and (ifnull(end_of_life,'')='' or end_of_life = '0000-00-00' or end_of_life > now())" % args['item_code'], as_dict =1 )
|
|
||||||
if item:
|
|
||||||
ret = {'description' : item and item[0]['description'],
|
|
||||||
'stock_uom' : item and item[0]['stock_uom'],
|
|
||||||
'bom_no' : item and item[0]['default_bom']
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
else:
|
|
||||||
msgprint("Item %s does not exist in system." %(args['item_code']))
|
|
||||||
raise Exception
|
|
||||||
|
|
||||||
def validate_data(self):
|
item = sql("""select description, stock_uom, default_bom from `tabItem` where name = %s
|
||||||
for d in getlist(self.doclist, 'pp_details'):
|
and (ifnull(end_of_life,'')='' or end_of_life = '0000-00-00' or end_of_life > now())""", item_code, as_dict =1 )
|
||||||
if not d.pro_created:
|
ret = {
|
||||||
|
'description' : item and item[0]['description'],
|
||||||
|
'stock_uom' : item and item[0]['stock_uom'],
|
||||||
|
'bom_no' : item and item[0]['default_bom']
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
|
||||||
bom = sql("select name from `tabBill Of Materials` where item = %s and docstatus < 2", d.item_code, as_dict = 1)
|
|
||||||
if d.bom_no and not bom:
|
|
||||||
msgprint("There is no Active BOM for item code " + cstr(d.item_code) + " at row no." + cstr(d.idx)+ " which is Submitted. ")
|
|
||||||
raise Exception
|
|
||||||
if bom and bom[0]['name'] and not d.bom_no:
|
|
||||||
msgprint("Please Enter BOM No. for item code " + cstr(d.item_code) + "at row no " + cstr(d.idx))
|
|
||||||
raise Exception
|
|
||||||
item = sql("select is_purchase_item from `tabItem` where name = %s", d.item_code,as_dict = 1)
|
|
||||||
# if not item[0]['is_mrp_item']:
|
|
||||||
# msgprint("Please Delete Row No " + cstr(d.idx) + " as Item " + cstr(d.item_code) + " is not MRP ITEM ")
|
|
||||||
# raise Exception
|
|
||||||
if not item[0]['is_purchase_item'] and not d.bom_no:
|
|
||||||
msgprint("Please Delete Row No. "+ cstr(d.idx)+" as Item " + cstr(d.item_code) + " is not a PURCHASE ITEM ")
|
|
||||||
raise Exception
|
|
||||||
if not flt(d.planned_qty):
|
|
||||||
msgprint("Please Enter Planned Qty for item code " + cstr(d.item_code) + "at row no " + cstr(d.idx))
|
|
||||||
raise Exception
|
|
||||||
if flt(d.prevdoc_reqd_qty) and flt(d.planned_qty) > flt(d.prevdoc_reqd_qty):
|
|
||||||
msgprint(" Planned Qty cannot be greater than total Qty at row no " + cstr(d.idx))
|
|
||||||
raise Exception
|
|
||||||
|
|
||||||
item = sql("select is_manufactured_item, is_sub_contracted_item from`tabItem` where name = %s", d.item_code, as_dict = 1)
|
def get_so_details(self, so):
|
||||||
if not item:
|
"""Pull other details from so"""
|
||||||
msgprint("Item %s is not present in Item Master." % d.item_code)
|
so = sql("select transaction_date, customer, grand_total from `tabSales Order` where name = %s", so, as_dict = 1)
|
||||||
raise Exception
|
ret = {
|
||||||
|
'sales_order_date': so and so[0]['transaction_date'] or '',
|
||||||
|
'customer' : so[0]['customer'] or '',
|
||||||
|
'grand_total': so[0]['grand_total']
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
|
||||||
if item[0]['is_manufactured_item'] == 'Yes' or item[0]['is_sub_contracted_item'] == 'Yes':
|
|
||||||
bom = sql("select name, docstatus from `tabBill Of Materials` where item = %s", d.item_code, as_dict =1)
|
|
||||||
if bom and bom[0]['name']:
|
|
||||||
if not d.bom_no:
|
|
||||||
msgprint("Please Enter BOM No for Item " + cstr(d.item_code) + " in Materials at Row No. " + cstr(d.idx) + " in BOM NO. " + self.doc.name)
|
|
||||||
raise Exception
|
|
||||||
else:
|
|
||||||
match = 0
|
|
||||||
for b in bom:
|
|
||||||
if flt(b['docstatus']) > 1:
|
|
||||||
msgprint("BOM %s is NOT SUBMITTED."% cstr(d.bom_no))
|
|
||||||
raise Exception
|
|
||||||
|
|
||||||
match = 1
|
def clear_so_table(self):
|
||||||
if not match:
|
""" Clears sales order table"""
|
||||||
msgprint("Item %s does not belong to Bill Of Material %s or Bill Of Material %s is NOT ACTIVE BOM." % (cstr(d.item_code),cstr(d.bom_no), cstr(d.bom_no)))
|
self.doc.clear_table(self.doclist, 'pp_so_details')
|
||||||
raise Exception
|
|
||||||
|
|
||||||
if not item[0]['is_manufactured_item'] == 'Yes' and not item[0]['is_sub_contracted_item']== 'Yes':
|
|
||||||
if d.bom_no:
|
|
||||||
msgprint("As in Item Master of Item %s Is Manufactured Item / Is Sub-Contracted Item is not 'Yes' hence there should be no BOM." % d.item_code)
|
|
||||||
raise Exception
|
|
||||||
|
|
||||||
return 1
|
|
||||||
|
|
||||||
def pull_document(self):
|
def clear_item_table(self):
|
||||||
if self.doc.sales_order:
|
""" Clears item table"""
|
||||||
open_so = sql("select distinct 'Sales Order' as prevdoc, t1.name, ifnull(t1.transaction_date, ''), ifnull(t2.confirmation_date,'') from `tabSales Order` t1, `tabSales Order Detail` t2, `tabDelivery Note Packing Detail` t3 where ifnull(t3.planned_qty,0) < ifnull(t3.qty,0) and (t2.qty - ifnull(t2.delivered_qty,0)) > 0 and t3.parent_detail_docname = t2.name and t2.parent = t1.name and t1.docstatus = 1 and t1.name = '%s' order by t1.transaction_date" % self.doc.sales_order)
|
self.doc.clear_table(self.doclist, 'pp_details')
|
||||||
self.add_open_documents(open_so)
|
|
||||||
#if self.doc.production_forecast:
|
|
||||||
#open_pf = sql("select distinct 'Production Forecast' as prevdoc, t1.name, ifnull(t1.transaction_date,''), ifnull(t1.forecast_due_date,'') from `tabProduction Forecast` t1, `tabPF Detail` t2 where t2.planned_qty < t2.qty and t2.parent = t1.name and t1.name = '%s' and t1.docstatus = 1 order by t1.forecast_due_date " % self.doc.production_forecast)
|
|
||||||
#self.add_open_documents(open_pf)
|
|
||||||
|
|
||||||
def validate_duplicate_docname(self, check_data):
|
|
||||||
for d in getlist(self.doclist, 'pp_so_details'):
|
|
||||||
if [ d.prevdoc_docname, d.document_date, d.confirmation_date] == check_data :
|
|
||||||
msgprint(cstr(d.prevdoc) + ": " + cstr(d.prevdoc_docname) + " appears more than once.")
|
|
||||||
raise Exception
|
|
||||||
|
|
||||||
def add_open_documents(self, open_doc):
|
|
||||||
for r in open_doc:
|
|
||||||
self.validate_duplicate_docname([r[1], r[2], r[3]])
|
|
||||||
pp_so = addchild(self.doc, 'pp_so_details', 'PP SO Detail', 1, self.doclist)
|
|
||||||
pp_so.prevdoc = r[0]
|
|
||||||
pp_so.prevdoc_docname = r[1]
|
|
||||||
pp_so.document_date = cstr(r[2])
|
|
||||||
pp_so.confirmation_date = cstr(r[3])
|
|
||||||
pp_so.save()
|
|
||||||
|
|
||||||
def get_open_docs(self):
|
def get_open_sales_orders(self):
|
||||||
# Step 1:=> Remove unwanted rows from PP SO DETAIL TABLE
|
""" Pull sales orders which are pending to deliver based on criteria selected"""
|
||||||
self.remove_unwanted_rows_from_table(check_field ='include_in_plan', table_fname='pp_so_details')
|
cond = self.get_filter_condition()
|
||||||
|
open_so = sql("""
|
||||||
|
select
|
||||||
|
distinct t1.name, t1.transaction_date, t1.customer, t1.grand_total
|
||||||
|
from
|
||||||
|
`tabSales Order` t1, `tabDelivery Note Packing Detail` t2
|
||||||
|
where
|
||||||
|
t1.name = t2.parent and t2.parenttype = 'Sales Order' and t1.docstatus = 1
|
||||||
|
and ifnull(t1.per_delivered, 0) < 100 and t1.status != 'Stopped' and company = '%s' %s
|
||||||
|
order by t1.name desc
|
||||||
|
"""% (self.doc.company, cond), as_dict = 1)
|
||||||
|
|
||||||
# Step 2:=> Check From Date should be before To Date
|
self.add_so_in_table(open_so)
|
||||||
if self.doc.from_date:
|
|
||||||
if (getdate(self.doc.from_date) > getdate(self.doc.to_date)):
|
|
||||||
msgprint("From Date cannot be after To Date")
|
|
||||||
raise Exception
|
|
||||||
|
|
||||||
# Step 3:=> At Least to date should be there
|
|
||||||
if not self.doc.to_date:
|
|
||||||
msgprint("To Date is Mandatory.")
|
|
||||||
raise Exception
|
|
||||||
|
|
||||||
# Step 4:=> GEt Open Sales ORder and Production Forecasts
|
|
||||||
open_so = sql("select distinct 'Sales Order' as prevdoc, t1.name, t1.transaction_date, t2.confirmation_date from `tabSales Order` t1, `tabSales Order Detail` t2 where (t2.qty - ifnull(t2.delivered_qty,0)) > 0 and t2.parent = t1.name %s and t1.transaction_date <= '%s' and t1.docstatus = 1 order by t1.transaction_date" % ((self.doc.from_date and "and t1.transaction_date >= '%s' " % self.doc.from_date or '') , self.doc.to_date))
|
|
||||||
#open_pf = sql("select distinct 'Production Forecast' as prevdoc, t1.name, t1.transaction_date, t1.forecast_due_date from `tabProduction Forecast` t1, `tabPF Detail` t2 where ifnull(t2.planned_qty,0) < ifnull(t2.qty,0) and t1.name = t2.parent %s and t1.forecast_due_date <= '%s' and t1.docstatus = 1 order by t1.forecast_due_date " % ( self.doc.from_date and "and t1.forecast_due_date >= '%s' " % self.doc.from_date or '', self.doc.to_date))
|
|
||||||
#open_doc = open_so + open_pf
|
|
||||||
open_doc = open_so
|
|
||||||
self.add_open_documents(open_doc)
|
|
||||||
|
|
||||||
def remove_unwanted_rows_from_table(self, check_field, table_fname):
|
def validate_company(self):
|
||||||
for d in getlist(self.doclist, table_fname):
|
if not self.doc.company:
|
||||||
if not d.fields[check_field]:
|
msgprint("Please enter Company", raise_exception=1)
|
||||||
d.fields['__oldparent'] = d.parent
|
|
||||||
d.parent = 'old_parent:' + d.parent # for client to send it back while saving
|
|
||||||
d.docstatus = 2
|
|
||||||
if not d.fields.get('__islocal'):
|
|
||||||
d.save()
|
|
||||||
else:
|
|
||||||
d.save()
|
|
||||||
|
|
||||||
def get_packing_list_items(self, sales_order):
|
|
||||||
#sales_com_obj.make_packing_list(self,'sales_order_details')
|
|
||||||
pack_l = sql("select t2.name, t2.parent_item, t2.item_code, t0.transaction_date, t1.confirmation_date,(t1.qty - ifnull(t1.delivered_qty,0)) * (ifnull(t2.qty,0) / ifnull(t1.qty,1)) as 'pending_qty' from `tabSales Order` t0, `tabSales Order Detail` t1, `tabDelivery Note Packing Detail` t2 where ifnull(t2.planned_qty,0) < ifnull(t2.qty,0) and (t1.qty - ifnull(t1.delivered_qty,0)) > 0 and t2.parent_detail_docname = t1.name and t0.name = t1.parent and t1.parent = '%s' and t2.parent = '%s' and t1.docstatus =1 and t2.docstatus = 1" % (sales_order, sales_order), as_dict =1)
|
|
||||||
for p in pack_l:
|
|
||||||
pi = addchild(self.doc, 'pp_details', 'PP Detail', 0, self.doclist)
|
|
||||||
pi.source_doctype = 'Sales Order'
|
|
||||||
pi.source_docname = sales_order
|
|
||||||
pi.source_detail_docname = p['name']
|
|
||||||
pi.parent_item = p['parent_item']
|
|
||||||
pi.item_code = p['item_code']
|
|
||||||
pi.document_date = cstr(p['transaction_date'])
|
|
||||||
pi.confirmation_date = cstr(p['confirmation_date'])
|
|
||||||
item_details = sql("select description, stock_uom from tabItem where name=%s and (ifnull(end_of_life,'')='' or end_of_life = '0000-00-00' or end_of_life > now())", p['item_code'])
|
|
||||||
pi.description = item_details and item_details[0][0] or ''
|
|
||||||
pi.stock_uom = item_details and item_details[0][1] or ''
|
|
||||||
pi.prevdoc_reqd_qty = flt(p['pending_qty'])
|
|
||||||
pi.save()
|
|
||||||
|
|
||||||
def get_items(self):
|
|
||||||
# Step 1:=> Remove unwanted rows from PP SO DETAIL TABLE
|
|
||||||
self.remove_unwanted_rows_from_table(check_field ='include_in_plan', table_fname='pp_so_details')
|
|
||||||
# Step 2:=> Remove unwanted rows from PP DETAIL TABLE
|
|
||||||
self.doc.clear_table(self.doclist, 'pp_details', 1)
|
|
||||||
# Step 3:=> Get All Details From Production Forecast and Sales Order which are marked Include In Plan in PP SO Detail
|
|
||||||
for d in getlist(self.doclist, 'pp_so_details'):
|
|
||||||
if d.include_in_plan:
|
|
||||||
# Step 3.a :=> Get packing List items from sales order
|
|
||||||
if d.prevdoc == 'Sales Order':
|
|
||||||
self.get_packing_list_items(d.prevdoc_docname)
|
|
||||||
# Step 3.b :=> Get Production Forecast items
|
|
||||||
if d.prevdoc == 'Production Forecast':
|
|
||||||
get_obj('DocType Mapper', 'Production Forecast-Production Planning Tool').dt_map('Production Forecast','Production Planning Tool', d.prevdoc_docname, self.doc, self.doclist, "[['Production Forecast','Production Planning Tool'],['PF Detail', 'PP Detail']]")
|
|
||||||
|
|
||||||
self.set_defaults_pp_detail()
|
def get_filter_condition(self):
|
||||||
|
self.validate_company()
|
||||||
|
|
||||||
def clear_table(self, table_name = ''):
|
cond = ''
|
||||||
self.doc.clear_table(self.doclist, table_name, 1)
|
if self.doc.from_date:
|
||||||
|
cond += ' and t1.transaction_date >= "' + self.doc.from_date + '"'
|
||||||
|
if self.doc.to_date:
|
||||||
|
cond += ' and t1.transaction_date <= "' + self.doc.to_date + '"'
|
||||||
|
if self.doc.customer:
|
||||||
|
cond += ' and t1.customer = "' + self.doc.customer + '"'
|
||||||
|
if self.doc.fg_item:
|
||||||
|
cond += ' and t2.item_code = "' + self.doc.fg_item + '"'
|
||||||
|
|
||||||
def set_defaults_pp_detail(self):
|
return cond
|
||||||
for d in getlist(self.doclist,'pp_details'):
|
|
||||||
if not d.mrp:
|
|
||||||
# set default BOM
|
|
||||||
if not d.bom_no:
|
|
||||||
bom = sql("select default_bom from `tabItem` where name = %s and (ifnull(end_of_life,'')='' or end_of_life ='0000-00-00' or end_of_life > now())", d.item_code, as_dict = 1)
|
|
||||||
if bom and bom[0]['default_bom']:
|
|
||||||
d.bom_no = bom[0]['default_bom']
|
|
||||||
# Set planned qty as prevdoc_reqd_qty
|
|
||||||
d.planned_qty = flt(d.prevdoc_reqd_qty)
|
|
||||||
d.save()
|
|
||||||
|
|
||||||
def make_items_dict(self, items_list):
|
|
||||||
# items_list = [[item_name, qty]]
|
|
||||||
for i in items_list:
|
|
||||||
if self.item_dict.has_key(i[0]):
|
|
||||||
self.item_dict[i[0]] = flt(self.item_dict[i[0]]) + flt(i[1])
|
|
||||||
else:
|
|
||||||
self.item_dict[i[0]] = flt(i[1])
|
|
||||||
|
|
||||||
def get_raw_materials(self, bom_dict):
|
|
||||||
for bom in bom_dict:
|
|
||||||
# get all purchase items
|
|
||||||
if self.doc.consider_sa_items == 'No':
|
|
||||||
fl_bom_items = sql("select item_code, ifnull(sum(qty_consumed_per_unit), 0) * '%s' from `tabFlat BOM Detail` where parent = '%s' and is_pro_applicable = 'No' and docstatus < 2 group by item_code" % (bom_dict[bom], bom))
|
|
||||||
self.make_items_dict(fl_bom_items)
|
|
||||||
|
|
||||||
# get all purchase items without sa child_items
|
def add_so_in_table(self, open_so):
|
||||||
if self.doc.consider_sa_items == 'Yes':
|
""" Add sales orders in the table"""
|
||||||
fl_bom_sa_items = sql("select item_code, ifnull(sum(qty_consumed_per_unit), 0) * '%s' from `tabFlat BOM Detail` where parent = '%s' and parent_bom != '%s' and is_pro_applicable = 'Yes' and docstatus < 2 group by item_code" % (bom_dict[bom], bom, bom))
|
so_list = []
|
||||||
self.make_items_dict(fl_bom_sa_items)
|
for d in getlist(self.doclist, 'pp_so_details'):
|
||||||
fl_bom_items = sql("select item_code, ifnull(sum(qty_consumed_per_unit), 0) * '%s' from `tabFlat BOM Detail` where parent = '%s' and parent_bom not in (select distinct parent_bom from `tabFlat BOM Detail` where parent = '%s' and parent_bom != '%s' and is_pro_applicable = 'Yes' and docstatus <2) and docstatus < 2 and is_pro_applicable = 'No' group by item_code" % (bom_dict[bom], bom, bom, bom) )
|
so_list.append(d.sales_order)
|
||||||
self.make_items_dict(fl_bom_items)
|
for r in open_so:
|
||||||
|
if cstr(r['name']) not in so_list:
|
||||||
|
pp_so = addchild(self.doc, 'pp_so_details', 'PP SO Detail', 1, self.doclist)
|
||||||
|
pp_so.sales_order = r['name']
|
||||||
|
pp_so.sales_order_date = cstr(r['transaction_date'])
|
||||||
|
pp_so.customer = cstr(r['customer'])
|
||||||
|
pp_so.grand_total = flt(r['grand_total'])
|
||||||
|
|
||||||
return self.item_dict
|
|
||||||
|
|
||||||
def send_csv(self, item_dict):
|
|
||||||
item_list = [['Item Code', 'Description', 'Stock UOM','Required Qty', 'Indented Qty', 'Ordered Qty', 'Actual Qty', ]]
|
|
||||||
for d in item_dict:
|
|
||||||
item_detail = sql("select description, stock_uom from `tabItem` where name = '%s'" % d)
|
|
||||||
item_qty= sql("select sum(indented_qty), sum(ordered_qty), sum(actual_qty) from `tabBin` where item_code = '%s' " % d)
|
|
||||||
item_list.append([d, cstr(item_detail[0][0]), cstr(item_detail[0][1]), flt(item_dict[d]), item_qty and flt(item_qty[0][0]), item_qty and flt(item_qty[0][1]), item_qty and flt(item_qty[0][2])])
|
|
||||||
return item_list
|
|
||||||
|
|
||||||
def get_raw_materials_report(self):
|
def get_items_from_so(self):
|
||||||
#self.validate_data()
|
""" Pull items from Sales Order, only proction item
|
||||||
bom_dict = self.check_criteria_for_same_items(check_for = 'Report')
|
and subcontracted item will be pulled from Packing item
|
||||||
item_dict = self.get_raw_materials(bom_dict)
|
and add items in the table
|
||||||
#msgprint(item_dict)
|
"""
|
||||||
#raise Exception
|
so = self.get_included_so()
|
||||||
return self.send_csv(item_dict)
|
items = self.get_packing_items(so)
|
||||||
|
self.add_items(items)
|
||||||
|
|
||||||
def raise_production_order(self):
|
|
||||||
self.validate_data()
|
|
||||||
pp_detail = self.check_criteria_for_same_items(check_for = 'Raise Production Order')
|
|
||||||
pro = get_obj(dt = 'Production Control').create_production_order(self.doc.company, self.doc.fiscal_year, pp_detail = pp_detail)
|
|
||||||
if len(pro) == 1:
|
|
||||||
result = "Only Production Order " + cstr(pro[0]) + " has been generated."
|
|
||||||
elif len(pro) > 1 :
|
|
||||||
result = "Production Order From " + cstr(pro[0]) + " to " + cstr(pro[len(pro) - 1]) + " has been generated."
|
|
||||||
else :
|
|
||||||
result = " No Production Order is generated."
|
|
||||||
msgprint(result)
|
|
||||||
|
|
||||||
def check_criteria_for_same_items(self, check_for):
|
def get_included_so(self):
|
||||||
pro_lbl = {'production_item': 0, 'description': 1, 'qty' : 2, 'stock_uom' : 3, 'bom_no': 4, 'consider_sa_items': 5}
|
so = "'" + "','".join([d.sales_order for d in getlist(self.doclist, 'pp_so_details') if d.include_in_plan]) + "'"
|
||||||
pp_detail, appended, bom_dict = [], 0, {}
|
return so
|
||||||
for d in getlist(self.doclist, 'pp_details'):
|
|
||||||
if check_for == 'Report':
|
|
||||||
if d.bom_no:
|
|
||||||
if bom_dict.has_key(d.bom_no):
|
|
||||||
bom_dict[d.bom_no] = flt(bom_dict[d.bom_no]) + flt(d.planned_qty)
|
|
||||||
else:
|
|
||||||
bom_dict[d.bom_no] = flt(d.planned_qty)
|
|
||||||
else:
|
|
||||||
self.make_items_dict([[d.item_code, d.planned_qty]])
|
|
||||||
|
|
||||||
if check_for == 'Raise Production Order' and not d.pro_created:
|
|
||||||
appended = 0
|
|
||||||
if pp_detail:
|
|
||||||
for i in pp_detail:
|
|
||||||
# if same bom_no
|
|
||||||
if d.bom_no and d.bom_no == i[pro_lbl['bom_no']]:
|
|
||||||
# set appended , add qty
|
|
||||||
appended, i[pro_lbl['qty']], d.pro_created = 1, i[pro_lbl['qty']] + flt(d.planned_qty) , 1
|
|
||||||
|
|
||||||
if not appended and d.bom_no:
|
|
||||||
pp_detail.append([d.item_code, d.description, d.planned_qty, d.stock_uom, d.bom_no, self.doc.consider_sa_items])
|
|
||||||
d.pro_created = 1
|
|
||||||
|
|
||||||
d.save()
|
def get_packing_items(self, so):
|
||||||
return (check_for =='Report') and bom_dict or pp_detail
|
packing_items = sql("""
|
||||||
|
select
|
||||||
|
t0.name, t2.parent_item, t2.item_code,
|
||||||
|
(t1.qty - ifnull(t1.delivered_qty,0)) * (ifnull(t2.qty,0) / ifnull(t1.qty,1)) as 'pending_qty'
|
||||||
|
from
|
||||||
|
`tabSales Order` t0, `tabSales Order Detail` t1, `tabDelivery Note Packing Detail` t2, `tabItem` t3
|
||||||
|
where
|
||||||
|
t0.name = t1.parent and t0.name = t2.parent and t1.name = t2.parent_detail_docname
|
||||||
|
and t0.name in (%s) and t0.docstatus = 1 and t1.qty > ifnull(t1.delivered_qty,0) and t3.name = t2.item_code
|
||||||
|
and (ifnull(t3.is_pro_applicable, 'No') = 'Yes' or ifnull(t3.is_sub_contracted_item, 'No') = 'Yes')
|
||||||
|
""" % so, as_dict=1)
|
||||||
|
return packing_items
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def add_items(self, packing_items):
|
||||||
|
for d in getlist(self.doclist, 'pp_details'):
|
||||||
|
if d.sales_order:
|
||||||
|
d.parent = ''
|
||||||
|
|
||||||
|
for p in packing_items:
|
||||||
|
item_details = sql("select description, stock_uom, default_bom from tabItem where name=%s", p['item_code'])
|
||||||
|
pi = addchild(self.doc, 'pp_details', 'PP Detail', 1, self.doclist)
|
||||||
|
pi.sales_order = p['name']
|
||||||
|
pi.parent_packing_item = p['parent_item']
|
||||||
|
pi.item_code = p['item_code']
|
||||||
|
pi.description = item_details and item_details[0][0] or ''
|
||||||
|
pi.stock_uom = item_details and item_details[0][1] or ''
|
||||||
|
pi.bom_no = item_details and item_details[0][2] or ''
|
||||||
|
pi.so_pending_qty = flt(p['pending_qty'])
|
||||||
|
pi.planned_qty = flt(p['pending_qty'])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def validate_data(self):
|
||||||
|
for d in getlist(self.doclist, 'pp_details'):
|
||||||
|
if not d.pro_created:
|
||||||
|
self.validate_bom_no(d)
|
||||||
|
|
||||||
|
if not flt(d.planned_qty):
|
||||||
|
msgprint("Please Enter Planned Qty for item: %s at row no: %s"% (d.item_code, d.idx), raise_exception=1)
|
||||||
|
return 'validated'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def validate_bom_no(self, d):
|
||||||
|
if not d.bom_no:
|
||||||
|
msgprint("Please enter bom no for item: %s at row no: %s" % (d.item_code, d.idx), raise_exception=1)
|
||||||
|
else:
|
||||||
|
bom = sql("""select name from `tabBill Of Materials` where item = %s and docstatus = 1
|
||||||
|
and name = %s and ifnull(is_active, 'No') = 'Yes'""", (d.item_code, d.bom_no), as_dict = 1)
|
||||||
|
if not bom:
|
||||||
|
msgprint("""Incorrect BOM No: %s entered for item: %s at row no: %s
|
||||||
|
May be BOM is inactive or for other item or does not exists in the system"""% (d.bom_no, d.item_doce, d.idx))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def download_raw_materials(self):
|
||||||
|
""" Create csv data for required raw material to produce finished goods"""
|
||||||
|
bom_dict = self.get_distinct_bom(action = 'download_rm')
|
||||||
|
self.get_raw_materials(bom_dict)
|
||||||
|
return self.get_csv()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_raw_materials(self, bom_dict):
|
||||||
|
""" Get raw materials considering sub-assembly items """
|
||||||
|
for bom in bom_dict:
|
||||||
|
if self.doc.consider_sa_items == 'Yes':
|
||||||
|
# Get all raw materials considering SA items as raw materials,
|
||||||
|
# so no childs of SA items
|
||||||
|
fl_bom_items = sql("""
|
||||||
|
select item_code, ifnull(sum(qty_consumed_per_unit), 0) * '%s', description, stock_uom
|
||||||
|
from `tabBOM Material`
|
||||||
|
where parent = '%s' and docstatus < 2
|
||||||
|
group by item_code
|
||||||
|
""" % (flt(bom_dict[bom]), bom))
|
||||||
|
|
||||||
|
else:
|
||||||
|
# get all raw materials with sub assembly childs
|
||||||
|
fl_bom_items = sql("""
|
||||||
|
select
|
||||||
|
item_code,ifnull(sum(qty_consumed_per_unit),0)*%s as qty, description, stock_uom
|
||||||
|
from
|
||||||
|
(
|
||||||
|
select distinct fb.name, fb.description, fb.item_code, fb.qty_consumed_per_unit, fb.stock_uom
|
||||||
|
from `tabFlat BOM Detail` fb,`tabItem` it
|
||||||
|
where it.name = fb.item_code and ifnull(it.is_pro_applicable, 'No') = 'No'
|
||||||
|
and ifnull(it.is_sub_contracted_item, 'No') = 'No' and fb.docstatus<2 and fb.parent=%s
|
||||||
|
) a
|
||||||
|
group by item_code,stock_uom
|
||||||
|
""" , (flt(bom_dict[bom]), bom))
|
||||||
|
|
||||||
|
self.make_items_dict(fl_bom_items)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def make_items_dict(self, item_list):
|
||||||
|
for i in item_list:
|
||||||
|
self.item_dict[i[0]] = [(flt(self.item_dict.get(i[1], 0)) + flt(i[1])), i[2], i[3]]
|
||||||
|
|
||||||
|
|
||||||
|
def get_csv(self):
|
||||||
|
item_list = [['Item Code', 'Description', 'Stock UOM', 'Required Qty', 'Indented Qty', 'Ordered Qty', 'Actual Qty']]
|
||||||
|
for d in self.item_dict:
|
||||||
|
item_qty= sql("select sum(indented_qty), sum(ordered_qty), sum(actual_qty) from `tabBin` where item_code = %s", d)
|
||||||
|
item_list.append([d, self.item_dict[d][1], self.item_dict[d][2], self.item_dict[d][0], flt(item_qty[0][0]), flt(item_qty[0][1]), flt(item_qty[0][2])])
|
||||||
|
return item_list
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def raise_production_order(self):
|
||||||
|
"""It will raise production order (Draft) for all distinct FG items"""
|
||||||
|
self.validate_company()
|
||||||
|
self.validate_data()
|
||||||
|
|
||||||
|
pp_items = self.get_distinct_bom(action = 'raise_pro_order')
|
||||||
|
pro = get_obj(dt = 'Production Control').create_production_order(self.doc.company, pp_items)
|
||||||
|
if pro:
|
||||||
|
for d in getlist(self.doclist, 'pp_details'):
|
||||||
|
d.is_pro_created = 1
|
||||||
|
msgprint("Following Production Order has been generated:\n" + '\n'.join(pro))
|
||||||
|
else :
|
||||||
|
msgprint("No Production Order is generated.")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_distinct_bom(self, action):
|
||||||
|
""" Club similar BOM and item for processing"""
|
||||||
|
|
||||||
|
bom_dict, item_dict, pp_items = {}, {}, []
|
||||||
|
for d in getlist(self.doclist, 'pp_details'):
|
||||||
|
if action == 'download_rm':
|
||||||
|
bom_dict[d.bom_no] = bom_dict.get(d.bom_no, 0) + flt(d.planned_qty)
|
||||||
|
elif not d.is_pro_created:
|
||||||
|
item_dict[d.item_code] = [(item_dict.get(d.item_code, 0) + flt(d.planned_qty)), d.bom_no, d.description, d.stock_uom]
|
||||||
|
|
||||||
|
if action == 'raise_pro_order':
|
||||||
|
for d in item_dict:
|
||||||
|
pp_items.append({
|
||||||
|
'production_item' : d,
|
||||||
|
'qty' : item_dict[d][0],
|
||||||
|
'bom_no' : item_dict[d][1],
|
||||||
|
'description' : item_dict[d][2],
|
||||||
|
'stock_uom' : item_dict[d][3],
|
||||||
|
'consider_sa_items' : self.doc.consider_sa_items
|
||||||
|
})
|
||||||
|
|
||||||
|
return action == 'download_rm' and bom_dict or pp_items
|
||||||
|
|||||||
@ -5,15 +5,16 @@
|
|||||||
{
|
{
|
||||||
'creation': '2010-08-08 17:09:14',
|
'creation': '2010-08-08 17:09:14',
|
||||||
'docstatus': 0,
|
'docstatus': 0,
|
||||||
'modified': '2010-12-30 14:49:58',
|
'modified': '2012-01-10 16:26:10',
|
||||||
'modified_by': 'umair@iwebnotes.com',
|
'modified_by': 'Administrator',
|
||||||
'owner': 'jai@webnotestech.com'
|
'owner': 'jai@webnotestech.com'
|
||||||
},
|
},
|
||||||
|
|
||||||
# These values are common for all DocType
|
# These values are common for all DocType
|
||||||
{
|
{
|
||||||
'_last_update': '1294312191',
|
'_last_update': '1326188323',
|
||||||
'colour': 'White:FFF',
|
'colour': 'White:FFF',
|
||||||
|
'default_print_format': 'Standard',
|
||||||
'doctype': 'DocType',
|
'doctype': 'DocType',
|
||||||
'in_create': 1,
|
'in_create': 1,
|
||||||
'issingle': 1,
|
'issingle': 1,
|
||||||
@ -23,7 +24,7 @@
|
|||||||
'section_style': 'Tabbed',
|
'section_style': 'Tabbed',
|
||||||
'server_code_error': ' ',
|
'server_code_error': ' ',
|
||||||
'show_in_menu': 1,
|
'show_in_menu': 1,
|
||||||
'version': 87
|
'version': 106
|
||||||
},
|
},
|
||||||
|
|
||||||
# These values are common for all DocField
|
# These values are common for all DocField
|
||||||
@ -58,32 +59,34 @@
|
|||||||
# DocPerm
|
# DocPerm
|
||||||
{
|
{
|
||||||
'doctype': 'DocPerm',
|
'doctype': 'DocPerm',
|
||||||
'idx': 1,
|
|
||||||
'role': 'System Manager'
|
'role': 'System Manager'
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocPerm
|
# DocPerm
|
||||||
{
|
{
|
||||||
'doctype': 'DocPerm',
|
'doctype': 'DocPerm',
|
||||||
'idx': 2,
|
|
||||||
'role': 'Production User'
|
'role': 'Production User'
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocPerm
|
# DocPerm
|
||||||
{
|
{
|
||||||
'doctype': 'DocPerm',
|
'doctype': 'DocPerm',
|
||||||
'idx': 3,
|
|
||||||
'role': 'Production Manager'
|
'role': 'Production Manager'
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'colour': 'White:FFF',
|
'colour': 'White:FFF',
|
||||||
'description': 'Select Sales Orders from which you want to create Production Orders. Enter the From and To Dates to get Open Orders in that period.',
|
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldtype': 'Section Break',
|
'fieldtype': 'Section Break',
|
||||||
'idx': 1,
|
'label': 'Select Sales Orders'
|
||||||
'label': 'Find Sales Orders'
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldtype': 'Column Break',
|
||||||
|
'width': '50%'
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
@ -91,7 +94,6 @@
|
|||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'from_date',
|
'fieldname': 'from_date',
|
||||||
'fieldtype': 'Date',
|
'fieldtype': 'Date',
|
||||||
'idx': 2,
|
|
||||||
'label': 'From Date'
|
'label': 'From Date'
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -100,125 +102,70 @@
|
|||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'to_date',
|
'fieldname': 'to_date',
|
||||||
'fieldtype': 'Date',
|
'fieldtype': 'Date',
|
||||||
'idx': 3,
|
|
||||||
'label': 'To Date'
|
'label': 'To Date'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldname': 'fg_item',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'label': 'FG Item',
|
||||||
|
'options': 'Item'
|
||||||
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldtype': 'Column Break',
|
'fieldtype': 'Column Break',
|
||||||
'idx': 4,
|
'width': '50%'
|
||||||
'width': '40%'
|
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldtype': 'Button',
|
'fieldname': 'customer',
|
||||||
'idx': 5,
|
'fieldtype': 'Link',
|
||||||
'label': 'Get Open Documents',
|
'label': 'Customer',
|
||||||
'options': 'get_open_docs'
|
'options': 'Customer'
|
||||||
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldname': 'company',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'label': 'Company',
|
||||||
|
'options': 'Company',
|
||||||
|
'reqd': 1
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldtype': 'Section Break',
|
'fieldtype': 'Section Break',
|
||||||
'idx': 6,
|
|
||||||
'options': 'Simple'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'colour': 'White:FFF',
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldtype': 'Button',
|
|
||||||
'idx': 7,
|
|
||||||
'label': 'Clear Document Table',
|
|
||||||
'trigger': 'Client'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'pp_so_details',
|
|
||||||
'fieldtype': 'Table',
|
|
||||||
'idx': 8,
|
|
||||||
'label': 'PP SO Details',
|
|
||||||
'options': 'PP SO Detail'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldtype': 'Section Break',
|
|
||||||
'idx': 9,
|
|
||||||
'options': 'Simple'
|
'options': 'Simple'
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'sales_order',
|
|
||||||
'fieldtype': 'Link',
|
|
||||||
'idx': 10,
|
|
||||||
'label': 'Sales Order',
|
|
||||||
'options': 'Sales Order'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'production_forecast',
|
|
||||||
'fieldtype': 'Link',
|
|
||||||
'hidden': 1,
|
|
||||||
'idx': 11,
|
|
||||||
'label': 'Production Forecast',
|
|
||||||
'options': 'Production Forecast'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldtype': 'Column Break',
|
'fieldtype': 'Column Break',
|
||||||
'idx': 12,
|
'width': '50%'
|
||||||
'width': '40%'
|
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldtype': 'Button',
|
'fieldtype': 'Button',
|
||||||
'idx': 13,
|
'label': 'Get Sales Orders',
|
||||||
'label': 'Add In Plan',
|
'options': 'get_open_sales_orders'
|
||||||
'options': 'pull_document'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'colour': 'White:FFF',
|
|
||||||
'description': 'Click on "Get Items" to get un-fulfilled items from your Sales Orders. After setting the quantities you can raise Production Orders or download the material requirements for analysis',
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldtype': 'Section Break',
|
|
||||||
'idx': 14,
|
|
||||||
'label': 'Items'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldtype': 'Button',
|
|
||||||
'idx': 15,
|
|
||||||
'label': 'Get Items',
|
|
||||||
'options': 'get_items'
|
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldtype': 'Column Break',
|
'fieldtype': 'Column Break',
|
||||||
'idx': 16,
|
|
||||||
'width': '50%'
|
'width': '50%'
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -227,8 +174,8 @@
|
|||||||
'colour': 'White:FFF',
|
'colour': 'White:FFF',
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldtype': 'Button',
|
'fieldtype': 'Button',
|
||||||
'idx': 17,
|
'label': 'Clear SO Table',
|
||||||
'label': 'Clear Item Table',
|
'options': 'clear_so_table',
|
||||||
'trigger': 'Client'
|
'trigger': 'Client'
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -236,10 +183,69 @@
|
|||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldtype': 'Section Break',
|
'fieldtype': 'Section Break',
|
||||||
'idx': 18,
|
|
||||||
'options': 'Simple'
|
'options': 'Simple'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'description': 'Select Sales Orders from which you want to create Production Orders. You can get sales orders based on above criteria.',
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldname': 'pp_so_details',
|
||||||
|
'fieldtype': 'Table',
|
||||||
|
'label': 'PP SO Details',
|
||||||
|
'options': 'PP SO Detail'
|
||||||
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'colour': 'White:FFF',
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldtype': 'Section Break',
|
||||||
|
'label': 'Items'
|
||||||
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldtype': 'Button',
|
||||||
|
'label': 'Get Items from SO',
|
||||||
|
'options': 'get_items_from_so'
|
||||||
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldtype': 'Column Break',
|
||||||
|
'width': '50%'
|
||||||
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'colour': 'White:FFF',
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldtype': 'Button',
|
||||||
|
'label': 'Clear Item Table',
|
||||||
|
'options': 'clear_item_table',
|
||||||
|
'trigger': 'Client'
|
||||||
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldtype': 'Section Break',
|
||||||
|
'options': 'Simple'
|
||||||
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'description': 'Enter items and planned qty for which you want to raise production orders or download raw materials for analysis. You can pull items (which are pending to deliver) from SO as well by adding SO in plan.',
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldname': 'pp_details',
|
||||||
|
'fieldtype': 'Table',
|
||||||
|
'label': 'PP Details',
|
||||||
|
'options': 'PP Detail'
|
||||||
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'colour': 'White:FFF',
|
'colour': 'White:FFF',
|
||||||
@ -248,35 +254,29 @@
|
|||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldname': 'consider_sa_items',
|
'fieldname': 'consider_sa_items',
|
||||||
'fieldtype': 'Select',
|
'fieldtype': 'Select',
|
||||||
'idx': 19,
|
'label': 'Consider Sub Assemblies as Raw Material',
|
||||||
'label': 'Consider Sub Assemblies',
|
|
||||||
'options': 'No\nYes',
|
'options': 'No\nYes',
|
||||||
'reqd': 1
|
'reqd': 1
|
||||||
},
|
},
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'pp_details',
|
|
||||||
'fieldtype': 'Table',
|
|
||||||
'idx': 20,
|
|
||||||
'label': 'PP Details',
|
|
||||||
'options': 'PP Detail'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldtype': 'Section Break',
|
'fieldtype': 'Section Break',
|
||||||
'idx': 21,
|
|
||||||
'options': 'Simple'
|
'options': 'Simple'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
# DocField
|
||||||
|
{
|
||||||
|
'doctype': 'DocField',
|
||||||
|
'fieldtype': 'Column Break',
|
||||||
|
'width': '50%'
|
||||||
|
},
|
||||||
|
|
||||||
# DocField
|
# DocField
|
||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldtype': 'Button',
|
'fieldtype': 'Button',
|
||||||
'idx': 22,
|
|
||||||
'label': 'Raise Production Order',
|
'label': 'Raise Production Order',
|
||||||
'options': 'raise_production_order'
|
'options': 'raise_production_order'
|
||||||
},
|
},
|
||||||
@ -285,7 +285,6 @@
|
|||||||
{
|
{
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldtype': 'Column Break',
|
'fieldtype': 'Column Break',
|
||||||
'idx': 23,
|
|
||||||
'width': '50%'
|
'width': '50%'
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -294,37 +293,7 @@
|
|||||||
'colour': 'White:FFF',
|
'colour': 'White:FFF',
|
||||||
'doctype': 'DocField',
|
'doctype': 'DocField',
|
||||||
'fieldtype': 'Button',
|
'fieldtype': 'Button',
|
||||||
'idx': 24,
|
'label': 'Download Raw Material',
|
||||||
'label': 'Download Raw Material Report',
|
|
||||||
'trigger': 'Client'
|
'trigger': 'Client'
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldtype': 'Section Break',
|
|
||||||
'idx': 25,
|
|
||||||
'label': 'Company Info'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'fiscal_year',
|
|
||||||
'fieldtype': 'Select',
|
|
||||||
'idx': 26,
|
|
||||||
'in_filter': 1,
|
|
||||||
'label': 'Fiscal Year',
|
|
||||||
'options': 'Link:Fiscal Year'
|
|
||||||
},
|
|
||||||
|
|
||||||
# DocField
|
|
||||||
{
|
|
||||||
'doctype': 'DocField',
|
|
||||||
'fieldname': 'company',
|
|
||||||
'fieldtype': 'Link',
|
|
||||||
'idx': 27,
|
|
||||||
'label': 'Company',
|
|
||||||
'options': 'Company'
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -73,6 +73,7 @@ class DocType:
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# get stock and incoming rate on posting date
|
# get stock and incoming rate on posting date
|
||||||
# ---------------------------------------------
|
# ---------------------------------------------
|
||||||
def get_stock_and_rate(self, bom_no = ''):
|
def get_stock_and_rate(self, bom_no = ''):
|
||||||
@ -88,6 +89,7 @@ class DocType:
|
|||||||
if not flt(d.incoming_rate):
|
if not flt(d.incoming_rate):
|
||||||
d.incoming_rate = self.get_incoming_rate(d.item_code, d.s_warehouse, self.doc.posting_date, self.doc.posting_time, d.transfer_qty, d.serial_no, d.fg_item, bom_no)
|
d.incoming_rate = self.get_incoming_rate(d.item_code, d.s_warehouse, self.doc.posting_date, self.doc.posting_time, d.transfer_qty, d.serial_no, d.fg_item, bom_no)
|
||||||
|
|
||||||
|
|
||||||
# Get stock qty on any date
|
# Get stock qty on any date
|
||||||
# ---------------------------
|
# ---------------------------
|
||||||
def get_as_on_stock(self, item, wh, dt, tm):
|
def get_as_on_stock(self, item, wh, dt, tm):
|
||||||
@ -97,29 +99,47 @@ class DocType:
|
|||||||
qty = flt(prev_sle.get('bin_aqat', 0))
|
qty = flt(prev_sle.get('bin_aqat', 0))
|
||||||
return qty
|
return qty
|
||||||
|
|
||||||
|
|
||||||
# Get incoming rate
|
# Get incoming rate
|
||||||
# -------------------
|
# -------------------
|
||||||
def get_incoming_rate(self, item, wh, dt, tm, qty = 0, serial_no = '', fg_item = 'No', bom_no = ''):
|
def get_incoming_rate(self, item, wh, dt, tm, qty = 0, serial_no = '', fg_item = 0, bom_no = ''):
|
||||||
in_rate = 0
|
in_rate = 0
|
||||||
if fg_item == 'Yes':
|
if fg_item:
|
||||||
# re-calculate cost for production item from bom
|
# re-calculate cost for production item from bom
|
||||||
get_obj('BOM Control').calculate_cost(bom_no)
|
get_obj('BOM Control').calculate_cost(bom_no)
|
||||||
in_rate = get_value('Bill Of Materials', bom_no, 'cost_as_per_mar')
|
in_rate = flt(get_value('Bill Of Materials', bom_no, 'total_cost'))
|
||||||
elif wh:
|
elif wh:
|
||||||
in_rate = get_obj('Valuation Control').get_incoming_rate(dt, tm, item, wh, qty, serial_no)
|
in_rate = get_obj('Valuation Control').get_incoming_rate(dt, tm, item, wh, qty, serial_no)
|
||||||
|
|
||||||
return in_rate
|
return in_rate
|
||||||
|
|
||||||
# makes dict of unique items with it's qty
|
|
||||||
#-----------------------------------------
|
|
||||||
def make_items_dict(self, items_list):
|
def make_items_dict(self, items_list):
|
||||||
# items_list = [[item_name, qty]]
|
"""makes dict of unique items with it's qty"""
|
||||||
for i in items_list:
|
for i in items_list:
|
||||||
if self.item_dict.has_key(i[0]):
|
if self.item_dict.has_key(i[0]):
|
||||||
self.item_dict[i[0]][0] = flt(self.item_dict[i[0]][0]) + flt(i[1])
|
self.item_dict[i[0]][0] = flt(self.item_dict[i[0]][0]) + flt(i[1])
|
||||||
else:
|
else:
|
||||||
self.item_dict[i[0]] = [flt(i[1]), cstr(i[2]), cstr(i[3])]
|
self.item_dict[i[0]] = [flt(i[1]), cstr(i[2]), cstr(i[3])]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def update_only_remaining_qty(self):
|
||||||
|
""" Only pending raw material to be issued to shop floor """
|
||||||
|
already_issued_item = {}
|
||||||
|
for t in sql("""select t1.item_code, sum(t1.qty) from `tabStock Entry Detail` t1, `tabStock Entry` t2
|
||||||
|
where t1.parent = t2.name and t2.production_order = %s and t2.process = 'Material Transfer'
|
||||||
|
and t2.docstatus = 1 group by t1.item_code""", self.doc.production_order):
|
||||||
|
already_issued_item[t[0]] = flt(t[1])
|
||||||
|
|
||||||
|
for d in self.item_dict.keys():
|
||||||
|
self.item_dict[d][0] -= already_issued_item.get(d, 0)
|
||||||
|
if self.item_dict[d][0] <= 0:
|
||||||
|
del self.item_dict[d]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_raw_materials(self,pro_obj):
|
def get_raw_materials(self,pro_obj):
|
||||||
"""
|
"""
|
||||||
get all items from flat bom except
|
get all items from flat bom except
|
||||||
@ -130,7 +150,6 @@ class DocType:
|
|||||||
if pro_obj.doc.consider_sa_items == 'Yes':
|
if pro_obj.doc.consider_sa_items == 'Yes':
|
||||||
# Get all raw materials considering SA items as raw materials,
|
# Get all raw materials considering SA items as raw materials,
|
||||||
# so no childs of SA items
|
# so no childs of SA items
|
||||||
|
|
||||||
fl_bom_sa_items = sql("""
|
fl_bom_sa_items = sql("""
|
||||||
select item_code, ifnull(sum(qty_consumed_per_unit), 0) * '%s', description, stock_uom
|
select item_code, ifnull(sum(qty_consumed_per_unit), 0) * '%s', description, stock_uom
|
||||||
from `tabBOM Material`
|
from `tabBOM Material`
|
||||||
@ -138,12 +157,10 @@ class DocType:
|
|||||||
group by item_code
|
group by item_code
|
||||||
""" % ((self.doc.process == 'Backflush') and flt(self.doc.fg_completed_qty) \
|
""" % ((self.doc.process == 'Backflush') and flt(self.doc.fg_completed_qty) \
|
||||||
or flt(pro_obj.doc.qty), cstr(pro_obj.doc.bom_no)))
|
or flt(pro_obj.doc.qty), cstr(pro_obj.doc.bom_no)))
|
||||||
|
|
||||||
self.make_items_dict(fl_bom_sa_items)
|
self.make_items_dict(fl_bom_sa_items)
|
||||||
|
|
||||||
if pro_obj.doc.consider_sa_items == 'No':
|
else:
|
||||||
# get all raw materials with sub assembly childs
|
# get all raw materials with sub assembly childs
|
||||||
|
|
||||||
fl_bom_sa_child_item = sql("""
|
fl_bom_sa_child_item = sql("""
|
||||||
select
|
select
|
||||||
item_code,ifnull(sum(qty_consumed_per_unit),0)*%s as qty,description,stock_uom
|
item_code,ifnull(sum(qty_consumed_per_unit),0)*%s as qty,description,stock_uom
|
||||||
@ -152,17 +169,20 @@ class DocType:
|
|||||||
select distinct fb.name, fb.description, fb.item_code, fb.qty_consumed_per_unit, fb.stock_uom
|
select distinct fb.name, fb.description, fb.item_code, fb.qty_consumed_per_unit, fb.stock_uom
|
||||||
from `tabFlat BOM Detail` fb,`tabItem` it
|
from `tabFlat BOM Detail` fb,`tabItem` it
|
||||||
where it.name = fb.item_code and ifnull(it.is_pro_applicable, 'No') = 'No'
|
where it.name = fb.item_code and ifnull(it.is_pro_applicable, 'No') = 'No'
|
||||||
and ifnull(it.is_sub_contracted_item, 'No') = 'No'
|
and ifnull(it.is_sub_contracted_item, 'No') = 'No' and fb.docstatus<2 and fb.parent=%s
|
||||||
and fb.docstatus<2 and fb.parent=%s
|
|
||||||
) a
|
) a
|
||||||
group by item_code,stock_uom
|
group by item_code,stock_uom
|
||||||
""" , ((self.doc.process == 'Backflush') and flt(self.doc.fg_completed_qty) \
|
""" , ((self.doc.process == 'Backflush') and flt(self.doc.fg_completed_qty) \
|
||||||
or flt(pro_obj.doc.qty), cstr(pro_obj.doc.bom_no)))
|
or flt(pro_obj.doc.qty), cstr(pro_obj.doc.bom_no)))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
self.make_items_dict(fl_bom_sa_child_item)
|
self.make_items_dict(fl_bom_sa_child_item)
|
||||||
|
|
||||||
|
# Update only qty remaining to be issued for production
|
||||||
|
if self.doc.process == 'Material Transfer':
|
||||||
|
self.update_only_remaining_qty()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def add_to_stock_entry_detail(self, pro_obj, item_dict, fg_item = 0):
|
def add_to_stock_entry_detail(self, pro_obj, item_dict, fg_item = 0):
|
||||||
sw, tw = '', ''
|
sw, tw = '', ''
|
||||||
if self.doc.process == 'Material Transfer':
|
if self.doc.process == 'Material Transfer':
|
||||||
@ -174,7 +194,7 @@ class DocType:
|
|||||||
se_child = addchild(self.doc, 'mtn_details', 'Stock Entry Detail', 0, self.doclist)
|
se_child = addchild(self.doc, 'mtn_details', 'Stock Entry Detail', 0, self.doclist)
|
||||||
se_child.s_warehouse = sw
|
se_child.s_warehouse = sw
|
||||||
se_child.t_warehouse = tw
|
se_child.t_warehouse = tw
|
||||||
se_child.fg_item = fg_item
|
se_child.fg_item = fg_item
|
||||||
se_child.item_code = cstr(d)
|
se_child.item_code = cstr(d)
|
||||||
se_child.description = item_dict[d][1]
|
se_child.description = item_dict[d][1]
|
||||||
se_child.uom = item_dict[d][2]
|
se_child.uom = item_dict[d][2]
|
||||||
@ -185,6 +205,7 @@ class DocType:
|
|||||||
se_child.conversion_factor = 1.00
|
se_child.conversion_factor = 1.00
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# get items
|
# get items
|
||||||
#------------------
|
#------------------
|
||||||
def get_items(self):
|
def get_items(self):
|
||||||
@ -201,6 +222,7 @@ class DocType:
|
|||||||
item_dict = {cstr(pro_obj.doc.production_item) : [self.doc.fg_completed_qty, pro_obj.doc.description, pro_obj.doc.stock_uom]}
|
item_dict = {cstr(pro_obj.doc.production_item) : [self.doc.fg_completed_qty, pro_obj.doc.description, pro_obj.doc.stock_uom]}
|
||||||
self.add_to_stock_entry_detail(pro_obj, item_dict, fg_item = 1)
|
self.add_to_stock_entry_detail(pro_obj, item_dict, fg_item = 1)
|
||||||
|
|
||||||
|
|
||||||
def validate_transfer_qty(self):
|
def validate_transfer_qty(self):
|
||||||
for d in getlist(self.doclist, 'mtn_details'):
|
for d in getlist(self.doclist, 'mtn_details'):
|
||||||
if flt(d.transfer_qty) <= 0:
|
if flt(d.transfer_qty) <= 0:
|
||||||
@ -210,6 +232,7 @@ class DocType:
|
|||||||
msgprint("Transfer Quantity is more than Available Qty at Row No " + cstr(d.idx))
|
msgprint("Transfer Quantity is more than Available Qty at Row No " + cstr(d.idx))
|
||||||
raise Exception
|
raise Exception
|
||||||
|
|
||||||
|
|
||||||
def calc_amount(self):
|
def calc_amount(self):
|
||||||
total_amount = 0
|
total_amount = 0
|
||||||
for d in getlist(self.doclist, 'mtn_details'):
|
for d in getlist(self.doclist, 'mtn_details'):
|
||||||
@ -217,6 +240,7 @@ class DocType:
|
|||||||
total_amount += flt(d.amount)
|
total_amount += flt(d.amount)
|
||||||
self.doc.total_amount = flt(total_amount)
|
self.doc.total_amount = flt(total_amount)
|
||||||
|
|
||||||
|
|
||||||
def add_to_values(self, d, wh, qty, is_cancelled):
|
def add_to_values(self, d, wh, qty, is_cancelled):
|
||||||
self.values.append({
|
self.values.append({
|
||||||
'item_code' : d.item_code,
|
'item_code' : d.item_code,
|
||||||
@ -269,8 +293,7 @@ class DocType:
|
|||||||
msgprint("error:Already Produced Qty for %s is %s and maximum allowed Qty is %s" % (pro_obj.doc.production_item, cstr(pro_obj.doc.produced_qty) or 0.00 , cstr(pro_obj.doc.qty)))
|
msgprint("error:Already Produced Qty for %s is %s and maximum allowed Qty is %s" % (pro_obj.doc.production_item, cstr(pro_obj.doc.produced_qty) or 0.00 , cstr(pro_obj.doc.qty)))
|
||||||
raise Exception
|
raise Exception
|
||||||
|
|
||||||
# Validate
|
|
||||||
# ------------------
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
sl_obj = get_obj("Stock Ledger", "Stock Ledger")
|
sl_obj = get_obj("Stock Ledger", "Stock Ledger")
|
||||||
sl_obj.scrub_serial_nos(self)
|
sl_obj.scrub_serial_nos(self)
|
||||||
@ -280,11 +303,12 @@ class DocType:
|
|||||||
pro_obj = get_obj('Production Order', self.doc.production_order)
|
pro_obj = get_obj('Production Order', self.doc.production_order)
|
||||||
self.validate_for_production_order(pro_obj)
|
self.validate_for_production_order(pro_obj)
|
||||||
self.get_stock_and_rate(pro_obj and pro_obj.doc.bom_no or '')
|
self.get_stock_and_rate(pro_obj and pro_obj.doc.bom_no or '')
|
||||||
self.validate_incoming_rate()
|
|
||||||
self.validate_warehouse(pro_obj)
|
self.validate_warehouse(pro_obj)
|
||||||
|
self.validate_incoming_rate()
|
||||||
self.calc_amount()
|
self.calc_amount()
|
||||||
get_obj('Sales Common').validate_fiscal_year(self.doc.fiscal_year,self.doc.posting_date,'Posting Date')
|
get_obj('Sales Common').validate_fiscal_year(self.doc.fiscal_year,self.doc.posting_date,'Posting Date')
|
||||||
|
|
||||||
|
|
||||||
# If target warehouse exists, incoming rate is mandatory
|
# If target warehouse exists, incoming rate is mandatory
|
||||||
# --------------------------------------------------------
|
# --------------------------------------------------------
|
||||||
def validate_incoming_rate(self):
|
def validate_incoming_rate(self):
|
||||||
@ -292,6 +316,7 @@ class DocType:
|
|||||||
if not flt(d.incoming_rate) and d.t_warehouse:
|
if not flt(d.incoming_rate) and d.t_warehouse:
|
||||||
msgprint("Rate is mandatory for Item: %s at row %s" % (d.item_code, d.idx), raise_exception=1)
|
msgprint("Rate is mandatory for Item: %s at row %s" % (d.item_code, d.idx), raise_exception=1)
|
||||||
|
|
||||||
|
|
||||||
# Validate warehouse
|
# Validate warehouse
|
||||||
# -----------------------------------
|
# -----------------------------------
|
||||||
def validate_warehouse(self, pro_obj):
|
def validate_warehouse(self, pro_obj):
|
||||||
@ -336,7 +361,7 @@ class DocType:
|
|||||||
msgprint(" Target Warehouse should be same as WIP Warehouse %s in Production Order %s at Row No %s" % (cstr(pro_obj.doc.wip_warehouse), cstr(pro_obj.doc.name), cstr(d.idx)) )
|
msgprint(" Target Warehouse should be same as WIP Warehouse %s in Production Order %s at Row No %s" % (cstr(pro_obj.doc.wip_warehouse), cstr(pro_obj.doc.name), cstr(d.idx)) )
|
||||||
raise Exception
|
raise Exception
|
||||||
if not cstr(d.s_warehouse):
|
if not cstr(d.s_warehouse):
|
||||||
msgprint("Please Enter Source Warehouse at Row No %s is mandatory." % (cstr(d.idx)))
|
msgprint("Please Enter Source Warehouse at Row No %s." % (cstr(d.idx)))
|
||||||
raise Exception
|
raise Exception
|
||||||
if self.doc.process == 'Backflush':
|
if self.doc.process == 'Backflush':
|
||||||
if flt(d.fg_item):
|
if flt(d.fg_item):
|
||||||
@ -362,24 +387,26 @@ class DocType:
|
|||||||
msgprint("The Total of FG Qty %s in Stock Entry Detail do not match with FG Completed Qty %s" % (flt(fg_qty), flt(self.doc.fg_completed_qty)))
|
msgprint("The Total of FG Qty %s in Stock Entry Detail do not match with FG Completed Qty %s" % (flt(fg_qty), flt(self.doc.fg_completed_qty)))
|
||||||
raise Exception
|
raise Exception
|
||||||
|
|
||||||
|
|
||||||
def update_production_order(self, is_submit):
|
def update_production_order(self, is_submit):
|
||||||
if self.doc.production_order:
|
if self.doc.production_order:
|
||||||
pro_obj = get_obj("Production Order", self.doc.production_order)
|
pro_obj = get_obj("Production Order", self.doc.production_order)
|
||||||
if flt(pro_obj.doc.docstatus) != 1:
|
if flt(pro_obj.doc.docstatus) != 1:
|
||||||
msgprint("One cannot do any transaction against Production Order : %s, as it's not submitted" % (pro_obj.doc.name))
|
msgprint("You cannot do any transaction against Production Order : %s, as it's not submitted" % (pro_obj.doc.name))
|
||||||
raise Exception
|
raise Exception
|
||||||
if pro_obj.doc.status == 'Stopped':
|
if pro_obj.doc.status == 'Stopped':
|
||||||
msgprint("One cannot do any transaction against Production Order : %s, as it's status is 'Stopped'" % (pro_obj.doc.name))
|
msgprint("You cannot do any transaction against Production Order : %s, as it's status is 'Stopped'" % (pro_obj.doc.name))
|
||||||
raise Exception
|
raise Exception
|
||||||
if getdate(pro_obj.doc.posting_date) > getdate(self.doc.posting_date):
|
if getdate(pro_obj.doc.posting_date) > getdate(self.doc.posting_date):
|
||||||
msgprint("Posting Date of Stock Entry cannot be before Posting Date of Production Order "+ cstr(self.doc.production_order))
|
msgprint("Posting Date of Stock Entry cannot be before Posting Date of Production Order "+ cstr(self.doc.production_order))
|
||||||
raise Exception
|
raise Exception
|
||||||
if self.doc.process == 'Backflush':
|
if self.doc.process == 'Backflush':
|
||||||
pro_obj.doc.produced_qty = flt(pro_obj.doc.produced_qty) + (is_submit and 1 or -1 ) * flt(self.doc.fg_completed_qty)
|
pro_obj.doc.produced_qty = flt(pro_obj.doc.produced_qty) + (is_submit and 1 or -1 ) * flt(self.doc.fg_completed_qty)
|
||||||
get_obj('Warehouse', pro_obj.doc.fg_warehouse).update_bin(0, 0, 0, 0, (is_submit and 1 or -1 ) * flt(self.doc.fg_completed_qty), pro_obj.doc.production_item, now())
|
get_obj('Warehouse', pro_obj.doc.fg_warehouse).update_bin(0, 0, 0, 0, (is_submit and 1 or -1 ) * flt(self.doc.fg_completed_qty), pro_obj.doc.production_item, now())
|
||||||
pro_obj.doc.status = (flt(pro_obj.doc.qty) == flt(pro_obj.doc.produced_qty)) and 'Completed' or 'In Process'
|
pro_obj.doc.status = (flt(pro_obj.doc.qty) == flt(pro_obj.doc.produced_qty)) and 'Completed' or 'In Process'
|
||||||
pro_obj.doc.save()
|
pro_obj.doc.save()
|
||||||
|
|
||||||
|
|
||||||
# Create / Update Serial No
|
# Create / Update Serial No
|
||||||
# ----------------------------------
|
# ----------------------------------
|
||||||
def update_serial_no(self, is_submit):
|
def update_serial_no(self, is_submit):
|
||||||
@ -400,8 +427,7 @@ class DocType:
|
|||||||
if self.doc.purpose == 'Purchase Return':
|
if self.doc.purpose == 'Purchase Return':
|
||||||
delete_doc("Serial No", serial_no)
|
delete_doc("Serial No", serial_no)
|
||||||
|
|
||||||
# On Submit
|
|
||||||
# ------------------
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
self.validate_transfer_qty()
|
self.validate_transfer_qty()
|
||||||
# Check for Approving Authority
|
# Check for Approving Authority
|
||||||
@ -411,14 +437,14 @@ class DocType:
|
|||||||
# update Production Order
|
# update Production Order
|
||||||
self.update_production_order(1)
|
self.update_production_order(1)
|
||||||
|
|
||||||
# On Cancel
|
|
||||||
# -------------------
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
self.update_serial_no(0)
|
self.update_serial_no(0)
|
||||||
self.update_stock_ledger(1)
|
self.update_stock_ledger(1)
|
||||||
# update Production Order
|
# update Production Order
|
||||||
self.update_production_order(0)
|
self.update_production_order(0)
|
||||||
|
|
||||||
|
|
||||||
def get_cust_values(self):
|
def get_cust_values(self):
|
||||||
tbl = self.doc.delivery_note_no and 'Delivery Note' or 'Receivable Voucher'
|
tbl = self.doc.delivery_note_no and 'Delivery Note' or 'Receivable Voucher'
|
||||||
record_name = self.doc.delivery_note_no or self.doc.sales_invoice_no
|
record_name = self.doc.delivery_note_no or self.doc.sales_invoice_no
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user