
在 odoo 16 中,`stockforecasted` 并未作为默认导出类暴露在模块路径中,而是注册到 `actions` 注册表中(键名为 `'replenish_report'`),直接 import 会导致 `undefined` 错误;正确方式是通过 `registry.category("actions").get('replenish_report')` 获取该组件实例再进行 patch。
Odoo 16 的前端架构采用模块化注册机制,许多核心组件(如库存预测报表 StockForecasted)并非以标准 ES 模块方式导出,而是通过 @web/core/registry 注册到特定类别中。StockForecasted 类实际被注册为 actions 类别下的 'replenish_report' 条目——这正是直接 import { StockForecasted } from "@stock/stock_forecasted/stock_forecasted" 失败的根本原因:该路径下无命名导出,控制台会抛出 TypeError: StockForecasted is undefined。
✅ 正确修补步骤如下:
- 确保依赖模块已加载:先 import "@stock/stock_forecasted/stock_forecasted",触发其内部注册逻辑;
- 从 registry 获取组件构造函数:使用 registry.category("actions").get('replenish_report') 获取已注册的 StockForecasted 类;
- 调用 patch() 进行原型增强:对 .prototype 执行 patch,并在重写方法中显式调用 await this._super(...arguments) 以保留原始逻辑。
以下是可直接使用的完整补丁代码示例:
/** @odoo-module **/
import { patch } from '@web/core/utils/patch';
import { registry } from '@web/core/registry';
import "@stock/stock_forecasted/stock_forecasted"; // 触发注册
const actionRegistry = registry.category("actions");
const StockForecasted = actionRegistry.get('replenish_report');
if (!StockForecasted) {
console.error("[Patch Error] 'replenish_report' component not found in actions registry.");
} else {
patch(StockForecasted.prototype, 'test_my_stock.StockForecasted', {
async _getReportValues(...args) {
console.log('_getReportValuesInherit: patch applied successfully');
// ✅ 必须调用父类原方法,否则功能中断
await this._super(...args);
// ? 在此处插入自定义逻辑,例如动态推导 resModel:
if (!this.resModel) {
if (this.props.action?.res_model) {
const [modelRecord] = await this.orm.read('ir.model', [Number(this.props.action.res_model)], ['model']);
this.resModel = modelRecord?.model || null;
} else if (this.props.action?._originalAction) {
try {
const originalContext = JSON.parse(this.props.action._originalAction)?.context;
this.resModel = originalContext?.active_model || null;
} catch (e) {
console.warn('Failed to parse _originalAction context', e);
}
}
}
},
});
}⚠️ 注意事项:
- 切勿省略 await this._super(...args):Odoo 的 _super 是异步代理,跳过将导致 this.context、this.orm 等关键属性未初始化,引发后续运行时错误;
- 添加存在性校验:actionRegistry.get() 可能返回 undefined(如模块未加载或注册名变更),建议加入 if (!StockForecasted) 防御性判断;
- 避免重复 patch:确保该 JS 文件仅被加载一次(推荐放在自定义模块的 static/src/js/ 下,并通过 assets 清单正确引入);
- 兼容性提示:Odoo 17+ 已重构部分 forecasted 逻辑,此方案专用于 Odoo 16,请勿直接迁移至新版。
通过 registry 机制获取并 patch 组件,是 Odoo 前端扩展的标准实践。掌握这一模式,可安全、可靠地定制包括 StockForecasted 在内的所有注册型组件行为。










