moved directory structure

This commit is contained in:
Rushabh Mehta
2012-09-24 19:13:42 +05:30
parent e47a6779e9
commit 2fa2f7178d
1637 changed files with 47 additions and 11450 deletions

5
production/__init__.py Normal file
View File

@@ -0,0 +1,5 @@
from __future__ import unicode_literals
install_docs = [
{"doctype":"Role", "role_name":"Production Manager", "name":"Production Manager"},
{"doctype":"Role", "role_name":"Production User", "name":"Production User"},
]

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,164 @@
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// On REFRESH
cur_frm.cscript.refresh = function(doc,dt,dn){
if(!doc.__islocal) {
set_field_permlevel('item',1);
unhide_field('update_cost_as_on_today');
} else {
hide_field('update_cost_as_on_today');
}
}
// 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 Item', 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 Item',rm[i].name, {'amount': amt}, 'bom_materials');
set_multiple('BOM Item',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) {
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['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_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';
}
cur_frm.fields_dict['bom_materials'].grid.get_field('bom_no').get_query = function(doc) {
var d = locals[this.doctype][this.docname];
return 'SELECT DISTINCT `tabBOM`.`name`, `tabBOM`.`remarks` FROM `tabBOM` WHERE `tabBOM`.`item` = "' + d.item_code + '" AND `tabBOM`.`is_active` = "Yes" AND `tabBOM`.docstatus = 1 AND `tabBOM`.`name` like "%s" ORDER BY `tabBOM`.`name` LIMIT 50';
}
cur_frm.cscript.validate = function(doc, dt, dn) {
calculate_op_cost(doc, dt, dn);
calculate_rm_cost(doc, dt, dn);
calculate_total(doc);
}

View File

@@ -0,0 +1,400 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
import webnotes
from webnotes.utils import cint, cstr, flt, get_defaults, getdate, now, nowdate
from webnotes.model.doc import Document, addchild, getchildren, make_autoname
from webnotes.model.doclist import getlist
from webnotes.model.code import get_obj
from webnotes import msgprint, errprint
set = webnotes.conn.set
sql = webnotes.conn.sql
get_value = webnotes.conn.get_value
# -----------------------------------------------------------------------------------------
class DocType:
def __init__(self, doc, doclist=[]):
self.doc = doc
self.doclist = doclist
def autoname(self):
last_name = sql("select max(name) from `tabBOM` where name like 'BOM/%s/%%'" % self.doc.item)
if last_name:
idx = cint(cstr(last_name[0][0]).split('/')[-1]) + 1
else:
idx = 1
self.doc.name = 'BOM/' + self.doc.item + ('/%.3i' % idx)
def get_item_det(self, item_code):
item = sql("""select name, is_asset_item, is_purchase_item, docstatus, is_sub_contracted_item,
description, stock_uom, default_bom, last_purchase_rate, standard_rate, is_manufactured_item from `tabItem`
where item_code = %s""", item_code, as_dict = 1)
return item
def get_item_detail(self, item_code):
""" Get stock uom and description for finished good item"""
item = self.get_item_det(item_code)
ret={
'description' : item and item[0]['description'] or '',
'uom' : item and item[0]['stock_uom'] or ''
}
return ret
def get_workstation_details(self,workstation):
""" Fetch hour rate from workstation master"""
ws = sql("select hour_rate from `tabWorkstation` where name = %s",workstation , as_dict = 1)
ret = {
'hour_rate' : ws and flt(ws[0]['hour_rate']) or '',
}
return ret
def validate_rm_item(self, item):
""" Validate raw material items"""
if item[0]['name'] == self.doc.item:
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':
msgprint("Sorry!!! Item " + item[0]['name'] + " is an Asset of the company. Entered in BOM => " + cstr(self.doc.name), raise_exception = 1)
if not item or item[0]['docstatus'] == 2:
msgprint("Item %s does not exist in system" % item[0]['item_code'], raise_exception = 1)
def get_bom_material_detail(self, arg):
""" Get raw material details like uom, desc and rate"""
arg = eval(arg)
item = self.get_item_det(arg['item_code'])
self.validate_rm_item(item)
arg['bom_no'] = arg['bom_no'] or item and cstr(item[0]['default_bom']) or ''
arg.update(item[0])
rate = self.get_rm_rate(arg)
ret_item = {
'description' : item and arg['description'] or '',
'stock_uom' : item and arg['stock_uom'] or '',
'bom_no' : arg['bom_no'],
'rate' : rate
}
return ret_item
def get_rm_rate(self, arg):
""" Get raw material rate as per selected method, if bom exists takes bom cost """
if arg['bom_no']:
bom = sql("""select name, total_cost/quantity as unit_cost from `tabBOM`
where is_active = 'Yes' and name = %s""", arg['bom_no'], as_dict=1)
rate = bom and bom[0]['unit_cost'] or 0
elif arg and (arg['is_purchase_item'] == 'Yes' or arg['is_sub_contracted_item'] == 'Yes'):
if self.doc.rm_cost_as_per == 'Valuation Rate':
rate = self.get_valuation_rate(arg)
elif self.doc.rm_cost_as_per == 'Last Purchase Rate':
rate = arg['last_purchase_rate']
elif self.doc.rm_cost_as_per == 'Standard Rate':
rate = arg['standard_rate']
return rate
def get_valuation_rate(self, arg):
""" Get average valuation rate of relevant warehouses
as per valuation method (MAR/FIFO)
as on costing date
"""
dt = self.doc.costing_date or nowdate()
time = self.doc.costing_date == nowdate() and now().split()[1] or '23:59'
warehouse = sql("select warehouse from `tabBin` where item_code = %s", arg['item_code'])
rate = []
for wh in warehouse:
r = get_obj('Valuation Control').get_incoming_rate(dt, time, arg['item_code'], wh[0], qty = arg.get('qty', 0))
if r:
rate.append(r)
return rate and flt(sum(rate))/len(rate) or 0
def manage_default_bom(self):
""" Uncheck others if current one is selected as default, update default bom in item master"""
if self.doc.is_default and self.doc.is_active == 'Yes':
sql("update `tabBOM` set is_default = 0 where name != %s and item=%s", (self.doc.name, self.doc.item))
# update default bom in Item Master
sql("update `tabItem` set default_bom = %s where name = %s", (self.doc.name, self.doc.item))
else:
sql("update `tabItem` set default_bom = '' where name = %s and default_bom = %s", (self.doc.item, self.doc.name))
def manage_active_bom(self):
""" Manage active/inactive """
if self.doc.is_active == 'Yes':
self.validate()
else:
self.check_active_parent_boms()
def check_active_parent_boms(self):
""" Check parent BOM before making it inactive """
act_pbom = sql("""select distinct t1.parent from `tabBOM Item` t1, `tabBOM` 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=1)
def calculate_cost(self):
"""Calculate bom totals"""
self.doc.costing_date = nowdate()
self.calculate_op_cost()
self.calculate_rm_cost()
self.doc.total_cost = self.doc.raw_material_cost + self.doc.operating_cost
self.doc.modified = now()
self.doc.save()
self.update_flat_bom_engine(is_submit = self.doc.docstatus)
def calculate_op_cost(self):
"""Update workstation rate and calculates totals"""
total_op_cost = 0
for d in getlist(self.doclist, 'bom_operations'):
hour_rate = sql("select hour_rate from `tabWorkstation` where name = %s", cstr(d.workstation))
d.hour_rate = hour_rate and flt(hour_rate[0][0]) or 0
d.operating_cost = flt(d.hour_rate) * flt(d.time_in_mins) / 60
d.save()
total_op_cost += d.operating_cost
self.doc.operating_cost = total_op_cost
def calculate_rm_cost(self):
"""Fetch RM rate as per today's valuation rate and calculate totals"""
total_rm_cost = 0
for d in getlist(self.doclist, 'bom_materials'):
#if self.doc.rm_cost_as_per == 'Valuation Rate':
arg = {'item_code': d.item_code, 'qty': d.qty, 'bom_no': d.bom_no}
ret = self.get_bom_material_detail(cstr(arg))
for k in ret:
d.fields[k] = ret[k]
d.amount = flt(d.rate) * flt(d.qty)
d.save()
total_rm_cost += d.amount
self.doc.raw_material_cost = total_rm_cost
def validate_main_item(self):
""" Validate main FG item"""
item = self.get_item_det(self.doc.item)
if not item:
msgprint("Item %s does not exists in the system or expired." % self.doc.item, raise_exception = 1)
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,
you can not make BOM for it""" % self.doc.item, raise_exception = 1)
def validate_operations(self):
""" Check duplicate operation no"""
self.op = []
for d in getlist(self.doclist, 'bom_operations'):
if cstr(d.operation_no) in self.op:
msgprint("Operation no: %s is repeated in Operations Table"% d.operation_no, raise_exception=1)
else:
# add operation in op list
self.op.append(cstr(d.operation_no))
def validate_materials(self):
""" Validate raw material entries """
check_list = []
for m in getlist(self.doclist, 'bom_materials'):
# check if operation no not in op table
if m.operation_no not in self.op:
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)
item = self.get_item_det(m.item_code)
if item[0]['is_manufactured_item'] == 'Yes' or item[0]['is_sub_contracted_item'] == 'Yes':
if not m.bom_no:
msgprint("Please enter BOM No aginst item: %s at row no: %s"% (m.item_code, m.idx), raise_exception=1)
else:
self.validate_bom_no(m.item_code, m.bom_no, m.idx)
elif m.bom_no:
msgprint("""As Item %s is not a manufactured / sub-contracted item,
you can enter BOM against it (Row No: %s)."""% (m.item_code, m.idx), raise_excepiton = 1)
if flt(m.qty) <= 0:
msgprint("Please enter qty against raw material: %s at row no: %s"% (m.item_code, m.idx), raise_exception = 1)
self.check_if_item_repeated(m.item_code, m.operation_no, check_list)
def validate_bom_no(self, item, bom_no, idx):
"""Validate BOM No of sub-contracted items"""
bom = sql("""select name from `tabBOM` where name = %s and item = %s
and ifnull(is_active, 'No') = 'Yes' and docstatus < 2 """, (bom_no, item), as_dict =1)
if not bom:
msgprint("""Incorrect BOM No: %s against item: %s at row no: %s.
It may be inactive or cancelled or for some other item."""% (bom_no, item, idx), raise_exception = 1)
def check_if_item_repeated(self, item, op, check_list):
if [cstr(item), cstr(op)] in check_list:
msgprint("Item %s has been entered twice against same operation" % item, raise_exception = 1)
else:
check_list.append([cstr(item), cstr(op)])
#----- Document on Save function------
def validate(self):
self.validate_main_item()
self.validate_operations()
self.validate_materials()
def check_recursion(self):
""" Check whether reqursion occurs in any bom"""
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 Item` 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]), self.doc.name), raise_exception = 1)
if b[0]:
bom_list.append(b[0])
def on_update(self):
self.check_recursion()
def add_to_flat_bom_detail(self, is_submit = 0):
"Add items to Flat BOM table"
self.doclist = self.doc.clear_table(self.doclist, 'flat_bom_details', 1)
for d in self.cur_flat_bom_items:
ch = addchild(self.doc, 'flat_bom_details', 'BOM Explosion Item', 1, self.doclist)
for i in d.keys():
ch.fields[i] = d[i]
ch.docstatus = is_submit
ch.save(1)
self.doc.save()
def get_child_flat_bom_items(self, bom_no, qty):
""" Add all items from Flat BOM of child BOM"""
child_fb_items = sql("""select item_code, description, stock_uom, qty, rate, amount, parent_bom, mat_detail_no, qty_consumed_per_unit
from `tabBOM Explosion Item` where parent = '%s' and docstatus = 1""" % bom_no, as_dict = 1)
for d in child_fb_items:
self.cur_flat_bom_items.append({
'item_code' : d['item_code'],
'description' : d['description'],
'stock_uom' : d['stock_uom'],
'qty' : flt(d['qty_consumed_per_unit'])*qty,
'rate' : flt(d['rate']),
'amount' : flt(d['amount']),
'parent_bom' : d['parent_bom'],
'mat_detail_no' : d['mat_detail_no'],
'qty_consumed_per_unit' : flt(d['qty_consumed_per_unit'])*qty/flt(self.doc.quantity)
})
# Get Current Flat BOM Items
# -----------------------------
def get_current_flat_bom_items(self):
""" Get all raw materials including items from child bom"""
self.cur_flat_bom_items = []
for d in getlist(self.doclist, 'bom_materials'):
self.cur_flat_bom_items.append({
'item_code' : d.item_code,
'description' : d.description,
'stock_uom' : d.stock_uom,
'qty' : flt(d.qty),
'rate' : flt(d.rate),
'amount' : flt(d.amount),
'parent_bom' : d.parent, #item and item[0][0]=='No' and d.bom_no or d.parent,
'mat_detail_no' : d.name,
'qty_consumed_per_unit' : flt(d.qty_consumed_per_unit)
})
if d.bom_no:
self.get_child_flat_bom_items(d.bom_no, d.qty)
def update_flat_bom_engine(self, is_submit = 0):
""" Update Flat BOM, following will be correct data"""
self.get_current_flat_bom_items()
self.add_to_flat_bom_detail(is_submit)
def get_parent_bom_list(self, bom_no):
p_bom = sql("select parent from `tabBOM Item` where bom_no = '%s'" % bom_no)
return p_bom and [i[0] for i in p_bom] or []
def on_submit(self):
self.manage_default_bom()
self.update_flat_bom_engine(1)
def on_cancel(self):
# check if used in any other bom
par = sql("""select t1.parent from `tabBOM Item` t1, `tabBOM` t2
where t1.parent = t2.name and t1.bom_no = %s and t1.docstatus = 1 and t2.is_active = 'Yes'""", self.doc.name)
if par:
msgprint("BOM can not be cancelled, as it is a child item in following active BOM %s"% [d[0] for d in par])
raise Exception

View File

@@ -0,0 +1,462 @@
# DocType, BOM
[
# These values are common in all dictionaries
{
'creation': '2012-03-27 14:36:02',
'docstatus': 0,
'modified': '2012-03-27 14:45:46',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all DocType
{
'_last_update': u'1326963484',
'allow_attach': 0,
'allow_copy': 0,
'allow_email': 0,
'allow_print': 0,
'allow_rename': 0,
'allow_trash': 1,
'colour': u'White:FFF',
'default_print_format': u'Standard',
'doctype': 'DocType',
'document_type': u'Master',
'hide_heading': 0,
'hide_toolbar': 0,
'in_create': 0,
'is_submittable': 1,
'issingle': 0,
'istable': 0,
'module': u'Production',
'name': '__common__',
'read_only': 0,
'search_fields': u'item',
'section_style': u'Simple',
'server_code_error': u' ',
'show_in_menu': 0,
'subject': u'%(item)s',
'version': 196
},
# These values are common for all DocField
{
'doctype': u'DocField',
'name': '__common__',
'parent': u'BOM',
'parentfield': u'fields',
'parenttype': u'DocType'
},
# These values are common for all DocPerm
{
'doctype': u'DocPerm',
'name': '__common__',
'parent': u'BOM',
'parentfield': u'permissions',
'parenttype': u'DocType',
'read': 1
},
# DocType, BOM
{
'doctype': 'DocType',
'name': u'BOM'
},
# DocPerm
{
'cancel': 1,
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'System Manager',
'submit': 1,
'write': 1
},
# DocPerm
{
'doctype': u'DocPerm',
'permlevel': 1,
'role': u'System Manager'
},
# DocPerm
{
'cancel': 1,
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'Production Manager',
'submit': 1,
'write': 1
},
# DocPerm
{
'doctype': u'DocPerm',
'permlevel': 1,
'role': u'Production Manager'
},
# DocPerm
{
'cancel': 1,
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'Production User',
'submit': 1,
'write': 1
},
# DocPerm
{
'doctype': u'DocPerm',
'permlevel': 1,
'role': u'Production User'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break0',
'fieldtype': u'Column Break',
'oldfieldtype': u'Column Break',
'permlevel': 0,
'width': u'50%'
},
# DocField
{
'colour': u'White:FFF',
'description': u'Select the item code for which Bill of Material is being created',
'doctype': u'DocField',
'fieldname': u'item',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Item',
'oldfieldname': u'item',
'oldfieldtype': u'Link',
'options': u'Item',
'permlevel': 0,
'reqd': 1,
'search_index': 1,
'trigger': u'Client'
},
# DocField
{
'colour': u'White:FFF',
'description': u'Total quantity of items for which raw materials required and operations done will be defined',
'doctype': u'DocField',
'fieldname': u'quantity',
'fieldtype': u'Currency',
'label': u'Quantity',
'oldfieldname': u'quantity',
'oldfieldtype': u'Currency',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'uom',
'fieldtype': u'Select',
'label': u'UOM',
'options': u'link:UOM',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'description',
'fieldtype': u'Text',
'label': u'Description',
'oldfieldname': u'description',
'oldfieldtype': u'Text',
'permlevel': 0,
'width': u'300px'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break1',
'fieldtype': u'Column Break',
'permlevel': 0,
'width': u'50%'
},
# DocField
{
'description': u'Select name of the project if BOM need to be created against any project',
'doctype': u'DocField',
'fieldname': u'project_name',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Project Name',
'oldfieldname': u'project_name',
'oldfieldtype': u'Link',
'options': u'Project',
'permlevel': 0,
'trigger': u'Client'
},
# DocField
{
'allow_on_submit': 1,
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'is_active',
'fieldtype': u'Select',
'hidden': 0,
'label': u'Is Active',
'no_copy': 1,
'oldfieldname': u'is_active',
'oldfieldtype': u'Select',
'options': u'\nYes\nNo',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'allow_on_submit': 1,
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'is_default',
'fieldtype': u'Check',
'label': u'Is Default',
'no_copy': 1,
'oldfieldname': u'is_default',
'oldfieldtype': u'Check',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'maintained_by',
'fieldtype': u'Data',
'label': u'Maintained By',
'oldfieldname': u'maintained_by',
'oldfieldtype': u'Data',
'permlevel': 0
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'remarks',
'fieldtype': u'Text',
'label': u'Remarks',
'no_copy': 1,
'oldfieldname': u'remarks',
'oldfieldtype': u'Text',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'operations',
'fieldtype': u'Section Break',
'label': u'Operations',
'oldfieldtype': u'Section Break',
'permlevel': 0
},
# DocField
{
'colour': u'White:FFF',
'description': u'Specify the operations, operating cost and give a unique Operation no to your operations.',
'doctype': u'DocField',
'fieldname': u'bom_operations',
'fieldtype': u'Table',
'label': u'BOM Operations',
'oldfieldname': u'bom_operations',
'oldfieldtype': u'Table',
'options': u'BOM Operation',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'materials',
'fieldtype': u'Section Break',
'label': u'Materials',
'oldfieldtype': u'Section Break',
'permlevel': 0
},
# DocField
{
'colour': u'White:FFF',
'description': u'Enter the raw materials required to manufacture the BOM item. Specify the operation no as entered in the previous tab which will be performed on the raw materials entered.',
'doctype': u'DocField',
'fieldname': u'bom_materials',
'fieldtype': u'Table',
'label': u'BOM Item',
'oldfieldname': u'bom_materials',
'oldfieldtype': u'Table',
'options': u'BOM Item',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'costing',
'fieldtype': u'Section Break',
'label': u'Costing',
'oldfieldtype': u'Section Break',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break2',
'fieldtype': u'Column Break',
'permlevel': 0,
'width': u'50%'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'rm_cost_as_per',
'fieldtype': u'Select',
'label': u'Consider Raw Material Cost As Per',
'options': u'Valuation Rate\nLast Purchase Rate\nStandard Rate',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'costing_date',
'fieldtype': u'Date',
'label': u'Costing Date',
'permlevel': 1
},
# DocField
{
'allow_on_submit': 1,
'doctype': u'DocField',
'fieldname': u'update_cost_as_on_today',
'fieldtype': u'Button',
'label': u'Update Cost as on today',
'options': u'calculate_cost',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break3',
'fieldtype': u'Column Break',
'permlevel': 0,
'width': u'50%'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'raw_material_cost',
'fieldtype': u'Float',
'label': u'Raw Material Cost',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'operating_cost',
'fieldtype': u'Float',
'label': u'Operating Cost',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'total_cost',
'fieldtype': u'Float',
'label': u'Total Cost',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'section_break0',
'fieldtype': u'Section Break',
'hidden': 1,
'options': u'Simple',
'permlevel': 0,
'print_hide': 0
},
# DocField
{
'colour': u'White:FFF',
'default': u'No Toolbar',
'doctype': u'DocField',
'fieldname': u'flat_bom_details',
'fieldtype': u'Table',
'hidden': 1,
'label': u'BOM Explosion Item',
'no_copy': 1,
'oldfieldname': u'flat_bom_details',
'oldfieldtype': u'Table',
'options': u'BOM Explosion Item',
'permlevel': 0,
'print_hide': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'trash_reason',
'fieldtype': u'Small Text',
'hidden': 1,
'label': u'Trash Reason',
'oldfieldname': u'trash_reason',
'oldfieldtype': u'Small Text',
'permlevel': 1
},
# DocField
{
'depends_on': u'eval:doc.amended_from',
'description': u'The date at which current entry is corrected in the system.',
'doctype': u'DocField',
'fieldname': u'amendment_date',
'fieldtype': u'Date',
'label': u'Amendment Date',
'no_copy': 1,
'permlevel': 0,
'print_hide': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'amended_from',
'fieldtype': u'Link',
'label': u'Amended From',
'no_copy': 1,
'options': u'Sales Invoice',
'permlevel': 1,
'print_hide': 1
}
]

View File

@@ -0,0 +1,48 @@
// render
wn.doclistviews['BOM'] = wn.views.ListView.extend({
init: function(d) {
this._super(d);
this.fields = this.fields.concat([
'`tabBOM`.item',
'`tabBOM`.uom',
'IFNULL(`tabBOM`.quantity, 0) as quantity',
'`tabBOM`.is_active',
'`tabBOM`.costing_date',
'`tabBOM`.total_cost',
'`tabBOM`.description',
]);
this.stats = this.stats.concat(['company']);
},
prepare_data: function(data) {
this._super(data);
data.costing_date = wn.datetime.str_to_user(data.costing_date);
data.description = (data.is_active === 'Yes' ? '' : '[Inactive] ') + data.description;
},
columns: [
{width: '3%', content: 'check'},
{width: '3%', content: 'docstatus'},
{width: '15%', content: 'name'},
{width: '15%', content: 'item'},
{width: '23%', content: 'description+tags'},
{
width: '12%',
content: function(parent, data) {
$(parent).html(data.quantity + ' ' + data.uom)
},
css: {'text-align':'right'},
},
{
width: '20%',
content: function(parent, data) {
$(parent).html(sys_defaults.currency + " "
+ fmt_money(data.total_cost));
},
css: {'text-align': 'right'},
},
{width: '12%', content:'costing_date', css: {
'text-align': 'right', 'color':'#777'
}},
]
});

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,122 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Please edit this list and import only required elements
from __future__ import unicode_literals
import webnotes
from webnotes.utils import cint, flt
from webnotes.model import db_exists
from webnotes.model.doc import Document, addchild, getchildren, make_autoname
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
get_value = webnotes.conn.get_value
in_transaction = webnotes.conn.in_transaction
convert_to_lists = webnotes.conn.convert_to_lists
# -----------------------------------------------------------------------------------------
class DocType:
def __init__(self, doc, doclist):
self.doc = doc
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, `tabBOM` 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 BOM 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, `tabBOM` 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 `tabBOM` 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 `tabBOM` 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 Item` 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('Production Control').traverse_bom_tree( bom_no = bom_no, qty = 1, calculate_cost = 1)
main_bom_list.reverse()
for bom in main_bom_list:
bom_obj = get_obj('BOM', 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 `tabBOM` 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

View File

@@ -0,0 +1,31 @@
# DocType, BOM Control
[
# These values are common in all dictionaries
{
'creation': '2012-03-27 14:36:02',
'docstatus': 0,
'modified': '2012-03-27 14:36:02',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all DocType
{
'colour': u'White:FFF',
'doctype': 'DocType',
'issingle': 1,
'module': u'Production',
'name': '__common__',
'section_style': u'Simple',
'server_code_error': u' ',
'show_in_menu': 0,
'version': 108
},
# DocType, BOM Control
{
'doctype': 'DocType',
'name': u'BOM Control'
}
]

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,138 @@
# DocType, BOM Explosion Item
[
# These values are common in all dictionaries
{
'creation': '2012-03-27 14:36:03',
'docstatus': 0,
'modified': '2012-03-27 14:36:03',
'modified_by': u'Administrator',
'owner': u'jai@webnotestech.com'
},
# These values are common for all DocType
{
'autoname': u'FBD/.######',
'colour': u'White:FFF',
'default_print_format': u'Standard',
'doctype': 'DocType',
'istable': 1,
'module': u'Production',
'name': '__common__',
'read_only': 0,
'section_style': u'Simple',
'server_code_error': u' ',
'show_in_menu': 0,
'version': 24
},
# These values are common for all DocField
{
'doctype': u'DocField',
'name': '__common__',
'parent': u'BOM Explosion Item',
'parentfield': u'fields',
'parenttype': u'DocType',
'permlevel': 0
},
# DocType, BOM Explosion Item
{
'doctype': 'DocType',
'name': u'BOM Explosion Item'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'item_code',
'fieldtype': u'Link',
'label': u'Item Code',
'oldfieldname': u'item_code',
'oldfieldtype': u'Link',
'options': u'Item'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'description',
'fieldtype': u'Text',
'label': u'Description',
'oldfieldname': u'description',
'oldfieldtype': u'Text',
'width': u'300px'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'qty',
'fieldtype': u'Float',
'label': u'Qty',
'oldfieldname': u'qty',
'oldfieldtype': u'Currency'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'rate',
'fieldtype': u'Float',
'label': u'Rate',
'oldfieldname': u'standard_rate',
'oldfieldtype': u'Currency'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'amount',
'fieldtype': u'Float',
'label': u'Amount',
'oldfieldname': u'amount_as_per_sr',
'oldfieldtype': u'Currency'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'stock_uom',
'fieldtype': u'Link',
'label': u'Stock UOM',
'oldfieldname': u'stock_uom',
'oldfieldtype': u'Link',
'options': u'UOM'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'parent_bom',
'fieldtype': u'Link',
'hidden': 0,
'label': u'Parent BOM',
'oldfieldname': u'parent_bom',
'oldfieldtype': u'Link',
'width': u'250px'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'mat_detail_no',
'fieldtype': u'Data',
'hidden': 1,
'label': u'Mat Detail No'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'qty_consumed_per_unit',
'fieldtype': u'Float',
'hidden': 0,
'label': u'Qty Consumed Per Unit',
'no_copy': 0
}
]

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,194 @@
# DocType, BOM Item
[
# These values are common in all dictionaries
{
'creation': '2012-03-27 14:36:02',
'docstatus': 0,
'modified': '2012-03-27 14:36:02',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all DocType
{
'colour': u'White:FFF',
'default_print_format': u'Standard',
'doctype': 'DocType',
'istable': 1,
'module': u'Production',
'name': '__common__',
'section_style': u'Simple',
'server_code_error': u' ',
'show_in_menu': 0,
'version': 27
},
# These values are common for all DocField
{
'doctype': u'DocField',
'name': '__common__',
'parent': u'BOM Item',
'parentfield': u'fields',
'parenttype': u'DocType'
},
# These values are common for all DocPerm
{
'doctype': u'DocPerm',
'name': '__common__',
'parent': u'BOM Item',
'parentfield': u'permissions',
'parenttype': u'DocType',
'read': 1,
'role': u'System Manager'
},
# DocType, BOM Item
{
'doctype': 'DocType',
'name': u'BOM Item'
},
# DocPerm
{
'doctype': u'DocPerm',
'permlevel': 0,
'write': 1
},
# DocPerm
{
'doctype': u'DocPerm',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'operation_no',
'fieldtype': u'Data',
'label': u'Operation No',
'oldfieldname': u'operation_no',
'oldfieldtype': u'Data',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'item_code',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Item Code',
'oldfieldname': u'item_code',
'oldfieldtype': u'Link',
'options': u'Item',
'permlevel': 0,
'reqd': 1,
'search_index': 1,
'trigger': u'Client'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'bom_no',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'BOM No',
'oldfieldname': u'bom_no',
'oldfieldtype': u'Link',
'options': u'BOM',
'permlevel': 0,
'reqd': 0,
'search_index': 1,
'trigger': u'Client',
'width': u'150px'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'qty',
'fieldtype': u'Float',
'label': u'Qty',
'oldfieldname': u'qty',
'oldfieldtype': u'Currency',
'permlevel': 0,
'reqd': 1,
'trigger': u'Client'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'stock_uom',
'fieldtype': u'Data',
'label': u'Stock UOM',
'oldfieldname': u'stock_uom',
'oldfieldtype': u'Data',
'permlevel': 1,
'reqd': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'rate',
'fieldtype': u'Float',
'label': u'Rate',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'amount',
'fieldtype': u'Float',
'label': u'Amount',
'oldfieldname': u'amount_as_per_mar',
'oldfieldtype': u'Currency',
'permlevel': 1,
'width': u'150px'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'scrap',
'fieldtype': u'Currency',
'label': u'Scrap %',
'oldfieldname': u'scrap',
'oldfieldtype': u'Currency',
'permlevel': 0,
'print_hide': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'description',
'fieldtype': u'Text',
'label': u'Item Description',
'oldfieldname': u'description',
'oldfieldtype': u'Text',
'permlevel': 0,
'reqd': 0,
'width': u'250px'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'qty_consumed_per_unit',
'fieldtype': u'Float',
'hidden': 1,
'label': u'Qty Consumed Per Unit',
'oldfieldname': u'qty_consumed_per_unit',
'oldfieldtype': u'Float',
'permlevel': 1,
'print_hide': 1
}
]

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,135 @@
# DocType, BOM Operation
[
# These values are common in all dictionaries
{
'creation': '2012-03-27 14:36:02',
'docstatus': 0,
'modified': '2012-03-27 14:36:02',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all DocType
{
'colour': u'White:FFF',
'default_print_format': u'Standard',
'doctype': 'DocType',
'istable': 1,
'module': u'Production',
'name': '__common__',
'section_style': u'Simple',
'server_code_error': u' ',
'show_in_menu': 0,
'version': 8
},
# These values are common for all DocField
{
'doctype': u'DocField',
'name': '__common__',
'parent': u'BOM Operation',
'parentfield': u'fields',
'parenttype': u'DocType',
'permlevel': 0
},
# These values are common for all DocPerm
{
'doctype': u'DocPerm',
'name': '__common__',
'parent': u'BOM Operation',
'parentfield': u'permissions',
'parenttype': u'DocType',
'read': 1,
'role': u'System Manager'
},
# DocType, BOM Operation
{
'doctype': 'DocType',
'name': u'BOM Operation'
},
# DocPerm
{
'doctype': u'DocPerm',
'permlevel': 0,
'write': 1
},
# DocPerm
{
'doctype': u'DocPerm',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'operation_no',
'fieldtype': u'Data',
'label': u'Operation No',
'oldfieldname': u'operation_no',
'oldfieldtype': u'Data',
'reqd': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'opn_description',
'fieldtype': u'Text',
'label': u'Opn Description',
'oldfieldname': u'opn_description',
'oldfieldtype': u'Text',
'reqd': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'workstation',
'fieldtype': u'Link',
'label': u'Workstation',
'oldfieldname': u'workstation',
'oldfieldtype': u'Link',
'options': u'Workstation',
'reqd': 0,
'trigger': u'Client'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'hour_rate',
'fieldtype': u'Currency',
'label': u'Hour Rate',
'oldfieldname': u'hour_rate',
'oldfieldtype': u'Currency',
'reqd': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'time_in_mins',
'fieldtype': u'Currency',
'label': u'Operation Time (mins)',
'oldfieldname': u'time_in_mins',
'oldfieldtype': u'Currency',
'reqd': 0
},
# DocField
{
'allow_on_submit': 0,
'doctype': u'DocField',
'fieldname': u'operating_cost',
'fieldtype': u'Currency',
'label': u'Operating Cost',
'oldfieldname': u'operating_cost',
'oldfieldtype': u'Currency',
'reqd': 0
}
]

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,116 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Please edit this list and import only required elements
from __future__ import unicode_literals
import webnotes
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, getchildren, make_autoname
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
get_value = webnotes.conn.get_value
in_transaction = webnotes.conn.in_transaction
convert_to_lists = webnotes.conn.convert_to_lists
# -----------------------------------------------------------------------------------------
class DocType:
def __init__( self, doc, doclist=[]):
self.doc = doc
self.doclist = doclist
self.pur_items = {}
self.bom_list = []
self.sub_assembly_items = []
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 ):
count, bom_list, qty_list = 0, [bom_no], [qty]
while (count < len(bom_list)):
# get child items from BOM MAterial Table.
child_items = sql("select item_code, bom_no, qty, qty_consumed_per_unit from `tabBOM Item` where parent = %s", bom_list[count], as_dict = 1)
child_items = child_items and child_items or []
for item in child_items:
# 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'])
# extracting Purchase Items
if ext_pur_items and not item['bom_no']:
self.pur_items[item['item_code']] = flt(self.pur_items.get(item['item_code'], 0)) + flt(item['reqd_qty'])
# For calculate cost extracting BOM Items check for duplicate boms, this optmizes the time complexity for while loop.
if calculate_cost and item['bom_no'] and (item['bom_no'] not in bom_list):
bom_list.append(item['bom_no'])
qty_list.append(item['reqd_qty'])
# Here repeated bom are considered to calculate total qty of raw material required
if not calculate_cost and item['bom_no']:
bom_list.append(item['bom_no'])
qty_list.append(item['reqd_qty'])
count += 1
return bom_list
# Raise Production Order
def create_production_order(self,company, pp_items):
"""Create production order. Called from Production Planning Tool"""
default_values = {
'posting_date' : nowdate(),
'origin' : 'MRP',
'wip_warehouse' : '',
'fg_warehouse' : '',
'status' : 'Draft',
'company' : company,
'fiscal_year' : get_defaults()['fiscal_year']
}
pro_list = []
for d in pp_items:
pro_doc = Document('Production Order')
for key in d.keys():
pro_doc.fields[key] = d[key]
for key in default_values:
pro_doc.fields[key] = default_values[key]
pro_doc.save(new = 1)
pro_list.append(pro_doc.name)
return pro_list
def update_bom(self, bom_no):
main_bom_list = self.traverse_bom_tree(bom_no, 1)
main_bom_list.reverse()
# run calculate cost and get
for bom in main_bom_list:
if bom and bom not in self.check_bom_list:
bom_obj = get_obj('BOM', bom, with_children = 1)
bom_obj.doc.save()
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)

View File

@@ -0,0 +1,31 @@
# DocType, Production Control
[
# These values are common in all dictionaries
{
'creation': '2012-03-27 14:36:05',
'docstatus': 0,
'modified': '2012-03-27 14:36:05',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all DocType
{
'colour': u'White:FFF',
'doctype': 'DocType',
'issingle': 1,
'module': u'Production',
'name': '__common__',
'section_style': u'Simple',
'server_code_error': u' ',
'show_in_menu': 0,
'version': 19
},
# DocType, Production Control
{
'doctype': 'DocType',
'name': u'Production Control'
}
]

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,118 @@
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
cur_frm.cscript.onload = function(doc, dt, dn) {
if (!doc.posting_date) doc.transaction_date = dateutil.obj_to_str(new Date());
if (!doc.status) doc.status = 'Draft';
cfn_set_fields(doc, dt, dn);
if (doc.origin != "MRP"){
doc.origin = "Manual";
set_field_permlevel('production_item', 0);
set_field_permlevel('bom_no', 0);
set_field_permlevel('consider_sa_items',0);
}
}
// ================================== Refresh ==========================================
cur_frm.cscript.refresh = function(doc, dt, dn) {
cfn_set_fields(doc, dt, dn);
}
var cfn_set_fields = function(doc, dt, dn) {
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']);
if (doc.status == 'Submitted' || doc.status == 'Material Transferred' || doc.status == 'In Process'){
cur_frm.add_custom_button('Transfer Material', cur_frm.cscript['Transfer Material']);
cur_frm.add_custom_button('Backflush', cur_frm.cscript['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
//
cur_frm.cscript['Stop Production Order'] = function() {
var doc = cur_frm.doc;
var check = confirm("Do you really want to stop production order: " + doc.name);
if (check) {
$c_obj(make_doclist(doc.doctype, doc.name), 'stop_unstop', 'Stopped', function(r, rt) {cur_frm.refresh();});
}
}
// Unstop PRODUCTION ORDER
//
cur_frm.cscript['Unstop Production Order'] = function() {
var doc = cur_frm.doc;
var check = confirm("Do really want to unstop production order: " + doc.name);
if (check)
$c_obj(make_doclist(doc.doctype, doc.name), 'stop_unstop', 'Unstopped', function(r, rt) {cur_frm.refresh();});
}
cur_frm.cscript['Transfer Material'] = function() {
var doc = cur_frm.doc;
cur_frm.cscript.make_se(doc, process = 'Material Transfer');
}
cur_frm.cscript['Backflush'] = function() {
var doc = cur_frm.doc;
cur_frm.cscript.make_se(doc, process = 'Backflush');
}
cur_frm.cscript.make_se = function(doc, process) {
var se = LocalDB.create('Stock Entry');
se = locals['Stock Entry'][se];
se.purpose = 'Production Order';
se.process = process;
se.posting_date = doc.posting_date;
se.production_order = doc.name;
se.fiscal_year = doc.fiscal_year;
se.company = doc.company;
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 `tabBOM`.`name` FROM `tabBOM` WHERE `tabBOM`.`is_active` = "Yes" AND `tabBOM`.docstatus = 1 AND `tabBOM`.`item` = "' + cstr(doc.production_item) + '" AND`tabBOM`.%(key)s LIKE "%s" ORDER BY `tabBOM`.`name` LIMIT 50';
}
else {
alert(" Please Enter Production Item First.")
}
}

View File

@@ -0,0 +1,114 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Please edit this list and import only required elements
from __future__ import unicode_literals
import webnotes
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, getchildren, make_autoname
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
get_value = webnotes.conn.get_value
in_transaction = webnotes.conn.in_transaction
convert_to_lists = webnotes.conn.convert_to_lists
# -----------------------------------------------------------------------------------------
class DocType:
def __init__(self, doc, doclist=[]):
self.doc = doc
self.doclist = doclist
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, prod_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""", 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 `tabBOM` 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())

View File

@@ -0,0 +1,358 @@
# DocType, Production Order
[
# These values are common in all dictionaries
{
'creation': '2012-05-15 12:14:48',
'docstatus': 0,
'modified': '2012-05-28 19:03:56',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all DocType
{
'_last_update': u'1325837006',
'colour': u'White:FFF',
'default_print_format': u'Standard',
'doctype': 'DocType',
'in_create': 0,
'is_submittable': 1,
'module': u'Production',
'name': '__common__',
'section_style': u'Tabbed',
'server_code_error': u' ',
'show_in_menu': 0,
'version': 1
},
# These values are common for all DocField
{
'doctype': u'DocField',
'name': '__common__',
'parent': u'Production Order',
'parentfield': u'fields',
'parenttype': u'DocType'
},
# These values are common for all DocPerm
{
'doctype': u'DocPerm',
'name': '__common__',
'parent': u'Production Order',
'parentfield': u'permissions',
'parenttype': u'DocType',
'read': 1
},
# DocType, Production Order
{
'doctype': 'DocType',
'name': u'Production Order'
},
# DocPerm
{
'amend': 1,
'cancel': 1,
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'System Manager',
'submit': 1,
'write': 1
},
# DocPerm
{
'doctype': u'DocPerm',
'permlevel': 1,
'role': u'All'
},
# DocPerm
{
'amend': 1,
'cancel': 1,
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'Production Manager',
'submit': 1,
'write': 1
},
# DocPerm
{
'amend': 1,
'cancel': 1,
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'Production User',
'submit': 1,
'write': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break0',
'fieldtype': u'Column Break',
'permlevel': 0,
'width': u'50%'
},
# DocField
{
'colour': u'White:FFF',
'description': u'Item for which this Production Order is raised.',
'doctype': u'DocField',
'fieldname': u'production_item',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Production Item',
'oldfieldname': u'production_item',
'oldfieldtype': u'Link',
'options': u'Item',
'permlevel': 1,
'reqd': 1,
'trigger': u'Client'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'description',
'fieldtype': u'Text',
'label': u'Description',
'oldfieldname': u'description',
'oldfieldtype': u'Text',
'permlevel': 0,
'width': u'300px'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'stock_uom',
'fieldtype': u'Data',
'label': u'Stock UOM',
'oldfieldname': u'stock_uom',
'oldfieldtype': u'Data',
'permlevel': 1
},
# DocField
{
'colour': u'White:FFF',
'description': u'Bill of Material which was considered for manufacturing the production item.',
'doctype': u'DocField',
'fieldname': u'bom_no',
'fieldtype': u'Link',
'label': u'BOM No',
'oldfieldname': u'bom_no',
'oldfieldtype': u'Link',
'options': u'BOM',
'permlevel': 1,
'reqd': 1,
'trigger': u'Client'
},
# DocField
{
'colour': u'White:FFF',
'description': u'Quantity of item for which Production Order is raised.',
'doctype': u'DocField',
'fieldname': u'qty',
'fieldtype': u'Currency',
'label': u'Qty',
'oldfieldname': u'qty',
'oldfieldtype': u'Currency',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'colour': u'White:FFF',
'description': u'The warehouse for finished goods where stock of produced items will be updated.',
'doctype': u'DocField',
'fieldname': u'fg_warehouse',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'FG Warehouse',
'oldfieldname': u'fg_warehouse',
'oldfieldtype': u'Link',
'options': u'Warehouse',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'colour': u'White:FFF',
'description': u'The work in progress warehouse where raw materials will be operated upon to create finished goods.',
'doctype': u'DocField',
'fieldname': u'wip_warehouse',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'WIP Warehouse',
'oldfieldname': u'wip_warehouse',
'oldfieldtype': u'Link',
'options': u'Warehouse',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'amended_from',
'fieldtype': u'Data',
'label': u'Amended From',
'no_copy': 1,
'oldfieldname': u'amended_from',
'oldfieldtype': u'Data',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'amendment_date',
'fieldtype': u'Date',
'label': u'Amendment Date',
'no_copy': 1,
'oldfieldname': u'amendment_date',
'oldfieldtype': u'Date',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break1',
'fieldtype': u'Column Break',
'oldfieldtype': u'Column Break',
'permlevel': 0,
'width': u'50%'
},
# DocField
{
'colour': u'White:FFF',
'description': u'The date on which current entry will get or has actually executed.',
'doctype': u'DocField',
'fieldname': u'posting_date',
'fieldtype': u'Date',
'label': u'Posting Date',
'oldfieldname': u'posting_date',
'oldfieldtype': u'Date',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'colour': u'White:FFF',
'description': u'Select "Yes" if stock is maintained and tracked for sub-assembly items. Select "No" if you want child items of sub-assembly for material transfer.',
'doctype': u'DocField',
'fieldname': u'consider_sa_items',
'fieldtype': u'Select',
'in_filter': 1,
'label': u'Consider SA Items as raw material',
'oldfieldname': u'consider_sa_items',
'oldfieldtype': u'Select',
'options': u'\nYes\nNo',
'permlevel': 1,
'reqd': 1
},
# DocField
{
'description': u'Select name of the project if Production Order need to be created against any project',
'doctype': u'DocField',
'fieldname': u'project_name',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Project Name',
'oldfieldname': u'project_name',
'oldfieldtype': u'Link',
'options': u'Project',
'permlevel': 0,
'trigger': u'Client'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'origin',
'fieldtype': u'Select',
'in_filter': 1,
'label': u'Origin',
'no_copy': 1,
'oldfieldname': u'origin',
'oldfieldtype': u'Select',
'options': u'Manual\nMRP',
'permlevel': 1,
'reqd': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'status',
'fieldtype': u'Select',
'in_filter': 1,
'label': u'Status',
'no_copy': 1,
'oldfieldname': u'status',
'oldfieldtype': u'Select',
'options': u'\nDraft\nSubmitted\nStopped\nIn Process\nCompleted\nCancelled',
'permlevel': 1,
'reqd': 1,
'search_index': 1
},
# DocField
{
'colour': u'White:FFF',
'description': u'Updated after finished goods are transferred to FG Warehouse through Stock Entry',
'doctype': u'DocField',
'fieldname': u'produced_qty',
'fieldtype': u'Currency',
'label': u'Produced Qty',
'no_copy': 1,
'oldfieldname': u'produced_qty',
'oldfieldtype': u'Currency',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'company',
'fieldtype': u'Link',
'label': u'Company',
'oldfieldname': u'company',
'oldfieldtype': u'Link',
'options': u'Company',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'fiscal_year',
'fieldtype': u'Select',
'in_filter': 1,
'label': u'Fiscal Year',
'oldfieldname': u'fiscal_year',
'oldfieldtype': u'Select',
'options': u'link:Fiscal Year',
'permlevel': 0,
'reqd': 1
}
]

View File

@@ -0,0 +1,40 @@
// render
wn.doclistviews['Production Order'] = wn.views.ListView.extend({
init: function(d) {
this._super(d);
this.fields = this.fields.concat([
'`tabProduction Order`.production_item',
'`tabProduction Order`.fg_warehouse',
'`tabProduction Order`.stock_uom',
'IFNULL(`tabProduction Order`.qty, 0) as qty',
'`tabProduction Order`.posting_date',
'`tabProduction Order`.status',
]);
this.stats = this.stats.concat(['company']);
},
prepare_data: function(data) {
this._super(data);
data.posting_date = wn.datetime.str_to_user(data.posting_date);
},
columns: [
{width: '3%', content: 'check'},
{width: '5%', content: 'avatar'},
{width: '3%', content: 'docstatus'},
{width: '17%', content: 'name'},
{width: '16%', content: 'production_item'},
{width: '20%', content: 'fg_warehouse'},
{width: '12%', content: 'status+tags'},
{
width: '12%',
content: function(parent, data) {
$(parent).html(data.qty + ' ' + data.stock_uom)
},
css: {'text-align':'right'}
},
{width: '12%', content:'posting_date', css: {
'text-align': 'right', 'color':'#777'
}},
]
});

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,159 @@
# DocType, Production Plan Item
[
# These values are common in all dictionaries
{
'creation': '2012-03-27 14:36:03',
'docstatus': 0,
'modified': '2012-03-27 14:36:03',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all DocType
{
'autoname': u'PPID/.#####',
'colour': u'White:FFF',
'default_print_format': u'Standard',
'doctype': 'DocType',
'istable': 1,
'module': u'Production',
'name': '__common__',
'section_style': u'Simple',
'server_code_error': u' ',
'show_in_menu': 0,
'version': 27
},
# These values are common for all DocField
{
'doctype': u'DocField',
'name': '__common__',
'parent': u'Production Plan Item',
'parentfield': u'fields',
'parenttype': u'DocType'
},
# DocType, Production Plan Item
{
'doctype': 'DocType',
'name': u'Production Plan Item'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'sales_order',
'fieldtype': u'Data',
'label': u'Sales Order',
'oldfieldname': u'source_docname',
'oldfieldtype': u'Data',
'permlevel': 1
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'item_code',
'fieldtype': u'Link',
'label': u'Item Code',
'oldfieldname': u'item_code',
'oldfieldtype': u'Link',
'options': u'Item',
'permlevel': 0,
'reqd': 1,
'trigger': u'Client',
'width': u'150px'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'bom_no',
'fieldtype': u'Link',
'label': u'BOM No',
'oldfieldname': u'bom_no',
'oldfieldtype': u'Link',
'options': u'BOM',
'permlevel': 0,
'reqd': 1,
'width': u'100px'
},
# DocField
{
'default': u'0.00',
'doctype': u'DocField',
'fieldname': u'so_pending_qty',
'fieldtype': u'Currency',
'label': u'SO Pending Qty',
'oldfieldname': u'prevdoc_reqd_qty',
'oldfieldtype': u'Currency',
'permlevel': 1,
'reqd': 0,
'width': u'100px'
},
# DocField
{
'default': u'0.00',
'doctype': u'DocField',
'fieldname': u'planned_qty',
'fieldtype': u'Currency',
'label': u'Planned Qty',
'oldfieldname': u'planned_qty',
'oldfieldtype': u'Currency',
'permlevel': 0,
'reqd': 1,
'width': u'100px'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'stock_uom',
'fieldtype': u'Data',
'label': u'UOM',
'oldfieldname': u'stock_uom',
'oldfieldtype': u'Data',
'permlevel': 1,
'reqd': 1,
'width': u'80px'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'description',
'fieldtype': u'Text',
'label': u'Description',
'oldfieldname': u'description',
'oldfieldtype': u'Text',
'permlevel': 1,
'width': u'200px'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'parent_packing_item',
'fieldtype': u'Link',
'label': u'Parent Packing Item',
'oldfieldname': u'parent_item',
'oldfieldtype': u'Link',
'options': u'Item',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'is_pro_created',
'fieldtype': u'Check',
'label': u'Is PRO Created',
'oldfieldname': u'pro_created',
'oldfieldtype': u'Check',
'permlevel': 1
}
]

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,124 @@
# DocType, Production Plan Sales Order
[
# These values are common in all dictionaries
{
'creation': '2012-03-27 14:36:04',
'docstatus': 0,
'modified': '2012-03-27 14:36:04',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all DocType
{
'autoname': u'PP/.SO/.#####',
'colour': u'White:FFF',
'default_print_format': u'Standard',
'doctype': 'DocType',
'istable': 1,
'module': u'Production',
'name': '__common__',
'section_style': u'Simple',
'server_code_error': u' ',
'show_in_menu': 0,
'version': 5
},
# These values are common for all DocField
{
'doctype': u'DocField',
'name': '__common__',
'parent': u'Production Plan Sales Order',
'parentfield': u'fields',
'parenttype': u'DocType'
},
# These values are common for all DocPerm
{
'doctype': u'DocPerm',
'name': '__common__',
'parent': u'Production Plan Sales Order',
'parentfield': u'permissions',
'parenttype': u'DocType',
'read': 1,
'role': u'System Manager'
},
# DocType, Production Plan Sales Order
{
'doctype': 'DocType',
'name': u'Production Plan Sales Order'
},
# DocPerm
{
'doctype': u'DocPerm',
'permlevel': 0,
'write': 1
},
# DocPerm
{
'doctype': u'DocPerm',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'sales_order',
'fieldtype': u'Link',
'label': u'Sales Order',
'oldfieldname': u'prevdoc_docname',
'oldfieldtype': u'Data',
'options': u'Sales Order',
'permlevel': 0,
'width': u'150px'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'sales_order_date',
'fieldtype': u'Date',
'label': u'Sales Order Date',
'oldfieldname': u'document_date',
'oldfieldtype': u'Date',
'permlevel': 1,
'width': u'100px'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'customer',
'fieldtype': u'Link',
'label': u'Customer',
'options': u'Customer',
'permlevel': 1,
'width': u'150px'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'grand_total',
'fieldtype': u'Currency',
'label': u'Grand Total',
'permlevel': 1,
'width': u'100px'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'include_in_plan',
'fieldtype': u'Check',
'label': u'Include In Plan',
'oldfieldname': u'include_in_plan',
'oldfieldtype': u'Check',
'permlevel': 0,
'width': u'100px'
}
]

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,50 @@
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
cur_frm.cscript.item_code = function(doc,cdt,cdn) {
var d = locals[cdt][cdn];
if (d.item_code) {
get_server_fields('get_item_details', d.item_code, '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) {
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';
}
cur_frm.fields_dict['pp_details'].grid.get_field('bom_no').get_query = function(doc) {
var d = locals[this.doctype][this.docname];
return 'SELECT DISTINCT `tabBOM`.`name` FROM `tabBOM` WHERE `tabBOM`.`item` = "' + d.item_code + '" AND `tabBOM`.`is_active` = "Yes" AND `tabBOM`.docstatus = 1 AND `tabBOM`.`name` like "%s" ORDER BY `tabBOM`.`name` LIMIT 50';
}

View File

@@ -0,0 +1,302 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
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
sql = webnotes.conn.sql
# -----------------------------------------------------------------------------------------
class DocType:
def __init__(self, doc, doclist=[]):
self.doc = doc
self.doclist = doclist
self.item_dict = {}
def get_item_details(self, item_code):
""" 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())""", item_code, as_dict =1 )
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
def get_so_details(self, so):
"""Pull other details from so"""
so = sql("select transaction_date, customer, grand_total from `tabSales Order` where name = %s", so, as_dict = 1)
ret = {
'sales_order_date': so and so[0]['transaction_date'] or '',
'customer' : so[0]['customer'] or '',
'grand_total': so[0]['grand_total']
}
return ret
def clear_so_table(self):
""" Clears sales order table"""
self.doclist = self.doc.clear_table(self.doclist, 'pp_so_details')
def clear_item_table(self):
""" Clears item table"""
self.doclist = self.doc.clear_table(self.doclist, 'pp_details')
def get_open_sales_orders(self):
""" Pull sales orders which are pending to deliver based on criteria selected"""
cond = self.get_filter_condition()
open_so = sql("""
select
distinct t1.name, t1.transaction_date, t1.customer, t1.grand_total
from
`tabSales Order` t1, `tabSales Order Item` t2, `tabDelivery Note Packing Item` t3, tabItem t4
where
t1.name = t2.parent and t1.name = t3.parent and t3.parenttype = 'Sales Order' and t1.docstatus = 1 and t2.item_code = t3.parent_item
and t4.name = t3.item_code and t1.status != 'Stopped' and t1.company = '%s' and ifnull(t2.qty, 0) > ifnull(t2.delivered_qty, 0)
and (ifnull(t4.is_pro_applicable, 'No') = 'Yes' or ifnull(t4.is_sub_contracted_item, 'No') = 'Yes') %s
order by t1.name desc
"""% (self.doc.company, cond), as_dict = 1)
self.add_so_in_table(open_so)
def validate_company(self):
if not self.doc.company:
msgprint("Please enter Company", raise_exception=1)
def get_filter_condition(self):
self.validate_company()
cond = ''
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 t3.item_code = "' + self.doc.fg_item + '"'
return cond
def add_so_in_table(self, open_so):
""" Add sales orders in the table"""
so_list = []
for d in getlist(self.doclist, 'pp_so_details'):
so_list.append(d.sales_order)
for r in open_so:
if cstr(r['name']) not in so_list:
pp_so = addchild(self.doc, 'pp_so_details', 'Production Plan Sales Order', 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'])
def get_items_from_so(self):
""" Pull items from Sales Order, only proction item
and subcontracted item will be pulled from Packing item
and add items in the table
"""
so = self.get_included_so()
items = self.get_packing_items(so)
self.add_items(items)
def get_included_so(self):
so = "'" + "','".join([cstr(d.sales_order) for d in getlist(self.doclist, 'pp_so_details') if d.include_in_plan]) + "'"
return so
def get_packing_items(self, so):
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 Item` t1, `tabDelivery Note Packing Item` 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', 'Production Plan Item', 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 `tabBOM` 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 Item`
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 `tabBOM Explosion Item` 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[0], [0])[0]) + flt(i[1])), i[2], i[3]]
def get_csv(self):
item_list = [['Item Code', 'Description', 'Stock UOM', 'Required Qty', 'Warehouse', 'Quantity Requested for Purchase', 'Ordered Qty', 'Actual Qty']]
for d in self.item_dict:
item_list.append([d, self.item_dict[d][1], self.item_dict[d][2], self.item_dict[d][0]]),
item_qty= sql("select warehouse, indented_qty, ordered_qty, actual_qty from `tabBin` where item_code = %s", d)
i_qty, o_qty, a_qty = 0,0,0
for w in item_qty:
i_qty, o_qty, a_qty = i_qty + flt(w[1]), o_qty + flt(w[2]), a_qty + flt(w[3])
item_list.append(['', '', '', '', w[0], flt(w[1]), flt(w[2]), flt(w[3])])
if item_qty:
item_list.append(['', '', '', '', 'Total', i_qty, o_qty, a_qty])
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

View File

@@ -0,0 +1,318 @@
# DocType, Production Planning Tool
[
# These values are common in all dictionaries
{
'creation': '2012-03-27 14:36:05',
'docstatus': 0,
'modified': '2012-03-27 14:36:05',
'modified_by': u'Administrator',
'owner': u'jai@webnotestech.com'
},
# These values are common for all DocType
{
'_last_update': u'1326188323',
'colour': u'White:FFF',
'default_print_format': u'Standard',
'doctype': 'DocType',
'in_create': 1,
'issingle': 1,
'module': u'Production',
'name': '__common__',
'read_only': 1,
'section_style': u'Tabbed',
'server_code_error': u' ',
'show_in_menu': 1,
'version': 106
},
# These values are common for all DocField
{
'doctype': u'DocField',
'name': '__common__',
'parent': u'Production Planning Tool',
'parentfield': u'fields',
'parenttype': u'DocType',
'permlevel': 0
},
# These values are common for all DocPerm
{
'create': 1,
'doctype': u'DocPerm',
'name': '__common__',
'parent': u'Production Planning Tool',
'parentfield': u'permissions',
'parenttype': u'DocType',
'permlevel': 0,
'read': 1,
'write': 1
},
# DocType, Production Planning Tool
{
'doctype': 'DocType',
'name': u'Production Planning Tool'
},
# DocPerm
{
'doctype': u'DocPerm',
'role': u'System Manager'
},
# DocPerm
{
'doctype': u'DocPerm',
'role': u'Production User'
},
# DocPerm
{
'doctype': u'DocPerm',
'role': u'Production Manager'
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'select_sales_orders',
'fieldtype': u'Section Break',
'label': u'Select Sales Orders'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break0',
'fieldtype': u'Column Break',
'width': u'50%'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'from_date',
'fieldtype': u'Date',
'label': u'From Date'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'to_date',
'fieldtype': u'Date',
'label': u'To Date'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'fg_item',
'fieldtype': u'Link',
'label': u'FG Item',
'options': u'Item'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break1',
'fieldtype': u'Column Break',
'width': u'50%'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'customer',
'fieldtype': u'Link',
'label': u'Customer',
'options': u'Customer'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'company',
'fieldtype': u'Link',
'label': u'Company',
'options': u'Company',
'reqd': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'section_break0',
'fieldtype': u'Section Break',
'options': u'Simple'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break2',
'fieldtype': u'Column Break',
'width': u'50%'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'get_sales_orders',
'fieldtype': u'Button',
'label': u'Get Sales Orders',
'options': u'get_open_sales_orders'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break3',
'fieldtype': u'Column Break',
'width': u'50%'
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'clear_so_table',
'fieldtype': u'Button',
'label': u'Clear SO Table',
'options': u'clear_so_table',
'trigger': u'Client'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'section_break1',
'fieldtype': u'Section Break',
'options': u'Simple'
},
# DocField
{
'description': u'Select Sales Orders from which you want to create Production Orders. You can get sales orders based on above criteria.',
'doctype': u'DocField',
'fieldname': u'pp_so_details',
'fieldtype': u'Table',
'label': u'Production Plan Sales Orders',
'options': u'Production Plan Sales Order'
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'items',
'fieldtype': u'Section Break',
'label': u'Items'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'get_items_from_so',
'fieldtype': u'Button',
'label': u'Get Items from SO',
'options': u'get_items_from_so'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break4',
'fieldtype': u'Column Break',
'width': u'50%'
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'clear_item_table',
'fieldtype': u'Button',
'label': u'Clear Item Table',
'options': u'clear_item_table',
'trigger': u'Client'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'section_break2',
'fieldtype': u'Section Break',
'options': u'Simple'
},
# DocField
{
'description': u'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': u'DocField',
'fieldname': u'pp_details',
'fieldtype': u'Table',
'label': u'Production Plan Items',
'options': u'Production Plan Item'
},
# DocField
{
'colour': u'White:FFF',
'default': u'No',
'description': u'Select "Yes" if stock is maintained and tracked for sub assembly items.',
'doctype': u'DocField',
'fieldname': u'consider_sa_items',
'fieldtype': u'Select',
'label': u'Consider Sub Assemblies as Raw Material',
'options': u'No\nYes',
'reqd': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'section_break3',
'fieldtype': u'Section Break',
'options': u'Simple'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break5',
'fieldtype': u'Column Break',
'width': u'50%'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'raise_production_order',
'fieldtype': u'Button',
'label': u'Raise Production Order',
'options': u'raise_production_order'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break6',
'fieldtype': u'Column Break',
'width': u'50%'
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'download_raw_material',
'fieldtype': u'Button',
'label': u'Download Raw Material',
'trigger': u'Client'
}
]

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,26 @@
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//--------- ONLOAD -------------
cur_frm.cscript.onload = function(doc, cdt, cdn) {
}
cur_frm.cscript.refresh = function(doc, cdt, cdn) {
}

View File

@@ -0,0 +1,50 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Please edit this list and import only required elements
from __future__ import unicode_literals
import webnotes
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, getchildren, make_autoname
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
get_value = webnotes.conn.get_value
in_transaction = webnotes.conn.in_transaction
convert_to_lists = webnotes.conn.convert_to_lists
# -----------------------------------------------------------------------------------------
class DocType:
def __init__(self, doc, doclist=[]):
self.doc = doc
self.doclist = doclist
def update_bom_operation(self):
bom_list = sql(" select DISTINCT parent from `tabBOM Operation` where workstation = '%s'" % self.doc.name)
for bom_no in bom_list:
sql("update `tabBOM Operation` set hour_rate = '%s' where parent = '%s' and workstation = '%s'"%( self.doc.hour_rate, bom_no[0], self.doc.name))
def on_update(self):
set(self.doc, 'overhead', flt(self.doc.hour_rate_electricity) + flt(self.doc.hour_rate_consumable) + flt(self.doc.hour_rate_rent))
set(self.doc, 'hour_rate', flt(self.doc.hour_rate_labour) + flt(self.doc.overhead))
self.update_bom_operation()

View File

@@ -0,0 +1,269 @@
# DocType, Workstation
[
# These values are common in all dictionaries
{
'creation': '2012-03-27 14:36:05',
'docstatus': 0,
'modified': '2012-03-27 18:46:49',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all DocType
{
'_last_update': u'1322125389',
'allow_email': 0,
'allow_trash': 1,
'autoname': u'field:workstation_name',
'colour': u'White:FFF',
'default_print_format': u'Standard',
'doctype': 'DocType',
'document_type': u'Master',
'module': u'Production',
'name': '__common__',
'section_style': u'Simple',
'server_code_error': u' ',
'show_in_menu': 0,
'version': 14
},
# These values are common for all DocField
{
'doctype': u'DocField',
'name': '__common__',
'parent': u'Workstation',
'parentfield': u'fields',
'parenttype': u'DocType'
},
# These values are common for all DocPerm
{
'doctype': u'DocPerm',
'name': '__common__',
'parent': u'Workstation',
'parentfield': u'permissions',
'parenttype': u'DocType',
'read': 1
},
# DocType, Workstation
{
'doctype': 'DocType',
'name': u'Workstation'
},
# DocPerm
{
'cancel': 1,
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'System Manager',
'write': 1
},
# DocPerm
{
'doctype': u'DocPerm',
'permlevel': 1,
'role': u'System Manager'
},
# DocPerm
{
'cancel': 1,
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'Production User',
'write': 1
},
# DocPerm
{
'cancel': 1,
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'Production User',
'write': 1
},
# DocPerm
{
'doctype': u'DocPerm',
'permlevel': 1,
'role': u'Production Manager'
},
# DocPerm
{
'doctype': u'DocPerm',
'permlevel': 1,
'role': u'Production User'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'trash_reason',
'fieldtype': u'Small Text',
'label': u'Trash Reason',
'oldfieldname': u'trash_reason',
'oldfieldtype': u'Small Text',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'workstation_name',
'fieldtype': u'Data',
'label': u'Workstation Name',
'oldfieldname': u'workstation_name',
'oldfieldtype': u'Data',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'warehouse',
'fieldtype': u'Link',
'label': u'Warehouse',
'oldfieldname': u'warehouse',
'oldfieldtype': u'Link',
'options': u'Warehouse',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'description',
'fieldtype': u'Text',
'label': u'Description',
'oldfieldname': u'description',
'oldfieldtype': u'Text',
'permlevel': 0,
'width': u'300px'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'capacity',
'fieldtype': u'Data',
'hidden': 1,
'label': u'Capacity',
'oldfieldname': u'capacity',
'oldfieldtype': u'Data',
'permlevel': 0,
'reqd': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'capacity_units',
'fieldtype': u'Select',
'hidden': 1,
'label': u'Capacity Units',
'oldfieldname': u'capacity_units',
'oldfieldtype': u'Select',
'options': u'\nUnits/Shifts\nUnits/Hour',
'permlevel': 0,
'reqd': 0
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'hour_rate_labour',
'fieldtype': u'Currency',
'label': u'Hour Rate Labour',
'oldfieldname': u'hour_rate_labour',
'oldfieldtype': u'Currency',
'permlevel': 0,
'reqd': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'over_heads',
'fieldtype': u'Section Break',
'label': u'Over Heads',
'oldfieldtype': u'Section Break',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'hour_rate_electricity',
'fieldtype': u'Currency',
'label': u'Hour Rate Electricity',
'oldfieldname': u'hour_rate_electricity',
'oldfieldtype': u'Currency',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'hour_rate_consumable',
'fieldtype': u'Currency',
'label': u'Hour Rate Consumable',
'oldfieldname': u'hour_rate_consumable',
'oldfieldtype': u'Currency',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'hour_rate_rent',
'fieldtype': u'Currency',
'label': u'Hour Rate Rent',
'oldfieldname': u'hour_rate_rent',
'oldfieldtype': u'Currency',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'overhead',
'fieldtype': u'Currency',
'label': u'Overhead',
'oldfieldname': u'overhead',
'oldfieldtype': u'Currency',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'hour_rate_section_break',
'fieldtype': u'Section Break',
'label': u'Hour Rate',
'oldfieldtype': u'Section Break',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'hour_rate',
'fieldtype': u'Currency',
'label': u'Hour Rate',
'oldfieldname': u'hour_rate',
'oldfieldtype': u'Currency',
'permlevel': 1
}
]

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,38 @@
<div class="layout-wrapper layout-wrapper-background">
<div class="appframe-area"></div>
<div class="layout-main-section">
<div style="width: 48%; float: left;">
<h4><a href="#!List/Production Order">Production Order</a></h4>
<p class="help">Orders for manufacturing</p>
<br>
<h4><a href="#!Form/Production Planning Tool/Production Planning Tool">Production Plan</a></h4>
<p class="help">Generate Purchase Requisition (MRP) and Production Orders</p>
</div>
<div style="width: 48%; float: right;">
<h4><a href="#!List/BOM">Bill of Materials</a></h4>
<p class="help">Bill of Materials (BOM) Master</p>
<br>
<h4><a href="#!List/Item">Item</a></h4>
<p class="help">Item Master</p>
</div>
<div style="clear: both"></div>
<hr>
<h3>Reports</h3>
<div class="reports-list"></div>
</div>
<div class="layout-side-section">
<div class="psidebar">
<div class="section">
<div class="section-head">Setup</div>
<div class="section-body">
<div class="section-item">
<a class="section-link"
title = "Workstation master"
href="#!List/Workstation">Workstations</a>
</div>
</div>
</div>
</div>
</div>
<div style="clear: both;"></div>
</div>

View File

@@ -0,0 +1,20 @@
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pscript['onload_production-home'] = function(wrapper) {
wrapper.appframe = new wn.ui.AppFrame($(wrapper).find('.appframe-area'), 'Production');
erpnext.module_page.setup_page('Production', wrapper);
}

View File

@@ -0,0 +1,28 @@
# Page, production-home
[
# These values are common in all dictionaries
{
'creation': '2012-02-21 13:24:34',
'docstatus': 0,
'modified': '2012-02-21 13:24:34',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all Page
{
'doctype': 'Page',
'module': u'Production',
'name': '__common__',
'page_name': u'production-home',
'standard': u'Yes',
'title': u'Production Home'
},
# Page, production-home
{
'doctype': 'Page',
'name': u'production-home'
}
]

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,37 @@
# Search Criteria, consumption_against_production
[
# These values are common in all dictionaries
{
'creation': '2012-04-03 12:49:50',
'docstatus': 0,
'modified': '2012-04-03 12:49:50',
'modified_by': u'Administrator',
'owner': u'jai@webnotestech.com'
},
# These values are common for all Search Criteria
{
'add_col': u'`tabProduction Order`.consider_sa_items',
'add_cond': u'`tabProduction Order`.name = `tabStock Entry`.production_order',
'add_tab': u'`tabProduction Order`',
'columns': u'Stock Entry\x01ID,Stock Entry\x01Production Order,Stock Entry\x01Process,Stock Entry\x01Posting Date,Stock Entry\x01Company,Stock Entry Detail\x01Source Warehouse,Stock Entry Detail\x01Target Warehouse,Stock Entry Detail\x01FG Item,Stock Entry Detail\x01Item Code,Stock Entry Detail\x01Description,Stock Entry Detail\x01Reqd Qty,Stock Entry Detail\x01Transfer Quantity',
'criteria_name': u'Consumption Against Production',
'doc_type': u'Stock Entry Detail',
'doctype': 'Search Criteria',
'filters': u"{'Stock Entry\x01Submitted':1,'Stock Entry\x01Purpose':'Production Order','Stock Entry\x01Process':''}",
'module': u'Production',
'name': '__common__',
'page_len': 50,
'parent_doc_type': u'Stock Entry',
'sort_by': u'`tabStock Entry`.`name`',
'sort_order': u'DESC',
'standard': u'Yes'
},
# Search Criteria, consumption_against_production
{
'doctype': 'Search Criteria',
'name': u'consumption_against_production'
}
]

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,32 @@
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
report.customize_filters = function() {
//to hide all filters
this.hide_all_filters();
// to unhide required filters
this.filter_fields_dict['Stock Entry'+FILTER_SEP +'ID'].df.filter_hide = 0;
this.filter_fields_dict['Stock Entry'+FILTER_SEP +'Production Order'].df.filter_hide = 0;
this.filter_fields_dict['Stock Entry'+FILTER_SEP +'From Posting Date'].df.filter_hide = 0;
this.filter_fields_dict['Stock Entry'+FILTER_SEP +'To Posting Date'].df.filter_hide = 0;
this.filter_fields_dict['Stock Entry Detail'+FILTER_SEP +'Target Warehouse'].df.filter_hide = 0;
this.filter_fields_dict['Stock Entry Detail'+FILTER_SEP +'Item Code'].df.filter_hide = 0;
}

View File

@@ -0,0 +1,34 @@
# Search Criteria, itemwise_production_report
[
# These values are common in all dictionaries
{
'creation': '2012-04-03 12:49:51',
'docstatus': 0,
'modified': '2012-04-03 12:49:51',
'modified_by': u'Administrator',
'owner': u'jai@webnotestech.com'
},
# These values are common for all Search Criteria
{
'columns': u'Stock Entry\x01ID,Stock Entry\x01Posting Date,Stock Entry\x01Production Order,Stock Entry\x01Process,Stock Entry\x01Company,Stock Entry Detail\x01Target Warehouse,Stock Entry Detail\x01Item Code,Stock Entry Detail\x01Description,Stock Entry Detail\x01Stock UOM,Stock Entry Detail\x01Transfer Quantity',
'criteria_name': u'Itemwise Production Report',
'doc_type': u'Stock Entry Detail',
'doctype': 'Search Criteria',
'filters': u"{'Stock Entry\x01Saved':1,'Stock Entry\x01Submitted':1,'Stock Entry\x01Purpose':'Production Order','Stock Entry\x01Process':'Backflush','Stock Entry Detail\x01FG Item':1}",
'module': u'Production',
'name': '__common__',
'page_len': 50,
'parent_doc_type': u'Stock Entry',
'sort_by': u'`tabStock Entry`.`name`',
'sort_order': u'DESC',
'standard': u'Yes'
},
# Search Criteria, itemwise_production_report
{
'doctype': 'Search Criteria',
'name': u'itemwise_production_report'
}
]

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,34 @@
# Search Criteria, production_orders_in_process
[
# These values are common in all dictionaries
{
'creation': '2012-04-03 12:49:52',
'docstatus': 0,
'modified': '2012-04-03 12:49:52',
'modified_by': u'Administrator',
'owner': u'jai@webnotestech.com'
},
# These values are common for all Search Criteria
{
'add_cond': u'`tabProduction Order`.qty > `tabProduction Order`.produced_qty',
'columns': u'Production Order\x01ID,Production Order\x01Origin,Production Order\x01Status,Production Order\x01Posting Date,Production Order\x01Production Item,Production Order\x01BOM No,Production Order\x01Description,Production Order\x01Stock UOM,Production Order\x01Qty,Production Order\x01Produced Qty,Production Order\x01FG Warehouse,Production Order\x01WIP Warehouse,Production Order\x01Consider SA Items,Production Order\x01Fiscal Year,Production Order\x01Company',
'criteria_name': u'Production Orders In Process',
'doc_type': u'Production Order',
'doctype': 'Search Criteria',
'filters': u"{'Production Order\x01Submitted':1,'Production Order\x01Origin':'','Production Order\x01Status':'','Production Order\x01Consider SA Items':'','Production Order\x01Fiscal Year':''}",
'module': u'Production',
'name': '__common__',
'page_len': 50,
'sort_by': u'`tabProduction Order`.`name`',
'sort_order': u'DESC',
'standard': u'Yes'
},
# Search Criteria, production_orders_in_process
{
'doctype': 'Search Criteria',
'name': u'production_orders_in_process'
}
]