Odoo中文社区可以通过以下两个域名访问:shine-it.net , odoo.net.cn

由于系统升迁的原因,本论坛部分较早期的内容存在格式和链接损坏失效的问题,并非本论坛系统本身的缺陷,望谅解

本社区没有维护任何QQ群讨论组,任何与本社区同名的QQ群讨论组的言论与本社区无关!

开发人员可以登录gitter讨论组: http://gitter.im/odoo-china/Talk, 需要github账号

如果您登录系统碰到问题,请在微信公众号留言:

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]]



  • 继续赞.....

    图文有码...



  • 这个,非常不错,我现在也在看这个的代码


Log in to reply