imporvement lot system

bzr revid: hmo@tinyerp.com-20080920135644-kn7ppbi5hg5f19by
This commit is contained in:
Harshad Modi 2008-09-20 19:26:44 +05:30
commit ba7f591217
5 changed files with 80 additions and 31 deletions

View File

@ -228,7 +228,6 @@ product_category()
class product_template(osv.osv): class product_template(osv.osv):
_name = "product.template" _name = "product.template"
_description = "Product Template" _description = "Product Template"
def _calc_seller_delay(self, cr, uid, ids, name, arg, context={}): def _calc_seller_delay(self, cr, uid, ids, name, arg, context={}):
result = {} result = {}
for product in self.browse(cr, uid, ids, context): for product in self.browse(cr, uid, ids, context):
@ -269,7 +268,9 @@ class product_template(osv.osv):
help='Coefficient to convert UOM to UOS\n' help='Coefficient to convert UOM to UOS\n'
' uom = uos * coeff'), ' uom = uos * coeff'),
'mes_type': fields.selection((('fixed', 'Fixed'), ('variable', 'Variable')), 'Measure Type', required=True), 'mes_type': fields.selection((('fixed', 'Fixed'), ('variable', 'Variable')), 'Measure Type', required=True),
'tracking': fields.boolean('Track Lots', help="Force to use a Production Lot number during stock operations for traceability."), 'track_production' : fields.boolean('Track Production Lots' , help="Force to use a Production Lot number during Production"),
'track_incoming' : fields.boolean('Track Incomming Lots', help="Force to use a Production Lot number during Purchase"),
'track_outgoing' : fields.boolean('Track Outging Lots', help="Force to use a Production Lot number during Sale"),
'seller_delay': fields.function(_calc_seller_delay, method=True, type='integer', string='Supplier Lead Time', help="This is the average delay in days between the purchase order confirmation and the reception of goods for this product and for the default supplier. It is used by the scheduler to order requests based on reordering delays."), 'seller_delay': fields.function(_calc_seller_delay, method=True, type='integer', string='Supplier Lead Time', help="This is the average delay in days between the purchase order confirmation and the reception of goods for this product and for the default supplier. It is used by the scheduler to order requests based on reordering delays."),
'seller_ids': fields.one2many('product.supplierinfo', 'product_id', 'Partners'), 'seller_ids': fields.one2many('product.supplierinfo', 'product_id', 'Partners'),
'loc_rack': fields.char('Rack', size=16), 'loc_rack': fields.char('Rack', size=16),
@ -424,7 +425,6 @@ class product_product(osv.osv):
uom_obj=self.pool.get('product.uom') uom_obj=self.pool.get('product.uom')
uom=uom_obj.browse(cursor,user,[uom_id])[0] uom=uom_obj.browse(cursor,user,[uom_id])[0]
uom_po=uom_obj.browse(cursor,user,[uom_po_id])[0] uom_po=uom_obj.browse(cursor,user,[uom_po_id])[0]
print uom.category_id.id , uom_po.category_id.id
if uom.category_id.id != uom_po.category_id.id: if uom.category_id.id != uom_po.category_id.id:
return {'value': {'uom_po_id': uom_id}} return {'value': {'uom_po_id': uom_id}}
return False return False

View File

@ -68,10 +68,17 @@
</group> </group>
<group colspan="2" col="2" name="uom"> <group colspan="2" col="2" name="uom">
<separator string="Lots" colspan="2"/> <separator string="UOM" colspan="2"/>
<field name="uom_id" on_change="onchange_uom(uom_id,uom_po_id)"/> <field name="uom_id" on_change="onchange_uom(uom_id,uom_po_id)"/>
<field name="uom_po_id"/> <field name="uom_po_id"/>
<field name="tracking"/> </group>
<group colspan="4" col="4" name="lot">
<separator string="Lots" colspan="4"/>
<field name="track_production" />
<field name="track_incoming" />
<field name="track_outgoing" />
</group> </group>
<group colspan="2" col="2" name="uos" groups="product.group_uos"> <group colspan="2" col="2" name="uos" groups="product.group_uos">

View File

@ -373,7 +373,6 @@ class stock_picking(osv.osv):
_name = "stock.picking" _name = "stock.picking"
_description = "Packing list" _description = "Packing list"
def _set_maximum_date(self, cr, uid, ids, name, value, arg, context): def _set_maximum_date(self, cr, uid, ids, name, value, arg, context):
print 'max', ids, name, value, arg, context
if not value: return False if not value: return False
for pick in self.browse(cr, uid, ids, context): for pick in self.browse(cr, uid, ids, context):
cr.execute("""update stock_move set cr.execute("""update stock_move set
@ -381,11 +380,9 @@ class stock_picking(osv.osv):
where where
picking_id=%d and picking_id=%d and
(date_planned=%s or date_planned>%s)""", (value,pick.id,pick.max_date,value)) (date_planned=%s or date_planned>%s)""", (value,pick.id,pick.max_date,value))
print 'Ok'
return True return True
def _set_minimum_date(self, cr, uid, ids, name, value, arg, context): def _set_minimum_date(self, cr, uid, ids, name, value, arg, context):
print 'min', ids, name, value, arg, context
if not value: return False if not value: return False
for pick in self.browse(cr, uid, ids, context): for pick in self.browse(cr, uid, ids, context):
cr.execute("""update stock_move set cr.execute("""update stock_move set
@ -393,7 +390,6 @@ class stock_picking(osv.osv):
where where
picking_id=%d and picking_id=%d and
(date_planned=%s or date_planned<%s)""", (value,pick.id,pick.min_date,value)) (date_planned=%s or date_planned<%s)""", (value,pick.id,pick.min_date,value))
print 'Ok'
return True return True
def get_min_max_date(self, cr, uid, ids, field_name, arg, context={}): def get_min_max_date(self, cr, uid, ids, field_name, arg, context={}):
@ -415,7 +411,6 @@ class stock_picking(osv.osv):
for pick, dt1,dt2 in cr.fetchall(): for pick, dt1,dt2 in cr.fetchall():
res[pick]['min_date'] = dt1 res[pick]['min_date'] = dt1
res[pick]['max_date'] = dt2 res[pick]['max_date'] = dt2
print res, ids
return res return res
_columns = { _columns = {
@ -789,6 +784,7 @@ class stock_production_lot(osv.osv):
res.append((record['id'], name)) res.append((record['id'], name))
return res return res
_name = 'stock.production.lot' _name = 'stock.production.lot'
_description = 'Production lot' _description = 'Production lot'
@ -804,8 +800,8 @@ class stock_production_lot(osv.osv):
from from
stock_report_prodlots stock_report_prodlots
where where
location_id in ('''+','.join(map(str, locations))+''' and location_id in ('''+','.join(map(str, locations))+''') and
prodlot_id in ('''+','.join(map(str, ids))+''' prodlot_id in ('''+','.join(map(str, ids))+''')
group by group by
prodlot_id prodlot_id
''') ''')
@ -865,6 +861,26 @@ class stock_move(osv.osv):
_name = "stock.move" _name = "stock.move"
_description = "Stock Move" _description = "Stock Move"
def _check_tracking(self, cr, uid, ids):
for move in self.browse(cr, uid, ids):
if not move.prodlot_id and \
(move.state == 'done' and \
( \
(move.product_id.track_production and move.location_id.usage=='production') or \
(move.product_id.track_production and move.location_dest_id.usage=='production') or \
(move.product_id.track_incoming and move.location_id.usage=='supplier') or \
(move.product_id.track_outgoing and move.location_dest_id.usage=='customer') \
)):
return False
return True
def _check_product_lot(self, cr, uid, ids):
for move in self.browse(cr, uid, ids):
if move.prodlot_id and (move.prodlot_id.product_id.id != move.product_id.id):
return False
return True
_columns = { _columns = {
'name': fields.char('Name', size=64, required=True, select=True), 'name': fields.char('Name', size=64, required=True, select=True),
'priority': fields.selection([('0','Not urgent'),('1','Urgent')], 'Priority'), 'priority': fields.selection([('0','Not urgent'),('1','Urgent')], 'Priority'),
@ -901,6 +917,15 @@ class stock_move(osv.osv):
'price_unit': fields.float('Unit Price', 'price_unit': fields.float('Unit Price',
digits=(16, int(config['price_accuracy']))), digits=(16, int(config['price_accuracy']))),
} }
_constraints = [
(_check_tracking,
'Production lot must be set',
['prodlot_id']),
(_check_product_lot,
'Move Production lot must be on the same Product Production lot',
['prodlot_id'])]
def _default_location_destination(self, cr, uid, context={}): def _default_location_destination(self, cr, uid, context={}):
if context.get('move_line', []): if context.get('move_line', []):
return context['move_line'][0][2]['location_dest_id'] return context['move_line'][0][2]['location_dest_id']
@ -939,6 +964,16 @@ class stock_move(osv.osv):
cursor.commit() cursor.commit()
def onchange_lot_id(self, cr, uid, context, prodlot_id=False,product_qty=False, loc_id=False):
if not prodlot_id or not loc_id:
return {}
prodlot = self.pool.get('stock.production.lot').browse(cr, uid, [prodlot_id])[0]
location=self.pool.get('stock.location').browse(cr,uid,[loc_id])[0]
warning={}
if not prodlot.stock_available or (location.usage == 'internal' and product_qty < prodlot.stock_available):
warning={'title':'Warning!','message':'Less stock available than given quantity'}
return {'warning':warning}
def onchange_product_id(self, cr, uid, context, prod_id=False, loc_id=False, loc_dest_id=False): def onchange_product_id(self, cr, uid, context, prod_id=False, loc_id=False, loc_dest_id=False):
if not prod_id: if not prod_id:
return {} return {}
@ -969,8 +1004,11 @@ class stock_move(osv.osv):
return result return result
def action_confirm(self, cr, uid, moves, context={}): def action_confirm(self, cr, uid, moves, context={}):
ids = moves
if not type(moves) == type([]):
ids = map(lambda m: m.id, moves) ids = map(lambda m: m.id, moves)
self.write(cr, uid, ids, {'state':'confirmed'}) self.write(cr, uid, ids, {'state':'confirmed'})
moves= self.pool.get('stock.move').browse(cr, uid, moves)
for picking, todo in self._chain_compute(cr, uid, moves, context).items(): for picking, todo in self._chain_compute(cr, uid, moves, context).items():
ptype = self.pool.get('stock.location').picking_type_get(cr, uid, todo[0][0].location_dest_id, todo[0][1][0]) ptype = self.pool.get('stock.location').picking_type_get(cr, uid, todo[0][0].location_dest_id, todo[0][1][0])
pickid = self.pool.get('stock.picking').create(cr, uid, { pickid = self.pool.get('stock.picking').create(cr, uid, {
@ -1176,10 +1214,6 @@ class stock_move(osv.osv):
'ref': ref, 'ref': ref,
}) })
if (move.product_id.tracking and not move.prodlot_id):
raise osv.except_osv('Warning ! ','You should put a production lot for : '+move.product_id.name)
self.write(cr, uid, ids, {'state':'done'}) self.write(cr, uid, ids, {'state':'done'})
wf_service = netsvc.LocalService("workflow") wf_service = netsvc.LocalService("workflow")

View File

@ -1163,7 +1163,7 @@
<field name="priority"/> <field name="priority"/>
<field name="address_id" select="1" context="{'context_display':'partner'}"/> <field name="address_id" select="1" context="{'context_display':'partner'}"/>
<newline/> <newline/>
<field name="prodlot_id" select="1" context="{'location_id':location_id, 'product_id':product_id}" domain="[('product_id','=',product_id)]"/> <field name="prodlot_id" select="1" context="{'location_id':location_id, 'product_id':product_id}" on_change="onchange_lot_id(prodlot_id,product_qty, location_id)" domain="[('product_id','=',product_id)]"/>
<field name="tracking_id" select="1"/> <field name="tracking_id" select="1"/>
<newline/> <newline/>
<label/> <label/>

View File

@ -155,14 +155,16 @@ class sale_order_line(osv.osv):
if product_info.sale_line_warn: if product_info.sale_line_warn:
title= "Message", title= "Message",
message= product_info.sale_line_warn_msg message= product_info.sale_line_warn_msg
result = super(sale_order_line, self).product_id_change( cr, uid, ids, pricelist, product, qty,
result = super(sale_order_line, self).product_id_change( cr, uid, ids, pricelist, product, qty=0, uom, qty_uos, uos, name, partner_id,
uom=False, qty_uos=0, uos=False, name='', partner_id=False, lang, update_tax, date_order, packaging)
lang=False, update_tax=True, date_order=False, packaging=False)['value'] if title and message:
warning['title']=title[0]
warning['message']=message
if result.get('warning',False): if result.get('warning',False):
warning['title']=title and title+' & '+result['warning']['title'] or result['warning']['title'] warning['title']= title and title[0]+' & '+result['warning']['title'] or result['warning']['title']
warning['message']=message and message +' '+result['warning']['message'] or result['warning']['message'] warning['message']=message and message +'\n\n'+result['warning']['message'] or result['warning']['message']
return {'value': result, 'warning':warning} return {'value': result['value'], 'warning':warning}
sale_order_line() sale_order_line()
@ -175,15 +177,21 @@ class purchase_order_line(osv.osv):
return {'value': {'price_unit': 0.0, 'name':'','notes':'', 'product_uom' : False}, 'domain':{'product_uom':[]}} return {'value': {'price_unit': 0.0, 'name':'','notes':'', 'product_uom' : False}, 'domain':{'product_uom':[]}}
product_obj = self.pool.get('product.product') product_obj = self.pool.get('product.product')
product_info = product_obj.browse(cr, uid, product) product_info = product_obj.browse(cr, uid, product)
title=False
message=False
if product_info.purchase_line_warn: if product_info.purchase_line_warn:
warning={ title = "Message"
'title': "Message", message = product_info.purchase_line_warn_msg
'message': product_info.purchase_line_warn_msg
}
result = super(purchase_order_line, self).product_id_change(cr, uid, ids, pricelist, product, qty, uom, result = super(purchase_order_line, self).product_id_change(cr, uid, ids, pricelist, product, qty, uom,
partner_id, date_order=False)['value'] partner_id, date_order)
return {'value': result, 'warning':warning} if title and message:
warning['title']=title[0]
warning['message']=message
if result.get('warning',False):
warning['title']= title and title[0]+' & '+result['warning']['title'] or result['warning']['title']
warning['message']=message and message +'\n\n'+result['warning']['message'] or result['warning']['message']
return {'value': result['value'], 'warning':warning}
purchase_order_line() purchase_order_line()