1. Odoo MTO与智能MTO核心概念解析
在制造业和供应链管理领域,按订单生产(Make to Order,简称MTO)是一种关键的生产策略。与传统的按库存生产(Make to Stock)不同,MTO模式下企业只在收到客户订单后才开始组织生产或采购,这种模式特别适合定制化产品、长尾商品或高价值物品的管理。
1.1 传统MTO的工作原理
传统MTO在Odoo中的实现主要依赖以下技术组件:
- 路由配置(Routes):在库存模块中定义"按订单补货"的特殊路由规则
- 产品设置:通过产品表单的库存选项卡启用MTO选项
- 采购/制造联动:销售订单确认时自动生成采购申请或制造订单
典型业务流程如下:
- 销售员创建报价单并确认订单
- 系统检查产品路由配置
- 根据路由规则生成采购订单或制造订单
- 完成采购/生产后执行库存调拨
- 最终完成客户交付
1.2 智能MTO的增强特性
智能MTO在传统基础上引入了以下创新:
- 动态路由决策:基于实时库存水平、供应商交期和生产能力等多元因素自动选择最优补货路径
- 需求预测集成:结合历史销售数据预测潜在订单,提前触发部分准备工作
- 跨仓库协同:在分布式仓库网络中智能选择补货来源
- 交期承诺计算:基于当前系统负载精确计算并承诺交付日期
python复制# 智能MTO的核心决策逻辑示例
def smart_mto_decision(product, quantity, warehouse):
suppliers = find_qualified_suppliers(product)
production_sites = get_production_capacity(product)
stock_levels = get_network_inventory(product)
options = []
for loc in stock_levels:
if loc.quantity >= quantity:
options.append(('transfer', loc, loc.transit_time))
for supplier in suppliers:
lead_time = supplier.lead_time + shipping_time(supplier, warehouse)
options.append(('purchase', supplier, lead_time))
for site in production_sites:
capacity = site.available_capacity()
if capacity >= quantity:
prod_time = quantity * site.unit_time
options.append(('manufacture', site, prod_time))
return sorted(options, key=lambda x: x[2])[0] # 返回交期最短的方案
2. Odoo MTO模块源码深度剖析
2.1 核心模型结构
Odoo中MTO功能主要涉及以下关键模型:
stock.route:定义补货路由规则product.product:产品的库存策略配置stock.rule:补货规则的具体实现procurement.group:补货需求的协调单元
mermaid复制classDiagram
class ProductProduct {
+route_ids: Many2many
+mto_pull_id: Many2one
}
class StockRoute {
+rule_ids: One2many
+name: Char
}
class StockRule {
+action: Selection
+procure_method: Selection
+route_id: Many2one
}
ProductProduct -- StockRoute : route_ids
StockRoute -- StockRule : rule_ids
2.2 关键方法解析
2.2.1 补货触发机制
_run_buy和_run_manufacture方法是MTO执行的核心:
python复制# addons/stock/models/stock_rule.py
def _run_mto(self, product_id, product_qty, product_uom, location_id, ...):
# 检查是否需要创建采购订单
if self.action == 'buy':
return self._run_buy(product_id, product_qty, product_uom, ...)
# 检查是否需要创建生产订单
elif self.action == 'manufacture':
return self._run_manufacture(product_id, product_qty, ...)
2.2.2 智能路由选择
Odoo 15引入的智能路由通过重写_get_stock_rules方法实现:
python复制def _get_stock_rules(self, product_id, warehouse_id, ...):
rules = super()._get_stock_rules(...)
if self.env.context.get('force_mto'):
return rules.filtered(lambda r: r.procure_method == 'make_to_order')
# 智能路由决策逻辑
if product_id.mto_forecasted_demand > product_id.qty_available:
return rules.filtered(lambda r: r.action in ['buy', 'manufacture'])
return rules
3. MTO实战配置指南
3.1 基础MTO配置步骤
-
启用MTO路由:
- 进入:库存 → 配置 → 路由
- 激活"按订单补货(MTO)"路由
-
产品配置:
python复制# 通过代码配置示例 product = env['product.product'].create({ 'name': 'MTO Product', 'type': 'product', 'route_ids': [(6, 0, [ env.ref('stock.route_warehouse0_mto').id, env.ref('purchase_stock.route_warehouse0_buy').id ])] }) -
仓库设置:
- 确保仓库的补货策略包含MTO选项
- 配置适当的采购和制造前置时间
3.2 智能MTO高级配置
-
需求预测集成:
xml复制<record id="ir_cron_mto_forecast" model="ir.cron"> <field name="name">MTO Forecast Update</field> <field name="model_id" ref="model_product_product"/> <field name="state">code</field> <field name="code">model.update_mto_forecast()</field> <field name="interval_number">1</field> <field name="interval_type">days</field> </record> -
多仓库协同配置:
- 设置仓库间的调拨路由规则
- 配置优先级和运输时间矩阵
-
交期承诺配置:
python复制# 交期计算规则示例 def _get_mto_promise_date(self, product, quantity, warehouse): calendar = warehouse.calendar_id supplier_lead = max(product.seller_ids.mapped('delay')) or 0 production_lead = product.produce_delay or 0 transfer_lead = warehouse.delivery_route_id.rule_ids.delay or 0 base_date = fields.Datetime.now() if product.route_ids & self.env.ref('mto.route_mto'): if product.make_or_buy == 'buy': return calendar.plan_days(supplier_lead + transfer_lead, base_date) else: return calendar.plan_days(production_lead + transfer_lead, base_date) return base_date
4. 性能优化与疑难排解
4.1 MTO模式下的性能瓶颈
-
数据库查询优化:
sql复制-- 为MTO查询添加索引 CREATE INDEX idx_product_route_mto ON product_route_rel (product_id, route_id) WHERE route_id = (SELECT id FROM stock_route WHERE code = 'mto'); -
批量处理优化:
python复制# 使用procurement.group批量处理MTO需求 def _run_mto_batch(self, product_ids, quantities): procurements = [] for product_id, qty in zip(product_ids, quantities): procurements.append(self.env['procurement.group'].Procurement( product_id, qty, product_id.uom_id, location_id, product_id.name, origin, company_id, {'warehouse_id': warehouse_id, 'mto_origin': origin})) return self.env['procurement.group'].run(procurements)
4.2 常见问题解决方案
问题1:MTO路由未触发
- 检查产品是否配置了MTO路由
- 验证仓库的路由配置是否包含MTO规则
- 检查库存可用量是否真的不足(可能被预留库存影响)
问题2:重复创建采购订单
python复制# 在采购规则中添加防重复逻辑
def _run_buy(self, product_id, product_qty, ...):
existing_po = self.env['purchase.order'].search([
('state', 'in', ['draft', 'sent', 'to approve']),
('order_line.product_id', '=', product_id.id),
('order_line.date_planned', '>=', fields.Date.today())
], limit=1)
if existing_po:
# 在现有采购订单中追加行
return existing_po._add_mto_line(product_id, product_qty, ...)
return super()._run_buy(product_id, product_qty, ...)
问题3:交期计算不准确
- 检查供应商主数据中的交货提前期
- 验证工作日历配置
- 确认运输时间设置
5. 智能MTO的扩展开发
5.1 与高级排产(APS)集成
python复制def _run_manufacture(self, product_id, product_qty, ...):
if self.env['mrp.config.settings'].is_aps_installed():
aps_schedule = self.env['aps.schedule'].create({
'product_id': product_id.id,
'quantity': product_qty,
'priority': self._get_mto_priority(origin),
'constraint_ids': [(0, 0, {
'type': 'delivery',
'date': fields.Datetime.from_string(origin.date_planned)
})]
})
return aps_schedule.generate_mo()
return super()._run_manufacture(product_id, product_qty, ...)
5.2 机器学习需求预测
python复制# 集成TensorFlow需求预测示例
class ProductProduct(models.Model):
_inherit = 'product.product'
def update_mto_forecast(self):
tf_model = load_model('mto_forecast.h5')
for product in self:
history = self.env['sale.order.line'].read_group(
[('product_id', '=', product.id)],
['qty_delivered', 'date_order:month'],
['date_order:month']
)
X = preprocess_history(history)
product.mto_forecasted_demand = tf_model.predict(X)
5.3 多级MTO网络
python复制class MultiLevelMTO(models.Model):
_name = 'multi.level.mto'
def propagate_mto_demand(self, product, quantity, origin):
locations = self.get_network_locations(product)
for loc in locations:
if loc.quantity >= quantity:
self.create_transfer(loc, origin.location_id, quantity)
break
elif loc.quantity > 0:
partial_qty = loc.quantity
self.create_transfer(loc, origin.location_id, partial_qty)
quantity -= partial_qty
if quantity > 0:
self.env['procurement.group'].run([
self.env['procurement.group'].Procurement(
product, quantity, product.uom_id,
origin.location_id, origin.name,
origin, origin.company_id,
{'warehouse_id': origin.warehouse_id})
])
关键提示:在生产环境中实施智能MTO时,建议先在小规模产品类别中试运行,逐步验证系统稳定性和业务适配性。特别注意库存准确性和主数据质量对智能决策的影响。
