stock entry cleanup

This commit is contained in:
Nabin Hait 2012-12-18 18:42:02 +05:30
parent 5f175dfd00
commit 1a6a94b760
9 changed files with 325 additions and 427 deletions

View File

@ -299,7 +299,11 @@ class DocType(TransactionBase):
def add_bom(self, d): def add_bom(self, d):
#----- fetching default bom from Bill of Materials instead of Item Master -- #----- fetching default bom from Bill of Materials instead of Item Master --
bom_det = sql("select t1.item, t2.item_code, t2.qty_consumed_per_unit, t2.moving_avg_rate, t2.value_as_per_mar, t2.stock_uom, t2.name, t2.parent from `tabBOM` t1, `tabBOM Item` t2 where t2.parent = t1.name and t1.item = '%s' and ifnull(t1.is_default,0) = 1 and t1.docstatus = 1" % d.item_code) bom_det = sql("""select t1.item, t2.item_code, t2.qty_consumed_per_unit,
t2.moving_avg_rate, t2.value_as_per_mar, t2.stock_uom, t2.name, t2.parent
from `tabBOM` t1, `tabBOM Item` t2
where t2.parent = t1.name and t1.item = %s
and ifnull(t1.is_default,0) = 1 and t1.docstatus = 1""", (d.item_code,))
if not bom_det: if not bom_det:
msgprint("No default BOM exists for item: %s" % d.item_code) msgprint("No default BOM exists for item: %s" % d.item_code)

View File

@ -93,21 +93,19 @@ cur_frm.cscript['Unstop Production Order'] = function() {
cur_frm.cscript['Issue Raw Materials'] = function() { cur_frm.cscript['Issue Raw Materials'] = function() {
var doc = cur_frm.doc; var doc = cur_frm.doc;
cur_frm.cscript.make_se(doc, process = 'Material Transfer'); cur_frm.cscript.make_se(doc, 'Material Transfer');
} }
cur_frm.cscript['Update Finished Goods'] = function() { cur_frm.cscript['Update Finished Goods'] = function() {
var doc = cur_frm.doc; var doc = cur_frm.doc;
cur_frm.cscript.make_se(doc, process = 'Backflush'); cur_frm.cscript.make_se(doc, 'Manufacture/Repack');
} }
cur_frm.cscript.make_se = function(doc, process) { cur_frm.cscript.make_se = function(doc, purpose) {
var se = wn.model.get_new_doc("Stock Entry"); var se = wn.model.get_new_doc("Stock Entry");
se.purpose = 'Production Order'; se.purpose = purpose;
se.process = process;
se.production_order = doc.name; se.production_order = doc.name;
se.company = doc.company; se.company = doc.company;
loaddoc('Stock Entry', se.name); loaddoc('Stock Entry', se.name);
} }

View File

@ -3,8 +3,8 @@ import webnotes
def execute(): def execute():
delete_doctypes() delete_doctypes()
rename_module() rename_module()
rebuilt_exploded_bom()
cleanup_bom() cleanup_bom()
rebuild_exploded_bom()
def delete_doctypes(): def delete_doctypes():
from webnotes.model import delete_doc from webnotes.model import delete_doc
@ -36,12 +36,14 @@ def rename_module():
# set end of life to null if "0000-00-00" # set end of life to null if "0000-00-00"
webnotes.conn.sql("""update `tabItem` set end_of_life=null where end_of_life='0000-00-00'""") webnotes.conn.sql("""update `tabItem` set end_of_life=null where end_of_life='0000-00-00'""")
def rebuilt_exploded_bom(): def rebuild_exploded_bom():
from webnotes.model.code import get_obj from webnotes.model.code import get_obj
for bom in webnotes.conn.sql("""select name from `tabBOM` where docstatus < 2"""): for bom in webnotes.conn.sql("""select name from `tabBOM` where docstatus < 2"""):
get_obj("BOM", bom[0], with_children=1).on_update() get_obj("BOM", bom[0], with_children=1).on_update()
def cleanup_bom(): def cleanup_bom():
webnotes.conn.sql("""UPDATE `tabBOM` SET is_active = if(is_active in ('Yes', 1), 1, 0), webnotes.conn.sql("""UPDATE `tabBOM` SET is_active = 1 where ifnull(is_active, 'No') = 'Yes'""")
with_operations = 1""") webnotes.conn.sql("""UPDATE `tabBOM` SET is_active = 0 where ifnull(is_active, 'No') = 'No'""")
webnotes.reload_doc("manufacturing", "doctype", "bom")
webnotes.conn.sql("""update `tabBOM` set with_operations = 1""")

View File

@ -12,35 +12,35 @@ def custom_fields():
"fieldname": "is_excisable_goods", "fieldname": "is_excisable_goods",
"fieldtype": "Select", "fieldtype": "Select",
"options": "\nYes\nNo", "options": "\nYes\nNo",
"insert_after": "company" "insert_after": "Company"
}, },
{ {
"label": "Excisable Goods", "label": "Excisable Goods",
"fieldname": "excisable_goods", "fieldname": "excisable_goods",
"fieldtype": "Select", "fieldtype": "Select",
"options": "\nReturnable\nNon-Returnable)", "options": "\nReturnable\nNon-Returnable)",
"insert_after": "amended_from" "insert_after": "Amended From"
}, },
{ {
"label": "Under Rule", "label": "Under Rule",
"fieldname": "under_rule", "fieldname": "under_rule",
"fieldtype": "Select", "fieldtype": "Select",
"options": "\nOrdinary\n57 AC (5) a\n57 F (2) Non-Exc.", "options": "\nOrdinary\n57 AC (5) a\n57 F (2) Non-Exc.",
"insert_after": "remarks" "insert_after": "Remarks"
}, },
{ {
"label": "Transporter", "label": "Transporter",
"fieldname": "transporter", "fieldname": "transporter",
"fieldtype": "Data", "fieldtype": "Data",
"options": "", "options": "",
"insert_after": "project_name" "insert_after": "Project Name"
}, },
{ {
"label": "Transfer Date", "label": "Transfer Date",
"fieldname": "transfer_date", "fieldname": "transfer_date",
"fieldtype": "Date", "fieldtype": "Date",
"options": "", "options": "",
"insert_after": "select_print_heading" "insert_after": "Select Print Heading"
}, },
] ]
@ -62,9 +62,13 @@ def create_custom_field(fld):
def deprecate_process(): def deprecate_process():
webnotes.conn.sql("""update `tabStock Entry` webnotes.conn.sql("""update `tabStock Entry`
set `purpose`="Production Order - Material Transfer" set `purpose`="Material Transfer"
where process="Material Transfer" and purpose="Production Order" """) where process="Material Transfer" and purpose="Production Order" """)
webnotes.conn.sql("""update `tabStock Entry` webnotes.conn.sql("""update `tabStock Entry`
set `purpose`="Production Order - Update Finished Goods" set `purpose`="Manufacture/Repack"
where process="Backflush" and purpose="Production Order" """) where (process="Backflush" and purpose="Production Order") or purpose="Other" """)
webnotes.conn.sql("""update `tabStock Entry`
set `purpose`="Subcontract"
where process="Subcontracting" """)

View File

@ -542,4 +542,8 @@ patch_list = [
'patch_module': 'patches.december_2012', 'patch_module': 'patches.december_2012',
'patch_file': 'clear_web_cache', 'patch_file': 'clear_web_cache',
}, },
{
'patch_module': 'patches.december_2012',
'patch_file': 'stock_entry_cleanup',
},
] ]

View File

@ -19,71 +19,19 @@ cur_frm.cscript.refresh = function(doc) {
cur_frm.cscript.toggle_related_fields(doc); cur_frm.cscript.toggle_related_fields(doc);
} }
cur_frm.cscript.toggle_related_fields = function(doc) { cur_frm.cscript.toggle_related_fields = function(doc) {
if(doc.purpose.startswith("Production Order") || doc.purpose == "Other") {
}
if (doc.purpose == 'Production Order' || doc.purpose == 'Other') {
unhide_field('get_items');
hide_field(['from_warehouse', 'to_warehouse','purchase_receipt_no',
'delivery_note_no', 'sales_invoice_no','warehouse_html']);
if (doc.purpose=='Production Order') unhide_field(['production_order', 'process']);
else {
doc.production_order = doc.process = '';
hide_field(['production_order', 'process']);
}
doc.from_warehouse = '';
doc.to_warehouse = '';
refresh_field(['from_warehosue', 'to_warehouse']);
if (doc.process == 'Backflush' || doc.purpose == 'Other') {
unhide_field('fg_completed_qty');
}
else{
hide_field('fg_completed_qty');
doc.fg_completed_qty = 0;
}
} else {
unhide_field(['from_warehouse', 'to_warehouse']);
hide_field(['production_order', 'process', 'get_items', 'fg_completed_qty',
'purchase_receipt_no','delivery_note_no', 'sales_invoice_no']);
doc.production_order = '';
doc.process = '';
doc.fg_completed_qty = 0;
}
if(doc.purpose == 'Purchase Return') { if(doc.purpose == 'Purchase Return') {
doc.customer = doc.customer_name = doc.customer_address = doc.customer = doc.customer_name = doc.customer_address =
doc.delivery_note_no = doc.sales_invoice_no = ''; doc.delivery_note_no = doc.sales_invoice_no = null;
unhide_field(['supplier','supplier_name','supplier_address','purchase_receipt_no']); doc.bom_no = doc.production_order = doc.fg_completed_qty = null;
$(cur_frm.fields_dict.contact_section.row.wrapper).toggle(true); } else if(doc.purpose == 'Sales Return') {
} doc.supplier=doc.supplier_name = doc.supplier_address = doc.purchase_receipt_no=null;
else if(doc.purpose == 'Sales Return'){ doc.bom_no = doc.production_order = doc.fg_completed_qty = null;
doc.supplier=doc.supplier_name = doc.supplier_address=doc.purchase_receipt_no=''; } else {
unhide_field(['customer', 'customer_name', 'customer_address',
'delivery_note_no', 'sales_invoice_no']);
$(cur_frm.fields_dict.contact_section.row.wrapper).toggle(true);
} else{
doc.customer = doc.customer_name = doc.customer_address = doc.customer = doc.customer_name = doc.customer_address =
doc.delivery_note_no = doc.sales_invoice_no = doc.supplier = doc.delivery_note_no = doc.sales_invoice_no = doc.supplier =
doc.supplier_name = doc.supplier_address = doc.purchase_receipt_no = ''; doc.supplier_name = doc.supplier_address = doc.purchase_receipt_no = null;
} }
refresh_many(lst);
} }
cur_frm.cscript.delivery_note_no = function(doc,cdt,cdn){ cur_frm.cscript.delivery_note_no = function(doc,cdt,cdn){
@ -108,43 +56,41 @@ cur_frm.cscript.supplier = function(doc,cdt,cdn){
} }
cur_frm.fields_dict['production_order'].get_query = function(doc) { cur_frm.fields_dict['production_order'].get_query = function(doc) {
return 'SELECT DISTINCT `tabProduction Order`.`name` FROM `tabProduction Order` WHERE `tabProduction Order`.`docstatus` = 1 AND `tabProduction Order`.`qty` > ifnull(`tabProduction Order`.`produced_qty`,0) AND `tabProduction Order`.`name` like "%s" ORDER BY `tabProduction Order`.`name` DESC LIMIT 50'; return 'select name from `tabProduction Order` \
where docstatus = 1 and qty > ifnull(produced_qty,0) AND %(key)s like "%s%%" \
order by name desc limit 50';
} }
cur_frm.cscript.purpose = function(doc, cdt, cdn) { cur_frm.cscript.purpose = function(doc, cdt, cdn) {
cur_frm.cscript.toggle_related_fields(doc, cdt, cdn); cur_frm.cscript.toggle_related_fields(doc, cdt, cdn);
} }
cur_frm.cscript.process = function(doc, cdt, cdn) {
cur_frm.cscript.toggle_related_fields(doc, cdt, cdn);
}
// item code - only if quantity present in source warehosue // item code - only if quantity present in source warehosue
//
var fld = cur_frm.fields_dict['mtn_details'].grid.get_field('item_code'); var fld = cur_frm.fields_dict['mtn_details'].grid.get_field('item_code');
fld.query_description = "If Source Warehouse is selected, only items present in the warehouse with actual qty > 0 will be selected" fld.query_description = "If Source Warehouse is selected, items with existing stock \
for that warehouse will be selected";
fld.get_query = function(doc, cdt, cdn) { fld.get_query = function(doc, cdt, cdn) {
var d = locals[cdt][cdn]; var d = locals[cdt][cdn];
if(d.s_warehouse) { if(d.s_warehouse) {
return 'SELECT tabItem.name, tabItem.description, tabBin.actual_qty ' return 'SELECT tabItem.name, tabItem.description, tabBin.actual_qty '
+'FROM tabItem, tabBin ' + 'FROM tabItem, tabBin '
+'WHERE tabItem.name = tabBin.item_code ' + 'WHERE tabItem.name = tabBin.item_code '
+'AND ifnull(`tabBin`.`actual_qty`,0) > 0 ' + 'AND ifnull(`tabBin`.`actual_qty`,0) > 0 '
+'AND tabBin.warehouse="'+ d.s_warehouse +'" ' + 'AND tabBin.warehouse="'+ d.s_warehouse +'" '
+'AND tabItem.docstatus < 2 ' + 'AND tabItem.docstatus < 2 '
+'AND (ifnull(`tabItem`.`end_of_life`,"") = "" OR `tabItem`.`end_of_life` > NOW() OR `tabItem`.`end_of_life`="0000-00-00") ' + 'AND (ifnull(`tabItem`.`end_of_life`,"") = "" OR `tabItem`.`end_of_life` > NOW() OR `tabItem`.`end_of_life`="0000-00-00") '
+'AND tabItem.%(key)s LIKE "%s" ' + 'AND tabItem.%(key)s LIKE "%s" '
+'ORDER BY tabItem.name ASC ' + 'ORDER BY tabItem.name ASC '
+'LIMIT 50' + 'LIMIT 50'
} else { } else {
return 'SELECT tabItem.name, tabItem.description ' return 'SELECT tabItem.name, tabItem.description '
+'FROM tabItem ' + 'FROM tabItem '
+'WHERE tabItem.docstatus < 2 ' + 'WHERE tabItem.docstatus < 2 '
+'AND (ifnull(`tabItem`.`end_of_life`,"") = "" OR `tabItem`.`end_of_life` > NOW() OR `tabItem`.`end_of_life`="0000-00-00") ' + 'AND (ifnull(`tabItem`.`end_of_life`,"") = "" OR `tabItem`.`end_of_life` > NOW() OR `tabItem`.`end_of_life`="0000-00-00") '
+'AND tabItem.%(key)s LIKE "%s" ' + 'AND tabItem.%(key)s LIKE "%s" '
+'ORDER BY tabItem.name ASC ' + 'ORDER BY tabItem.name ASC '
+'LIMIT 50' + 'LIMIT 50'
} }
} }
@ -190,7 +136,6 @@ cur_frm.cscript.item_code = function(doc, cdt, cdn) {
'warehouse' : cstr(d.s_warehouse) || cstr(d.t_warehouse), 'warehouse' : cstr(d.s_warehouse) || cstr(d.t_warehouse),
'transfer_qty' : d.transfer_qty, 'transfer_qty' : d.transfer_qty,
'serial_no' : d.serial_no, 'serial_no' : d.serial_no,
'fg_item' : d.fg_item,
'bom_no' : d.bom_no 'bom_no' : d.bom_no
}; };
get_server_fields('get_item_details',JSON.stringify(args),'mtn_details',doc,cdt,cdn,1); get_server_fields('get_item_details',JSON.stringify(args),'mtn_details',doc,cdt,cdn,1);
@ -203,7 +148,6 @@ cur_frm.cscript.s_warehouse = function(doc, cdt, cdn) {
'warehouse' : cstr(d.s_warehouse) || cstr(d.t_warehouse), 'warehouse' : cstr(d.s_warehouse) || cstr(d.t_warehouse),
'transfer_qty' : d.transfer_qty, 'transfer_qty' : d.transfer_qty,
'serial_no' : d.serial_no, 'serial_no' : d.serial_no,
'fg_item' : d.fg_item,
'bom_no' : d.bom_no 'bom_no' : d.bom_no
} }
get_server_fields('get_warehouse_details', JSON.stringify(args), get_server_fields('get_warehouse_details', JSON.stringify(args),
@ -212,16 +156,10 @@ 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.transfer_qty = function(doc,cdt,cdn) {
var d = locals[cdt][cdn];
if (doc.from_warehouse && (flt(d.transfer_qty) > flt(d.actual_qty))) {
alert("Transfer Quantity is more than Available Qty");
}
}
cur_frm.cscript.qty = function(doc, cdt, cdn) { cur_frm.cscript.qty = function(doc, cdt, cdn) {
var d = locals[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'); set_multiple('Stock Entry Detail', d.name,
{'transfer_qty': flt(d.qty) * flt(d.conversion_factor)}, 'mtn_details');
refresh_field('mtn_details'); refresh_field('mtn_details');
} }

View File

@ -48,6 +48,18 @@ class DocType(TransactionBase):
self.validate_bom() self.validate_bom()
self.validate_finished_goods() self.validate_finished_goods()
def on_submit(self):
self.update_serial_no(1)
self.update_stock_ledger(0)
# update Production Order
self.update_production_order(1)
def on_cancel(self):
self.update_serial_no(0)
self.update_stock_ledger(1)
# update Production Order
self.update_production_order(0)
def validate_serial_nos(self): def validate_serial_nos(self):
sl_obj = get_obj("Stock Ledger") sl_obj = get_obj("Stock Ledger")
sl_obj.scrub_serial_nos(self) sl_obj.scrub_serial_nos(self)
@ -56,10 +68,8 @@ class DocType(TransactionBase):
def validate_warehouse(self, pro_obj): def validate_warehouse(self, pro_obj):
"""perform various (sometimes conditional) validations on warehouse""" """perform various (sometimes conditional) validations on warehouse"""
source_mandatory = ["Material Issue", "Material Transfer", source_mandatory = ["Material Issue", "Material Transfer", "Purchase Return"]
"Production Order - Material Transfer", "Purchase Return"] target_mandatory = ["Material Receipt", "Material Transfer", "Sales Return"]
target_mandatory = ["Material Receipt", "Material Transfer",
"Production Order - Material Transfer", "Sales Return"]
fg_qty = 0 fg_qty = 0
for d in getlist(self.doclist, 'mtn_details'): for d in getlist(self.doclist, 'mtn_details'):
@ -89,11 +99,15 @@ class DocType(TransactionBase):
if self.doc.purpose not in source_mandatory: if self.doc.purpose not in source_mandatory:
d.s_warehouse = None d.s_warehouse = None
if self.doc.purpose == "Production Order - Update Finished Goods": if self.doc.purpose == "Manufacture/Repack":
if d.item_code == pro_obj.doc.item: if d.bom_no:
d.s_warehouse = None d.s_warehouse = None
if cstr(d.t_warehouse) != pro_obj.doc.fg_warehouse: if not d.t_warehouse:
msgprint(_("Row # ") + "%s: " % cint(d.idx)
+ _("Target Warehouse") + _(" is mandatory"), raise_exception=1)
elif pro_obj and cstr(d.t_warehouse) != pro_obj.doc.fg_warehouse:
msgprint(_("Row # ") + "%s: " % cint(d.idx) msgprint(_("Row # ") + "%s: " % cint(d.idx)
+ _("Target Warehouse") + _(" should be same as that in ") + _("Target Warehouse") + _(" should be same as that in ")
+ _("Production Order"), raise_exception=1) + _("Production Order"), raise_exception=1)
@ -104,18 +118,14 @@ class DocType(TransactionBase):
msgprint(_("Row # ") + "%s: " % cint(d.idx) msgprint(_("Row # ") + "%s: " % cint(d.idx)
+ _("Source Warehouse") + _(" is mandatory"), raise_exception=1) + _("Source Warehouse") + _(" is mandatory"), raise_exception=1)
# if self.doc.fg_completed_qty and flt(self.doc.fg_completed_qty) != flt(fg_qty):
# msgprint("The Total of FG Qty %s in Stock Entry Detail do not match with FG Completed Qty %s" % (flt(fg_qty), flt(self.doc.fg_completed_qty)))
# raise Exception
def validate_production_order(self, pro_obj=None): def validate_production_order(self, pro_obj=None):
if not pro_obj: if not pro_obj:
if self.doc.production_order:
pro_obj = get_obj('Production Order', self.doc.production_order) pro_obj = get_obj('Production Order', self.doc.production_order)
else:
return
if self.doc.purpose == "Production Order - Material Transfer": if self.doc.purpose == "Manufacture/Repack":
self.doc.fg_completed_qty = 0
elif self.doc.purpose == "Production Order - Update Finished Goods":
if not flt(self.doc.fg_completed_qty): if not flt(self.doc.fg_completed_qty):
msgprint(_("Manufacturing Quantity") + _(" is mandatory"), raise_exception=1) msgprint(_("Manufacturing Quantity") + _(" is mandatory"), raise_exception=1)
@ -128,7 +138,7 @@ class DocType(TransactionBase):
+ _("Hence, maximum allowed Manufacturing Quantity") + _("Hence, maximum allowed Manufacturing Quantity")
+ " = %s." % flt(pro_obj.doc.qty) - flt(pro_obj.doc.produced_qty), + " = %s." % flt(pro_obj.doc.qty) - flt(pro_obj.doc.produced_qty),
raise_exception=1) raise_exception=1)
else: elif self.doc.purpose != "Material Transfer":
self.doc.production_order = None self.doc.production_order = None
def get_stock_and_rate(self): def get_stock_and_rate(self):
@ -184,16 +194,88 @@ class DocType(TransactionBase):
+ _(" or the BOM is cancelled or inactive"), raise_exception=1) + _(" or the BOM is cancelled or inactive"), raise_exception=1)
def validate_finished_goods(self): def validate_finished_goods(self):
"""validation: finished good quantity should be same as manufacturing quantity"""
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
+ _("Quantity as per Stock UOM should be equal to Manufacturing Quantity"),
raise_exception=1)
def update_serial_no(self, is_submit):
"""Create / Update Serial No"""
sl_obj = get_obj('Stock Ledger')
if is_submit:
sl_obj.validate_serial_no_warehouse(self, 'mtn_details')
for d in getlist(self.doclist, 'mtn_details'):
if d.serial_no:
serial_nos = sl_obj.get_sr_no_list(d.serial_no)
for x in serial_nos:
serial_no = x.strip()
if d.s_warehouse:
sl_obj.update_serial_delivery_details(self, d, serial_no, is_submit)
if d.t_warehouse:
sl_obj.update_serial_purchase_details(self, d, serial_no, is_submit,
self.doc.purpose)
if self.doc.purpose == 'Purchase Return':
#delete_doc("Serial No", serial_no)
serial_doc = Document("Serial No", serial_no)
serial_doc.status = is_submit and 'Purchase Returned' or 'In Store'
serial_doc.docstatus = is_submit and 2 or 0
serial_doc.save()
def update_stock_ledger(self, is_cancelled=0):
self.values = []
for d in getlist(self.doclist, 'mtn_details'):
if cstr(d.s_warehouse):
self.add_to_values(d, cstr(d.s_warehouse), -flt(d.transfer_qty), is_cancelled)
if cstr(d.t_warehouse):
self.add_to_values(d, cstr(d.t_warehouse), flt(d.transfer_qty), is_cancelled)
get_obj('Stock Ledger', 'Stock Ledger').update_stock(self.values,
self.doc.amended_from and 'Yes' or 'No')
def update_production_order(self, is_submit):
if self.doc.production_order:
# first perform some validations
# (they are here coz this fn is also called during on_cancel)
pro_obj = get_obj("Production Order", self.doc.production_order)
if flt(pro_obj.doc.docstatus) != 1:
msgprint("""You cannot do any transaction against
Production Order : %s, as it's not submitted"""
% (pro_obj.doc.name), raise_exception=1)
if pro_obj.doc.status == 'Stopped':
msgprint("""You cannot do any transaction against Production Order : %s,
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
if self.doc.purpose == "Manufacture/Repack":
pro_obj.doc.produced_qty = flt(pro_obj.doc.produced_qty) + \
(is_submit and 1 or -1 ) * flt(self.doc.fg_completed_qty)
args = {
"item_code": pro_obj.doc.production_item,
"posting_date": self.doc.posting_date,
"planned_qty": (is_submit and -1 or 1 ) * flt(self.doc.fg_completed_qty)
}
get_obj('Warehouse', pro_obj.doc.fg_warehouse).update_bin(args)
# update production order status
pro_obj.doc.status = (flt(pro_obj.doc.qty)==flt(pro_obj.doc.produced_qty)) \
and 'Completed' or 'In Process'
pro_obj.doc.save()
def get_item_details(self, arg): def get_item_details(self, arg):
import json import json
arg, actual_qty, in_rate = json.loads(arg), 0, 0 arg, actual_qty, in_rate = json.loads(arg), 0, 0
item = sql("select stock_uom, description, item_name from `tabItem` where name = %s and (ifnull(end_of_life,'')='' or end_of_life ='0000-00-00' or end_of_life > now())", (arg.get('item_code')), as_dict = 1) item = sql("""select stock_uom, description, item_name from `tabItem`
where name = %s and (ifnull(end_of_life,'')='' or end_of_life ='0000-00-00'
or end_of_life > now())""", (arg.get('item_code')), as_dict = 1)
if not item: if not item:
msgprint("Item is not active", raise_exception=1) msgprint("Item is not active", raise_exception=1)
@ -213,12 +295,13 @@ class DocType(TransactionBase):
ret.update(stock_and_rate) ret.update(stock_and_rate)
return ret return ret
def get_uom_details(self, arg = ''): def get_uom_details(self, arg = ''):
arg, ret = eval(arg), {} arg, ret = eval(arg), {}
uom = sql("select conversion_factor from `tabUOM Conversion Detail` where parent = %s and uom = %s", (arg['item_code'],arg['uom']), as_dict = 1) uom = sql("""select conversion_factor from `tabUOM Conversion Detail`
where parent = %s and uom = %s""", (arg['item_code'], arg['uom']), as_dict = 1)
if not uom: if not uom:
msgprint("There is no Conversion Factor for UOM '%s' in Item '%s'" % (arg['uom'], arg['item_code'])) msgprint("There is no Conversion Factor for UOM '%s' in Item '%s'" % (arg['uom'],
arg['item_code']))
ret = {'uom' : ''} ret = {'uom' : ''}
else: else:
ret = { ret = {
@ -235,114 +318,31 @@ class DocType(TransactionBase):
self.doc.posting_date, self.doc.posting_time), self.doc.posting_date, self.doc.posting_time),
"incoming_rate" : self.get_incoming_rate(arg.get('item_code'), "incoming_rate" : self.get_incoming_rate(arg.get('item_code'),
arg.get('warehouse'), self.doc.posting_date, self.doc.posting_time, arg.get('warehouse'), self.doc.posting_date, self.doc.posting_time,
arg.get('transfer_qty'), arg.get('serial_no'), arg.get('fg_item'), arg.get('transfer_qty'), arg.get('serial_no'), arg.get('bom_no')) or 0
arg.get('bom_no')) or 0
} }
return ret return ret
def make_items_dict(self, items_list):
"""makes dict of unique items with it's qty"""
for i in items_list:
if self.item_dict.has_key(i[0]):
self.item_dict[i[0]][0] = flt(self.item_dict[i[0]][0]) + flt(i[1])
else:
self.item_dict[i[0]] = [flt(i[1]), cstr(i[2]), cstr(i[3])]
def update_only_remaining_qty(self):
""" Only pending raw material to be issued to shop floor """
already_issued_item = {}
result = sql("""select t1.item_code, sum(t1.qty)
from `tabStock Entry Detail` t1, `tabStock Entry` t2
where t1.parent = t2.name and t2.production_order = %s
and t2.purpose = 'Production Order - Material Transfer'
and t2.docstatus = 1 group by t1.item_code""", self.doc.production_order)
for t in result:
already_issued_item[t[0]] = flt(t[1])
for d in self.item_dict.keys():
self.item_dict[d][0] -= already_issued_item.get(d, 0)
if self.item_dict[d][0] <= 0:
del self.item_dict[d]
def get_raw_materials(self, bom_no, fg_qty, use_multi_level_bom):
"""
get all items from flat bom except
child items of sub-contracted and sub assembly items
and sub assembly items itself.
"""
if use_multi_level_bom:
# get all raw materials with sub assembly childs
fl_bom_sa_child_item = 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
""" , (fg_qty, bom_no))
self.make_items_dict(fl_bom_sa_child_item)
else:
# Get all raw materials considering multi level BOM,
# if multi level bom consider childs of Sub-Assembly items
fl_bom_sa_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
""" % (fg_qty, bom_no))
self.make_items_dict(fl_bom_sa_items)
# Update only qty remaining to be issued for production
if self.doc.purpose == 'Production Order - Material Transfer':
self.update_only_remaining_qty()
def add_to_stock_entry_detail(self, source_wh, target_wh, item_dict, fg_item = 0, bom_no = ''):
for d in item_dict:
se_child = addchild(self.doc, 'mtn_details', 'Stock Entry Detail', 0, self.doclist)
se_child.s_warehouse = source_wh
se_child.t_warehouse = target_wh
se_child.fg_item = fg_item
se_child.item_code = cstr(d)
se_child.description = item_dict[d][1]
se_child.uom = item_dict[d][2]
se_child.stock_uom = item_dict[d][2]
se_child.reqd_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.conversion_factor = 1.00
if fg_item: se_child.bom_no = bom_no
def get_items(self): def get_items(self):
bom_no = self.doc.bom_no self.doclist = self.doc.clear_table(self.doclist, 'mtn_details', 1)
fg_qty = self.doc.fg_completed_qty
if self.doc.purpose.startswith('Production Order'):
if not self.doc.production_order:
webnotes.msgprint(_("Please specify Production Order"), raise_exception=1)
if self.doc.production_order:
# common validations # common validations
pro_obj = get_obj('Production Order', self.doc.production_order) pro_obj = get_obj('Production Order', self.doc.production_order)
if pro_obj: if pro_obj:
self.validate_production_order(pro_obj) self.validate_production_order(pro_obj)
bom_no = pro_obj.doc.bom_no self.doc.bom_no = pro_obj.doc.bom_no
fg_qty = (self.doc.purpose == 'Production Order - Update Finished Goods') \ self.doc.fg_completed_qty = (self.doc.purpose == "Manufacture/Repack") \
and flt(self.doc.fg_completed_qty) or flt(pro_obj.doc.qty) and flt(self.doc.fg_completed_qty) \
or flt(pro_obj.doc.qty) - flt(pro_obj.doc.produced_qty)
else:
# invalid production order
self.doc.production_order = None
self.get_raw_materials(bom_no, fg_qty, self.doc.use_multi_level_bom) if self.doc.bom_no:
self.doclist = self.doc.clear_table(self.doclist, 'mtn_details', 1) if self.doc.purpose in ["Material Issue", "Material Transfer", "Manufacture/Repack",
"Subcontract"]:
self.get_raw_materials()
# add raw materials to Stock Entry Detail table # add raw materials to Stock Entry Detail table
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,
@ -354,7 +354,8 @@ class DocType(TransactionBase):
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]
}) })
elif self.doc.bom_no: elif self.doc.purpose in ["Material Receipt", "Manufacture/Repack",
"Subcontract"]:
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, None, {
@ -362,136 +363,97 @@ class DocType(TransactionBase):
[self.doc.fg_completed_qty, item[0]["description"], item[0]["uom"]] [self.doc.fg_completed_qty, item[0]["description"], item[0]["uom"]]
}) })
fg_item_dict = {}
if self.doc.purpose == 'Production Order - Update Finished Goods':
sw = ''
tw = cstr(pro_obj.doc.fg_warehouse)
fg_item_dict = {
cstr(pro_obj.doc.production_item) : [self.doc.fg_completed_qty,
pro_obj.doc.description, pro_obj.doc.stock_uom]
}
elif self.doc.purpose == 'Other' and self.doc.bom_no:
sw, tw = '', ''
item = sql("select item, description, uom from `tabBOM` where name = %s", self.doc.bom_no, as_dict=1)
fg_item_dict = {
item[0]['item'] : [self.doc.fg_completed_qty,
item[0]['description'], item[0]['uom']]
}
if fg_item_dict:
self.add_to_stock_entry_detail(sw, tw, fg_item_dict, fg_item = 1, bom_no = bom_no)
self.get_stock_and_rate() self.get_stock_and_rate()
def validate_qty_as_per_stock_uom(self): def get_raw_materials(self):
for d in getlist(self.doclist, 'mtn_details'): """
if flt(d.transfer_qty) <= 0: get all items from flat bom except
msgprint("Row No #%s: Qty as per Stock UOM can not be less than \ child items of sub-contracted and sub assembly items
or equal to zero" % cint(d.idx), raise_exception=1) and sub assembly items itself.
"""
if self.doc.use_multi_level_bom:
# get all raw materials with sub assembly childs
fl_bom_sa_child_item = 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""" , (self.doc.fg_completed_qty, self.doc.bom_no))
self.make_items_dict(fl_bom_sa_child_item)
else:
# Get all raw materials considering multi level BOM,
# if multi level bom consider childs of Sub-Assembly items
fl_bom_sa_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""" % (self.doc.fg_completed_qty, self.doc.bom_no))
self.make_items_dict(fl_bom_sa_items)
# Update only qty remaining to be issued for production
if self.doc.purpose == 'Material Transfer' and self.doc.production_order:
self.update_only_remaining_qty()
def make_items_dict(self, items_list):
"""makes dict of unique items with it's qty"""
for i in items_list:
if self.item_dict.has_key(i[0]):
self.item_dict[i[0]][0] = flt(self.item_dict[i[0]][0]) + flt(i[1])
else:
self.item_dict[i[0]] = [flt(i[1]), cstr(i[2]), cstr(i[3])]
def update_only_remaining_qty(self):
""" Only pending raw material to be issued to shop floor """
already_issued_item = {}
result = sql("""select t1.item_code, sum(t1.qty)
from `tabStock Entry Detail` t1, `tabStock Entry` t2
where t1.parent = t2.name and t2.production_order = %s and t2.docstatus = 1
and t2.purpose = 'Material Transfer'
group by t1.item_code""", self.doc.production_order)
for t in result:
already_issued_item[t[0]] = flt(t[1])
for d in self.item_dict.keys():
self.item_dict[d][0] -= already_issued_item.get(d, 0)
if self.item_dict[d][0] <= 0:
del self.item_dict[d]
def add_to_stock_entry_detail(self, source_wh, target_wh, item_dict, fg_item = 0, bom_no = ''):
for d in item_dict:
se_child = addchild(self.doc, 'mtn_details', 'Stock Entry Detail', 0, self.doclist)
se_child.s_warehouse = source_wh
se_child.t_warehouse = target_wh
se_child.item_code = cstr(d)
se_child.description = item_dict[d][1]
se_child.uom = item_dict[d][2]
se_child.stock_uom = item_dict[d][2]
se_child.qty = flt(item_dict[d][0])
se_child.transfer_qty = flt(item_dict[d][0])
se_child.conversion_factor = 1.00
if fg_item: 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({
'item_code' : d.item_code, 'item_code': d.item_code,
'warehouse' : wh, 'warehouse': wh,
'posting_date' : self.doc.posting_date, 'posting_date': self.doc.posting_date,
'posting_time' : self.doc.posting_time, 'posting_time': self.doc.posting_time,
'voucher_type' : 'Stock Entry', 'voucher_type': 'Stock Entry',
'voucher_no' : self.doc.name, 'voucher_no': self.doc.name,
'voucher_detail_no' : d.name, 'voucher_detail_no': d.name,
'actual_qty' : qty, 'actual_qty': qty,
'incoming_rate' : flt(d.incoming_rate) or 0, 'incoming_rate': flt(d.incoming_rate) or 0,
'stock_uom' : d.stock_uom, 'stock_uom': d.stock_uom,
'company' : self.doc.company, 'company': self.doc.company,
'is_cancelled' : (is_cancelled ==1) and 'Yes' or 'No', 'is_cancelled': (is_cancelled ==1) and 'Yes' or 'No',
'batch_no' : d.batch_no, 'batch_no': d.batch_no,
'serial_no' : d.serial_no 'serial_no': d.serial_no
}) })
def update_stock_ledger(self, is_cancelled=0):
self.values = []
for d in getlist(self.doclist, 'mtn_details'):
if cstr(d.s_warehouse):
self.add_to_values(d, cstr(d.s_warehouse), -flt(d.transfer_qty), is_cancelled)
if cstr(d.t_warehouse):
self.add_to_values(d, cstr(d.t_warehouse), flt(d.transfer_qty), is_cancelled)
get_obj('Stock Ledger', 'Stock Ledger').update_stock(self.values, self.doc.amended_from and 'Yes' or 'No')
def update_production_order(self, is_submit):
if self.doc.production_order:
pro_obj = get_obj("Production Order", self.doc.production_order)
if flt(pro_obj.doc.docstatus) != 1:
msgprint("""You cannot do any transaction against
Production Order : %s, as it's not submitted"""
% (pro_obj.doc.name), raise_exception=1)
if pro_obj.doc.status == 'Stopped':
msgprint("""You cannot do any transaction against Production Order : %s,
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)
if self.doc.purpose == "Production Order - Update Finished Goods":
pro_obj.doc.produced_qty = flt(pro_obj.doc.produced_qty) + \
(is_submit and 1 or -1 ) * flt(self.doc.fg_completed_qty)
args = {
"item_code": pro_obj.doc.production_item,
"posting_date": self.doc.posting_date,
"planned_qty": (is_submit and -1 or 1 ) * flt(self.doc.fg_completed_qty)
}
get_obj('Warehouse', pro_obj.doc.fg_warehouse).update_bin(args)
pro_obj.doc.status = (flt(pro_obj.doc.qty)==flt(pro_obj.doc.produced_qty)) \
and 'Completed' or 'In Process'
pro_obj.doc.save()
# Create / Update Serial No
# ----------------------------------
def update_serial_no(self, is_submit):
sl_obj = get_obj('Stock Ledger')
if is_submit:
sl_obj.validate_serial_no_warehouse(self, 'mtn_details')
for d in getlist(self.doclist, 'mtn_details'):
if d.serial_no:
serial_nos = sl_obj.get_sr_no_list(d.serial_no)
for x in serial_nos:
serial_no = x.strip()
if d.s_warehouse:
sl_obj.update_serial_delivery_details(self, d, serial_no, is_submit)
if d.t_warehouse:
sl_obj.update_serial_purchase_details(self, d, serial_no, is_submit, self.doc.purpose)
if self.doc.purpose == 'Purchase Return':
#delete_doc("Serial No", serial_no)
serial_doc = Document("Serial No", serial_no)
serial_doc.status = is_submit and 'Purchase Returned' or 'In Store'
serial_doc.docstatus = is_submit and 2 or 0
serial_doc.save()
def on_submit(self):
self.validate_qty_as_per_stock_uom()
self.update_serial_no(1)
self.update_stock_ledger(0)
# update Production Order
self.update_production_order(1)
def on_cancel(self):
self.update_serial_no(0)
self.update_stock_ledger(1)
# update Production Order
self.update_production_order(0)
def get_cust_values(self): def get_cust_values(self):
"""fetches customer details""" """fetches customer details"""
if self.doc.delivery_note_no: if self.doc.delivery_note_no:
@ -525,7 +487,8 @@ class DocType(TransactionBase):
return result and result[0] or {} return result and result[0] or {}
def get_supp_addr(self): def get_supp_addr(self):
res = sql("select supplier_name,address from `tabSupplier` where name = '%s'"%self.doc.supplier) res = sql("""select supplier_name from `tabSupplier`
where name=%s""", self.doc.supplier)
addr = self.get_address_text(supplier = self.doc.supplier) addr = self.get_address_text(supplier = self.doc.supplier)
ret = { ret = {
'supplier_name' : res and res[0][0] or '', 'supplier_name' : res and res[0][0] or '',

View File

@ -2,9 +2,9 @@
{ {
"owner": "Administrator", "owner": "Administrator",
"docstatus": 0, "docstatus": 0,
"creation": "2012-12-17 11:42:09", "creation": "2012-12-18 13:47:41",
"modified_by": "Administrator", "modified_by": "Administrator",
"modified": "2012-12-17 18:19:44" "modified": "2012-12-18 17:17:16"
}, },
{ {
"is_submittable": 1, "is_submittable": 1,
@ -74,8 +74,8 @@
"report_hide": 0 "report_hide": 0
}, },
{ {
"permlevel": 0,
"print_hide": 0, "print_hide": 0,
"permlevel": 0,
"no_copy": 0, "no_copy": 0,
"oldfieldtype": "Select", "oldfieldtype": "Select",
"allow_on_submit": 0, "allow_on_submit": 0,
@ -88,7 +88,7 @@
"search_index": 0, "search_index": 0,
"reqd": 1, "reqd": 1,
"hidden": 0, "hidden": 0,
"options": "Material Issue\nMaterial Receipt\nMaterial Transfer\nSales Return\nPurchase Return\nSubcontracting\nProduction Order - Material Transfer\nProduction Order - Update Finished Goods\nOther", "options": "Material Issue\nMaterial Receipt\nMaterial Transfer\nManufacture/Repack\nSubcontract\nSales Return\nPurchase Return",
"report_hide": 0, "report_hide": 0,
"in_filter": 1 "in_filter": 1
}, },
@ -231,7 +231,7 @@
}, },
{ {
"print_hide": 1, "print_hide": 1,
"depends_on": "eval:doc.purpose.startsWith(\"Production Order\")", "depends_on": "eval:inList([\"Material Transfer\", \"Manufacture/Repack\"], doc.purpose)",
"no_copy": 0, "no_copy": 0,
"search_index": 1, "search_index": 1,
"allow_on_submit": 0, "allow_on_submit": 0,
@ -249,7 +249,7 @@
"in_filter": 1 "in_filter": 1
}, },
{ {
"depends_on": "eval:!doc.purpose.startsWith(\"Production Order\")", "depends_on": "eval:!inList([\"Sales Return\", \"Purchase Return\"], doc.purpose)",
"doctype": "DocField", "doctype": "DocField",
"label": "BOM No", "label": "BOM No",
"options": "BOM", "options": "BOM",
@ -259,52 +259,22 @@
}, },
{ {
"print_hide": 1, "print_hide": 1,
"depends_on": "eval:!inList([\"Sales Return\", \"Purchase Return\"], doc.purpose)",
"no_copy": 0, "no_copy": 0,
"oldfieldtype": "Currency", "search_index": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"doctype": "DocField", "doctype": "DocField",
"label": "Manufacturing Quantity", "label": "Manufacturing Quantity",
"oldfieldname": "fg_completed_qty", "oldfieldname": "fg_completed_qty",
"fieldname": "fg_completed_qty", "fieldname": "fg_completed_qty",
"fieldtype": "Currency", "fieldtype": "Currency",
"search_index": 0, "oldfieldtype": "Currency",
"reqd": 0, "reqd": 0,
"hidden": 0, "hidden": 0,
"permlevel": 0, "permlevel": 0,
"report_hide": 0, "report_hide": 0,
"in_filter": 0 "in_filter": 0
}, },
{
"description": "If checked, BOM for sub-assembly items will be considered for getting raw materials. Otherwise, all sub-assembly items will be treated as a raw material.",
"doctype": "DocField",
"label": "Use Multi-Level BOM",
"fieldname": "use_multi_level_bom",
"fieldtype": "Check",
"permlevel": 0
},
{
"print_hide": 1,
"no_copy": 0,
"oldfieldtype": "Button",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Get Items",
"permlevel": 0,
"fieldname": "get_items",
"fieldtype": "Button",
"search_index": 0,
"reqd": 0,
"hidden": 0,
"options": "get_items",
"report_hide": 0,
"in_filter": 0
},
{
"doctype": "DocField",
"fieldname": "cb1",
"fieldtype": "Column Break",
"permlevel": 0
},
{ {
"print_hide": 1, "print_hide": 1,
"depends_on": "eval:doc.purpose==\"Sales Return\"", "depends_on": "eval:doc.purpose==\"Sales Return\"",
@ -324,17 +294,6 @@
"report_hide": 0, "report_hide": 0,
"in_filter": 0 "in_filter": 0
}, },
{
"print_hide": 1,
"depends_on": "eval:doc.purpose==\"Sales Return\"",
"doctype": "DocField",
"label": "Sales Invoice No",
"options": "Sales Invoice",
"fieldname": "sales_invoice_no",
"fieldtype": "Link",
"hidden": 1,
"permlevel": 0
},
{ {
"print_hide": 1, "print_hide": 1,
"depends_on": "eval:doc.purpose==\"Purchase Return\"", "depends_on": "eval:doc.purpose==\"Purchase Return\"",
@ -354,6 +313,51 @@
"report_hide": 0, "report_hide": 0,
"in_filter": 0 "in_filter": 0
}, },
{
"doctype": "DocField",
"fieldname": "cb1",
"fieldtype": "Column Break",
"permlevel": 0
},
{
"description": "If checked, BOM for sub-assembly items will be considered for getting raw materials. Otherwise, all sub-assembly items will be treated as a raw material.",
"default": "1",
"depends_on": "eval:!inList([\"Sales Return\", \"Purchase Return\"], doc.purpose)",
"doctype": "DocField",
"label": "Use Multi-Level BOM",
"fieldname": "use_multi_level_bom",
"fieldtype": "Check",
"permlevel": 0
},
{
"print_hide": 1,
"depends_on": "eval:!inList([\"Sales Return\", \"Purchase Return\"], doc.purpose)",
"no_copy": 0,
"search_index": 0,
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Get Items",
"permlevel": 0,
"fieldname": "get_items",
"fieldtype": "Button",
"oldfieldtype": "Button",
"reqd": 0,
"hidden": 0,
"options": "get_items",
"report_hide": 0,
"in_filter": 0
},
{
"print_hide": 1,
"depends_on": "eval:doc.purpose==\"Sales Return\"",
"doctype": "DocField",
"label": "Sales Invoice No",
"options": "Sales Invoice",
"fieldname": "sales_invoice_no",
"fieldtype": "Link",
"hidden": 1,
"permlevel": 0
},
{ {
"depends_on": "eval:(doc.purpose==\"Sales Return\" || doc.purpose==\"Purchase Return\")", "depends_on": "eval:(doc.purpose==\"Sales Return\" || doc.purpose==\"Purchase Return\")",
"doctype": "DocField", "doctype": "DocField",

View File

@ -2,9 +2,9 @@
{ {
"owner": "Administrator", "owner": "Administrator",
"docstatus": 0, "docstatus": 0,
"creation": "2012-07-03 13:29:47", "creation": "2012-12-18 13:47:41",
"modified_by": "Administrator", "modified_by": "Administrator",
"modified": "2012-12-17 16:12:42" "modified": "2012-12-18 17:08:52"
}, },
{ {
"istable": 1, "istable": 1,
@ -132,17 +132,6 @@
"fieldtype": "Link", "fieldtype": "Link",
"permlevel": 0 "permlevel": 0
}, },
{
"print_hide": 1,
"oldfieldtype": "Currency",
"doctype": "DocField",
"label": "Reqd Qty",
"oldfieldname": "reqd_qty",
"fieldname": "reqd_qty",
"fieldtype": "Currency",
"permlevel": 3,
"in_filter": 0
},
{ {
"print_hide": 1, "print_hide": 1,
"no_copy": 1, "no_copy": 1,
@ -191,23 +180,15 @@
"in_filter": 0 "in_filter": 0
}, },
{ {
"print_hide": 1,
"description": "BOM No. for a Finished Good Item", "description": "BOM No. for a Finished Good Item",
"no_copy": 0,
"doctype": "DocField", "doctype": "DocField",
"label": "BOM No", "label": "BOM No",
"options": "BOM", "options": "BOM",
"fieldname": "bom_no", "fieldname": "bom_no",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 1,
"permlevel": 0 "permlevel": 0
},
{
"print_hide": 1,
"oldfieldtype": "Check",
"doctype": "DocField",
"label": "FG Item",
"oldfieldname": "fg_item",
"fieldname": "fg_item",
"fieldtype": "Check",
"permlevel": 0,
"in_filter": 1
} }
] ]