📦 epiQ 多網站電商 · 架構藍圖

← 回管控中心
Odoo 18 · Multi-Website E-Commerce

資料結構與業務流程藍圖

本文件呈現 epiQ 多網站電商(烈酒站 / 雪茄站 / Apple 風商城)的資料模型(Class 圖)業務代客下單流程模組依賴關係,供與主管討論架構決策、缺口補齊與後續開發排程之用。

📅 產出日期 2026-06-04 🗂 來源 repo epiq · eCommerce · Website(DbtWebsite) 🐳 部署 Docker / Odoo 18.0 / port 10003 ✅ 已安裝模組 7 個
1

系統總覽

三 repo · 一個 Odoo 實例

三個獨立 Git repo 以 Docker volume 掛載成同一個 Odoo 18 實例的 addons,共同組成多網站電商。下表為目前已安裝、彼此依賴完整、運作正常的 7 個模組。

🎨 epiq

/mnt/extra-addons · 分支 18.0

  • theme_epiq_liquor 烈酒站佈景
  • theme_epiq_tobacco 雪茄站佈景
  • theme_apple_shop Apple 風商城

🛒 eCommerce

/mnt/ecommerce · 分支 dev-18.0

  • dobtor_website_sale_assisted 業務代訂
  • dobtor_inquiry 詢價模式
  • dobtor_legal_restrict_popup 法規彈窗

🌐 Website (DbtWebsite)

/mnt/website · 分支 dev-18.0

  • dobtor_website_menu_visibility 選單/頁面權限控制
核心依賴鏈: theme_apple_shopdobtor_website_sale_assistedwebsite_sale + dobtor_website_menu_visibility。三者跨 repo 串接,已驗證安裝成功、資料流通正常、無衝突。
2

模組依賴關係

install graph
模組依賴圖(綠=已裝可用 · 黃=未裝待設定 · 紅=缺依賴裝不起來)
graph TD
    subgraph core["Odoo 18 核心"]
        direction LR
        W[website]
        WS[website_sale]
        PAY[payment]
        ACC[account]
    end

    MV["選單/頁面權限
menu_visibility"]:::ok AS["業務代訂
sale_assisted"]:::ok THEMES["3 個佈景主題
liquor · tobacco · apple_shop"]:::ok EXTRA["詢價 inquiry
法規彈窗 legal_popup"]:::ok PEC["金流 payment_ecpay
payment_newebpay"]:::warn EIT["電子發票
ecpay_invoice_tw"]:::warn MISS["租賃 / BYOD / CTBC 模組
缺 property_rental、user_signup"]:::no W --> MV WS --> AS MV --> AS AS --> THEMES W --> THEMES WS --> EXTRA PAY --> PEC WS --> PEC ACC --> EIT PAY -.缺依賴.-> MISS classDef ok fill:#E3EFE7,stroke:#2D6A4F,stroke-width:2px,color:#1b4332; classDef warn fill:#F7ECDC,stroke:#92400E,stroke-width:2px,color:#5c2e0a; classDef no fill:#F6E2E2,stroke:#991B1B,stroke-width:1.5px,color:#7a1414,stroke-dasharray:5 3;
已安裝可用(7) repo 已有、未安裝(金流/發票) 缺外部依賴、目前裝不起來
3

資料模型 · 存取控制層

dobtor_website_menu_visibility

控制「選單顯示」與「URL 實際存取權」兩個獨立軸。新建 website.url.visibility 模型集中管理規則;ir.http 在每次請求時強制執行。

Class 圖 — 權限控制(+=新建模型,◇=繼承擴充 Odoo 核心)
classDiagram
    class website_url_visibility {
        +新建模型
        Char url
        Many2one website_id
        Integer sequence
        Selection visibility
        Many2many group_ids
        Char visibility_password
        Html access_denied_message
        _match_url(path, website_id)
        _enforce()
        _is_internal_sales_context() ◀assisted擴充
    }
    class website_menu {
        ◇inherit
        Selection menu_visibility
        _compute_visible()
        get_tree() RPC
        save() RPC
        resolve_content_access()
        _get_content_access()
    }
    class ir_http {
        ◇inherit
        _pre_dispatch() 強制規則
        _handle_error() connected→login
        _get_error_html() 403 拒絕頁
    }
    class ir_ui_view {
        ◇inherit
        visibility 欄位整合
    }
    class website_mv {
        ◇inherit website
        Html dobtor_menu_access_denied_message
        Integer dobtor_menu_access_denied_delay
    }
    class res_groups {
        Odoo 核心
    }

    website_url_visibility "1" --> "*" res_groups : group_ids
    website_url_visibility --> website_mv : website_id
    ir_http ..> website_url_visibility : _match_url/_enforce
    website_menu ..> website_url_visibility : resolve
    website_menu --> res_groups : 受限群組
      
visibility 模式行為未授權結果
'' Public公開,不限制
connected需登入導向 /web/login(302)
restricted_group限特定群組(如業務)HTTP 403 拒絕頁 (本次修正:原為 200)
password需輸入密碼密碼輸入頁
4

資料模型 · 業務代客下單層

dobtor_website_sale_assisted

業務以自己的帳號登入,但購物車與報價單綁定到所選客戶(價目表、稅務、聯絡人皆跟客戶走),業務僅留為訂單的負責人 user_id。選定客戶存於 session ws_assisted_partner_id

Class 圖 — 業務代訂與訂單關聯
classDiagram
    class website_as {
        ◇inherit website
        Boolean assisted_allow_create_customer
        _assisted_can_render() 授權判斷
        _assisted_active() 已選客戶?
        _get_cart_partner_sudo() 取客戶
        sale_get_order() cart綁客戶
        _prepare_sale_order_values()
        _get_current_pricelist() 跟客戶
        _get_current_fiscal_position()
    }
    class WebsiteSaleAssisted_Controller {
        「/shop/assisted/*」
        search() 搜尋客戶
        set() 選定客戶
        clear() 取消代訂
        create_customer() 新增客戶
        share_link() 產付款連結
    }
    class sale_order {
        Odoo 核心
        Many2one partner_id ◀客戶
        Many2one user_id ◀業務
        Selection state
        Monetary amount_total
        access_token portal
        _portal_ensure_token()
        action_quotation_sent()
    }
    class res_partner {
        客戶
        Char name / email / phone
        property_product_pricelist
    }
    class res_users {
        業務(內部)
        partner_id
        groups_id
    }
    class payment_transaction {
        Odoo 核心
        state
        sale_order_ids
    }

    website_as ..> sale_order : sale_get_order()
    WebsiteSaleAssisted_Controller ..> website_as : guard
    sale_order "*" --> "1" res_partner : partner_id 客戶
    sale_order "*" --> "1" res_users : user_id 業務
    sale_order "1" --> "*" payment_transaction : 線上付款
    res_users --> res_partner : partner_id
      

🔗 /shop/assisted/* 端點

/search關鍵字搜尋客戶
/set選定客戶(重置購物車)
/clear取消代訂
/create_customer新增客戶(受開關控制)
/share_link產生付款連結

🛡️ 安全設計

  • 每個端點都 _assisted_guard() 重驗授權,不信任 session
  • 授權對 request.env.user(真實使用者)判斷,sudo() 不會放大權限
  • 切換客戶自動清空舊購物車與價目表,避免跨客戶汙染
  • 付款進行中的購物車不會被重用
5

業務代客下單 · 完整流程

兩條結單路徑
流程圖 — 從業務登入到客戶付款
flowchart TD
    A([業務登入
公司內部帳號]) --> B{進入 /shop} B -->|公開訪客| B0[HTTP 403
看不到商品]:::block B -->|授權業務| C[顯示「業務代訂」工具列] C --> D[搜尋客戶
/assisted/search] D --> E{客戶存在?} E -->|是| F[選定客戶
/assisted/set] E -->|否| G[新增客戶
/assisted/create_customer] G --> F F --> H[session 記住客戶
ws_assisted_partner_id] H --> I[瀏覽商品 → 加入購物車] I --> J[(購物車 = 報價單
partner=客戶
user=業務
價目表跟客戶)] J --> K{結單方式} K -->|路徑 A| L[直接代付結帳
/shop/checkout] L --> M[確認訂單 sale.order] M --> N[[拋後端
會計每月結單]]:::pendingA K -->|路徑 B| O[產生付款連結
/assisted/share_link] O --> P[portal token
報價單轉寄送狀態] P --> Q[把連結傳給客戶
LINE / 複製] Q --> R([客戶開啟付款網頁
看到訂單內容]) R --> S{已裝金流?} S -->|否 目前| S0[無法線上付款]:::pendingB S -->|是 待裝| T[線上付款
payment.transaction] T --> U([付款完成
訂單確認]) classDef block fill:#F6E2E2,stroke:#991B1B,color:#7a1414; classDef pendingA fill:#F7ECDC,stroke:#92400E,color:#5c2e0a; classDef pendingB fill:#F7ECDC,stroke:#92400E,color:#5c2e0a;

🅰️ 路徑 A — 直接代付結帳

業務在購物車按「直接代付結帳」,走 Odoo 原生 /shop/checkout 結帳流程,產生正式 sale.order。訂單確認後進入標準後端會計流程。

待確認 「每月批次結單給會計」目前無專屬程式,需釐清是走 Odoo 標準開票政策 + 會計月底處理,或另開發排程。

🅱️ 路徑 B — 線上付款連結

業務按「產生付款連結寄客戶」,系統建立 portal access token,產出含訂單內容的付款網頁網址,可透過 LINE 或複製傳給客戶自行線上付款。

缺金流 程式完整,但目前未安裝任何 payment provider,客戶開啟後無法付款。需安裝設定 payment_ecpay / payment_newebpay

6

缺口與後續待辦

明天討論重點
項目狀態說明與下一步
金流 payment provider 阻斷路徑B repo 已有 payment_ecpaypayment_newebpay,但尚未安裝。需安裝並設定商店金鑰,路徑 B 才能真正收款。
每月批次結單(會計) 待釐清 代訂模組只負責產單與付款連結。「每月給會計結單」需確認:走 Odoo 標準 invoicing policy + 月底人工,還是要另開發排程批次?
電子發票 ecpay_invoice_tw 未安裝 若每月結單需自動開立電子發票,此模組可整合,但目前未裝。
缺失外部依賴模組 需向主管索取 dobtor_byod_sale(缺 dobtor_user_signup)、dobtor_bank_integration / payment_ctbc(缺 dobtor_property_rental_management) — 屬租賃/BYOD情境,與零售代客下單無關,明天向主管索取對應 repo。
重複空殼資料夾 Website/ 建議清理 GitHub 下同時有 Website/(空殼)與 DbtWebsite/(實際生效)。建議刪除空殼避免混淆。
本次已修正 4 項 bug 已完成 403 拒絕碼、業務 sudo 權限、Mac 落地頁代訂列注入、多網站首頁 guard,13/13 測試通過。
明天討論建議順序:① 確認「每月結單」走標準流程或另開發 → ② 決定金流商(ECPay / 藍新)並取得測試金鑰 → ③ 向主管索取缺失的 dobtor 依賴 repo(若需租賃/BYOD/CTBC)。