本文件呈現 epiQ 多網站電商(烈酒站 / 雪茄站 / Apple 風商城)的資料模型(Class 圖)、業務代客下單流程與模組依賴關係,供與主管討論架構決策、缺口補齊與後續開發排程之用。
三個獨立 Git repo 以 Docker volume 掛載成同一個 Odoo 18 實例的 addons,共同組成多網站電商。下表為目前已安裝、彼此依賴完整、運作正常的 7 個模組。
/mnt/extra-addons · 分支 18.0
theme_epiq_liquor 烈酒站佈景theme_epiq_tobacco 雪茄站佈景theme_apple_shop Apple 風商城/mnt/ecommerce · 分支 dev-18.0
dobtor_website_sale_assisted 業務代訂dobtor_inquiry 詢價模式dobtor_legal_restrict_popup 法規彈窗/mnt/website · 分支 dev-18.0
dobtor_website_menu_visibility 選單/頁面權限控制theme_apple_shop → dobtor_website_sale_assisted → website_sale + dobtor_website_menu_visibility。三者跨 repo 串接,已驗證安裝成功、資料流通正常、無衝突。
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;
控制「選單顯示」與「URL 實際存取權」兩個獨立軸。新建 website.url.visibility 模型集中管理規則;ir.http 在每次請求時強制執行。
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 | 需輸入密碼 | 密碼輸入頁 |
業務以自己的帳號登入,但購物車與報價單綁定到所選客戶(價目表、稅務、聯絡人皆跟客戶走),業務僅留為訂單的負責人 user_id。選定客戶存於 session ws_assisted_partner_id。
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
/search | 關鍵字搜尋客戶 |
/set | 選定客戶(重置購物車) |
/clear | 取消代訂 |
/create_customer | 新增客戶(受開關控制) |
/share_link | 產生付款連結 |
_assisted_guard() 重驗授權,不信任 sessionrequest.env.user(真實使用者)判斷,sudo() 不會放大權限
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;
業務在購物車按「直接代付結帳」,走 Odoo 原生 /shop/checkout 結帳流程,產生正式 sale.order。訂單確認後進入標準後端會計流程。
待確認 「每月批次結單給會計」目前無專屬程式,需釐清是走 Odoo 標準開票政策 + 會計月底處理,或另開發排程。
業務按「產生付款連結寄客戶」,系統建立 portal access token,產出含訂單內容的付款網頁網址,可透過 LINE 或複製傳給客戶自行線上付款。
缺金流 程式完整,但目前未安裝任何 payment provider,客戶開啟後無法付款。需安裝設定 payment_ecpay / payment_newebpay。
| 項目 | 狀態 | 說明與下一步 |
|---|---|---|
| 金流 payment provider | 阻斷路徑B | repo 已有 payment_ecpay、payment_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 測試通過。 |