Busabase
Busabase is an open-source (MIT) database and workspace for AI agents — data, docs, skills, and apps in one place. Run it locally, self-host it inside your network, or use Busabase Cloud, and turn age
翻訳待ち
No updates detected yet. GitHub releases will appear here.
Loading the full README. The saved excerpt is shown below.
Barefoot Inc Malaysia(Johor Bahru 店舗 / Shopee / Lazada / 自社直販)の販売実績を 1枚の静的 HTML にまとめたダッシュボード。ビルド成果物は index.html 単体で、 外部ライブラリ・CDN・API に一切依存しない。 チャートは手書きの inline SVG。ビルドに Node も npm も不要で、必要なのは Python 3 だけ。 管理画面から Orders をエクスポートした xlsx を用意して、上から順に実行する。 エクスポートは差分で出てくることがある。 2026-08-28 のエクスポートは INV-71 以降だけを 含んでいた。過去分のファイルもあわせて渡すこと。aggregate.py が order_id で統合し、 同じ注文が複数ファイルにあれば後ろのファイルを採用する。 元の xlsx は移動・削除されることがある(9/14 分は Downloads から消え、ごみ箱から取り出した)。 aggregate.py は実行のたびに統合済みの生データを raw_orders.json に保存するので、次回からは 過去分の xlsx の代わりにこれを先頭に渡せばよい。Read the full README ↗
Barefoot Inc Malaysia(Johor Bahru 店舗 / Shopee / Lazada / 自社直販)の販売実績を
1枚の静的 HTML にまとめたダッシュボード。ビルド成果物は index.html 単体で、
外部ライブラリ・CDN・API に一切依存しない。
初回データ: 2026-07-17(開業日)〜 2026-08-21
| ファイル | 役割 |
|---|---|
index.html | ビルド成果物。これ単体で動く。Vercel が配信するのもこれ |
dashboard.html | テンプレート(HTML / CSS / チャート描画)。__PAYLOAD__ にデータが差し込まれる |
payload.json | 集計済みデータ。テンプレートに埋め込まれる |
xlsxread.py | xlsx リーダー(zipfile + xml の標準ライブラリのみ。pandas 不要) |
aggregate.py | 明細行の読み込み・商品分類・注文単位への集約 → agg.json |
build_payload.py | 期間定義に沿った集計 → payload.json |
audit.py | 各集計が全注文を拾えているかの検算 |
parse_sheet.py / reconcile_regions.py / build_regions.py | 販売記録シートとの突合 → regions.json |
build.py | テンプレート + payload → index.html |
チャートは手書きの inline SVG。ビルドに Node も npm も不要で、必要なのは Python 3 だけ。
管理画面から Orders をエクスポートした xlsx を用意して、上から順に実行する。
実績を更新するときは、購入者の地域も毎回やる。 2026-10-19 に Keisuke が指示。エクスポートを取り込んだら、そのまま 販売記録シートを読み直して
regions.jsonまで更新すること。 忘れてもbuild_payload.pyが「地域がありません」と警告を出す。
python aggregate.py "<Orders.xlsx>" ["<追加のOrders.xlsx>" ...] && python build_payload.py && python build.py
エクスポートは差分で出てくることがある。 2026-08-28 のエクスポートは INV-71 以降だけを
含んでいた。過去分のファイルもあわせて渡すこと。aggregate.py が order_id で統合し、
同じ注文が複数ファイルにあれば後ろのファイルを採用する。
元の xlsx は移動・削除されることがある(9/14 分は Downloads から消え、ごみ箱から取り出した)。
aggregate.py は実行のたびに統合済みの生データを raw_orders.json に保存するので、次回からは
過去分の xlsx の代わりにこれを先頭に渡せばよい。
python aggregate.py raw_orders.json "<新しいOrders.xlsx>" && python build_payload.py && python build.py
raw_orders.json は顧客名・電話・住所を含む。.gitignore 済みで、リポジトリは public なので
絶対にコミットしないこと。
書式が外れたセルは日付が Excel のシリアル値(46261.5090 など)で降ってくるため、
fix_date() で文字列に戻している。起点は Excel 標準の 1899-12-30。
order_id 103-110 の10行を実データと突き合わせて日時とも一致を確認済み(2026-08-31)。
起点を1日ずらすと日付が全て翌日になるので、変えないこと。
同じ注文が複数ファイルに入っていても order_id で1件に寄せるため、同じファイルを
何度渡しても二重計上にはならない。
環境変数 ORDERS_XLSX でも指定できる(複数は ; 区切り)。
build_payload.py は卸売を含む payload.json と、卸売を除いた payload_retail.json の2つを
書き出す(後者は同じスクリプトを EXCLUDE_WH=1 で自動的に再実行して作る)。画面の各セクションの
見出し下にある「卸売を除く」チェックは、そのセクションだけ後者のデータで描き直す。チェック状態は
ブラウザ(localStorage)に保存される。客単価はチェックに関係なく常に卸売を除いた値。
index.html を commit して push すれば Vercel が自動で再デプロイする。
各集計が全注文を拾えているかは audit.py で検算する。日次・週別・月別・チャネル・曜日・
決済・地域・州・モデル・サイズ・カラー・明細の合計を、売上の 純売上/注文数/点数 と突き合わせ、
ズレがあれば内容を出して exit 1 する。ビルドのたびに回す。
python build_payload.py && python audit.py && python build.py
過去に見つかった取りこぼし: モデル別に送料の行が1点として混ざっていた / OLN0001 が商品マスタに 無くカラーと数量が落ちていた / モデル別のグラフと表に卸売の列が無かった。
モデル・カラー・サイズ別の実績を Excel にまとめるときは build_sku_xlsx.py を回す。
ダッシュボードの生成には関わらない補助スクリプトで、ここだけ openpyxl を使う。
python build_sku_xlsx.py # 商品別実績.xlsx(*.xlsx は gitignore 済み)
シートは 概要(モデル別) / モデル×カラー / SKU明細 / サイズ別マトリクス の4枚。
売上の列が2本あるのは、SiteGiant のエクスポートが明細行に定価を入れ、値引きを注文合計側でしか 引いていないため。明細をそのまま足すと純売上より多くなる(2026-10-11 時点で +RM3,657.39)。 「売上(定価)」は明細どおりの額、「売上(実売)」は注文合計を明細金額の比で按分した額で、後者は 全体の純売上と一致する。ダッシュボードのモデル別売上は定価ベースのまま。
エクスポートは注文のあった日しか教えてくれないので、最終日の翻日以降が
「売上ゼロ」なのか「まだデータが無い」のか区別できない。build_payload.py の ASOF に
「この日まで確認済み」を入れると、その日までを対象期間にして日次グラフにゼロの印を出す。
データの最終日が ASOF より後ならデータ側を採るので、更新を忘れても期間が短くはならない。
環境変数 ASOF=2026-09-24 でも指定できる。
build_payload.py の WEEKS / MONTHS を編集する。開業週だけ 7/17(金)〜7/26(日) の
10日間で、以降は月曜起点の週次。週を足すときは WEEKS に1行追加するだけ。
WEEKS = [
('W1', '開業週', '2026-07-17', '2026-07-26'),
('W2', '第2週', '2026-07-27', '2026-08-02'),
...
]
order_id 134 / 161 のように、どのエクスポートにも現れない注文がある。管理画面の注文詳細から
aggregate.py の MANUAL_ORDERS に書き起こす。明細が複数ある注文は lines=[_ml(...), ...] で書く。
161 は画面に明細単価が出ていなかったため注文合計を点数で均等割りしており、モデル別の金額だけは推定値。後日エクスポートに現れたらそちらが優先
される(手動分は order_id が未登録のときだけ取り込む)ので、消さずに残しておいてよい。
元データの payment_method は表記ゆれを含めて 15 種類あるので、build_payload.py の PAYGRP で QR決済 / カード / 現金 / 銀行振込・ネットバンキング にまとめている。
画面では大分類を出し、行をクリックすると内訳が開く。未登録の決済方法は「その他・未記録」に
落ち、集計時に警告が出るので PAYGRP に足すこと。Apple Pay は店頭の非接触カード決済とみて
カードに入れている。
SiteGiant には購入者の地域が無いので、Google Drive の
Sales record for Malaysia.xlsx(店舗側が手でつけている台帳)の From 欄 を
日付・チャネル・金額・商品・時刻で突き合わせて注文に紐づけている。
実績を更新したら毎回これも回す(注文は増えるのに地域が古いままだと、
地域別から直近の売上が丸ごと漏れる)。
Drive のファイルID: 1vnEY7dHckpuRsJ_5p30d-uc0HwDtHNHT
(月ごとにシートが分かれている。読むときは全シートが1本のテキストで返る)
作業ファイルの置き場: C:/Users/Barefootinc TH/Downloads/Sales Records/MY/_region_work
顧客名・住所を含むのでリポジトリには置かない。以前はセッションの作業フォルダに置いていたが、
フォルダが変わると sheet_raw.txt を全月分書き直すことになるため 2026-11-09 に移した。
W="C:/Users/Barefootinc TH/Downloads/Sales Records/MY/_region_work"
# 1. シートの中身を sheet_raw.txt に落とす(Drive から取得)
# 2. 行に切り直す → sheet.json
SHEET_WORKDIR="$W" python parse_sheet.py
# 3. 取込データと突合 → region_map.json、未結合の一覧を標準出力へ
SHEET_WORKDIR="$W" python reconcile_regions.py
# 4. 公開用に order_id と地域だけ抜き出す → regions.json
SHEET_WORKDIR="$W" python build_regions.py
手順 1 の書き方は、既存の sheet_raw.txt に新しい行を差し込む。シートの末尾には
27,,,,,,,,,,,,,, のような空行が並んでいるので、そこを実データで置き換え、
最後の ,TOTAL,... 行も新しい値に直す。ファイル全体が改行なしの1行になっている
のが前提(parse_sheet.py が 15 セル単位で切り直す)。
列数はシートごとに違う。Nov2026 から備考列が1本増えて 16 列になった。parse_sheet.py は
見出し行の空セル数からシートごとに列数を数えるので、この後列が増えてもそのまま負える。
使うのは先頭15列だけで、16列目以降(備考)は落とす。
シートの記述と SiteGiant が食い違うときは SiteGiant を正 として、シートからは From 欄(地域)だけを取る。シート側の金額はマーケットプレイスの手数料引き後だったり、 色・サイズの書き違いがあったりする。
自動で突合できない行は reconcile_regions.py の MANUAL に理由付きで書く。
「シート側の未結合 0 行」になるまでやる。
sheet_raw.txt / sheet.json / region_map.json / unmatched.json は顧客名・住所・電話を
含むので .gitignore 済み。リポジトリに入れるのは regions.json(order_id と地域のみ。
従業員・親族の名前は「関係者」にまとめて落とす)だけ。
突合は自動でつかないものだけ reconcile_regions.py の MANUAL に理由付きで書く。
マーケットプレイスはシートが手取り額、SiteGiant が注文合計なので金額が数%ずれる。
同額の注文が同じ日に並ぶと取り違えるため、モデルとサイズも点数に入れている。
地域は国籍ではない。 From 欄は店頭で聞き取った自己申告で、国籍の列はシートに無い。
オーナーが「これは実績に入れない」と判断した伝票は aggregate.py の VOID に理由付きで書く。
bucket が void になり、test と同じく全集計・未入金台帳・地域突合から外れる。
キャンセルバケツに入れないのは、失注として数えてしまうから。起こし直しやプレゼントは 「売れなかった」わけではないので、キャンセル率の分母からも外している。
現在の登録:
This is the beginning of the README. Read the rest at the original. Read the full README ↗