daily-log
2026年1月24日の開発日記
今日はPRレビュー・マージ作業に加え、Codex CLIを使った再帰的レビューによる計画品質の向上、仕訳タブのPhase 1実装など、多岐にわたる作業を行った。
今日やったこと
1. PRレビュー・マージ作業(PR #14)
PR #14のレビューとCopilot指摘への対応を実施した。
Copilot指摘7件の対応:
| # | 指摘内容 | 対応 |
|---|---|---|
| 1 | エラーハンドリング不足 | try-catchを追加 |
| 2 | 型定義の曖昧さ | TypeScript型を明示化 |
| 3 | マジックナンバー | 定数に抽出 |
| 4 | ログ出力の不足 | logger.info/errorを追加 |
| 5 | バリデーション漏れ | 入力チェックを強化 |
| 6 | SQL文字列結合 | パラメータバインドに修正 |
| 7 | 未使用インポート | 削除 |
migrations.py実装追加:
DBスキーマ変更を管理するマイグレーション機能を追加した。
# migrations.py
def get_current_version(conn: Connection) -> int:
"""現在のDBバージョンを取得"""
result = conn.execute(
"SELECT version FROM schema_version ORDER BY version DESC LIMIT 1"
).fetchone()
return result[0] if result else 0
def run_migrations(conn: Connection) -> None:
"""未適用のマイグレーションを実行"""
current = get_current_version(conn)
for version, migration_fn in MIGRATIONS.items():
if version > current:
migration_fn(conn)
conn.execute(
"INSERT INTO schema_version (version, applied_at) VALUES (?, datetime('now'))",
(version,)
)
conn.commit()
2. 勘定科目マスターDB化計画 - Codex再帰レビュー
Codex CLI(GPT-5.2)を使い、勘定科目マスターDB化計画を再帰的にレビューした。
アプローチ:
- 計画ファイルをCodexにレビュー依頼
- 指摘事項を修正
- 再度レビュー依頼
- 10回繰り返し
結果:
| レビュー回 | Critical | High | Medium | Low |
|---|---|---|---|---|
| 1回目 | 3 | 5 | 8 | 12 |
| 3回目 | 1 | 3 | 6 | 8 |
| 5回目 | 0 | 2 | 4 | 6 |
| 7回目 | 0 | 1 | 3 | 4 |
| 10回目 | 0 | 0 | 2 | 3 |
10回のレビューでCritical/Highをすべてゼロにできた。主な改善点:
- エラーリカバリ手順の追加: マイグレーション失敗時のロールバック手順を明記
- 後方互換性の保証: 既存APIのレスポンス形式を維持するアダプターレイヤー追加
- パフォーマンス考慮: インデックス設計とクエリ最適化計画を追記
- テスト計画の具体化: 単体テスト・統合テストのカバレッジ目標を設定
# Codexレビューの実行例
codex review ./plans/account-master-db-plan.md \
--focus "security,performance,error-handling" \
--severity-threshold high
3. 仕訳タブの実装(Phase 1)
仕訳タブのバックエンド・フロントエンド両方を実装し、CSVエクスポート機能まで完成させた。
バックエンド(FastAPI):
# routes/shiwake.py
@router.get("/api/shiwake")
async def get_shiwake_list(
year: int = Query(...),
month: int = Query(...),
status: Optional[str] = Query(None),
limit: int = Query(100),
offset: int = Query(0)
) -> ShiwakeListResponse:
"""仕訳一覧を取得"""
query = """
SELECT
id, date, debit_account, debit_amount,
credit_account, credit_amount, description, status
FROM shiwake
WHERE strftime('%Y', date) = ? AND strftime('%m', date) = ?
"""
params = [str(year), f"{month:02d}"]
if status:
query += " AND status = ?"
params.append(status)
query += " ORDER BY date DESC LIMIT ? OFFSET ?"
params.extend([limit, offset])
rows = conn.execute(query, params).fetchall()
return ShiwakeListResponse(items=[ShiwakeItem(**row) for row in rows])
フロントエンド(Vue.js):
<!-- ShiwakeTab.vue -->
<template>
<div class="shiwake-tab">
<div class="toolbar">
<MonthSelector v-model="selectedMonth" />
<StatusFilter v-model="statusFilter" />
<ExportButton @click="exportCsv" />
</div>
<DataTable
:columns="columns"
:data="shiwakeList"
:loading="isLoading"
@row-click="openDetail"
/>
</div>
</template>
<script setup lang="ts">
const { data: shiwakeList, isLoading } = useShiwakeList({
year: selectedYear,
month: selectedMonth,
status: statusFilter
})
const exportCsv = async () => {
const csv = await generateShiwakeCsv(shiwakeList.value)
downloadFile(csv, `shiwake-${selectedYear.value}-${selectedMonth.value}.csv`)
}
</script>
CSVエクスポート機能:
- 選択した月の仕訳をCSV形式でダウンロード
- 会計ソフトインポート形式に対応(日付、借方、貸方、金額、摘要)
- UTF-8 BOM付きで文字化け対策
4. 日付形式統一計画作成
プロジェクト全体で日付形式をYYYY-MM-DD形式に統一するための計画を作成した。
現状の問題:
- バックエンド:
2026/01/24(スラッシュ区切り) - フロントエンド:
2026-01-24(ハイフン区切り) - DB: 混在(文字列型で保存されている箇所あり)
統一計画:
-- マイグレーションSQL
-- Step 1: 新しいカラムを追加
ALTER TABLE receipts ADD COLUMN date_normalized TEXT;
-- Step 2: データ変換
UPDATE receipts
SET date_normalized =
CASE
WHEN date LIKE '%/%/%' THEN
substr(date, 1, 4) || '-' ||
substr(date, 6, 2) || '-' ||
substr(date, 9, 2)
ELSE date
END;
-- Step 3: 旧カラム削除・リネーム(別マイグレーションで実行)
-- ALTER TABLE receipts DROP COLUMN date;
-- ALTER TABLE receipts RENAME COLUMN date_normalized TO date;
影響範囲:
| テーブル | カラム | 現在の形式 | 件数 |
|---|---|---|---|
| receipts | date | 混在 | 約1,200件 |
| creditcard | transaction_date | YYYY/MM/DD | 約800件 |
| shiwake | date | YYYY-MM-DD | 約500件(正常) |
5. 計画ファイル管理改善
/plansページに依存関係表示と優先順位パネルを追加した。
依存関係表示:
// 計画ファイルのfrontmatter
interface PlanMeta {
title: string
status: 'pending' | 'planned' | 'in_progress' | 'completed' | 'archived'
depends_on?: string[] // 依存する計画ファイルのパス
priority?: 'high' | 'medium' | 'low'
}
// 依存グラフの可視化
const buildDependencyGraph = (plans: Plan[]): DependencyGraph => {
const graph = new Map<string, string[]>()
plans.forEach(plan => {
if (plan.depends_on) {
graph.set(plan.path, plan.depends_on)
}
})
return graph
}
優先順位パネル:
- High: 赤いバッジ、カラム上部に表示
- Medium: 黄色いバッジ
- Low: グレーのバッジ
6. 月次推移表の改善
月次推移表に売上勘定科目を追加し、ドリルダウンパネルを実装した。
売上勘定科目の追加:
// 追加した勘定科目
const SALES_ACCOUNTS = [
{ code: '411', name: '技術売上', category: 'sales' },
{ code: '412', name: '店販売上', category: 'sales' }
]
// 月次推移データの取得
const fetchMonthlyData = async (year: number): Promise<MonthlyData[]> => {
const response = await fetch(`/api/monthly-summary?year=${year}`)
const data = await response.json()
// 売上科目を先頭に表示
return data.sort((a, b) => {
if (a.category === 'sales' && b.category !== 'sales') return -1
if (a.category !== 'sales' && b.category === 'sales') return 1
return a.code.localeCompare(b.code)
})
}
ドリルダウンパネル:
セルをクリックすると、その月・その勘定科目の明細一覧をサイドパネルで表示。
<template>
<div class="drilldown-panel" v-if="selectedCell">
<h3>{{ selectedCell.accountName }} - {{ selectedCell.month }}月</h3>
<table>
<tr v-for="item in drilldownItems" :key="item.id">
<td>{{ item.date }}</td>
<td>{{ item.description }}</td>
<td class="amount">{{ formatCurrency(item.amount) }}</td>
</tr>
</table>
<div class="total">合計: {{ formatCurrency(selectedCell.total) }}</div>
</div>
</template>
今日の学び
- 再帰レビューの効果: Codexに同じ計画を繰り返しレビューさせることで、見落としていた問題点が次々と浮かび上がる。10回程度で収束することが多い
- マイグレーション設計: 日付形式の統一のように、既存データに影響する変更は段階的に行う。新カラム追加 -> データ変換 -> 旧カラム削除の3ステップが安全
- 依存関係の可視化: 計画ファイル間の依存関係を明示することで、着手順序が明確になる。「Aが終わらないとBに着手できない」が一目でわかる
明日やること
- 勘定科目マスターDB化計画の実装開始
- 日付形式統一マイグレーションの実行(receiptsテーブル)
- 仕訳タブPhase 2(インライン編集機能)の設計
関連計画ファイル
| ファイル | ステータス | 内容 |
|---|---|---|
| account-master-db-plan.md | planned | 勘定科目マスターDB化 |
| date-format-unification-plan.md | planned | 日付形式統一 |
| shiwake-tab-phase2-plan.md | pending | 仕訳タブPhase 2 |