| title | 電商平台 ERP & 報表系統 |
|---|---|
| emoji | 📊 |
| colorFrom | blue |
| colorTo | purple |
| sdk | streamlit |
| sdk_version | 1.54.0 |
| app_file | app.py |
| pinned | false |
一站式電商進銷存管理系統,整合蝦皮、露天、官網 (EasyStore)、MO店等多平台訂單資料,提供即時庫存追蹤、營收報表與數據分析。
經營多平台電商最痛苦的是什麼?每天打開 4 個後台、下載 4 份報表、手動對帳到眼花。
這套系統解決的核心問題:
- 多平台訂單整合:一鍵匯入蝦皮、露天、官網、MO店訂單,自動轉換格式
- 即時庫存追蹤:入庫、出庫、組合商品自動扣庫,庫存異常一目瞭然
- 成本與利潤計算:自動計算商品成本、平台手續費、物流費用、淨利
- 日報表 / 月報表:退貨、未取貨、部份退貨等複雜情境全自動處理
- 數據圖表分析:營收趨勢、平台佔比、單品銷售排行,輔助經營決策
| 類別 | 技術 |
|---|---|
| 語言 | Python 3.10+ |
| 前端框架 | Streamlit |
| 資料處理 | Pandas, NumPy |
| 視覺化 | Plotly |
| 檔案格式 | Excel (openpyxl) |
| 部署平台 | Hugging Face Spaces / Streamlit Community Cloud |
| 首頁 | 日報表 | 數據圖表 |
|---|---|---|
![]() |
![]() |
![]() |
| 單品銷售查詢 | 銷售排行 |
|---|---|
![]() |
![]() |
git clone https://github.com/lee2nd/e-commerce-ERP-system-streamlit-app.git
cd e-commerce-ERP-system-streamlit-apppython -m venv .venv
# Windows
.venv\Scripts\activate
# macOS / Linux
source .venv/bin/activatepip install -r requirements.txtstreamlit run app.py應用程式將在 http://localhost:8501 啟動。
- Fork 本專案至你的 GitHub
- 在 Hugging Face Spaces 建立新 Space
- 選擇 Streamlit SDK,連結你的 GitHub repo
- 等待自動部署完成
- 刪除雅虎平台,新增 mo 店 / easystore
- 刪除分類 A/B 報表,統一合併為一個報表
- 入庫人可以刪掉
- 出庫的出庫人可刪除 column
- 導出日報表不分 AB
- 新增商品明細的「主貨號」和「貨號」
- 入庫多一欄主貨號(概念等同目前原本的貨號)
- 新的貨號可以參考蝦皮
- 對照表依照「貨號」自動匹配商品
- 對齊最新的 columns
- 解決實際環境 data 存下路徑的問題,用 Streamlit 的 Manage App 去觀察(目前 app 重開,資料就會洗掉了)
- 名稱統一改 MO 店
- 入庫合併同商品同日期的資料
- 入庫設定 user 可以刪除資料
- 對照表:入庫品名用貨號去自動匹配,不由人工輸入
- 入庫品名若未匹配到,標註「未匹配」
- 出庫若未匹配到,直接沿用原報表名稱
- 庫存明細若未匹配到,則不納入計算
- 庫存平均成本根據入庫平均成本連動變動
- 庫存明細的規格預設按照尺碼大小排序:XS>S>M>L>XL>2XL>3XL>4XL>5XL
-
入庫貨號重複防呆(貨號相同但品名/規格不同)
- Excel 上傳:檔案內部或與現有資料有貨號衝突時,顯示衝突明細並封鎖匯入按鈕
- 網頁手動新增:若新增的貨號與現有資料品名/規格不符,顯示衝突明細並阻止新增
-
庫存明細排序修正
- 排序邏輯改為:主貨號 → 顏色(規格去掉尺碼的部分)→ 尺碼大小
- 例如 HFE03002:黑色M > 黑色L > 黑色XL > 米咖色M > 米咖色L > 米咖色XL
-
新增「組合貨號」功能
- 匯入資料新增第三個分頁「🔗 組合貨號」,支援新增/刪除/清除組合貨號
- 組合貨號由多組原料貨號 × 數量組成,例如:
YGK03002-RDL30-RR-DIY=YGJ03002-RDL×30+YGK03002-RR×1 - 資料存在
data/和data_dev/的組合貨號.xlsx(欄位:組合貨號、原料貨號、原料數量) - 庫存明細:出庫中的組合貨號會自動展開為原料貨號扣庫存
- 對照表:組合貨號自動匹配,入庫品名顯示為「組合:原料A×數量+原料B×數量」
- 導出出庫:組合貨號在出庫映射中正確識別,不再標為未匹配
- 日報表:組合貨號成本 = 各原料成本 × 原料數量之總和
-
日報表改為
data_editor可編輯- 欄位設定:日期(DateColumn)、訂單狀態(SelectboxColumn 下拉)、金額欄位(NumberColumn 格式化)
- 訂單編號、平台欄位設為唯讀
- 新增「💾 儲存修改」按鈕,將手動修改寫回 Excel
- 重新產生日報表時,以「訂單編號 + 日期」為 key,保留已存在的手動修改,只新增全新訂單
-
日報表訂單狀態邏輯微調
- 蝦皮
- 遺失賠償:
不成立原因含「遺失」關鍵字 → 狀態=遺失賠償,計算同已完成 - 退貨:
退貨 / 退款狀態非空 → 狀態=退貨 - 其他不成立原因(無「遺失」)→ 跳過(取消/無效訂單)
- 遺失賠償:
- 露天:
交易狀況含「已領取退貨」→ 狀態=未取貨 - 官網:Remark 含「cancel / 取消訂購」→ 未取貨;Financial Status 含「refund」→ 退貨
- 未取貨訂單:只計實際運費為成本,折扣優惠、商品成本、手續費等一律歸零
- 蝦皮
-
未匹配標記寫入備註欄位
- 重新產生日報表時,若該訂單所有商品均未在入庫中匹配到,備註欄自動填入「未匹配」
- 日報表頁面新增「未匹配篩選」radio(全部 / 未匹配 / 已匹配)
- 舊資料自動補寫:頁面載入時檢查备註空白且商品名稱空或商品成本=0 的列,自動回填「未匹配」並存檔
-
露天手續費計算修正
- 成交手續費:單價 × 數量 × 3%,四捨五入,最低 1 元,最高 400 元
- 其他服務費:單價 × 數量 × 5%,四捨五入,最低 1 元,最高 300 元
- 金流與系統處理費:(結帳總金額 + 露天折扣碼金額) × 1.5%,四捨五入,最低 1 元,無上限
-
日報表修改成本後,總成本與淨利自動重算
- 點擊「💾 儲存修改」後,自動依公式重算篩選範圍內所有列的總成本與淨利
- 總成本 = 商品成本+折扣優惠+未取貨/退貨運費+成交手續費+其他服務費+金流與系統處理費+發票處理費+其他費用
- 淨利 = 訂單金額 − 總成本
-
入庫分批上傳資料保留修正
- 原本第二次上傳會整份覆蓋,舊資料消失
- 修正為以「貨號 + 入庫日期」為 PK,已存在則保留舊資料,只新增未出現過的列
- 匯入成功後顯示實際新增筆數
-
未匹配判斷邏輯勘誤
- 未匹配的唯一依據:貨號在入庫中找不到(
備註欄位含「未匹配」) - 移除舊邏輯中用
商品成本 == 0判斷未匹配的錯誤(退貨訂單商品成本為 0 是正確的,不應標為未匹配) - 頁面載入時自動修正:退貨/未取貨且商品名稱有值的列,若被誤標「未匹配」會自動清除
- 未匹配的唯一依據:貨號在入庫中找不到(
-
導出出庫新增匹配狀態欄位與篩選
匹配狀態欄位顯示「已匹配」或「未匹配」- 新增 Radio 篩選器(全部 / 已匹配 / 未匹配)
- 欄位順序調整:
平台移至最後一欄
-
物流處理費(運費差額)正負號修正
- 物流處理費作為費用計入總成本,正負方向需與成本邏輯一致
- 官網原公式:
實際運費支出 − 買家支付運費,修正為:買家支付運費 − 實際運費支出 - 露天公式維持:
實際運費支出 − 買家支付運費(已正確,不變)
-
導出出庫新增平台與日期範圍篩選
- 篩選器列改為三欄:匹配狀態(Radio)、平台(下拉選單)、日期範圍(日期區間選擇器)
- 平台選項依實際資料動態生成,預設顯示全部;日期區間預設為資料最早至最晚日期
-
日報表「儲存修改」時物流處理費連動重算
- 修改「實際運費支出」後,點擊儲存時自動依平台公式重算「物流處理費(運費差額)」
- 露天:
max(0, 實際運費支出 − 買家支付運費) - 官網:
max(0, 買家支付運費 − 實際運費支出)
-
官網訂單狀態判斷邏輯更新
- 未出貨,取消訂單:
Fulfillment Service為空 且Fulfillment Status= "Restocked" / "Unfulfilled" → 跳過不列出 - 已出貨,退貨:
Fulfillment Service不為空 且Refunded Amount≠ 0 → 狀態=退貨 - 已出貨,未取貨:
Fulfillment Service不為空 且(Fulfillment Status= "Restocked"/"Unfulfilled" 或 最後一筆Transaction status= "Pending")→ 狀態=未取貨 Transaction status以同訂單最後一列非空值為準(付款紀錄以最後一筆判定)
- 未出貨,取消訂單:
-
蝦皮部份退貨訂單拆成兩行顯示
- 原本只顯示保留商品(有效數量),退貨商品直接略過
- 更新後:拆為兩筆—第一筆「已完成」(保留商品,含一般費用)、第二筆「退貨」(退回商品,只計退貨運費)
- 兩筆備註均標示「部份退貨」,可與整單退貨區分
- 若未匹配,備註格式為「未匹配、部份退貨」,不影響現有未匹配篩選邏輯
- 重新產生日報表時,以「
訂單編號 + 日期」→「訂單編號 + 日期 + 訂單狀態」(3/25更新)為 key,保留已存在的手動修改,只新增全新訂單
-
大資料量
st.dataframe效能優化utils/data_manager.py主要 load 函式加上@st.cache_data(load_storage、load_platform_orders、load_compare_table、load_delivery、load_inventory_details),資料只在首次載入時讀檔,重新渲染不重複 I/O- 對應的 save / clear 函式呼叫
.clear()確保寫入後下一次 rerun 拿到最新資料
-
分頁顯示(每頁 500 筆)
- 適用頁面:匯入資料(入庫、各平台訂單)、對照表、導出出庫、庫存明細
- 頁碼改為
st.selectbox下拉選單,格式:「第 X 頁(共 N 頁)」 - 搜尋 / 篩選作用於完整資料集,分頁只影響顯示範圍
-
全表下載
- 各表格新增「⬇️ 下載」按鈕,下載對象為篩選後的完整資料(CSV UTF-8 BOM),非當頁切片
-
月報表
-
有儲存修改功能的頁面顯示最後修改時間
-
一鍵下載所有 data / data_dev 資料 & 可上傳覆蓋
-
導出出庫增加「訂單編號」欄位
-
月報表「其他費用(一)」無法修改
- 修正為可編輯欄位
-
蝦皮報表折扣優惠計入修正
- 折扣優惠:
[Q_賣家負擔優惠券]+[R_賣家負擔蝦幣回饋券] - 蝦皮報表欄位名稱近期有變動,原為
[Q_賣場優惠券]、[R_賣家蝦幣回饋券]
- 折扣優惠:
-
數據圖表優化
- 修正 Arrow 序列化錯誤(年度平均訂單量欄位混合型別)
- 圖表顏色調整:蝦皮橘色、露天藍色、官網綠色
-
單品銷售查詢 & 銷售排行
- 移除
_NULL_LIKE中的"tbd"判斷
- 移除
-
程式碼清理
- 刪除未使用的變數與函式
- 刪除未使用的套件(
xlrd、beautifulsoup4、html5lib)
-
日報表儲存後資料異常修正
- 修正物流處理費(運費差額)重算公式與
calculators.py不一致的問題 - 露天:
-max(0, 買家支付運費 − 實際運費支出)(≤0) - 官網:
實際運費支出 − 買家支付運費(可正可負)
- 修正物流處理費(運費差額)重算公式與
-
時區修正(Streamlit Cloud UTC+0 → 台灣時間 UTC+8)
- 問題:
datetime.now()與pd.Timestamp.now()在 Streamlit Cloud(UTC+0)環境下會顯示 UTC 時間,比台灣時間少 8 小時 - 修正方式:所有產生「最後儲存時間」的呼叫改用
TZ_TAIPEI = timezone(timedelta(hours=8)),即datetime.now(tz=TZ_TAIPEI) - 無需安裝額外套件(使用標準庫
datetime.timezone+datetime.timedelta) - 影響檔案:
app.py、pages/1_📥_匯入資料.py、pages/2_📋_對照表.py、pages/3_📦_導出出庫.py、pages/4_🔎_庫存明細.py、pages/5_📊_日報表.py、pages/6_📈_月報表.py
- 問題:
-
數值型態降級(dtype downcast)
utils/data_manager.py新增_optimize_dtypes():int64 降為最小可用整數型態、float64 降為 float32- 所有 load 函式回傳前自動套用,節省記憶體
-
全面加入
@st.cache_data(ttl=300)- 原本部分 load 函式已有 cache,本次補齊所有遺漏(
load_daily_report、load_combo_sku) - TTL = 300 秒,避免長時間不重新載入
- 原本部分 load 函式已有 cache,本次補齊所有遺漏(
-
Session state 大型暫存清理
app.py:ZIP 下載後主動清除個別檔案快取、個別檔案下載時清除 ZIP 快取- 避免 session_state 堆積過多 bytes 導致 OOM
-
月報表新增「營登租金」欄位
- 手動可編輯,預設值 $1,155
- 計入「總成本」公式
-
月報表新增「備註」欄位
- 文字欄位,可輸入任意備註內容
- 更新月報表時自動保留既有備註
-
數據圖表新增薪資費用、廣告費用合計趨勢線
- 圖表新增兩條虛線:薪資費用(橘色)、廣告費用合計(紫色),掛右軸
- 年度摘要指標新增「薪資費用」、「廣告費用合計」區塊
-
數據圖表「總淨利額」改從月報表取得
- 原本從日報表直接計算(
訂單金額 − 總成本),未包含月報表手動費用 - 修正為讀取月報表的「淨利」欄位,確保與月報表一致
- 原本從日報表直接計算(
-
數據圖表「年度平均訂單量」分母修正
- 原本固定除以 12,年中時數值偏低
- 修正為除以「實際有訂單資料的月份數」,更準確反映月均量
- 只有有月份的 "年度平均訂單量" 才顯示,其他的月份放 0
-
pandas FutureWarning 修正
數據圖表頁面pd.concat合計列前先.dropna(axis=1, how="all")避免全空欄警告
-
修正 hover 數值出現2次問題
-
導出出庫:官網訂單編號修正
- 官網原始資料使用
Order Name欄位,但出庫取值時統一用訂單編號,導致官網訂單編號為空 - 修正
_get_order_data:官網改為讀取Order Name欄位
- 導出出庫:平台篩選改為多選
- 原本為單選下拉選單(
st.selectbox),改為多選(st.multiselect) - 預設選取所有平台,可自由勾選/取消
- 數據圖表:年度摘要指標字體縮小
- 總營業額等 metric 數值過長會被截斷顯示
... - 注入自訂 CSS 將 metric 數值字體縮小為
1.2rem,避免溢位截斷
- 露天未取貨訂單運費欄位修正
- 原本
買家支付運費、平台補助運費、實際運費支出、物流處理費(運費差額)在未取貨時仍帶入原值,導致總成本計算偏差 - 修正:未取貨時以上四欄歸零,僅保留
未取貨/退貨運費= 實際運費支出
- 導出出庫:平台多選全取消時顯示空表
- 原本全部取消勾選時,篩選邏輯因空 list 判斷失效,仍顯示所有資料
- 修正:改為無條件套用
isin(plat_filter),空 list 時正確回傳空結果
- 蝦皮訂單包含未匹配商品時,日報表未顯示「未匹配」
- 問題:蝦皮訂單編號
2505283XEMY4EP含 5 個商品(4 個已匹配、1 個未匹配),對照表及出庫正確顯示未匹配,但日報表未標註 - 原因:日報表依訂單分組後使用
any(r["_matched"])判斷,只要有任一商品匹配即不標記「未匹配」 - 修正:改為
all(r["_matched"]),只有全部商品皆匹配才算已匹配;任一商品未匹配即在備註標記「未匹配」 - 影響範圍:
_process_shopee(部份退貨/整單退貨/已完成)、_process_ruten、_process_easystore
- 對照表及出庫未顯示未匹配,但日報表正常顯示(與 Bug 7 相反)
- 問題:官網訂單
#114621、#117136與蝦皮訂單250513RDPQHFS0的商品,對照表及出庫顯示為已匹配,但日報表正確顯示未匹配 - 原因 1(對照表 SKU 過時):
auto_match_compare_table使用drop_duplicates(keep="first"),保留最早出現的 SKU;如平台上的 SKU 已變更(如HME03001-GY-L→TB300001-灰色-L-新標),對照表仍沿用舊 SKU(在入庫中存在),導致誤判為已匹配 - 修正 1:改為
drop_duplicates(keep="last"),使用最新訂單的 SKU 重新比對入庫 - 原因 2(出庫官網 ffill 跨訂單污染):
_filter_easystore對Remark、Fulfillment Service、Fulfillment Status做整表ffill(),前一筆訂單的「取消訂購」或「Restocked」狀態可能洩漏至後續訂單,導致有效訂單被錯誤過濾 - 修正 2:改為先
ffill("Order Name"),再groupby("Order Name").ffill()避免跨訂單污染
- 露天已取消訂單仍出現在日報表與出庫中
- 問題:露天訂單
25112338114612,訂單狀態= 「已取消」,但日報表仍列出為「已完成」,出庫也包含該筆 - 原因:
_process_ruten僅檢查交易狀況欄位是否含「取消」,但此訂單的交易狀況= 「請於11/27前完成出貨」(不含「取消」),而訂單狀態= 「已取消」未被檢查 - 修正(日報表):
_process_ruten新增訂單狀態欄位的「取消」關鍵字檢查 - 修正(出庫):
_filter_ruten新增訂單狀態含「取消」的過濾條件
- 首頁新增記憶體監控
- 顯示三項指標:本程序 RSS(MB)、佔系統記憶體(%)、佔 Cloud 上限 1 GB(%)
- 使用量超過 80% 時顯示警告
- 新增
psutil依賴
- 程式碼清理
- 移除未使用的變數:
app.py中的_sys_mem、日報表.py中的_PLAT_COLORS - 移除未使用的套件:
requirements.txt中的lxml(程式碼中無任何引用)
- 防止 Hugging Face Spaces 閒置斷線
- 問題:Hugging Face Spaces 負載平衡器在偵測到 WebSocket 閒置一段時間後,會強制切斷連線,導致網頁反灰或顯示斷線
- 解法 A(Keep-alive):
requirements.txt加入streamlit-autorefresh;app.py在set_page_config後呼叫st_autorefresh(interval=3 * 60 * 1000, key="keep_alive"),每 3 分鐘在背景發送訊號保持連線 - 解法 B(停用 WebSocket 壓縮):新增
.streamlit/config.toml,設定enableWebsocketCompression = false,避免代理伺服器誤判連線狀態
- UI 優化更新
- 視覺風格升級:導入全域 CSS 樣式集(
utils/styles.py),優化按鈕、卡片、標籤頁與滾動條視覺效果,透過apply_global_styles()套用至所有頁面。 - 介面一致性:統一各頁面的標題層級與間距,提升操作體驗。
- 主題配色:自定義
.streamlit/config.toml主題配色,採用更專業的深藍(#2563EB)與簡潔白背景。
- 首頁新增一鍵還原與一鍵全刪功能
- 一鍵上傳 ZIP 還原:可上傳先前下載的備份 ZIP,自動解壓並將所有
.xlsx覆蓋還原至data/目錄(本地或雲端皆支援)。 - 一鍵刪除全部資料:刪除
data/目錄下所有.xlsx檔案;需手動輸入「確認刪除」才能啟用按鈕,防止誤操作。 - 操作結果訊息改為就近顯示:各功能按鈕的執行結果(成功/失敗)顯示在該區塊附近,不再跳到頁面頂部。
-
顯示隱藏的項目的 .git folder 刪掉
-
先把 github 上面的 data folder 最新資料下載下來,放在本地專案的 data 資料夾中(極重要)
-
重新初始化一個乾淨的 Git git init git add . git commit -m "Clean history without Excel files"
-
把分支名稱設定為 main git branch -M main
-
重新連上你的 GitHub git remote add origin https://github.com/lee2nd/e-commerce-ERP-system-streamlit-app.git
-
強制覆蓋 GitHub 上的舊紀錄 (加上 -f) git push -f origin main
-
publish branch main 到 GitHub
- 存放 2~3 年的資料
- 入庫 : 1000+
- 蝦皮 : 5000 ~ 8000 / 每月
- MOMO & 露天 & 官網 : 100-300 / 每月
| 情境 | 日報表 | 庫存 / 出庫 |
|---|---|---|
| 未取貨(#144485) | 需列出,未取貨/退貨運費 固定 $65 |
不扣庫存、不計入出庫 |
| 出貨前取消(#143166) | 可直接刪除,不列出 | 不扣庫存、不計入出庫 |
| 情境 | 日報表 | 庫存 / 出庫 |
|---|---|---|
| 未取貨(260101T9JAVCHM) | 可直接刪除,不列出 | 不扣庫存、不計入出庫 |
| 出貨前取消(260101U289VMH1) | 可直接刪除,不列出 | 不扣庫存、不計入出庫 |
| 整單退貨(260101UQC2FXC5) | 需列出,退貨運費 需列出(即使為 $0) |
不扣庫存、不計入出庫 |
| 部份退貨(260101VGTQ5TTD) | 需列出,退貨運費 需列出(即使為 $0);AI欄_數量與AJ欄_退貨數量的差額為實際退貨數量,無差額代表該項全退 |
退貨部份不扣庫存、不計入出庫;實際成交數量計入庫存與出庫。例:HME03002-ST-DN-XL 購買3退2 → 計入庫存/出庫 ×1 |
| 部份退貨(260111RDUTKB7X) | 需列出,退貨運費 需列出(即使為 $0);未退貨品項的「退貨/退款狀態」欄位為空白 |
退貨品項不扣庫存;未退貨品項計入庫存與出庫。例:HFA02001-TN-BK-M 全退,HFF02001-SK-140G 保留 → 計入庫存/出庫 ×1 |
| 情境 | 日報表 | 庫存 / 出庫 |
|---|---|---|
| 買家未取貨 | 需列出,未取貨/退貨運費 依該筆訂單的付款方式(D欄_付款方式)計入 |
不扣庫存、不計入出庫 |
露天運費對照:
- 7-11 取貨 → $60
- 全家取貨 → $60
- OK 超商取貨 → $60
- 萊爾富取貨 → $50
- 中華郵政 → $65
- MOMO: 87150737
- 蝦皮: 030812




