OPENERP demo 测试数据分析及源码分析
-
首先 需要修正一下OPENERP 5.0.7里的 产品BOM信息
[attach]465[/attach]
[attach]466[/attach]
为了 简单 我们 先测试官方demo 测试数据 的 销售订单 SO003 我是在2010/03/26日创建的生产帐套
第一我们需要取消除了 定期盘存以外其他的数据
首先打开 pgAdmin III 里数据库
删除 stock_picking
mrp_procurement
mrp_production
mrp_production_move_ids
mrp_production_product_line
mrp_production_workcenter_line
表的信息
删除stock_move表里第16行以后的数据 (1-16行是盘点数据或者说是初始库存)
取消 SO003,SO004,SO005的订单
然后 审核订单 SO003 ---测试就从这里开始了
因为SO003的 分拣策略 为分批出货 订单明细的获得方式都是 订货(MTO/来单生产)
同时 SO003的订单明细 有 [color=Red][PC1] 基本电脑[/color] 基本电脑 3台 订单明细的交货期(Delivery Lead Time:delay) 为2天
[color=Red][PC2] 基础+PC(按订单组装) [/color]3台 订单明细的交货期(Delivery Lead Time:delay) 为7天
而公司的配置信息内设置了 交货安全期(company.security_lead) 为5天 依据源码
date_planned = DateTime.now() + DateTime.DateTimeDeltaFromDays(line.delay or 0.0)
date_planned = (date_planned - DateTime.DateTimeDeltaFromDays(company.security_lead)).strftime('%Y-%m-%d %H:%M:%S')
[color=Red][PC1] 基本电脑 [/color]计划时间 就是 当期时间(2010/03/26)+2天-5天 =2010/03/23
[color=Red][PC2] 基础+PC(按订单组装)[/color] 计划时间 就是 当期时间(2010/03/26)+7天-5天 =2010/03/28
[attach]467[/attach]所以 审核订单 SO003
第一 会创建 一个出库单
第二 会创建 1) 会和上面的出单一样的计划时间
[attach]468[/attach]
订单 的 审核订单按钮会执行 sale.py 里的 action_ship_create方法
里面有
[color=Red] wf_service = netsvc.LocalService("workflow")[/color]
[color=Red] wf_service.trg_validate(uid, 'mrp.procurement', proc_id, 'button_confirm', cr)[/color]
[color=Red] self.pool.get('sale.order.line').write(cr, uid, [line.id], {'procurement_id': proc_id})[/color]上面红色字的就会 触发 需求单 里的工作流 的方法
[attach]469[/attach]
到 工作流 produce 里面的方法 action_produce_assign_product
def action_produce_assign_product(self, cr, uid, ids, context={}):
produce_id = False
company = self.pool.get('res.users').browse(cr, uid, uid, context).company_id
for procurement in self.browse(cr, uid, ids):
res_id = procurement.move_id.id
loc_id = procurement.location_id.id
newdate = DateTime.strptime(procurement.date_planned, '%Y-%m-%d %H:%M:%S') - DateTime.RelativeDateTime(days=procurement.product_id.product_tmpl_id.produce_delay or 0.0)
newdate = newdate - DateTime.RelativeDateTime(days=company.manufacturing_lead)
produce_id = self.pool.get('mrp.production').create(cr, uid, {
'origin': procurement.origin,
'product_id': procurement.product_id.id,
'product_qty': procurement.product_qty,
'product_uom': procurement.product_uom.id,
'product_uos_qty': procurement.product_uos and procurement.product_uos_qty or False,
'product_uos': procurement.product_uos and procurement.product_uos.id or False,
'location_src_id': procurement.location_id.id,
'location_dest_id': procurement.location_id.id,
'bom_id': procurement.bom_id and procurement.bom_id.id or False,
'date_planned': newdate.strftime('%Y-%m-%d %H:%M:%S'),
'move_prod_id': res_id,
})
[color=Red] self.write(cr, uid, [procurement.id], {'state':'running'})[/color]
bom_result = self.pool.get('mrp.production').action_compute(cr, uid,
[produce_id], properties=[x.id for x in procurement.property_ids])
wf_service = netsvc.LocalService("workflow")
[color=Red]wf_service.trg_validate(uid, 'mrp.production', produce_id, 'button_confirm', cr)[/color]
self.pool.get('stock.move').write(cr, uid, [res_id],
{'location_id':procurement.location_id.id})
return produce_id上面的 [color=Red]self.write(cr, uid, [procurement.id], {'state':'running'})[/color] 说明 需求单 的状态为 运行中
[attach]470[/attach]
根据
newdate = DateTime.strptime(procurement.date_planned, '%Y-%m-%d %H:%M:%S') - DateTime.RelativeDateTime(days=procurement.product_id.product_tmpl_id.produce_delay or 0.0)
newdate = newdate - DateTime.RelativeDateTime(days=company.manufacturing_lead)
[color=Red][PC1] 基本电脑 [/color]的 procurement.date_planned为 2010/03/23 - [color=Red][PC1] 基本电脑 [/color]的生产提前期(5.0.7翻译为 制造周期)为1天(procurement.product_id.product_tmpl_id.produce_delay) -公司的生产提前期(company.manufacturing_lead) 为1天
newdate =2010/03/21
[color=Red][PC2] 基础+PC(按订单组装)[/color] 的 procurement.date_planned为 2010/03/28 - [color=Red][PC1] 基本电脑 [/color]的生产提前期(5.0.7翻译为 制造周期)为1天(procurement.product_id.product_tmpl_id.produce_delay) -公司的生产提前期(company.manufacturing_lead) 为1天
newdate =2010/03/26[color=Red]wf_service.trg_validate(uid, 'mrp.production', produce_id, 'button_confirm', cr) [/color]会触发
[attach]471[/attach]
(因一个贴子的字数限制 后面的内容在下面 或下一页)[[i] 本帖最后由 leetaizhu 于 2010-3-28 23:50 编辑 [/i]]
-
def test_if_product(self, cr, uid, ids):
res = True
for production in self.browse(cr, uid, ids):
[color=Red] if not production.product_lines:[/color]
if not self.action_compute(cr, uid, [production.id]):
res = False
return res因为 上面 创建的 生产单里面没有 创建生产明细 所以会 执行 self.action_compute(cr, uid, [production.id])
def action_compute(self, cr, uid, ids, properties=[]):
results = []
for production in self.browse(cr, uid, ids):
cr.execute('delete from mrp_production_product_line where production_id=%s', (production.id,))
cr.execute('delete from mrp_production_workcenter_line where production_id=%s', (production.id,))
bom_point = production.bom_id
bom_id = production.bom_id.id
if not bom_point:
bom_id = self.pool.get('mrp.bom')._bom_find(cr, uid, production.product_id.id, production.product_uom.id, properties)
if bom_id:
bom_point = self.pool.get('mrp.bom').browse(cr, uid, bom_id)
routing_id = bom_point.routing_id.id or False
self.write(cr, uid, [production.id], {'bom_id': bom_id, 'routing_id': routing_id})if not bom_id: raise osv.except_osv(_('Error'), _("Couldn't find bill of material for product")) #if bom_point.routing_id and bom_point.routing_id.location_id: # self.write(cr, uid, [production.id], {'location_src_id': bom_point.routing_id.location_id.id}) factor = production.product_qty * production.product_uom.factor / bom_point.product_uom.factor
[color=Red] res = self.pool.get('mrp.bom')._bom_explode(cr, uid, bom_point, factor / bom_point.product_qty, properties)[/color]
results = res[0]
results2 = res[1]
for line in results:
line['production_id'] = production.id
self.pool.get('mrp.production.product.line').create(cr, uid, line)
for line in results2:
line['production_id'] = production.id
self.pool.get('mrp.production.workcenter.line').create(cr, uid, line)
return len(results)
这里 就把 生产单产品的BOM的产品和工作中心信息 创建到 生产单的生产明细行里和生产单的工作中心明细行里
[attach]472[/attach]
[attach]473[/attach]
这之后 就执行下面的方法了
def action_confirm(self, cr, uid, ids):
picking_id=False
proc_ids = []
for production in self.browse(cr, uid, ids):
if not production.product_lines:
self.action_compute(cr, uid, [production.id])
production = self.browse(cr, uid, [production.id])[0]
routing_loc = None
pick_type = 'internal'
address_id = False
if production.bom_id.routing_id and production.bom_id.routing_id.location_id:
routing_loc = production.bom_id.routing_id.location_id
if routing_loc.usage<>'internal':
pick_type = 'out'
address_id = routing_loc.address_id and routing_loc.address_id.id or False
routing_loc = routing_loc.id
picking_id = self.pool.get('stock.picking').create(cr, uid, {
'origin': (production.origin or '').split(':')[0] +':'+production.name,
'type': pick_type,
'move_type': 'one',
'state': 'auto',
'address_id': address_id,
'auto_picking': self._get_auto_picking(cr, uid, production),
})source = production.product_id.product_tmpl_id.property_stock_production.id data = { 'name':'PROD:'+production.name, 'date_planned': production.date_planned, 'product_id': production.product_id.id, 'product_qty': production.product_qty, 'product_uom': production.product_uom.id, 'product_uos_qty': production.product_uos and production.product_uos_qty or False, 'product_uos': production.product_uos and production.product_uos.id or False, 'location_id': source, 'location_dest_id': production.location_dest_id.id, 'move_dest_id': production.move_prod_id.id, 'state': 'waiting' } res_final_id = self.pool.get('stock.move').create(cr, uid, data) self.write(cr, uid, [production.id], {'move_created_ids': [(6, 0, [res_final_id])]}) moves = [] for line in production.product_lines: move_id=False newdate = production.date_planned if line.product_id.type in ('product', 'consu'): res_dest_id = self.pool.get('stock.move').create(cr, uid, { 'name':'PROD:'+production.name, 'date_planned': production.date_planned, 'product_id': line.product_id.id, 'product_qty': line.product_qty, 'product_uom': line.product_uom.id, 'product_uos_qty': line.product_uos and line.product_uos_qty or False, 'product_uos': line.product_uos and line.product_uos.id or False, 'location_id': routing_loc or production.location_src_id.id, 'location_dest_id': source, 'move_dest_id': res_final_id, 'state': 'waiting', }) moves.append(res_dest_id) move_id = self.pool.get('stock.move').create(cr, uid, { 'name':'PROD:'+production.name, 'picking_id':picking_id, 'product_id': line.product_id.id, 'product_qty': line.product_qty, 'product_uom': line.product_uom.id, 'product_uos_qty': line.product_uos and line.product_uos_qty or False, 'product_uos': line.product_uos and line.product_uos.id or False, 'date_planned': newdate, 'move_dest_id': res_dest_id, 'location_id': production.location_src_id.id, 'location_dest_id': routing_loc or production.location_src_id.id, 'state': 'waiting', }) proc_id = self.pool.get('mrp.procurement').create(cr, uid, { 'name': (production.origin or '').split(':')[0] + ':' + production.name, 'origin': (production.origin or '').split(':')[0] + ':' + production.name, 'date_planned': newdate, 'product_id': line.product_id.id, 'product_qty': line.product_qty, 'product_uom': line.product_uom.id, 'product_uos_qty': line.product_uos and line.product_qty or False, 'product_uos': line.product_uos and line.product_uos.id or False, 'location_id': production.location_src_id.id, 'procure_method': line.product_id.procure_method, 'move_id': move_id, }) wf_service = netsvc.LocalService("workflow") wf_service.trg_validate(uid, 'mrp.procurement', proc_id, 'button_confirm', cr) proc_ids.append(proc_id) wf_service = netsvc.LocalService("workflow") wf_service.trg_validate(uid, 'stock.picking', picking_id, 'button_confirm', cr) self.write(cr, uid, [production.id], {'picking_id':picking_id, 'move_lines': [(6,0,moves)], 'state':'confirmed'}) return picking_id
这个方法比较复杂同时也是最核心的地方
首先来 看看 这里面有三个 创建 self.pool.get('stock.move').create 的地方
分别来看看
第一个 self.pool.get('stock.move').create 创建是
[attach]474[/attach]
第二个 self.pool.get('stock.move').create 创建是
[attach]475[/attach]
第三个 self.pool.get('stock.move').create 创建是
[attach]476[/attach]
proc_id = self.pool.get('mrp.procurement').create(cr, uid, {
'name': (production.origin or '').split(':')[0] + ':' + production.name,
'origin': (production.origin or '').split(':')[0] + ':' + production.name,
'date_planned': newdate,
'product_id': line.product_id.id,
'product_qty': line.product_qty,
'product_uom': line.product_uom.id,
'product_uos_qty': line.product_uos and line.product_qty or False,
'product_uos': line.product_uos and line.product_uos.id or False,
'location_id': production.location_src_id.id,
'procure_method': line.product_id.procure_method,
'move_id': move_id,
})
wf_service = netsvc.LocalService("workflow")
wf_service.trg_validate(uid, 'mrp.procurement', proc_id, 'button_confirm', cr)
这里 这个 wf_service.trg_validate(uid, 'mrp.procurement', proc_id, 'button_confirm', cr) 是不是 很熟悉 对就是上面出现的 好像进入到 递归运算里了[[i] 本帖最后由 leetaizhu 于 2010-3-29 01:52 编辑 [/i]]