updates in manufacturing module

This commit is contained in:
Nabin Hait
2012-12-19 19:33:41 +05:30
parent 4ecc785aab
commit 6435437e5b
14 changed files with 170 additions and 135 deletions

View File

@@ -61,7 +61,7 @@ cur_frm.fields_dict["bom_operations"].grid.on_row_delete = function(cdt, cdn){
cur_frm.cscript.item = function(doc, dt, dn) { cur_frm.cscript.item = function(doc, dt, dn) {
if (doc.item) { if (doc.item) {
get_server_fields('get_item_details',doc.item,'',doc,dt,dn,1); get_server_fields('get_item_details', doc.item, '', doc, dt, dn, 1);
} }
} }
@@ -94,6 +94,10 @@ cur_frm.cscript.bom_no = function(doc, cdt, cdn) {
get_bom_material_detail(doc, cdt, cdn); get_bom_material_detail(doc, cdt, cdn);
} }
cur_frm.cscript.is_default = function(doc) {
if (doc.is_default) cur_frm.set_value("is_active", 1);
}
var get_bom_material_detail= function(doc, cdt, cdn) { var get_bom_material_detail= function(doc, cdt, cdn) {
var d = locals[cdt][cdn]; var d = locals[cdt][cdn];
if (d.item_code) { if (d.item_code) {

View File

@@ -20,7 +20,7 @@ from webnotes.utils import cint, cstr, flt, now, nowdate
from webnotes.model.doc import Document, addchild from webnotes.model.doc import Document, addchild
from webnotes.model.wrapper import getlist from webnotes.model.wrapper import getlist
from webnotes.model.code import get_obj from webnotes.model.code import get_obj
from webnotes import msgprint from webnotes import msgprint, _
sql = webnotes.conn.sql sql = webnotes.conn.sql
@@ -47,28 +47,24 @@ class DocType:
def on_update(self): def on_update(self):
self.check_recursion() self.check_recursion()
self.update_cost_and_exploded_items() self.calculate_cost()
self.update_exploded_items()
self.doc.save()
def on_submit(self): def on_submit(self):
self.manage_default_bom() self.manage_default_bom()
def on_cancel(self): 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 = 1""", 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=1)
webnotes.conn.set(self.doc, "is_active", 0) webnotes.conn.set(self.doc, "is_active", 0)
webnotes.conn.set(self.doc, "is_default", 0) webnotes.conn.set(self.doc, "is_default", 0)
# check if used in any other bom
self.validate_bom_links()
self.manage_default_bom() self.manage_default_bom()
self.update_cost_and_exploded_items(calculate_cost=False)
def on_update_after_submit(self): def on_update_after_submit(self):
self.validate_bom_links()
self.manage_default_bom() self.manage_default_bom()
self.validate_inactive_bom()
def get_item_det(self, item_code): def get_item_det(self, item_code):
item = sql("""select name, is_asset_item, is_purchase_item, docstatus, description, item = sql("""select name, is_asset_item, is_purchase_item, docstatus, description,
@@ -79,7 +75,9 @@ class DocType:
return item return item
def get_item_details(self, item_code): def get_item_details(self, item_code):
return { 'uom' : webnotes.conn.get_value("Item", item_code, "stock_uom")} res = sql("""select description, stock_uom as uom
from `tabItem` where item_code = %s""", item_code, as_dict = 1, debug=1)
return res and res[0] or {}
def get_workstation_details(self,workstation): def get_workstation_details(self,workstation):
return {'hour_rate': webnotes.conn.get_value("Workstation", workstation, "hour_rate")} return {'hour_rate': webnotes.conn.get_value("Workstation", workstation, "hour_rate")}
@@ -158,7 +156,6 @@ class DocType:
""" Uncheck others if current one is selected as default, """ Uncheck others if current one is selected as default,
update default bom in item master update default bom in item master
""" """
webnotes.conn.set(self.doc, "is_default", cint(self.doc.is_default))
if self.doc.is_default and self.doc.is_active: if self.doc.is_default and self.doc.is_active:
from webnotes.model.utils import set_default from webnotes.model.utils import set_default
set_default(self.doc, "item") set_default(self.doc, "item")
@@ -174,6 +171,8 @@ class DocType:
def clear_operations(self): def clear_operations(self):
if not self.doc.with_operations: if not self.doc.with_operations:
self.doclist = self.doc.clear_table(self.doclist, 'bom_operations') self.doclist = self.doc.clear_table(self.doclist, 'bom_operations')
for d in self.doclist.get({"parentfield": "bom_materials"}):
d.operation_no = None
def validate_main_item(self): def validate_main_item(self):
""" Validate main FG item""" """ Validate main FG item"""
@@ -209,8 +208,7 @@ class DocType:
(m.operation_no, m.item_code, m.idx), raise_exception = 1) (m.operation_no, m.item_code, m.idx), raise_exception = 1)
item = self.get_item_det(m.item_code) item = self.get_item_det(m.item_code)
if item[0]['is_manufactured_item'] == 'Yes' or \ if item[0]['is_manufactured_item'] == 'Yes':
item[0]['is_sub_contracted_item'] == 'Yes':
if not m.bom_no: if not m.bom_no:
msgprint("Please enter BOM No aginst item: %s at row no: %s" % msgprint("Please enter BOM No aginst item: %s at row no: %s" %
(m.item_code, m.idx), raise_exception=1) (m.item_code, m.idx), raise_exception=1)
@@ -240,8 +238,8 @@ class DocType:
def check_if_item_repeated(self, item, op, check_list): def check_if_item_repeated(self, item, op, check_list):
if [cstr(item), cstr(op)] in check_list: if [cstr(item), cstr(op)] in check_list:
msgprint("Item %s has been entered twice against same operation" % msgprint(_("Item") + " %s " % (item,) + _("has been entered atleast twice")
item, raise_exception = 1) + (cstr(op) and _(" against same operation") or ""), raise_exception=1)
else: else:
check_list.append([cstr(item), cstr(op)]) check_list.append([cstr(item), cstr(op)])
@@ -262,28 +260,24 @@ class DocType:
if b[0]: if b[0]:
bom_list.append(b[0]) bom_list.append(b[0])
def update_cost_and_exploded_items(self, calculate_cost=True): def update_cost_and_exploded_items(self):
bom_list = self.traverse_tree() bom_list = self.traverse_tree()
bom_list.reverse()
for bom in bom_list: for bom in bom_list:
bom_obj = get_obj("BOM", bom, with_children=1) bom_obj = get_obj("BOM", bom, with_children=1)
if calculate_cost: bom_obj.on_update()
bom_obj.calculate_cost()
bom_obj.update_exploded_items()
if bom == self.doc.name:
self.doc, self.doclist = bom_obj.doc, bom_obj.doclist
def traverse_tree(self): def traverse_tree(self):
def _get_childs(bom_no): def _get_children(bom_no):
return [cstr(d[0]) for d in webnotes.conn.sql("""select bom_no from `tabBOM Item` return [cstr(d[0]) for d in webnotes.conn.sql("""select bom_no from `tabBOM Item`
where parent = %s and ifnull(bom_no, '') != ''""", bom_no)] where parent = %s and ifnull(bom_no, '') != ''""", bom_no)]
bom_list, count = [self.doc.name], 0 bom_list, count = [self.doc.name], 0
while(count < len(bom_list)): while(count < len(bom_list)):
for child_bom in _get_childs(bom_list[count]): for child_bom in _get_children(bom_list[count]):
if child_bom not in bom_list: if child_bom not in bom_list:
bom_list.append(child_bom) bom_list.append(child_bom)
count += 1 count += 1
bom_list.reverse()
return bom_list return bom_list
def calculate_cost(self): def calculate_cost(self):
@@ -291,8 +285,6 @@ class DocType:
self.calculate_op_cost() self.calculate_op_cost()
self.calculate_rm_cost() self.calculate_rm_cost()
self.doc.total_cost = self.doc.raw_material_cost + self.doc.operating_cost self.doc.total_cost = self.doc.raw_material_cost + self.doc.operating_cost
self.doc.modified = now()
self.doc.save()
def calculate_op_cost(self): def calculate_op_cost(self):
"""Update workstation rate and calculates totals""" """Update workstation rate and calculates totals"""
@@ -370,17 +362,19 @@ class DocType:
ch.fields[i] = d[i] ch.fields[i] = d[i]
ch.docstatus = self.doc.docstatus ch.docstatus = self.doc.docstatus
ch.save(1) ch.save(1)
self.doc.save()
def get_parent_bom_list(self, bom_no): def get_parent_bom_list(self, bom_no):
p_bom = sql("select parent from `tabBOM Item` where bom_no = '%s'" % 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 [] return p_bom and [i[0] for i in p_bom] or []
def validate_inactive_bom(self): def validate_bom_links(self):
if not self.doc.is_active: if not self.doc.is_active:
act_pbom = sql("""select distinct t1.parent from `tabBOM Item` t1, `tabBOM` t2 act_pbom = sql("""select distinct bom_item.parent from `tabBOM Item` bom_item
where t1.bom_no = %s and t2.name = t1.parent and t2.is_active = 1 where bom_item.bom_no = %s and bom_item.docstatus = 1
and t2.docstatus = 1 and t1.docstatus =1 """, self.doc.name) and exists (select * from `tabBOM` where name = bom_item.parent
and docstatus = 1 and is_active = 1)""", self.doc.name)
if act_pbom and act_pbom[0][0]: if act_pbom and act_pbom[0][0]:
msgprint("""Sorry cannot inactivate as BOM: %s is child action = self.doc.docstatus < 2 and _("deactivate") or _("cancel")
of one or many other active parent BOMs""" % self.doc.name, raise_exception=1) msgprint(_("Cannot ") + action + _(": It is linked to other active BOM(s)"),
raise_exception=1)

View File

@@ -2,9 +2,9 @@
{ {
"owner": "Administrator", "owner": "Administrator",
"docstatus": 0, "docstatus": 0,
"creation": "2012-12-14 10:15:15", "creation": "2012-12-19 12:29:06",
"modified_by": "Administrator", "modified_by": "Administrator",
"modified": "2012-12-14 16:51:01" "modified": "2012-12-19 15:52:47"
}, },
{ {
"istable": 0, "istable": 0,
@@ -222,6 +222,13 @@
"permlevel": 0, "permlevel": 0,
"in_filter": 1 "in_filter": 1
}, },
{
"doctype": "DocField",
"label": "Item Desription",
"fieldname": "description",
"fieldtype": "Small Text",
"permlevel": 1
},
{ {
"print_hide": 1, "print_hide": 1,
"no_copy": 1, "no_copy": 1,
@@ -256,17 +263,6 @@
"hidden": 0, "hidden": 0,
"options": "BOM Explosion Item" "options": "BOM Explosion Item"
}, },
{
"print_hide": 1,
"description": "The date at which current entry is corrected in the system.",
"no_copy": 1,
"depends_on": "eval:doc.amended_from",
"doctype": "DocField",
"label": "Amendment Date",
"fieldname": "amendment_date",
"fieldtype": "Date",
"permlevel": 0
},
{ {
"create": 1, "create": 1,
"doctype": "DocPerm", "doctype": "DocPerm",

View File

@@ -18,7 +18,7 @@ from __future__ import unicode_literals
import webnotes import webnotes
from webnotes.utils import cstr, flt from webnotes.utils import cstr, flt
from webnotes.model.code import get_obj from webnotes.model.code import get_obj
from webnotes import msgprint from webnotes import msgprint, _
class DocType: class DocType:
def __init__( self, doc, doclist=[]): def __init__( self, doc, doclist=[]):
@@ -31,7 +31,9 @@ class DocType:
bom_list = self.get_parent_boms() bom_list = self.get_parent_boms()
for bom in bom_list: for bom in bom_list:
bom_obj = get_obj("BOM", bom, with_children=1) bom_obj = get_obj("BOM", bom, with_children=1)
bom_obj.on_update() bom_obj.update_cost_and_exploded_items()
webnotes.msgprint(_("BOM replaced"))
def validate_bom(self): def validate_bom(self):
if cstr(self.doc.current_bom) == cstr(self.doc.new_bom): if cstr(self.doc.current_bom) == cstr(self.doc.new_bom):

View File

@@ -19,7 +19,6 @@ cur_frm.cscript.onload = function(doc, dt, dn) {
cfn_set_fields(doc, dt, dn); cfn_set_fields(doc, dt, dn);
} }
// ================================== Refresh ==========================================
cur_frm.cscript.refresh = function(doc, dt, dn) { cur_frm.cscript.refresh = function(doc, dt, dn) {
cur_frm.set_intro(""); cur_frm.set_intro("");
cfn_set_fields(doc, dt, dn); cfn_set_fields(doc, dt, dn);
@@ -36,23 +35,6 @@ cur_frm.cscript.refresh = function(doc, dt, dn) {
} }
} }
} }
cur_frm.cscript.update_status_html(doc);
}
cur_frm.cscript.update_status_html = function(doc) {
$(cur_frm.get_field("status_html").wrapper).empty();
if(doc.issued_qty) {
$(repl("<div class='progress'>\
<div class='bar bar-success' style='width: %(manufactured)s%' \
title='%(manufactured_qty)s %(uom)s manufactured'></div> \
</div>"), {
manufactured_qty: doc.produced_qty,
manufactured: Math.round((doc.produced_qty / doc.qty) * 100),
uom: doc.stock_uom,
}).appendTo(cur_frm.get_field("status_html").wrapper);
}
} }
var cfn_set_fields = function(doc, dt, dn) { var cfn_set_fields = function(doc, dt, dn) {
@@ -106,6 +88,9 @@ cur_frm.cscript.make_se = function(doc, purpose) {
se.purpose = purpose; se.purpose = purpose;
se.production_order = doc.name; se.production_order = doc.name;
se.company = doc.company; se.company = doc.company;
se.fg_completed_qty = doc.qty - doc.produced_qty;
se.bom_no = doc.bom_no;
se.use_multi_level_bom = 1;
loaddoc('Stock Entry', se.name); loaddoc('Stock Entry', se.name);
} }

View File

@@ -47,8 +47,8 @@ class DocType:
% cstr(self.doc.production_item), raise_exception=1) % cstr(self.doc.production_item), raise_exception=1)
if self.doc.bom_no: if self.doc.bom_no:
bom = sql("""select name from `tabBOM` where name = %s and docstatus = 1 bom = sql("""select name from `tabBOM` where name=%s and docstatus=1
and is_active = 'Yes' and item = %s""" and is_active=1 and item=%s"""
, (self.doc.bom_no, self.doc.production_item), as_dict =1) , (self.doc.bom_no, self.doc.production_item), as_dict =1)
if not bom: if not bom:
msgprint("""Incorrect BOM: %s entered. msgprint("""Incorrect BOM: %s entered.

View File

@@ -2,9 +2,9 @@
{ {
"owner": "Administrator", "owner": "Administrator",
"docstatus": 0, "docstatus": 0,
"creation": "2012-12-11 15:15:05", "creation": "2012-12-19 12:29:07",
"modified_by": "Administrator", "modified_by": "Administrator",
"modified": "2012-12-11 18:30:35" "modified": "2012-12-19 17:45:59"
}, },
{ {
"is_submittable": 1, "is_submittable": 1,
@@ -99,14 +99,6 @@
"fieldname": "column_break1", "fieldname": "column_break1",
"fieldtype": "Column Break" "fieldtype": "Column Break"
}, },
{
"read_only": 0,
"depends_on": "issued_qty",
"doctype": "DocField",
"label": "Status HTML",
"fieldname": "status_html",
"fieldtype": "HTML"
},
{ {
"read_only": 0, "read_only": 0,
"oldfieldtype": "Currency", "oldfieldtype": "Currency",
@@ -186,16 +178,12 @@
"options": "Company" "options": "Company"
}, },
{ {
"read_only": 0,
"oldfieldtype": "Select",
"doctype": "DocField", "doctype": "DocField",
"label": "Fiscal Year", "label": "Fiscal Year",
"oldfieldname": "fiscal_year",
"fieldname": "fiscal_year", "fieldname": "fiscal_year",
"fieldtype": "Select", "fieldtype": "Select",
"reqd": 1, "reqd": 1,
"options": "link:Fiscal Year", "options": "link:Fiscal Year"
"in_filter": 1
}, },
{ {
"read_only": 1, "read_only": 1,
@@ -207,16 +195,6 @@
"fieldname": "amended_from", "fieldname": "amended_from",
"fieldtype": "Data" "fieldtype": "Data"
}, },
{
"print_hide": 1,
"description": "The date at which current entry is corrected in the system.",
"no_copy": 1,
"depends_on": "eval:doc.amended_from",
"doctype": "DocField",
"label": "Amendment Date",
"fieldname": "amendment_date",
"fieldtype": "Date"
},
{ {
"doctype": "DocPerm" "doctype": "DocPerm"
} }

View File

@@ -188,6 +188,8 @@ class DocType:
items = self.get_distinct_items_and_boms()[1] items = self.get_distinct_items_and_boms()[1]
pro = self.create_production_order(items) pro = self.create_production_order(items)
if pro: if pro:
pro = ["""<a href="#Form/Production Order/%s" target="_blank">%s</a>""" % \
(p, p) for p in pro]
msgprint("Following Production Order has been generated:\n" + '\n'.join(pro)) msgprint("Following Production Order has been generated:\n" + '\n'.join(pro))
else : else :
msgprint("No Production Order generated.") msgprint("No Production Order generated.")

View File

@@ -154,6 +154,9 @@ erpnext.setup_mousetrap = function() {
Mousetrap.bind(["command+s", "ctrl+s"], function() { Mousetrap.bind(["command+s", "ctrl+s"], function() {
if(cur_frm && !cur_frm.save_disabled && cint(cur_frm.doc.docstatus)===0) if(cur_frm && !cur_frm.save_disabled && cint(cur_frm.doc.docstatus)===0)
cur_frm.save(); cur_frm.save();
else if(cur_frm && !cur_frm.save_disabled && cint(cur_frm.doc.docstatus)===1
&& cur_frm.doc.__unsaved)
cur_frm.frm_head.appframe.buttons['Update'].click();
else if(wn.container.page.save_action) else if(wn.container.page.save_action)
wn.container.page.save_action(); wn.container.page.save_action();
return false; return false;

View File

@@ -16,6 +16,40 @@
wn.provide('erpnext.utils'); wn.provide('erpnext.utils');
// TODO
erpnext.utils.Controller = Class.extend({
init: function(opts) {
$.extend(this, opts);
},
onload_post_render: function() {
this.setup_defaults();
},
setup_defaults: function() {
var me = this;
var defaults = {
posting_date: wn.datetime.get_today(),
}
$.each(defaults, function(k, v) {
if(!me.frm.doc[k]) me.frm.set_value(k, v);
});
},
refresh: function() {
erpnext.hide_naming_series();
if(this.frm.doc.__islocal && this.frm.fields_dict.naming_series
&& !this.frm.doc.naming_series) {
var series_opts = $.map((this.frm.fields_dict.naming_series.df.options ||
"").split("\n"), function(v) { return v ? v : null; });
if (series_opts.length==1) this.frm.set_value("naming_series", series_opts[0]);
}
}
});
// searches for enabled profiles // searches for enabled profiles
erpnext.utils.profile_query = function() { erpnext.utils.profile_query = function() {
return "select name, concat_ws(' ', first_name, middle_name, last_name) \ return "select name, concat_ws(' ', first_name, middle_name, last_name) \

View File

@@ -14,10 +14,44 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
cur_frm.cscript.refresh = function(doc) { wn.provide("erpnext.stock");
erpnext.hide_naming_series();
cur_frm.cscript.toggle_related_fields(doc); erpnext.stock.StockEntry = erpnext.utils.Controller.extend({
} onload_post_render: function() {
this._super();
if(this.frm.doc.__islocal && (this.frm.doc.production_order || this.frm.doc.bom_no)
&& !getchildren('Stock Entry Detail', this.frm.doc.name, 'mtn_details').length) {
// if production order / bom is mentioned, get items
this.get_items();
}
},
refresh: function() {
this._super();
this.toggle_related_fields(doc);
if (this.frm.doc.docstatus==1) this.frm.add_custom_button("Show Stock Ledger",
this.show_stock_ledger)
},
get_items: function() {
this.frm.call({
doc: this.frm.doc,
method: "get_items",
callback: function(r) {
if(!r.exc) refresh_field("mtn_details");
}
});
},
qty: function(doc, cdt, cdn) {
var d = locals[cdt][cdn];
d.transfer_qty = flt(d.qty) * flt(d.conversion_factor);
refresh_field('mtn_details');
},
});
cur_frm.cscript = new erpnext.stock.StockEntry({frm: cur_frm});
cur_frm.cscript.toggle_related_fields = function(doc) { cur_frm.cscript.toggle_related_fields = function(doc) {
if(doc.purpose == 'Purchase Return') { if(doc.purpose == 'Purchase Return') {
@@ -34,6 +68,16 @@ cur_frm.cscript.toggle_related_fields = function(doc) {
} }
} }
cur_frm.cscript.show_stock_ledger = function() {
var args = {
voucher_no: cur_frm.doc.name,
from_date: wn.datetime.str_to_user(cur_frm.doc.posting_date),
to_date: wn.datetime.str_to_user(cur_frm.doc.posting_date)
};
wn.set_route('stock-ledger',
$.map(args, function(val, key) { return key+"="+val; }).join("&&"));
}
cur_frm.cscript.delivery_note_no = function(doc,cdt,cdn){ cur_frm.cscript.delivery_note_no = function(doc,cdt,cdn){
if(doc.delivery_note_no) get_server_fields('get_cust_values','','',doc,cdt,cdn,1); if(doc.delivery_note_no) get_server_fields('get_cust_values','','',doc,cdt,cdn,1);
} }
@@ -156,13 +200,6 @@ cur_frm.cscript.s_warehouse = function(doc, cdt, cdn) {
cur_frm.cscript.t_warehouse = cur_frm.cscript.s_warehouse; cur_frm.cscript.t_warehouse = cur_frm.cscript.s_warehouse;
cur_frm.cscript.qty = function(doc, cdt, cdn) {
var d = locals[cdt][cdn];
set_multiple('Stock Entry Detail', d.name,
{'transfer_qty': flt(d.qty) * flt(d.conversion_factor)}, 'mtn_details');
refresh_field('mtn_details');
}
cur_frm.cscript.uom = function(doc, cdt, cdn) { cur_frm.cscript.uom = function(doc, cdt, cdn) {
var d = locals[cdt][cdn]; var d = locals[cdt][cdn];
if(d.uom && d.item_code){ if(d.uom && d.item_code){

View File

@@ -17,7 +17,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import webnotes import webnotes
from webnotes.utils import cstr, flt, getdate, now from webnotes.utils import cstr, cint, flt, getdate, now
from webnotes.model import db_exists, delete_doc from webnotes.model import db_exists, delete_doc
from webnotes.model.doc import Document, addchild from webnotes.model.doc import Document, addchild
from webnotes.model.wrapper import getlist, copy_doclist from webnotes.model.wrapper import getlist, copy_doclist
@@ -154,13 +154,15 @@ class DocType(TransactionBase):
d.s_warehouse or d.t_warehouse, self.doc.posting_date, d.s_warehouse or d.t_warehouse, self.doc.posting_date,
self.doc.posting_time, d.transfer_qty, d.serial_no, d.bom_no) self.doc.posting_time, d.transfer_qty, d.serial_no, d.bom_no)
d.amount = flt(d.qty) * flt(d.incoming_rate)
def get_as_on_stock(self, item_code, warehouse, posting_date, posting_time): def get_as_on_stock(self, item_code, warehouse, posting_date, posting_time):
"""Get stock qty on any date""" """Get stock qty on any date"""
bin = sql("select name from tabBin where item_code = %s and warehouse = %s", bin = sql("select name from tabBin where item_code = %s and warehouse = %s",
(item_code, warehouse)) (item_code, warehouse))
if bin: if bin:
prev_sle = get_obj('Bin', bin[0][0]).get_prev_sle(posting_date, posting_time) prev_sle = get_obj('Bin', bin[0][0]).get_prev_sle(posting_date, posting_time)
return flt(prev_sle["bin_aqat"]) return flt(prev_sle.get("bin_aqat")) or 0
else: else:
return 0 return 0
@@ -169,9 +171,10 @@ class DocType(TransactionBase):
in_rate = 0 in_rate = 0
if bom_no: if bom_no:
result = flt(webnotes.conn.sql("""select ifnull(total_cost, 0) / ifnull(quantity, 1) result = webnotes.conn.sql("""select ifnull(total_cost, 0) / ifnull(quantity, 1)
from `tabBOM` where name = %s and docstatus=1""", bom_no)) from `tabBOM` where name = %s and docstatus=1 and is_active=1""",
in_rate = result and result[0][0] or 0 (bom_no,))
in_rate = result and flt(result[0][0]) or 0
elif warehouse: elif warehouse:
in_rate = get_obj("Valuation Control").get_incoming_rate(posting_date, posting_time, in_rate = get_obj("Valuation Control").get_incoming_rate(posting_date, posting_time,
item_code, warehouse, qty, serial_no) item_code, warehouse, qty, serial_no)
@@ -198,8 +201,9 @@ class DocType(TransactionBase):
for d in getlist(self.doclist, 'mtn_details'): for d in getlist(self.doclist, 'mtn_details'):
if d.bom_no and flt(d.transfer_qty) != flt(self.doc.fg_completed_qty): if d.bom_no and flt(d.transfer_qty) != flt(self.doc.fg_completed_qty):
msgprint(_("Row #") + " %s: " % d.idx msgprint(_("Row #") + " %s: " % d.idx
+ _("Quantity as per Stock UOM should be equal to Manufacturing Quantity"), + _("Quantity should be equal to Manufacturing Quantity. ")
raise_exception=1) + _("To fetch items again, click on 'Get Items' button \
or update the Quantity manually."), raise_exception=1)
def update_serial_no(self, is_submit): def update_serial_no(self, is_submit):
"""Create / Update Serial No""" """Create / Update Serial No"""
@@ -249,10 +253,6 @@ class DocType(TransactionBase):
msgprint("""You cannot do any transaction against Production Order : %s, msgprint("""You cannot do any transaction against Production Order : %s,
as it's status is 'Stopped'"""% (pro_obj.doc.name), raise_exception=1) as it's status is 'Stopped'"""% (pro_obj.doc.name), raise_exception=1)
if getdate(pro_obj.doc.posting_date) > getdate(self.doc.posting_date):
msgprint("""Posting Date of Stock Entry cannot be before Posting Date of
Production Order: %s"""% cstr(self.doc.production_order), raise_exception=1)
# update bin # update bin
if self.doc.purpose == "Manufacture/Repack": if self.doc.purpose == "Manufacture/Repack":
pro_obj.doc.produced_qty = flt(pro_obj.doc.produced_qty) + \ pro_obj.doc.produced_qty = flt(pro_obj.doc.produced_qty) + \
@@ -348,20 +348,20 @@ class DocType(TransactionBase):
self.add_to_stock_entry_detail(self.doc.from_warehouse, self.doc.to_warehouse, self.add_to_stock_entry_detail(self.doc.from_warehouse, self.doc.to_warehouse,
self.item_dict) self.item_dict)
# add finished good item to Stock Entry Detail table # add finished good item to Stock Entry Detail table -- along with bom_no
if self.doc.production_order: if self.doc.production_order and self.doc.purpose == "Manufacture/Repack":
self.add_to_stock_entry_detail(None, pro_obj.doc.fg_warehouse, { self.add_to_stock_entry_detail(None, pro_obj.doc.fg_warehouse, {
cstr(pro_obj.doc.production_item): cstr(pro_obj.doc.production_item):
[self.doc.fg_completed_qty, pro_obj.doc.description, pro_obj.doc.stock_uom] [self.doc.fg_completed_qty, pro_obj.doc.description, pro_obj.doc.stock_uom]
}) }, bom_no=pro_obj.doc.bom_no)
elif self.doc.purpose in ["Material Receipt", "Manufacture/Repack",
"Subcontract"]: elif self.doc.purpose in ["Material Receipt", "Manufacture/Repack"]:
item = webnotes.conn.sql("""select item, description, uom from `tabBOM` item = webnotes.conn.sql("""select item, description, uom from `tabBOM`
where name=%s""", (self.doc.bom_no,), as_dict=1) where name=%s""", (self.doc.bom_no,), as_dict=1)
self.add_to_stock_entry_detail(None, None, { self.add_to_stock_entry_detail(None, self.doc.to_warehouse, {
item[0]["item"] : item[0]["item"] :
[self.doc.fg_completed_qty, item[0]["description"], item[0]["uom"]] [self.doc.fg_completed_qty, item[0]["description"], item[0]["uom"]]
}) }, bom_no=self.doc.bom_no)
self.get_stock_and_rate() self.get_stock_and_rate()
@@ -422,7 +422,7 @@ class DocType(TransactionBase):
if self.item_dict[d][0] <= 0: if self.item_dict[d][0] <= 0:
del self.item_dict[d] del self.item_dict[d]
def add_to_stock_entry_detail(self, source_wh, target_wh, item_dict, fg_item = 0, bom_no = ''): def add_to_stock_entry_detail(self, source_wh, target_wh, item_dict, bom_no=None):
for d in item_dict: for d in item_dict:
se_child = addchild(self.doc, 'mtn_details', 'Stock Entry Detail', 0, self.doclist) se_child = addchild(self.doc, 'mtn_details', 'Stock Entry Detail', 0, self.doclist)
se_child.s_warehouse = source_wh se_child.s_warehouse = source_wh
@@ -434,7 +434,7 @@ class DocType(TransactionBase):
se_child.qty = flt(item_dict[d][0]) se_child.qty = flt(item_dict[d][0])
se_child.transfer_qty = flt(item_dict[d][0]) se_child.transfer_qty = flt(item_dict[d][0])
se_child.conversion_factor = 1.00 se_child.conversion_factor = 1.00
if fg_item: se_child.bom_no = bom_no if bom_no: se_child.bom_no = bom_no
def add_to_values(self, d, wh, qty, is_cancelled): def add_to_values(self, d, wh, qty, is_cancelled):
self.values.append({ self.values.append({

View File

@@ -2,9 +2,9 @@
{ {
"owner": "Administrator", "owner": "Administrator",
"docstatus": 0, "docstatus": 0,
"creation": "2012-12-18 13:47:41", "creation": "2012-12-19 12:29:07",
"modified_by": "Administrator", "modified_by": "Administrator",
"modified": "2012-12-18 17:17:16" "modified": "2012-12-19 18:09:15"
}, },
{ {
"is_submittable": 1, "is_submittable": 1,
@@ -260,6 +260,7 @@
{ {
"print_hide": 1, "print_hide": 1,
"depends_on": "eval:!inList([\"Sales Return\", \"Purchase Return\"], doc.purpose)", "depends_on": "eval:!inList([\"Sales Return\", \"Purchase Return\"], doc.purpose)",
"description": "As per Stock UOM",
"no_copy": 0, "no_copy": 0,
"search_index": 0, "search_index": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
@@ -271,9 +272,9 @@
"oldfieldtype": "Currency", "oldfieldtype": "Currency",
"reqd": 0, "reqd": 0,
"hidden": 0, "hidden": 0,
"in_filter": 0,
"permlevel": 0, "permlevel": 0,
"report_hide": 0, "report_hide": 0
"in_filter": 0
}, },
{ {
"print_hide": 1, "print_hide": 1,
@@ -337,13 +338,12 @@
"allow_on_submit": 0, "allow_on_submit": 0,
"doctype": "DocField", "doctype": "DocField",
"label": "Get Items", "label": "Get Items",
"permlevel": 0,
"fieldname": "get_items", "fieldname": "get_items",
"fieldtype": "Button", "fieldtype": "Button",
"oldfieldtype": "Button", "oldfieldtype": "Button",
"reqd": 0, "reqd": 0,
"hidden": 0, "hidden": 0,
"options": "get_items", "permlevel": 0,
"report_hide": 0, "report_hide": 0,
"in_filter": 0 "in_filter": 0
}, },

View File

@@ -44,7 +44,7 @@ class DocType:
def validate_mandatory(self): def validate_mandatory(self):
mandatory = ['warehouse','transaction_date','posting_date','voucher_type','voucher_no','actual_qty','company'] mandatory = ['warehouse','posting_date','voucher_type','voucher_no','actual_qty','company']
for k in mandatory: for k in mandatory:
if self.doc.fields.get(k)==None: if self.doc.fields.get(k)==None:
msgprint("Stock Ledger Entry: '%s' is mandatory" % k, raise_exception = 1) msgprint("Stock Ledger Entry: '%s' is mandatory" % k, raise_exception = 1)