odoo 銷售訂單確認怎麼觸發的發貨規則
阿新 • • 發佈:2021-10-27
最近有需求需要呼叫庫存補貨規則,流程稍微有點複雜,在這裡簡單整理下
# 1. 訂單確認呼叫 @api.multi def _action_confirm(self): for order in self: order.order_line._action_launch_stock_rule() # 呼叫規則了 super(SaleOrder, self)._action_confirm() # 2.呼叫規則 @api.multi def _action_launch_stock_rule(self): """ Launch procurement group run method with required/custom fields genrated by a sale order line. procurement group will launch '_run_pull', '_run_buy' or '_run_manufacture' depending on the sale order line product rule. """ precision = self.env['decimal.precision'].precision_get('Product Unit of Measure') errors = [] for line in self: if line.state != 'sale' or not line.product_id.type in ('consu','product'): continue qty = line._get_qty_procurement() if float_compare(qty, line.product_uom_qty, precision_digits=precision) >= 0: continue group_id = line.order_id.procurement_group_id if not group_id: group_id = self.env['procurement.group'].create({ 'name': line.order_id.name, 'move_type': line.order_id.picking_policy, 'sale_id': line.order_id.id, 'partner_id': line.order_id.partner_shipping_id.id, }) line.order_id.procurement_group_id = group_id else: # In case the procurement group is already created and the order was # cancelled, we need to update certain values of the group. updated_vals = {} if group_id.partner_id != line.order_id.partner_shipping_id: updated_vals.update({'partner_id': line.order_id.partner_shipping_id.id}) if group_id.move_type != line.order_id.picking_policy: updated_vals.update({'move_type': line.order_id.picking_policy}) if updated_vals: group_id.write(updated_vals) values = line._prepare_procurement_values(group_id=group_id) product_qty = line.product_uom_qty - qty procurement_uom = line.product_uom quant_uom = line.product_id.uom_id get_param = self.env['ir.config_parameter'].sudo().get_param if procurement_uom.id != quant_uom.id and get_param('stock.propagate_uom') != '1': product_qty = line.product_uom._compute_quantity(product_qty, quant_uom, rounding_method='HALF-UP') procurement_uom = quant_uom try: self.env['procurement.group'].run(line.product_id, product_qty, procurement_uom, line.order_id.partner_shipping_id.property_stock_customer, line.name, line.order_id.name, values) # 這塊程式碼執行玩就生成出庫單了 except UserError as error: errors.append(error.name) if errors: raise UserError('\n'.join(errors)) return True # 3. 獲取規則 @api.model def run(self, product_id, product_qty, product_uom, location_id, name, origin, values): """ Method used in a procurement case. The purpose is to supply the product passed as argument in the location also given as an argument. In order to be able to find a suitable location that provide the product it will search among stock.rule. """ values.setdefault('company_id', self.env['res.company']._company_default_get('procurement.group')) values.setdefault('priority', '1') values.setdefault('date_planned', fields.Datetime.now()) rule = self._get_rule(product_id, location_id, values) # 獲取規則記錄 if not rule: raise UserError(_('No procurement rule found in location "%s" for product "%s".\n Check routes configuration.') % (location_id.display_name, product_id.display_name)) action = 'pull' if rule.action == 'pull_push' else rule.action if hasattr(rule, '_run_%s' % action): getattr(rule, '_run_%s' % action)(product_id, product_qty, product_uom, location_id, name, origin, values) # 使用規則生成調波單 else: _logger.error("The method _run_%s doesn't exist on the procument rules" % action) return True # 4. 使用規則生成調撥單 def _run_pull(self, product_id, product_qty, product_uom, location_id, name, origin, values): if not self.location_src_id: msg = _('No source location defined on stock rule: %s!') % (self.name, ) raise UserError(msg) # create the move as SUPERUSER because the current user may not have the rights to do it (mto product launched by a sale for example) # Search if picking with move for it exists already: group_id = False if self.group_propagation_option == 'propagate': group_id = values.get('group_id', False) and values['group_id'].id elif self.group_propagation_option == 'fixed': group_id = self.group_id.id data = self._get_stock_move_values(product_id, product_qty, product_uom, location_id, name, origin, values, group_id) # Since action_confirm launch following procurement_group we should activate it. move = self.env['stock.move'].sudo().with_context(force_company=data.get('company_id', False)).create(data) # 在這裡建立stock_move記錄 move._action_confirm() # stock.move 在確認時建立stock.picking return True # 5. stock.move 確認並建立picking def _action_confirm(self, merge=True, merge_into=False): """ Confirms stock move or put it in waiting if it's linked to another move. :param: merge: According to this boolean, a newly confirmed move will be merged in another move of the same picking sharing its characteristics. """ move_create_proc = self.env['stock.move'] move_to_confirm = self.env['stock.move'] move_waiting = self.env['stock.move'] to_assign = {} for move in self: # if the move is preceeded, then it's waiting (if preceeding move is done, then action_assign has been called already and its state is already available) if move.move_orig_ids: move_waiting |= move else: if move.procure_method == 'make_to_order': move_create_proc |= move else: move_to_confirm |= move if move._should_be_assigned(): key = (move.group_id.id, move.location_id.id, move.location_dest_id.id) if key not in to_assign: to_assign[key] = self.env['stock.move'] to_assign[key] |= move # create procurements for make to order moves for move in move_create_proc: values = move._prepare_procurement_values() origin = (move.group_id and move.group_id.name or (move.origin or move.picking_id.name or "/")) self.env['procurement.group'].run(move.product_id, move.product_uom_qty, move.product_uom, move.location_id, move.rule_id and move.rule_id.name or "/", origin, values) move_to_confirm.write({'state': 'confirmed'}) (move_waiting | move_create_proc).write({'state': 'waiting'}) # assign picking in batch for all confirmed move that share the same details for moves in to_assign.values(): moves._assign_picking() self._push_apply() if merge: return self._merge_moves(merge_into=merge_into) return self
懂得,原來世界如此簡單!