odoo 销售订单出库单操作代码简单剖析

来源:互联网 发布:淘宝卖家取消订单投诉 编辑:程序博客网 时间:2024/04/29 02:44

odoo开发技术交流群【73934270

继上一章节的销售订单,我们打开对应的出库单:


点击检查可用,执行了 stock.picking 类的 action_assign 方法,具体代码:

def action_assign(self, cr, uid, ids, context=None):    """ Checks the product type and accordingly writes the state.    """    import pdb;pdb.set_trace()    context = context or {}    quant_obj = self.pool.get("stock.quant")    to_assign_moves = []    main_domain = {}    todo_moves = []    operations = set()    for move in self.browse(cr, uid, ids, context=context):        if move.state not in ('confirmed', 'waiting', 'assigned'):            continue        if move.location_id.usage in ('supplier', 'inventory', 'production'):            to_assign_moves.append(move.id)            #in case the move is returned, we want to try to find quants before forcing the assignment            if not move.origin_returned_move_id:                continue        if move.product_id.type == 'consu':            to_assign_moves.append(move.id)            continue        else:            todo_moves.append(move)            #we always keep the quants already assigned and try to find the remaining quantity on quants not assigned only            main_domain[move.id] = [('reservation_id', '=', False), ('qty', '>', 0)]            #if the move is preceeded, restrict the choice of quants in the ones moved previously in original move            ancestors = self.find_move_ancestors(cr, uid, move, context=context)            if move.state == 'waiting' and not ancestors:                #if the waiting move hasn't yet any ancestor (PO/MO not confirmed yet), don't find any quant available in stock                main_domain[move.id] += [('id', '=', False)]            elif ancestors:                main_domain[move.id] += [('history_ids', 'in', ancestors)]            #if the move is returned from another, restrict the choice of quants to the ones that follow the returned move            if move.origin_returned_move_id:                main_domain[move.id] += [('history_ids', 'in', move.origin_returned_move_id.id)]            for link in move.linked_move_operation_ids:                operations.add(link.operation_id)    # Check all ops and sort them: we want to process first the packages, then operations with lot then the rest    operations = list(operations)    operations.sort(key=lambda x: ((x.package_id and not x.product_id) and -4 or 0) + (x.package_id and -2 or 0) + (x.lot_id and -1 or 0))    for ops in operations:        #first try to find quants based on specific domains given by linked operations        for record in ops.linked_move_operation_ids:            move = record.move_id            if move.id in main_domain:                domain = main_domain[move.id] + self.pool.get('stock.move.operation.link').get_specific_domain(cr, uid, record, context=context)                qty = record.qty                if qty:                    quants = quant_obj.quants_get_prefered_domain(cr, uid, ops.location_id, move.product_id, qty, domain=domain, prefered_domain_list=[], restrict_lot_id=move.restrict_lot_id.id, restrict_partner_id=move.restrict_partner_id.id, context=context)                    quant_obj.quants_reserve(cr, uid, quants, move, record, context=context)    for move in todo_moves:        if move.linked_move_operation_ids:            continue        #then if the move isn't totally assigned, try to find quants without any specific domain        if move.state != 'assigned':            qty_already_assigned = move.reserved_availability            qty = move.product_qty - qty_already_assigned            quants = quant_obj.quants_get_prefered_domain(cr, uid, move.location_id, move.product_id, qty, domain=main_domain[move.id], prefered_domain_list=[], restrict_lot_id=move.restrict_lot_id.id, restrict_partner_id=move.restrict_partner_id.id, context=context)            quant_obj.quants_reserve(cr, uid, quants, move, context=context)    #force assignation of consumable products and incoming from supplier/inventory/production    if to_assign_moves:        self.force_assign(cr, uid, to_assign_moves, context=context)
个人对该段代码的分析认为,根据move的去向是出库还是入库,来觉得对该条move记录是进行强制可用,还是分配库存产品,鉴于本例分析为销售订单出库,所以,本次操作需要进行库存分配,所以真正触碰到的代码是:

if move.state != 'assigned':            qty_already_assigned = move.reserved_availability            qty = move.product_qty - qty_already_assigned            quants = quant_obj.quants_get_prefered_domain(cr, uid, move.location_id, move.product_id, qty, domain=main_domain[move.id], prefered_domain_list=[], restrict_lot_id=move.restrict_lot_id.id, restrict_partner_id=move.restrict_partner_id.id, context=context)            quant_obj.quants_reserve(cr, uid, quants, move, context=context)

正常情况下此时的出库单的清单里的数量后面会显示以保留字样


点击【转移】按钮,执行的方法是 stock.picking 类的 do_enter_transfer_details 方法,代码和弹出框


@api.cr_uid_ids_contextdef do_enter_transfer_details(self, cr, uid, picking, context=None):    if not context:        context = {}    context.update({        'active_model': self._name,        'active_ids': picking,        'active_id': len(picking) and picking[0] or False    })    created_id = self.pool['stock.transfer_details'].create(cr, uid, {'picking_id': len(picking) and picking[0] or False}, context)    #Allen Mark: 上一句是生成临时表(暂时理解为临时表),采购订单也有这个过程    return self.pool['stock.transfer_details'].wizard_view(cr, uid, created_id, context)
上面代码执行生成临时表stock.transfer_details 记录,同时生成stock.picking 对应的stock.pack.operation记录(出库单实际出库记录),编辑好出库数量,继续点击弹出框底部按钮【应用】,执行的方法为 stock.transfer_details 类的 do_detailed_transfer 方法,代码:

@api.onedef do_detailed_transfer(self):    processed_ids = []    # Create new and update existing pack operations    for lstits in [self.item_ids, self.packop_ids]:        for prod in lstits:            pack_datas = {                'product_id': prod.product_id.id,                'product_uom_id': prod.product_uom_id.id,                'product_qty': prod.quantity,                'package_id': prod.package_id.id,                'lot_id': prod.lot_id.id,                'location_id': prod.sourceloc_id.id,                'location_dest_id': prod.destinationloc_id.id,                'result_package_id': prod.result_package_id.id,                'date': prod.date if prod.date else datetime.now(),                'owner_id': prod.owner_id.id,            }            if prod.packop_id:                prod.packop_id.with_context(no_recompute=True).write(pack_datas)                processed_ids.append(prod.packop_id.id)            else:                pack_datas['picking_id'] = self.picking_id.id                packop_id = self.env['stock.pack.operation'].create(pack_datas)                processed_ids.append(packop_id.id)    #以上代码就是在点击转移的时候弹出界面(该界面表是中转表stock.transfer_details),供用户修改数据,并回填给stock_pack_operation,stock_picking方法do_transfer()使用    # Delete the others    packops = self.env['stock.pack.operation'].search(['&', ('picking_id', '=', self.picking_id.id), '!', ('id', 'in', processed_ids)])    packops.unlink()    # Execute the transfer of the picking    self.picking_id.do_transfer()    return True

上面代码执行完毕,一切正常的话,该出库单流程结束


有几张图因为csdn上传图片失败,后续正常后补上


0 0
原创粉丝点击