MAS-121: 24タブCAPEX特有の償却・借入条件マスタ化
概要
| 項目 | 値 |
|---|---|
| 案件ID | MAS-121 |
| カテゴリ | DDL・マスタ設計 |
| Phase | P2 |
| 優先度 | ★★ |
| 所要時間目安 | 3-4時間 |
| 対象ファイル | 100_config/101_sys_config.js, 200_data/202_repository.js, 400_domain/403_rpa_capex.js, 000_infra/002_constants.js, 800_ops/809_migration_s49_capex_master.js(新規) |
| 前提案件 | MAS-119(22タブ人件費料率マスタ化、マイグレーション 809 枠の連動確認)、MAS-120(12マスタ標準決済条件 — 決済手段連携は本案件スコープ外) |
目的
24_bud_capex_loan の CPX レコードで手入力されている 償却月数 / 返済月数 / 月額返済額 / 月額支払利息 / 頭金分割回数 / 返済日 を、①科目マスタ(11_mst_account) の「標準償却月数」列 と ②新規マスタ 19_mst_loan_pattern の 2 系統のマスタから自動補完する。400_domain/403_rpa_capex.js の RPA は JOIN 方式へ改修するが、32_wrk_invoice への生成フォーマットは現状互換を維持する。
現在のコード
① 400_domain/403_rpa_capex.js L87-93: ハードコードではないが「行から直接パース」している箇所
const depMonths = col['償却月数'] !== -1 ? (parseInt(String(row[col['償却月数']]), 10) || 0) : 0;
const debtAccount = col['負債科目'] !== -1 ? String(row[col['負債科目']]).trim() : '';
const loanAmount = col['借入金額'] !== -1 ? (Number(row[col['借入金額']]) || 0) : 0;
const repayMonths = col['返済月数'] !== -1 ? (parseInt(String(row[col['返済月数']]), 10) || 0) : 0;
const monthlyRepay = col['月額返済額'] !== -1 ? (Number(row[col['月額返済額']]) || 0) : 0;
const firstRepay = col['初回返済額'] !== -1 ? (Number(row[col['初回返済額']]) || 0) : 0;
const monthlyInterest = col['月額支払利息'] !== -1 ? (Number(row[col['月額支払利息']]) || 0) : 0;
24タブ上で人間が「償却月数 60」「月額返済額 120000」等を手入力するフォーマット依存。L212 の downSplits(頭金分割回数)、L218 / L309 の downDayRaw / repayDayRaw(返済日)、L216 / L310 の downLagStr / capLagStr(決済ラグ) も同様に行入力依存。
② 100_config/101_sys_config.js L644 / L658: 既存 DDL スキーマ
'MST_ACCT': { headers: ["有効フラグ","主科目コード","諸表区分","大分類","表示区分","表示科目","正式科目名","固変区分","デフォルト税率","科目名","説明"], color: "#666666" },
...
'BUD_CAPEX': { headers: ["有効フラグ","管理ID","発生日(P/L計上日)","資産・契約名","取引先名","資産科目","取得価額","償却月数","負債科目","借入金額","返済月数","月額返済額","初回返済額","月額支払利息","頭金分割回数","決済ラグ(月)","返済日","休日調整","会社支払開始年月","決済手段","組織名","起票ターゲット月","最終起票年月日","備考"], color: "#b45f06" },
「標準償却月数」列は MST_ACCT に未設定。BUD_CAPEX には「借入パターン」列が未設定。
③ 200_data/202_repository.js L304-350 AccountRepository.findAsMap()
findAsMap: function() {
if (AccountRepository._cache) return AccountRepository._cache;
var result = AccountRepository.findAll();
var map = {};
for (var i = 0; i < result.dtos.length; i++) {
var dto = result.dtos[i];
var flag = dto['有効フラグ'];
if (flag === false || String(flag).toUpperCase() === 'FALSE') continue;
var name = String(dto['科目名'] || '').trim();
if (name) {
map[name] = {
stmt: String(dto['諸表区分'] || '').trim(),
cat: String(dto['大分類'] || '').trim(),
};
}
}
AccountRepository._cache = map;
return map;
},
戻り値は { stmt, cat } のみで deprecMonths は未対応。キャッシュは AccountRepository._cache (L344) で、AccountRepository.resetCache() (L347) でクリア。
④ 000_infra/002_constants.js L75 SHEET_DEFAULTS の 24_bud_capex エントリ
{ pattern: '24_bud_capex', prefix: 'CPX_', defaults: { '取引先名': '', '負債科目': '長期借入金', '月額返済額': 0, '月額支払利息': 0, '借入金額': 0, '取得価額': 0, _dynamic: { '発生日(P/L計上日)': 'nextYm' } } },
「借入パターン」の既定値は未設定。ID_PREFIX_MAP(L93-112)の末尾は 15_mst_dictionary(L111)で、19_mst_loan_pattern 用のエントリは未登録。
⑤ 100_config/101_sys_config.js L363 onEdit(e) ハンドラ
onEdit(e) は L363 で宣言され、L412 の末尾で if (typeof handleUxAssist === 'function') handleUxAssist(e); を呼ぶ。つまり「24タブのセル編集→handleUxAssist(300_ui/301_ui_assist.js L15)→ 24_bud_capex_loan 系の分岐がまだ無い」構造。現状、24タブの自動補完は handleUxAssist の validSheets(L20)に '24_bud_capex_loan' が列挙されているだけで、CAPEX 固有の補完分岐は未実装。
⑥ templates/operations_sidebar.html L89 🔧 マイグレーション メニュー
<h3>🔧 マイグレーション</h3>
<button class="btn" onclick="run('migrationD01D03', this)">D-01〜D-03 科目マスタ追加</button>
<button class="btn" onclick="run('migrationD04D06', this)">D-04/D-06 説明列データ</button>
<button class="btn" onclick="run('migrationI10', this)">I-10 取引先略称</button>
<button class="btn" onclick="run('migrationI24', this)">I-24 立替精算STL</button>
修正方針
5 Step 構成。各 Step は独立に dev デプロイ→動作確認→prod デプロイのゲートを挟んで進める。
Step 1: DDL スキーマ拡張(100_config/101_sys_config.js 内 setupAllSchemas)
- L644
MST_ACCTのheaders末尾に"標準償却月数"を追加("説明"の後ろ) - L658
BUD_CAPEXのheadersの"償却月数"直後に"借入パターン"を追加 schemasオブジェクトに'MST_LOAN'を新規エントリ追加:'MST_LOAN': { headers: ["有効フラグ","パターン名","金利","返済方式","返済月数","頭金分割回数","返済日","休日調整","備考"], color: "#666666" },- L593 付近の
confSheet.appendRow(['BUD_CAPEX', ...])近傍に、MST_LOAN用の01_sys_configエントリ追加:if (!existKeys.includes('MST_LOAN')) confSheet.appendRow(['MST_LOAN', '', '19_mst_loan_pattern', 'マスタ_借入パターン']); 000_infra/002_constants.jsL75 のSHEET_DEFAULTS内24_bud_capexエントリに'借入パターン': ''を追加ID_PREFIX_MAP(L93-112) に{ pattern: '19_mst_loan_pattern', prefix: 'LPN_', digit: 4, isDate: false }を末尾に追加(自動ID発番要否は「人間が検討すべき事項」に記載、デフォルトは追加する方針)
Step 2: Repository の拡張(200_data/202_repository.js)
2-A: AccountRepository.findAsMap() (L323-341) の戻り値拡張
map[name] = {
stmt: String(dto['諸表区分'] || '').trim(),
cat: String(dto['大分類'] || '').trim(),
deprecMonths: parseInt(Utils.parseAmt(dto['標準償却月数']), 10) || 0,
};
Utils.parseAmt(000_infra/004_utils.js L191)はカンマ区切り・全角数字を許容。parseInt でさらに整数化。値が不正(NaN / 負値)の場合は 0 をフォールバック(onEdit 側でゼロはスキップ)。
2-B: LoanPatternRepository を 202_repository.js 末尾(L350 の後)に新規追加
AccountRepository のパターンを完全踏襲:
var LoanPatternRepository = {
_getSheet: function() {
return Utils.getSheetByKey('MST_LOAN', '19_mst_loan_pattern');
},
findAll: function() {
return readSheetAsDtos_(LoanPatternRepository._getSheet());
},
findAsMap: function() {
if (LoanPatternRepository._cache) return LoanPatternRepository._cache;
var result = LoanPatternRepository.findAll();
var map = {};
for (var i = 0; i < result.dtos.length; i++) {
var dto = result.dtos[i];
var flag = dto['有効フラグ'];
if (flag === false || String(flag).toUpperCase() === 'FALSE') continue;
var name = String(dto['パターン名'] || '').trim();
if (name) {
map[name] = {
rate: Number(Utils.parseAmt(dto['金利'])) || 0,
method: String(dto['返済方式'] || '').trim(),
repayMonths: parseInt(Utils.parseAmt(dto['返済月数']), 10) || 0,
downSplits: parseInt(Utils.parseAmt(dto['頭金分割回数']), 10) || 1,
repayDay: parseInt(Utils.parseAmt(dto['返済日']), 10) || 0,
holidayAdjust: String(dto['休日調整'] || '').trim(),
};
}
}
LoanPatternRepository._cache = map;
return map;
},
_cache: null,
resetCache: function() { LoanPatternRepository._cache = null; },
};
Step 3: onEdit 自動補完ロジック(100_config/101_sys_config.js の onEdit)
実装先は 101_sys_config.js の onEdit(e)(L363)の末尾、handleUxAssist 呼び出しの直前(L412 の手前)。handleUxAssist は汎用アシストを担当し、CAPEX 固有のマスタ JOIN 補完は分離して 101_sys_config.js 側に置くことで、DDL と補完規則を 1 ファイルで管理する(DDL 変更時に両ファイルを触らないため)。
// S-49: CAPEX マスタ JOIN 自動補完
try {
if (sheetName === '24_bud_capex_loan') {
var sheetRef = e.range.getSheet();
var hdr = sheetRef.getRange(1, 1, 1, sheetRef.getLastColumn()).getValues()[0];
var iAssetAcct = hdr.indexOf('資産科目');
var iDepMonths = hdr.indexOf('償却月数');
var iLoanPtn = hdr.indexOf('借入パターン');
var iMonths = hdr.indexOf('返済月数');
var iDownSp = hdr.indexOf('頭金分割回数');
var iDay = hdr.indexOf('返済日');
var iAdjust = hdr.indexOf('休日調整');
// 3-A: 資産科目 → 標準償却月数
if (iAssetAcct >= 0 && col === iAssetAcct + 1 && val) {
var acctMap = AccountRepository.findAsMap();
var acct = acctMap[String(val).trim()];
var dm = acct ? acct.deprecMonths : 0;
if (iDepMonths >= 0 && dm > 0) {
var depCell = sheetRef.getRange(row, iDepMonths + 1);
if (depCell.isBlank()) depCell.setValue(dm);
} else if (iDepMonths >= 0 && acct && dm <= 0) {
SpreadsheetApp.getActiveSpreadsheet().toast(
'科目「' + val + '」の標準償却月数が未登録です', 'S-49 補完');
}
}
// 3-B: 借入パターン → 返済月数 / 頭金分割回数 / 返済日 / 休日調整
if (iLoanPtn >= 0 && col === iLoanPtn + 1 && val) {
var ptnMap = LoanPatternRepository.findAsMap();
var ptn = ptnMap[String(val).trim()];
if (!ptn) {
SpreadsheetApp.getActiveSpreadsheet().toast(
'借入パターン「' + val + '」が未登録です', 'S-49 補完');
} else {
var setIfBlankAndPositive = function(colIdx, v) {
if (colIdx < 0 || !v) return;
var c = sheetRef.getRange(row, colIdx + 1);
if (c.isBlank()) c.setValue(v);
};
setIfBlankAndPositive(iMonths, ptn.repayMonths);
setIfBlankAndPositive(iDownSp, ptn.downSplits);
setIfBlankAndPositive(iDay, ptn.repayDay);
if (iAdjust >= 0 && ptn.holidayAdjust) {
var adjC = sheetRef.getRange(row, iAdjust + 1);
if (adjC.isBlank()) adjC.setValue(ptn.holidayAdjust);
}
}
}
}
} catch (err) { console.error('[S49_ONEDIT] ' + err.message); }
設計根拠: 月額返済額・月額支払利息は「借入金額×金利×返済方式」で計算するため Step 4 の RPA 側で算出し、24 タブには原則書き込まない(書き込みたい場合は「人間が検討すべき事項」の端数処理方針を確定してから別案件で対応)。
Step 4: RPA 改修(400_domain/403_rpa_capex.js)
4-A: L87-93 の行直接パースを一部マスタ JOIN に置換
depMonthsが 0/空欄の場合、AccountRepository.findAsMap()[assetAccount].deprecMonthsでフォールバックrepayMonths/monthlyRepay/monthlyInterest/ 頭金分割 / 返済日 / 決済ラグ が空欄の場合、LoanPatternRepository.findAsMap()[ptn]の値でフォールバック- ただし 24 タブに既に手入力された値は尊重(マスタ値で上書きしない。L87-93 の既存ロジックの「0 は 0」動作は維持)
parseInt→Utils.parseAmtに段階的に置換して全角・カンマ混入を吸収(L88-93, L212, L218, L309, L310)
4-B: 月額返済額・月額支払利息の算出ロジック(借入パターン参照時のみ)
// 借入パターンから推定する場合(24タブの値が空欄 or 0)
var ptnDef = null;
if (col['借入パターン'] !== -1) {
var ptnName = String(row[col['借入パターン']]).trim();
if (ptnName) ptnDef = LoanPatternRepository.findAsMap()[ptnName] || null;
}
if (ptnDef && loanAmount > 0 && ptnDef.repayMonths > 0) {
var annualRate = ptnDef.rate;
if (ptnDef.method === '元利均等') {
var r = annualRate / 12;
if (r === 0) {
if (monthlyRepay === 0) monthlyRepay = Math.floor(loanAmount / ptnDef.repayMonths);
} else {
if (monthlyRepay === 0) {
monthlyRepay = Math.floor(loanAmount * r * Math.pow(1 + r, ptnDef.repayMonths) /
(Math.pow(1 + r, ptnDef.repayMonths) - 1));
}
}
if (monthlyInterest === 0) monthlyInterest = Math.floor(loanAmount * r);
} else { // '元金均等' or 空
if (monthlyRepay === 0) monthlyRepay = Math.floor(loanAmount / ptnDef.repayMonths);
if (monthlyInterest === 0) monthlyInterest = Math.floor(loanAmount * annualRate / 12);
}
}
4-C: 返済日の休日調整
L326-L330 の new Date(...) で作っている repayDate について、休日調整 列(既存)に値があれば Utils.adjustToBusinessDay(ymdStr, direction) を適用:
var adjust = col['休日調整'] !== -1 ? String(row[col['休日調整']]).trim() : '';
if (adjust === '前' || adjust === '後') {
var yStr = Utilities.formatDate(repayDate, Session.getScriptTimeZone(), 'yyyy-MM-dd');
var adjusted = Utils.adjustToBusinessDay(yStr, adjust);
var ap = adjusted.split('-').map(Number);
repayDate = new Date(ap[0], ap[1] - 1, ap[2]);
}
頭金返済 (downRepayDate, L231-L236) にも同等処理を追加。
4-D: 既存の冪等性チェック(isDuplicate_ 呼び出し、L167/L181/L197/L239/L269/L286/L336/L351)は変更しない
Step 5: マイグレーション(800_ops/809_migration_s49_capex_master.js 新規)
CLAUDE.md §マイグレーションスクリプト運用ガイドラインに準拠:
- ファイル名:
800_ops/809_migration_s49_capex_master.js - 関数名:
migrationS49CapexMaster() - Human-in-the-Loop:
19_mst_loan_patternへ直接書き込まず、新規ワークシート99_wrk_loan_pattern_proposalsに提案を出力する方式- 列:
[提案パターン名, 金利, 返済方式, 返済月数, 頭金分割回数, 返済日, 休日調整, 抽出元CPX件数, 代表例_管理ID] - ユーザーはレビュー・修正後、承認したパターンのみを手動で
19_mst_loan_patternへコピー
- 列:
- 冪等性:
99_wrk_loan_pattern_proposals既存行を読み込み、提案パターン名で重複スキップ - ログ出力:
Utils.logInfo('migrationS49CapexMaster', summary)+SpreadsheetApp.getUi().alert('マイグレーション完了', summary, ...) - メニュー登録:
templates/operations_sidebar.htmlL89 の<h3>🔧 マイグレーション</h3>ブロック末尾に:<button class="btn" onclick="run('migrationS49CapexMaster', this)">S-49 CAPEX借入パターン抽出</button>
影響範囲
| 種別 | ファイル | 変更規模 |
|---|---|---|
| 修正 | 100_config/101_sys_config.js(DDL 追加 + onEdit 補完ロジック追加 + 01_sys_config エントリ) | ~40行 |
| 修正 | 200_data/202_repository.js(AccountRepository.findAsMap 拡張 + LoanPatternRepository 新規) | ~40行 |
| 修正 | 400_domain/403_rpa_capex.js(マスタ JOIN + 休日調整 + 月額算出) | ~40行 |
| 修正 | 000_infra/002_constants.js(SHEET_DEFAULTS + ID_PREFIX_MAP) | ~3行 |
| 修正 | templates/operations_sidebar.html(マイグレーションボタン 1 行追加) | ~1行 |
| 新規 | 800_ops/809_migration_s49_capex_master.js | ~80行 |
| 新規シート | 19_mst_loan_pattern(DDL 管理下) | - |
| 一時シート | 99_wrk_loan_pattern_proposals(マイグレーション実行時に動的生成) | - |
注意事項
- キャッシュクリア:
AccountRepository.findAsMap()拡張後はAccountRepository.resetCache()を呼んでから動作確認する。LoanPatternRepositoryも同様にresetCache()を備える。setupAllSchemasの直後にも両resetCache()を呼ぶこと(DDL で列追加した直後にキャッシュが古い値を返すリスク)。 - DDL 上書きリスク:
setupAllSchemasのisFull=true実行時に既存データが上書きされる列はない(ヘッダー追加のみ)が、MST_LOAN新規作成時は既存同名シートの有無を必ずconfSheet.appendRow前のexistKeys.includesで確認する(失敗パターン #3)。 - マイグレーション番号 809: CLAUDE.md 記載「次のマイグレーションは 809 から」に基づく。MAS-119(人件費料率マスタ化)も 809 を予約している可能性がある。着手前に
800_ops/配下の既存ファイルと他ブランチを確認し、競合する場合は本案件を 810 / 811 にずらす。現時点では808_migration_i24.jsまでが最新。 LoanPatternRepositoryは新規ファイルではなく202_repository.js末尾に追記。MAS-192 で Repository 一元化方針が決定済み。- 24 タブの sheet 名は
24_bud_capex_loan(24_bud_capexではない)。handleUxAssist側(L20validSheets)・403_rpa_capex.js(L18)・SHEET_DEFAULTS(L75)は24_bud_capexを prefix として扱うため、onEdit 分岐では 完全一致で'24_bud_capex_loan'を使う(失敗パターン #19)。 - onEdit は編集 1 回で複数セルが変化するバルク編集(ペースト)もあり得る。
e.range.getNumRows() > 1の場合は補完をスキップ(handleUxAssistが L16 で同様ガードしている既存実装に倣う)。 - 型変換ガード: 24 タブにユーザーが
"60ヶ月"などの文字列を直打ちするケースがあるため、マスタ JOIN では常にUtils.parseAmt→parseIntの二段階で整数化する(失敗パターン #21-#24)。
エッジケース
| 条件 | 動作・表示値 | 理由 |
|---|---|---|
| 「標準償却月数」が空欄 | 自動補完しない(既存値を維持)。Toast警告「科目『XXX』の標準償却月数が未登録です」 | 不正値での上書き防止 |
| 「標準償却月数」が 0 または負値 | 自動補完しない。Toast警告同文 | ゼロ除算防止。マスタ側の誤登録を早期検出 |
| 「返済月数」が 0 | RPA 側で月額返済額 = 0 を設定。ループ未実行 | ゼロ除算ガード必須 |
| 「借入金額」= 0 | RPA 側で月額返済額 = 0、月額支払利息 = 0。Row B(借入計上)も生成しない(既存 L181 ガード) | 正常系として計算スキップ |
| 「金利」= 0 | 利息計算結果 = 0(計算は実行)。Row F(支払利息)は monthlyInterest > 0 ガードで非生成 | 無利子借入として扱う |
| 月額返済額の端数 | Math.floor() で切り捨て。最終回の残差調整は本案件では未対応(既存 L265 fee = (m === depMonths) ? remaining : monthlyDep と同パターンで将来対応) | 端数処理方針は「人間が検討すべき事項」で業務要件確認後に別案件 |
| ユーザーが自動補完値を手動上書き | 上書き後の値を尊重(onEdit 補完は isBlank() 時のみ)。再度「借入パターン」を編集しても既値は上書きされない | ユーザー意図の上書きは尊重する原則 |
19_mst_loan_pattern にパターン未登録 | 自動補完しない。Toast警告「借入パターン『XXX』が未登録です」 | フォールバック動作の明確化 |
11_mst_account に科目未登録 | AccountRepository.findAsMap()[科目名] が undefined → acct ? acct.deprecMonths : 0 で 0 扱い → 補完しない(Toast も出さない) | 既存動作(未登録 = 無視)に準拠 |
| バルク編集(複数行ペースト) | e.range.getNumRows() > 1 で補完スキップ | 既存 handleUxAssist L16 と同ガード |
休日調整 が空 or '前'/'後' 以外 | 既存ロジック(repayDate そのまま)を維持 | 既存互換 |
返済方式 が '元利均等' 以外(空含む) | 元金均等として処理(Math.floor(loanAmount / repayMonths) + Math.floor(loanAmount * rate / 12)) | デフォルト単純式にフォールバック |
24 タブで 償却月数 が手入力済み | 手入力値を優先(マスタで上書きしない) | 既存データ互換性 |
AccountRepository / LoanPatternRepository のキャッシュが古い | setupAllSchemas 直後と migrationS49CapexMaster 直後に resetCache() を呼ぶ | キャッシュ鮮度保証 |
| 全角数字「60」が入力された | Utils.parseAmt で半角化後 parseInt で整数化 | 失敗パターン #22 対策 |
標準償却月数 に "60ヶ月" と文字列入力 | Utils.parseAmt('60ヶ月') が 60 を返す([^\d.-] を除去) | 既存ヘルパー仕様に準拠 |
実データ検証
実装前に MCP で以下を確認すること(失敗パターン #3: DDLコード値 vs 実データの乖離防止):
| 項目 | 確認対象 | 期待値 |
|---|---|---|
| 列存在 | 11_mst_account の「標準償却月数」列 | 未存在(DDL で新規追加対象) |
| 列存在 | 24_bud_capex_loan の「借入パターン」列 | 未存在(DDL で新規追加対象) |
| シート存在 | 19_mst_loan_pattern | 未存在(DDL で新規作成対象) |
| シート存在 | 99_wrk_loan_pattern_proposals | 未存在(マイグレーション実行時に動的生成) |
| 現在列構成 | 24_bud_capex_loan の既存列 | DDL 定義(L658)の 24 列と一致しているか |
| データ型 | 403_rpa_capex.js で参照される 償却月数 / 返済月数 | 数値 or 文字列混在の可能性 → Utils.parseAmt で吸収 |
| マイグレーション番号 | 800_ops/ の既存 8NN_migration_*.js | 808 までが使用済。809 の他案件予約有無を git log --all --oneline で確認 |
| キー登録 | 01_sys_config に MST_LOAN キー | 未登録(Step 1 で追加対象) |
関連ドキュメント
| ドキュメント | 関連箇所 |
|---|---|
| CLAUDE.md | §マイグレーションスクリプト運用ガイドライン / §GAS ファイル番号体系 / §プロダクトポリシー(Human-in-the-Loop) |
| MAS-119 人件費料率マスタ化 | マイグレーション 809 番号帯の共有。類似の「予算タブから料率系マスタを抽出」パターン |
| MAS-120 取引先マスタ拡張 | onEdit 自動補完パターンの先行事例(取引先選択時の補完) |
| MAS-116 マイグレーション基盤 | マイグレーション設計原則 |
| failure_patterns.md #3 | DDL コード値 vs 実データの乖離 |
| failure_patterns.md #18-#20 | コード未読による固有名詞誤記(対策: Phase 1 で Read) |
| failure_patterns.md #21-#24 | 数式設計の落とし穴(全角スペース・getLastColumn 膨張・型変換) |
| prd.md | Human-in-the-Loop プロダクトポリシー |
人間が検討すべき事項
- 元利均等 vs 元金均等の両対応: Step 4-B の数式は両対応済みだが、実務で使うのはどちらか? 金融機関ごとの標準契約パターンを確認。
- 金利期中変動の扱い: 本案件は固定金利のみサポート。変動金利借入は将来案件で対応。既存 CPX に変動金利案件がある場合、借入パターンは「固定金利換算の代表値」で登録する運用ルールを合意する。
- 端数処理方針:
Math.floor切り捨て採用。最終回での残差一括調整は本案件では未対応(既存 L265 償却ロジックfee = (m === depMonths) ? remaining : monthlyDepパターンは将来別案件で踏襲)。 - 資産科目毎の償却月数: 税法耐用年数表との整合(例: ソフトウェア=60、什器備品=48、建物付属設備=180)を税理士と確認。暫定値での移行と本確定値の切替フローを決める。
- 自動補完時の上書きポリシー: 本案件は「空欄のみ補完」。編集済みセルへの強制再補完は
confirm dialogを出す等の拡張は別案件。 19_mst_loan_patternへの自動 ID 発番要否: Step 1 ではID_PREFIX_MAPにLPN_接頭辞を追加する方針だが、人間がパターン名を自由に命名する運用なら ID 列は不要の可能性。→ 現時点はスキーマに ID 列を含めず、パターン名をキーとする(Step 1 の DDL 定義はこれに従う)。- 提案シート名
99_wrk_loan_pattern_proposalsと99_error_logの命名競合: 既存99_で始まるシートは99_error_log(実データ確認で有無を確認)のみ想定。異なる用途なので命名競合は実害なし。必要ならwrk_loan_pattern_proposals(番号なし)へ変更。 - マイグレーション番号 809 の他案件ブランチ競合: 着手前に
git log --all --oneline -- 800_ops/809_*で確認。MAS-119 も 809 候補(TODO_future.md 記載)のため要調整。 - 既存 CPX の借入パターン抽出: 同一取引先でも案件別に条件が異なるケース(例: 日本政策金融公庫の複数回借入)があり、「取引先名 + 金利 + 返済月数」の複合キーで最頻値抽出する方針でよいか。
- 「借入パターン」列のプルダウン設定: Step 1 DDL 後に
100_config/101_sys_config.jsのsetVali('BUD_CAPEX', ...)に借入パターン列のバリデーション設定が必要(L1127 パターンに追加)。本案件は Step 1 スコープに含めるが、MST_LOANキーを L1127 のsetVali呼び出し形式で追加するかどうかは要検討。
実装プロンプト(Claude Code 用)
あなたはGAS会計システム(bizlp-gas-accounting)のシニア開発者です。
案件 MAS-121「24タブCAPEX特有の償却・借入条件マスタ化」を実装してください。
## 実行前タスク
1. `100_config/101_sys_config.js` を Read: setupAllSchemas 内 MST_ACCT 定義(L644)・BUD_CAPEX 定義(L658)・01_sys_config 追記箇所(L593 付近)・onEdit ハンドラ(L363-L413)の handleUxAssist 呼び出し(L412)位置。メニュー文字列は `templates/operations_sidebar.html` L89「🔧 マイグレーション」ブロックを確認。
2. `400_domain/403_rpa_capex.js` を Read: 行直接パース箇所(L87-L93、L212、L216、L218、L309、L310)、isDuplicate_ 呼び出し(L166/L181/L197/L239/L269/L286/L336/L351)、`repayDate` 生成(L326-L330)、`downRepayDate` 生成(L231-L236)、24 タブ名 `'24_bud_capex_loan'`(L18/L20)。
3. `200_data/202_repository.js` を Read: AccountRepository.findAsMap()(L323-L341)、_cache(L344)、resetCache(L347)、readSheetAsDtos_(L19-L29)、末尾(L350)。
4. `000_infra/002_constants.js` を Read: SHEET_DEFAULTS の 24_bud_capex エントリ(L75)、ID_PREFIX_MAP 末尾 15_mst_dictionary(L111)。
5. `000_infra/004_utils.js` を Read: `adjustToBusinessDay(ymdStr, direction)` (L168-L184、`direction` は '前' / '後')、`parseAmt(val)` (L191-L198)。
6. MCP で実データ確認: `11_mst_account` の「標準償却月数」列が未存在 / `24_bud_capex_loan` の「借入パターン」列が未存在 / `19_mst_loan_pattern` シートが未存在 / `800_ops/` 配下で 808 が最新。
## 修正対象ファイル
- `100_config/101_sys_config.js`(DDL 3 箇所 + onEdit 補完ロジック 1 箇所 追加)
- `200_data/202_repository.js`(AccountRepository.findAsMap 拡張 + LoanPatternRepository 新規追加)
- `400_domain/403_rpa_capex.js`(マスタ JOIN フォールバック + 休日調整 + 月額算出)
- `000_infra/002_constants.js`(SHEET_DEFAULTS の 24_bud_capex に '借入パターン': '' 追加、ID_PREFIX_MAP 末尾に LPN_ 追加)
- `templates/operations_sidebar.html`(🔧 マイグレーション セクションに 1 行追加)
- `800_ops/809_migration_s49_capex_master.js`(新規作成)
## 実装内容
Step 1: DDL スキーマ拡張(`101_sys_config.js` + `002_constants.js`)
- L644 MST_ACCT headers 末尾に "標準償却月数" を追加
- L658 BUD_CAPEX headers の "償却月数" の直後に "借入パターン" を追加
- schemas オブジェクトに 'MST_LOAN': { headers: ["有効フラグ","パターン名","金利","返済方式","返済月数","頭金分割回数","返済日","休日調整","備考"], color: "#666666" } を追加
- L593 付近に if (!existKeys.includes('MST_LOAN')) confSheet.appendRow(['MST_LOAN', '', '19_mst_loan_pattern', 'マスタ_借入パターン']); を追加
- 002_constants.js L75 の 24_bud_capex エントリ defaults に '借入パターン': '' を追加
- 002_constants.js L112(15_mst_dictionary の次行)に { pattern: '19_mst_loan_pattern', prefix: 'LPN_', digit: 4, isDate: false } を追加
Step 2: 202_repository.js の拡張
- AccountRepository.findAsMap() の map[name] = { ... } に deprecMonths: parseInt(Utils.parseAmt(dto['標準償却月数']), 10) || 0 を追加
- 末尾(L350 の後)に LoanPatternRepository を新規追加(AccountRepository のパターンを完全踏襲。findAsMap のキーは「パターン名」、値は { rate, method, repayMonths, downSplits, repayDay, holidayAdjust })
Step 3: onEdit 自動補完ロジック(`101_sys_config.js`)
- L412 の `handleUxAssist` 呼び出しの直前に、sheetName === '24_bud_capex_loan' の分岐を try/catch で追加
- バルク編集時は e.range.getNumRows() > 1 でスキップ
- 「資産科目」列編集時: AccountRepository.findAsMap()[科目名].deprecMonths で補完、0/負値は Toast 警告
- 「借入パターン」列編集時: LoanPatternRepository.findAsMap()[パターン名] から返済月数・頭金分割回数・返済日・休日調整を補完、未登録は Toast 警告
- 補完は isBlank() 時のみ
Step 4: 403_rpa_capex.js の改修
- L87-L93 の行直接パースに、マスタ JOIN フォールバックを追加(行の値が 0/空欄の場合のみマスタ値を使う)
- 月額返済額 / 月額支払利息が 0 かつ borrowPattern 指定ありの場合、元利均等/元金均等の式で算出
- L326-L330 の repayDate / L231-L236 の downRepayDate に、Utils.adjustToBusinessDay で休日調整
- parseInt を Utils.parseAmt 経由に置換(L88, L90, L212, L218, L309, L310)
- 既存の isDuplicate_ ガードは変更しない
Step 5: 809_migration_s49_capex_master.js を新規作成
- 関数名: migrationS49CapexMaster()
- 24_bud_capex_loan の有効行から「取引先名 + 金利 + 返済月数 + 頭金分割回数 + 返済日 + 休日調整」の複合キーで最頻パターン抽出
- 提案を 99_wrk_loan_pattern_proposals シートに書き込み(無ければ新規作成)
- 19_mst_loan_pattern へ直接書き込まない
- 冪等性: 99_wrk_loan_pattern_proposals 既存行のパターン名と重複はスキップ
- Utils.auditLog / Utils.logInfo / SpreadsheetApp.getUi().alert でログ出力
- templates/operations_sidebar.html L89-L94 の <h3>🔧 マイグレーション</h3> ブロック末尾に <button class="btn" onclick="run('migrationS49CapexMaster', this)">MAS-121 CAPEX借入パターン抽出</button> を追加
## 制約
- 既存の冪等性チェック機構(403_rpa_capex.js の isDuplicate_)は変更しない
- AccountRepository.findAll() インターフェースは変更しない(findAsMap の戻り値のみ拡張)
- DDL 変更は setupAllSchemas 内のみ。スプレッドシートを直接操作しない
- マイグレーションスクリプトは 19_mst_loan_pattern へ直接書き込まない
- LoanPatternRepository は新規ファイルではなく 202_repository.js 末尾に追記する
- 24 タブのシート名判定は `'24_bud_capex_loan'` の完全一致を使う(`24_bud_capex` 部分一致は NG。名前衝突リスク)
- ユーザーが 24 タブに手入力した値は尊重(マスタ値で上書きしない)
## エッジケース
| 条件 | 動作 |
|------|------|
| 標準償却月数が空欄・0・負値 | 補完しない。Toast 警告 |
| 返済月数が 0 | 月額返済額 = 0(ゼロ除算ガード) |
| 借入金額 = 0 | 月額返済額 = 0、月額支払利息 = 0 |
| 金利 = 0 | 利息 = 0(計算は実行、Row F は既存 monthlyInterest > 0 ガードで非生成) |
| 月額端数 | Math.floor() 切り捨て |
| パターン未登録 | 補完しない。Toast 警告 |
| バルク編集(複数行ペースト) | e.range.getNumRows() > 1 で補完スキップ |
| 返済方式=空 | 元金均等として処理 |
| 休日調整が「前」「後」以外 | 既存の repayDate 維持 |
| 全角数字入力 | Utils.parseAmt で吸収 |
## 実データ検証
- MCP で 11_mst_account の「標準償却月数」列が未存在であること
- MCP で 24_bud_capex_loan の「借入パターン」列が未存在であること
- MCP で 19_mst_loan_pattern シートが未存在であること
- 800_ops/ で 809 が未使用であること(MAS-119 と競合する場合は番号を再調整)
## 動作確認
1. npm run push:dev でデプロイ
2. GASエディタから setupAllSchemas を実行 → 19_mst_loan_pattern シート作成、11_mst_account に「標準償却月数」列追加、24_bud_capex_loan に「借入パターン」列追加を確認
3. 11_mst_account で代表的な資産科目(ソフトウェア=60、什器備品=48 等)に標準償却月数を登録
4. 19_mst_loan_pattern に 1-2 パターン登録(例: "日本政策金融公庫_A": 金利 0.02, 元金均等, 返済月数 60, 頭金分割 1, 返済日 27, 休日調整 "後")
5. 24_bud_capex_loan の「資産科目」を編集 → 「償却月数」が自動補完されること
6. 24_bud_capex_loan の「借入パターン」を編集 → 「返済月数」「頭金分割回数」「返済日」「休日調整」が自動補完されること
7. 未登録科目・未登録パターンで Toast 警告が出ること
8. 既に値が入ったセルが編集で上書きされないこと
9. migrationS49CapexMaster() を実行 → 99_wrk_loan_pattern_proposals に提案が書き出され、19_mst_loan_pattern へ直接書き込まれないことを確認
10. generateCapexInvoices() を dev 環境で実行 → マスタ参照で INV が正常生成されること。発行済 INV との重複(isDuplicate_)が維持されること
11. 900_test/901_test_runner.js の全テストを実行し回帰なしを確認
### 拡張思考の使用状況
| フェーズ | 拡張思考 | 備考 |
|---------|---------|------|
| Phase 1(調査・設計) | あり | 固有名詞・行番号の確定に活用 |
| Phase 2(清書) | なし | Phase 1 確定内容の書き下しに徹する |
推奨実行モデル
| 工程 | 推奨モデル | 理由 |
|---|---|---|
| Step 1 DDL 追加 | Claude Haiku 4.5 | 仕様書で列名・挿入位置が完全定義済み、判断要素なし |
| Step 2 Repository 拡張 | Claude Sonnet 4.6 | 既存 AccountRepository パターンの正確な踏襲、_cache 制御を含む |
| Step 3 onEdit 追加 | Claude Sonnet 4.6 | 挿入位置(handleUxAssist 呼び出し直前)の特定、既存ガード(L16 numRows > 1)の流用 |
| Step 4 RPA 改修 | Claude Opus 4.6 | 月額算出の元利均等/元金均等分岐、休日調整の日付型変換、既存 isDuplicate_ との整合性維持など複数ファイル横断の会計ロジック判断 |
| Step 5 マイグレーション | Claude Sonnet 4.6 | 808_migration_i24.js パターンの踏襲、Human-in-the-Loop 提案シート方式の実装 |
変更履歴
| 日付 | 変更内容 |
|---|---|
| 2026-04-19 | 初版作成。CAPEX 償却・借入条件マスタ化の DDL 設計・Repository 拡張・onEdit 自動補完・403_rpa_capex.js の JOIN 改修・マイグレーション 809 の全5 Step を確定 |
仕様書作成プロンプト(再現性・監査性のため必ず記録)
仕様書作成プロンプト(展開して表示)
【タイムアウト回避・実行原則(v1.7・必ず遵守すること)】
1. **拡張思考の使い分け**: Phase 1(設計)では拡張思考をフル活用し、ファイル名形式・エッジケース一覧・Step分割粒度・固有名詞(関数名/シート名/列名/行番号)を完全に確定させる。Phase 2(清書)の各 Step 内では拡張思考を最小限に抑え、Phase 1 で確定済みの内容の書き下しに徹する。出力途中で再考しない。
2. **テキスト報告の禁止**: 「〜を作成します」等の text のみで tool_use なしに turn を終了しない。説明は 1 文以内。直ちに tool を呼ぶ。
3. **4-5 分割の Write/Edit 実行**: 2-1(骨格 ~20行)/ 2-2(概要〜注意事項 ~300行)/ 2-3a(エッジケース〜人間検討事項 ~200行)/ 2-3b(実装プロンプト〜変更履歴 ~250行)/ 2-4(`<details>` プロンプト記録)に分割。1回の Write/Edit は 300 行以内を目安とする。
4. **各 Step で何を書くかを具体指示**: 設計判断を Phase 2 実行時に持ち込まないよう、Phase 1 で全固有名詞・行番号・ファイル名を確定させてから Phase 2 に進む。
======================================================================
あなたはGAS会計システム(bizlp-gas-accounting)のシニア開発者兼仕様書ライターです。
案件 S-49「24タブCAPEX特有の償却・借入条件マスタ化」の開発仕様書を作成してください。
作成後は `docs/_config.json` の `nav` 配列の適切なセクションに必ず追記してください。
---
## Phase 1: 実行前タスク(テキスト報告禁止。即座にツール実行)
### 1-A: 案件定義の読み込み
`docs/_internal/TODO_future.md` で S-49 の案件名・概要・期待される効果・人間が検討すべき事項を取得する。
### 1-B: プロジェクト規約の読み込み
`CLAUDE.md` を読み込み、以下を把握する:
- マイグレーション番号体系(§マイグレーションスクリプト運用ガイドラインに「804-808使用済み。次のマイグレーションは809から」と記載)
- DDL管理は `setupAllSchemas` で行う規則
- onEdit ハンドラの配置に関する規約
### 1-C: 関連コードの調査(Grep で発見 → 必ず Read で構造を確認。名前からの類推・記憶での記述禁止)
以下の順番で Read し、仕様書に記述する固有名詞・構造・行番号を実コードから取得すること。
**① `100_config/101_sys_config.js`**(最優先)
- `setupAllSchemas` 内の既存DDLスキーマ定義パターン(`11_mst_account`・`24_bud_capex` のカラム定義の実際の形式と行番号)
- `onEdit(e)` ハンドラの実装箇所と行番号、シート別自動補完ロジックの既存パターン
- 「🔧 マイグレーション」メニューの実在する文字列(造語禁止。Read した文字列のみ引用)
**② `400_domain/403_rpa_capex.js`**
- 償却月数・金利・返済月数がハードコードされている変数名と行番号
- INVレコード生成ロジックの構造
- 既存の冪等性チェック機構の実装箇所と行番号
- `AccountRepository` や `Constants` を参照している既存箇所
**③ `200_data/202_repository.js`**
- `AccountRepository` の全実装(`_getSheet`・`findAll`・`findAsMap`・`_cache`・`resetCache`)の行番号
- `findAsMap()` の現在の戻り値構造(実コードを Read して確認: `{ stmt: string, cat: string }` が現状の形)
- 内部ヘルパー関数 `readSheetAsDtos_`・`appendDtosToSheet_` 等の行番号(`LoanPatternRepository` 実装の参考)
**④ `000_infra/002_constants.js`**
- `SHEET_DEFAULTS` 内の `24_bud_capex` エントリの現在の `defaults` フィールド構造(「借入パターン」列追加前の実状態)
- `ID_PREFIX_MAP` の末尾行番号(`19_mst_loan_pattern` の自動ID発番要否の判断後、追加が必要な場合の挿入位置)
**⑤ `300_ui/301_ui_assist.js`**
- `24_bud_capex` 関連のUI処理が存在するか確認
- onEdit補完ロジックの実装先が `101_sys_config.js` と `301_ui_assist.js` のどちらか判断する
**⑥ `docs/_internal/failure_patterns.md`**
- #3(DDLコード値 vs 実データの乖離)を確認 → 実データ検証ステップに反映
- #18-#20(コード未読による固有名詞誤記)を確認 → Phase 1 調査の徹底
- #21-#24(数式設計の落とし穴)を確認 → onEdit補完時の型変換リスクに反映
### 1-D: 実データ確認(MCP で確認。Phase 2 着手前に完了すること)
- `11_mst_account` シートに「標準償却月数」列が既存か未存在か(DDL追加対象の確認)
- `24_bud_capex` シートの現在の列構成と「借入パターン」列の有無
- `19_mst_loan_pattern` シートが既存か未存在か(新規DDL作成の要否)
- `403_rpa_capex.js` のハードコード値のデータ型(文字列 vs 数値。型変換ガードの要否判断)
---
## Phase 2: 仕様書の分割作成
出力先: `docs/dev/dev_mas-121_capex_master_ref.md`
**【重要】1回のツール呼び出しで全内容を出力しない。以下5 Stepに分割して実行する。**
### Step 2-1: 骨格の作成(Write / ~20行)
`docs/_internal/dev_spec_prompt_template.md` のセクション構成に従い、見出しのみの骨格ファイルを新規作成する。
---
### Step 2-2: 概要〜注意事項の追記(Edit or Bash / ~300行)
#### 概要テーブル
| 項目 | 値 |
|------|---|
| 案件ID | S-49 |
| カテゴリ | DDL・マスタ設計 |
| 対象ファイル | `100_config/101_sys_config.js`, `200_data/202_repository.js`, `400_domain/403_rpa_capex.js`, `000_infra/002_constants.js`, `800_ops/809_migration_s49_capex_master.js`(新規) |
| 前提案件 | TODO_future.md の S-49 エントリを参照 |
#### 修正方針(Phase 1 の Read 結果を元に固有名詞・行番号を埋め込んで記述)
**Step 1: DDLスキーマ拡張(`100_config/101_sys_config.js` 内 `setupAllSchemas`)**
- `11_mst_account` に「標準償却月数」列を追加(Phase 1 で確認した既存カラム定義の直後。列名は Read で確認した実際の形式に合わせる)
- `24_bud_capex` に「借入パターン」列を追加
- `19_mst_loan_pattern` を新規DDL定義(既存 `11_mst_account`〜`15_mst_dictionary` の命名規則に準拠した新規マスタシート。項目: パターン名, 金利, 返済方式, 返済月数, 頭金分割回数, 返済日, 休日調整)
- `000_infra/002_constants.js` の `SHEET_DEFAULTS` 内 `24_bud_capex` エントリに `'借入パターン': ''` を追加
- 自動ID発番が必要と判断した場合: `Constants.ID_PREFIX_MAP` に `{ pattern: '19_mst_loan_pattern', prefix: 'LPN_', digit: 4, isDate: false }` を追加(要検討)
**Step 2: Repository の拡張(`200_data/202_repository.js`)**
- `AccountRepository.findAsMap()` を拡張: 現在の戻り値 `{ stmt: string, cat: string }` に `deprecMonths: number` を追加(「標準償却月数」列の値を `Utils.parseAmt()` でパース)
- `LoanPatternRepository` を `202_repository.js` 末尾に新規追加(`AccountRepository` の `_getSheet` / `findAll` / `findAsMap` / `_cache` / `resetCache` パターンを完全踏襲。`findAsMap()` のキーはパターン名、値は借入条件オブジェクト)
- `LoanPatternRepository._getSheet()` は `Utils.getSheetByKey('MST_LOAN', '19_mst_loan_pattern')` パターンで実装(システムキー文字列は要検討)
**Step 3: onEdit 自動補完ロジック(実装先は Phase 1 調査結果で確定)**
- `24_bud_capex` の「資産科目」セル編集時: `AccountRepository.findAsMap()` から `deprecMonths` を取得し「標準償却月数」列へ自動補完。値が `0`・負値・空欄の場合は補完しない
- `24_bud_capex` の「借入パターン」セル編集時: `LoanPatternRepository.findAsMap()` から借入条件を取得し対応列へ自動補完。パターン未登録の場合は `SpreadsheetApp.getActiveSpreadsheet().toast()` で警告
- ユーザーによる手動上書きは尊重する(補完は空欄のみ対象とするか、確認ダイアログを出すかは「人間が検討すべき事項」に委ねる)
**Step 4: RPA改修(`400_domain/403_rpa_capex.js`)**
- Phase 1 で特定したハードコード箇所(行番号を明記)を `AccountRepository.findAsMap()` / `LoanPatternRepository.findAsMap()` 参照に置換
- 既存の冪等性チェック機構(Phase 1 で確認した実装箇所)は変更しない
- 返済日の休日調整: `Utils.adjustToBusinessDay(ymdStr, direction)` を使用(`direction` の引数値 `'前'` / `'後'` は `004_utils.js` の実装を Read して確認済みのものを使用)
- 金額・率の読み取り: `Utils.parseAmt(val)` を使用してデータ形式の揺れに対応
**Step 5: マイグレーション(`800_ops/809_migration_s49_capex_master.js`)**
- CLAUDE.md §マイグレーションスクリプト運用ガイドラインに準拠(関数命名: `migrationS49CapexMaster()`、冪等性必須、`Utils.logInfo` + `SpreadsheetApp.getUi().alert` でログ出力)
- Human-in-the-Loop: `19_mst_loan_pattern` へ直接書き込まず、提案内容を一時ワークシートへ出力する方式
- 提案シート名: `99_wrk_loan_pattern_proposals`(注: `99_error_log` との命名競合を Phase 1 で確認し、問題があれば別名を採用すること)
- ユーザーがレビュー・修正後、承認したパターンのみを手動で `19_mst_loan_pattern` へコピーする運用フローを記述
- 冪等性: 実行前に `19_mst_loan_pattern` の既存データを読み込み、パターン名が重複するレコードはスキップ
- メニュー登録: `101_sys_config.js` の「🔧 マイグレーション」メニューに追加(メニュー文字列は Phase 1 で Read した実在する文字列のみ使用)
#### 影響範囲
- 変更ファイル: `100_config/101_sys_config.js`(DDL・onEdit)、`200_data/202_repository.js`(Repository拡張・追加)、`400_domain/403_rpa_capex.js`(マスタ参照)、`000_infra/002_constants.js`(SHEET_DEFAULTS・ID_PREFIX_MAP)
- 新規ファイル: `800_ops/809_migration_s49_capex_master.js`
- 新規シート: `19_mst_loan_pattern`(DDL管理下)
#### 注意事項
- `AccountRepository.findAsMap()` 拡張後は必ず `AccountRepository.resetCache()` を呼び出してキャッシュをクリアしてから動作確認すること
- DDLスキーマ変更後に `setupAllSchemas` を実行すると既存データが上書きされる列がある — 実行前に影響列を確認すること(失敗パターン #3 参照)
- マイグレーション番号 `809` は CLAUDE.md 記載の「次のマイグレーションは809から」に基づく。着手前に他案件ブランチとの競合がないか確認すること
- `LoanPatternRepository` は新規ファイルではなく `202_repository.js` 末尾に追記する
---
### Step 2-3a: エッジケース〜人間が検討すべき事項の追記(Edit or Bash / ~200行)
(エッジケーステーブル、実データ検証、人間が検討すべき事項を記載。上記本文を参照)
### Step 2-3b: 実装プロンプト〜変更履歴の追記(Edit or Bash / ~250行)
(実装プロンプトは行頭4スペースインデントで出力。上記本文を参照)
### Step 2-4: 仕様書作成プロンプトの記録(Edit or Bash / プロンプトサイズ依存)
末尾に `<details><summary>仕様書作成プロンプト(展開して表示)</summary>` ブロックを追加し、この `<instruction>` タグの全文を記録する。
---
## Phase 3: 保存・登録・記録
### 3-A: ファイル保存確認
`docs/dev/dev_mas-121_capex_master_ref.md` が正しく保存されていることを確認する。
### 3-B: `docs/_config.json` への登録(必須)
追加前に `git pull origin main` で最新化すること。
`nav` 配列の §E.2(バグ修正・実務要件・DDL)セクションに追加:
{ "file": "dev/dev_mas-121_capex_master_ref.md", "title": "E.2.X S-49 CAPEX償却・借入条件マスタ化" }
### 3-C: `docs/_internal/changelog.md` への追記
ヘッダー直後の先頭行に追記:
| 2026-04-19 | [dev_mas-121_capex_master_ref.md](dev_mas-121_capex_master_ref.md) | 初版作成。CAPEX償却・借入条件マスタ化(DDL・Repository拡張・onEdit補完・RPA改修・マイグレーション設計) |
### 3-D: コミット&プッシュ
git add docs/dev/dev_mas-121_capex_master_ref.md docs/_internal/changelog.md docs/_config.json
git commit -m "docs: S-49 CAPEX償却・借入条件マスタ化の開発仕様書を作成
DDLスキーマ拡張・LoanPatternRepository新規追加・onEdit自動補完・
403_rpa_capex.js改修・マイグレーション(809)設計を含む。
https://claude.ai/code/session_XXXXX"
git push -u origin {現在のブランチ}