0總覽:開發原則與協作方式
這頁整理給實際動手開發的你看——兩個獨立的客製系統案,客戶不同、互不相關,但技術理念一致。重點是架構、資料模型與資訊流程;報價與合約是我跟業主那邊談的事,這頁不放,專心看技術就好。
| 第一案 | 第二案 | |
|---|---|---|
| 是什麼 | 冰棒/食品廠的 B2B 訂購系統 + 官網 | 多據點冰品飲料店的營運資料系統 |
| 本質 | 交易系統:下單 → 處理 → 出貨 | 資料系統:每日填報 → 報表 → 決策 |
| 核心技術 | WordPress + WooCommerce(散客)/Django + PostgreSQL(廠商) | Django + PostgreSQL + Metabase |
為什麼都用 Django + PostgreSQL 當後端骨架
- 後台幾乎免費:Django admin 自動生成商品/訂單/廠商管理介面,含權限控管,不用自己刻後台 UI。
- Python 生態成熟,AI 輔助寫 Django 的品質穩定,教學資源多。
- 兩案共用一套骨架,學一次架構,兩邊都能用。
開發規範(兩案都要遵守)
- Docker:本機與伺服器同一套
docker compose,不要「本機跑得動,伺服器跑不動」。 - secrets 一定放
.env,寫進.gitignore,絕不進 git;LINE channel secret、WooCommerce API 金鑰、資料庫密碼都算。 - 測試環境/正式環境分開:正式環境只從 git 部署,不手動改。
- pytest 覆蓋關鍵案例:權限隔離(誰能看誰的資料)、狀態流轉、金額快照、外部串接的簽章驗證。
- git 天天 commit,訊息寫清楚做了什麼;
README要寫到任何人一天內能跑起來 —— 這是保護你自己,也保護專案。 - 每週抓 30 分鐘,一起在測試環境上過一次目前做到哪裡——這樣兩邊對進度有共同的畫面,也比較好抓下一步要做什麼。
T期程規劃(兩個硬期限)
第一案客戶端有兩個外部硬期限,不是我們自己排的:
10/15 Demo:目的是給客戶寫企劃申請補助,不是完整系統
Demo 的標準是「讓人看得懂、看得出可行」,不是「每個功能都能用」:
| 模組 | Demo 要做到 | 不用做到 |
|---|---|---|
| 官網(WordPress) | 品牌頁、商品展示 | 不用完整 SEO |
| 散客商店 | 可瀏覽、加購物車 | 金流測試模式即可,不用真的收款 |
| 廠商 B2B | 一個假帳號能示範「登入 → 看專屬價格 → 下單」 | 不用做完所有例外處理與完整權限測試 |
| LINE 整合 | 用這頁的流程圖展示規劃,或最多做到圖文選單導流 | LIFF、Webhook、簽章驗證先不用真的接 |
| 進銷存整合 | 用架構圖說明規劃 | 不用做 |
這頁上面的流程圖本身就是很好的企劃素材 —— 系統還沒做出來,用圖說明「這是規劃中的架構」,對申請補助反而更清楚,不用為了 Demo 硬做還沒到時候的整合。
11/30 初步可執行版本
在 Demo 基礎上,把「真的能用」的部分做出來:廠商登入下單全流程(含權限隔離)、後台訂單處理、LINE 綁定與基本通知。WooCommerce↔Django 的自動化進銷存整合、完整資安檢查、多廠商試營運,留到 12 月之後繼續做,這個時間點不強求。
B開發基本知識:備份/Git/Commit
這些不是「加分項」,是任何專案都要有的底線——尤其時程壓縮的時候,更需要靠這些習慣讓自己隨時能回頭、不會因為一次失誤全部重來。
為什麼一定要用 Git
- Git 是版本控制工具:每次
commit就是存一個「這一刻的完整快照」,之後不管怎麼改壞,都能回到任何一個快照。 - 沒有 Git 的專案,一旦改壞、找不回原本能動的版本,等於從頭來過——這在趕時程的時候是最不能承受的風險。
- Git 也是團隊同步進度的方式:commit 紀錄本身就是一份「做了什麼、什麼時候做的」的日誌,不用另外寫報告。
基本節奏
- 能跑的功能就 commit,不用等整個模組做完。一天至少一次,通常會更多次。
- Commit 訊息寫清楚做了什麼,例如
加上廠商登入與專屬價格顯示,不要只寫update。 - Push 到遠端(GitHub):本機硬碟壞掉不會遺失工作進度。
- 正式環境只從 git 部署,不要在伺服器上手動改檔案——手動改的東西下次部署會被蓋掉,而且沒有紀錄。
Secrets 絕不進 Git
LINE channel secret、WooCommerce API 金鑰、資料庫密碼——這些放進 .env 檔案,並且把 .env 寫進 .gitignore。一旦 commit 進 git 歷史,就算之後刪掉,舊紀錄裡還是找得到,等於外洩。寫程式的第一件事就是先設定好 .gitignore。
備份(資料庫,跟 Git 是兩件事)
Git 管的是程式碼,不是資料庫內容(訂單、廠商資料這些)。資料庫要另外每日自動備份(例如排程跑 pg_dump),存到跟主機分開的地方(例如 Cloudflare R2)。備份沒有實際「還原測試」過,等於沒有備份——這個要在正式上線前至少演練一次。
測試環境/正式環境分開
兩套環境,兩份資料庫。所有改動先在測試環境做、確認沒問題,才部署到正式環境。這樣就算測試環境搞壞了,也不影響客戶正在用的系統。
S資安強化清單
照著這個架構的隔離設計做,能擋掉大部分自動化攻擊;但沒有專業資安審查、時程又壓縮,對「有目的的針對性攻擊」不算難打。 最大的單一弱點是 IDOR:Django 不會自動擋「廠商 A 改網址參數看到廠商 B 的資料」,這件事要靠工程師在每一個 API/頁面手動檢查歸屬。這種漏洞的麻煩之處是功能測試會過(頁面看起來能動),只有專門去試才會發現,也是真實世界資料外洩最常見的原因之一。
這些是紀律問題,不是預算問題——請直接做,不要因為趕 Demo/11/30 而跳過
| 項目 | 做什麼 |
|---|---|
| IDOR 系統性測試 | 每一個會回傳資料的 API/頁面都要測,不是測一次:用廠商 A 的帳號嘗試存取廠商 B 的訂單編號、廠商編號,一律應被拒絕 |
| Django admin 換路徑 | 不要用預設的 /admin/;帳密要夠強;有能力可加雙因素驗證(django-otp) |
| 登入速率限制 | 廠商登入、Django admin 登入都要限制嘗試次數(django-ratelimit 或 Cloudflare 規則),防暴力破解 |
正式環境 DEBUG=False | 務必確認關閉,否則錯誤畫面會把程式碼路徑和環境變數整包顯示給訪客看——這是最容易被忽略、代價最大的一個設定 |
| Cookie 安全設定 | Secure/HttpOnly/SameSite 都要開,防 session 被偷 |
| 依賴套件掃描 | GitHub Dependabot(免費)追蹤 Python 套件與 WordPress 外掛的已知漏洞 |
| 失敗事件留紀錄 | 登入失敗、Webhook 簽章驗證失敗都要記錄,能看出異常大量的嘗試 |
| WordPress 外掛數量控制 | 能不裝就不裝,裝的都要是有在維護的——外掛越多攻擊面越大 |
| 報表工具用唯讀帳號 | Metabase(或任何 BI 工具)連資料庫一律用唯讀帳號,不要用有寫入權限的帳號——防止誤改,分析查詢卡住鎖表時影響範圍也小很多 |
寫任何新的 API 或頁面時,先問自己一句:「這裡有沒有檢查『這筆資料屬於目前登入的這個廠商』?」 這一句話能擋掉這個系統最大的風險。
1第一案:冰棒/食品廠訂購系統
把現有的 LINE 訂購流程電子化,服務兩種對象:一般消費者(散客)在官網買,廠商在 LINE 裡走 B2B 下單流程。兩者是兩個獨立系統,同一台主機、不同容器、不同資料庫,網路互相隔離。
WordPress + WooCommerce
- 服務對象:一般消費者
- 品牌介紹、商品展示、購物車、結帳
- 三種付款:匯款(BACS,免費內建)/超商取貨付款(綠界物流模組)/藍新或綠界線上金流
- 標準配置,不是客製開發
Django + PostgreSQL
- 服務對象:廠商(B2B)
- 廠商登入、專屬價格表、下單、歷史訂單
- 後台:商品、廠商、訂單狀態流轉
- LINE LIFF 整合、Django admin 客製後台
資料模型(Django 側)
| Model | 說明 |
|---|---|
Product | 商品:名稱、分類、規格、單位(箱/支)、每箱數量、圖片、狀態、消費者顯示價 |
PriceList | 價格表:廠商 × 商品 → 單價、最小訂量(廠商專屬價格) |
Vendor | 廠商:公司名、聯絡人、電話、地址、付款條件、狀態 |
VendorUser | 廠商使用者:帳號、密碼(可空)、LINE userId(可空)、所屬廠商、角色 |
Order | 訂單:編號、廠商、配送日、時段、狀態、備註、建立來源(web/liff/manual)、操作紀錄 |
OrderItem | 訂單品項:訂單、商品、數量、單價快照、小計(改價不影響歷史訂單) |
Notification | 通知紀錄:對象、類型、訊息、送出結果(成功/額度不足/失敗) |
RetailSaleLog | 散客銷售紀錄:WooCommerce 訂單編號、品項、下單時間、Webhook 簽章驗證結果、原始 JSON 備查 |
LINE LIFF 下單流程
廠商在 LINE 裡完成下單,不用記帳密
技術要點:Messaging API channel 和 LINE Login channel(LIFF 用)必須在同一個 Provider 下,userId 才會一致,這是最常見的坑。LIFF 頁面必須 HTTPS。
進銷存三層資料庫設計(第二期,2026-09-25 會議定案)
一支冰棒可能用多種原料(百香果冰棒=百香果+檸檬),同一種原料也會被多種冰棒共用(檸檬同時用在百香果冰棒和荔枝冰棒)——這是多對多關係,拆成三層來解,同一個資料庫、三張表,不是三個獨立資料庫(避免跨資料庫同步失敗、資料對不上)。
| 要點 | 說明 |
|---|---|
| 批次事後記錄,不是即時扣庫存 | 工廠可能一整週處理完一批草莓才回填紀錄,系統只能事後知道「這批用超了/剩太多」,這是工廠實際作業流程決定的,不是系統做不到 |
| 多存貨地點 | 成品可能存放在 2~3 個不同地點,資料表不能寫死成單一地點 |
| 加分功能(非核心,之後再加) | 損耗率超過閾值(例如 30%)提示「建議換供應商」;比對計畫用量與實際剩餘,提示「買超了」或「不夠要多買」——這些是 if-else 規則,不是 AI,先把「記錄」做對再加 |
散客與廠商訂單如何整合進銷存(重點:不直連資料庫)
兩個系統之間只透過有驗證機制保護的 API 溝通,沒有任何一邊拿到對方資料庫的帳密。
方向 1:WooCommerce → Django(簽章驗證)
| 項目 | 做法 |
|---|---|
| WooCommerce 端 | 設定 > 進階 > Webhook > 新增;主題「訂單建立/更新」;Delivery URL 填 Django 端點;Secret 自訂一組隨機字串 |
| 驗證方式 | 請求帶 X-WC-Webhook-Signature:用 Secret 對原始請求內容做 HMAC-SHA256,結果轉 base64;Django 重算比對,不一致回 401 |
方向 2:Django → WooCommerce(第二期,回寫庫存)
| 項目 | 做法 |
|---|---|
| WooCommerce 端 | 設定 > 進階 > REST API > 新增金鑰,權限選「讀取/寫入」,取得 Consumer Key/Secret |
| Django 端 | pip install woocommerce,呼叫 PUT /wc/v3/products/{id} 更新庫存數量 |
2第二案:多據點營運決策系統
核心不是做 AI 排班,是先把每天手寫的進銷存變成乾淨的資料底座。 沒有累積 3~6 個月資料前,任何預測都是猜的。先做「資料收集 → 報表」,AI/預測留到有資料之後。
屏東海生館(國立海洋生物博物館)先試點:客戶有 3~4 家店面,海生館品項較少、影響最重,跑順了再擴其他店。海生館主賣冰棒(第一案工廠供貨)與冷泡茶等現場泡製飲料。
資料模型
客戶自己把需求想成五張表:產品資料、銷售紀錄、銷售排名(判斷熱銷用)、進貨紀錄、人事排班紀錄。下面是對應到我們規劃的欄位細節版本:
| Model | 說明 |
|---|---|
Store | 店別:名稱、地點類型(入口/出口/園區內/海邊)、營業時間、固定成本 |
Product | 商品:名稱、分類、售價、成本、保存天數、前置準備時間、狀態 |
Employee | 員工:姓名、店別、角色(正職/PT/發券/支援)、薪資方式、時薪 |
DailyReport | 每日回報:店別、日期、天氣(自動)、假日/活動標籤、營收、折扣金額、手寫表照片、POS 照片、狀態 |
DailyItem | 每日品項:回報、商品、期初、進貨/製備、銷量、報廢(數量、原因)、期末 |
Shift | 班次:回報、員工、角色、上班、下班、工時、當日人事成本 |
Calendar | 日曆:日期、假日、活動名稱、影響店別 |
WeatherHistory | 歷史天氣實況:店別(或地區)、日期、最高溫、降雨量、是否下雨——用來回測過去營收跟天氣的關聯 |
WeatherForecast | 天氣預報:店別(或地區)、預報發布時間、預測目標日、降雨機率、預估溫度——用來預測未來、輔助排班 |
每日盤點如何自動算出銷量(會議中的具體範例)
昨晚結存:冷泡茶剩 10 罐 → 今天早上多泡 5 罐(10+5=15)→ 今晚盤點剩 5 罐 → 系統自動算出今天賣了 15−5=10 罐,乘以售價得到當日銷售額。
重點:店員只要「盤點今天剩多少」,不用自己心算賣了多少。 一整天賣很多雜項時要求店員每筆心算會漏會錯,系統用「期初+進貨−期末」自動反推,這是表單設計最重要的原則,也是店長願不願意持續填報的關鍵。
每日填報 → 報表 的資訊流程
填報 UX 原則:昨日數字自動帶入,只改變動的格子;可以先送出、明天補;填完立刻看到今日營收與昨日比較。
推算邏輯(要跟客戶簽認的公式)
- 銷量 = 期初 + 進貨 − 報廢 − 期末
- 營收 = Σ 銷量 × 售價
- 毛利 = 營收 − Σ 銷量 × 成本
- 人事成本 = Σ 工時 × 時薪(月薪制按當月營業日攤)
- 人力成本比 = 人事成本 ÷ 營收
- 每人每小時產值 = 營收 ÷ 總工時
- 報廢率 = 報廢數量 ÷(期初 + 進貨)
- 當日門市邊際貢獻(客戶提出的說法,術語照抄)= 當日營業額 − 銷貨成本 − 人事成本 − 耗損率報廢成本
報表用詞照客戶說法呈現,不要自創新名詞讓客戶要重新對應。
Metabase 使用方式與帳號安全
兩個常見疑慮:直接連資料庫查資料會不會改壞原始資料?報表頁面會不會被外部看到?
- 操作路徑分兩條,不會混在一起:填寫資料走「每日回報表單」,查資料走「Metabase 報表頁面」,使用者沒有管道從報表頁面回頭改到原始資料。
- 給 Metabase 連資料庫的帳號要用唯讀(read-only),不要用有寫入權限的帳號——防止誤改,也讓分析查詢卡住鎖表時影響範圍變小。
- Metabase 不是公開網站,不會被搜尋引擎索引,訪問要先登入。
- 權限依角色分級:老闆看全部店、店長只看自己店、一般員工可能完全看不到報表。
技術棧
與第一案共用 Django + PostgreSQL + Docker 骨架;報表層用 Metabase(自架、免費、開源版),不自己刻圖表元件。天氣資料接中央氣象署開放資料平台 API。