>cat/works/attendance-bot/README.md

title: Discord 出退勤bot — 勤怠打刻+管理ダッシュボード
year: 2026
role: Design / Full Stack
category: 受託
stack: Cloudflare WorkersHonoD1Discord APIGrok APITypeScript

普段の業務連絡で使っている Discord 上だけで出退勤を打刻でき、勤怠の集計・訂正・出力は Web 管理ダッシュボードで行う勤怠管理システムです。打刻ボットと管理ダッシュボードを同一の Cloudflare Workers で配信し、データは D1(SQLite 互換)に保存。独自サーバーを持たずに運用できる構成にしました。

打刻は Discord のスラッシュコマンドで完結し、返信はすべて ephemeral(本人のみ表示)。時刻指定なしで定時8時間を一発記録できる /teiji と、残業を時間数で上乗せする /zangyo2本を主軸に、内部は始業/終業のペアで保存します。閲覧・訂正・削除・追加・出力は管理ダッシュボードに集約しています。

コマンド内容
/teiji勤務を記録(時刻なし=定時8時間/startend 指定でその区間)
/zangyo残業を時間数で上乗せ(今日ぶん・複数回で積み増し)
/tag今日の勤務に現場名などのメモを付ける
/dashboard管理ダッシュボードのリンクを表示
/ask今月の勤怠を AI(Grok)が要約して回答

管理ダッシュボード

同じ Worker が配信するサーバー HTML(ビルド工程なし・自動エスケープ)。認証は Discord OAuth2 + 署名 Cookie セッションで、独自ドメインなし*.workers.dev のまま)でも動きます。認可はルートごとに分け、管理者は全員分の閲覧・編集・チーム出力、メンバーは自分の打刻だけを訂正・削除・追加できる所有チェック付きです。月ごとの稼働合計、日別の稼働をマス目で可視化する勤怠ヒートマップ(草)、CSV/JSON 出力を備え、出力データはそのまま出勤表・請求書づくりに渡せます。

設計上の工夫

  • 時刻の扱い:保存は UTC ISO8601、表示・集計の境界でのみ JST に変換。出勤状態(未出勤/勤務中)は「日付フィルタなしの最終ログ」から導出するため、日跨ぎや打刻の押し忘れに強い。
  • 集計と AI の分離/ask SQL で数値を確定集計してから、Grok には言い回しだけを依頼する。金額や時間の計算を LLM に渡さないので、集計値が崩れない。
  • 記録の安全性:打刻ログ自体は append-only。ミスの恒久修正が運用上の要だったため、ダッシュボードからの訂正・削除・追加のみ UPDATE / DELETE / INSERT直接行う設計にしています。