You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Odoo中重写Owl服务companyService的start函数

Odoo 自定义company服务start函数重写方案
  • 你可以通过Odoo前端服务注册机制替换原生company服务的start方法,无需修改框架核心源码,只需将自定义JS文件放到自定义模块的静态资源路径下加载即可。
  • 原代码中提供的parseCompanyIds、computeAllowedCompanyIds为通用工具函数,重写时可直接复用,无需重复编写。

原生start函数核心逻辑

  • 优先从路由hash、其次从浏览器cookie中读取用户历史保存的选中公司ID列表
  • 校验读取到的公司ID是否都在用户权限范围内,非法值会被替换为用户当前默认公司ID
  • 将最终生效的公司ID列表同步写入路由hash、cookie,同时更新用户上下文的allowed_company_ids字段
  • 对外暴露服务实例,提供可用公司查询、当前公司查询、公司切换三个核心能力

可直接修改的重写模板

/** @odoo-module **/
import { browser } from "@web/core/browser/browser";
import { registry } from "@web/core/registry";
import { symmetricalDifference } from "@web/core/utils/arrays";
import { session } from "@web/session";

function parseCompanyIds(cidsFromHash) {
    const cids = [];
    if (typeof cidsFromHash === "string") {
        cids.push(...cidsFromHash.split(",").map(Number));
    } else if (typeof cidsFromHash === "number") {
        cids.push(cidsFromHash);
    }
    return cids;
}

function computeAllowedCompanyIds(cids) {
    const { user_companies } = session;
    let allowedCompanyIds = cids || [];
    const availableCompaniesFromSession = user_companies.allowed_companies;
    const notReallyAllowedCompanies = allowedCompanyIds.filter(
        (id) => !(id in availableCompaniesFromSession)
    );

    if (!allowedCompanyIds.length || notReallyAllowedCompanies.length) {
        allowedCompanyIds = [user_companies.current_company];
    }
    return allowedCompanyIds;
}

export const customCompanyService = {
    dependencies: ["user", "router", "cookie"],
    start(env, { user, router, cookie }) {
        let cids;
        if ("cids" in router.current.hash) {
            cids = parseCompanyIds(router.current.hash.cids);
        } else if ("cids" in cookie.current) {
            cids = parseCompanyIds(cookie.current.cids);
        }

        // --------------------------
        // 在此区域编写自定义公司选择逻辑
        // 示例1:默认加载用户所有有权限的公司(即你当前贴出的代码逻辑)
        let allowedCompanyIds = Object.values(session.user_companies.allowed_companies).map(company => company.id);
        // 示例2:恢复Odoo原生逻辑,默认加载用户上次选中的公司
        // let allowedCompanyIds = computeAllowedCompanyIds(cids);
        // 示例3:固定只加载指定ID的公司
        // let allowedCompanyIds = [1];
        // --------------------------

        const stringCIds = allowedCompanyIds.join(",");
        router.replaceState({ cids: stringCIds }, { lock: true });
        cookie.setCookie("cids", stringCIds);
        user.updateContext({ allowed_company_ids: allowedCompanyIds });
        
        const availableCompanies = session.user_companies.allowed_companies;
        return {
            availableCompanies,
            get allowedCompanyIds() {
                return allowedCompanyIds.slice();
            },
            get currentCompany() {
                return availableCompanies[allowedCompanyIds[0]];
            },
            setCompanies(mode, ...companyIds) {
                // 如需自定义公司切换规则,可修改此方法内的nextCompanyIds计算逻辑
                let nextCompanyIds;
                if (mode === "toggle") {
                    nextCompanyIds = symmetricalDifference(allowedCompanyIds, companyIds);
                } else if (mode === "loginto") {
                    const companyId = companyIds[0];
                    if (allowedCompanyIds.length === 1) {
                        nextCompanyIds = [companyId];
                    } else {
                        nextCompanyIds = [
                            companyId,
                            ...allowedCompanyIds.filter((id) => id !== companyId),
                        ];
                    }
                }
                nextCompanyIds = nextCompanyIds.length ? nextCompanyIds : [companyIds[0]];

                router.pushState({ cids: nextCompanyIds }, { lock: true });
                cookie.setCookie("cids", nextCompanyIds);
                browser.setTimeout(() => browser.location.reload());
            },
        };
    },
};

// 移除原有公司服务,注册自定义版本
registry.category("services").remove("company").add("company", customCompanyService);

重写注意事项

  • 不可删除服务声明中的dependencies配置,缺少依赖会导致服务启动失败
  • 返回的服务实例必须保留availableCompanies、allowedCompanyIds、currentCompany、setCompanies四个核心成员,否则依赖公司服务的其他前端组件会出现运行异常
  • 自定义逻辑修改完成后,将文件放到自定义模块的/static/src/js/路径下,在资源清单中引入即可生效

内容的提问来源于stack exchange,提问作者CHIU TZE CHEUNG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 09:27:09