MAS-135: 決済手段マスタの新設(決済条件マスタ化)
概要
| 項目 | 内容 |
|---|---|
| 案件ID | MAS-135 |
| カテゴリ | DDL・マスタ |
| Phase | P2 |
| 優先度 | ★★ |
| 所要時間 | 6〜8 時間(5 Step) |
| 実装ステータス | 📝 仕様書段階・実装未着手 (2026-04-28 監査時点) |
| 対象ファイル | 100_config/101_sys_config.js(DDL / システムキー / メニュー), 200_data/202_repository.js(PaymentMethodRepository 新設), 000_infra/003_contracts.js(PaymentMethodDTO @typedef 追加), 400_domain/400_rpa_common.js(決済日計算ヘルパー集約先), 400_domain/402_rpa_subscription.js L206-222(決済日計算の呼び出し箇所), 400_domain/405_rpa_adhoc.js L94-101(同), 400_domain/406_rpa_pipeline.js L155-164(同), 300_ui/301_ui_assist.js(onEdit 補完拡張), 800_ops/812_migration_payment_method.js(新規マイグレーション) |
| 前提案件 | MAS-120(実装完了 PR #215) — 取引先マスタ標準決済条件(12_mst_partner の 5 列拡張 + PartnerRepository.findPaymentTermsMap())が既に稼働中。本案件はその次段フォールバック層(取引先マスタ未登録の取引先向け)を提供する |
目的
決済手段(JCB / 楽天カード / 口座振替 / 銀行振込 / 立替精算 / 現金 等)ごとにほぼ固定で決まる決済条件(決済ラグ(月) / 支払基準日 / 休日調整方向)を新規マスタ 18_mst_payment_method に集約し、以下 3 つの課題を同時に解決する:
- 手入力による設定不整合の解消 — 20 番台予算タブ・32_wrk_invoice の各行で「決済手段=JCB」を選んでも、「決済ラグ(月)」「支払基準日」が手入力のため JCB 13 日 / 25 日 / 月末等、表記ゆれや設定忘れが混在する。マスタ参照に統一することで 1 箇所更新で全行に反映される
- カード会社の締日改定への追従 — カード会社が締日を変更した場合、マスタ 1 行の書き換えで全取引先・全タブに即反映。現状は既存行の手修正が必要
- MAS-120(取引先マスタ)の補完 — 取引先マスタに標準決済条件が登録されていない取引先(スポット契約・新規取引先など)でも、決済手段を選ぶだけで妥当なデフォルトを得られる
本案件は (a) 取引先マスタ(MAS-120) → (b) 決済手段マスタ(本件) → (c) 個別手入力値 という 3 層のフォールバック優先順位を確立する中間層を担う。
現在のコード
決済日計算ロジックの所在(集約された共通ヘルパーは存在しない)
調査の結果、決済日(決済日_計画)の算出ロジックは RPA 実装ファイルごとにインラインで記述されており、400_domain/400_rpa_common.js にも集約された共通ヘルパーは存在しない。各所の記述は概ね同一ロジックだが、フォールバック挙動が微妙に異なる。
402_rpa_subscription.js L206-222(SaaS サブスク):
// ラグ計算
let lagStr = idxLag !== -1 ? String(row[idxLag]) : '0';
lagStr = lagStr.replace(/[0-9]/g, function(s) { return String.fromCharCode(s.charCodeAt(0) - 0xFEE0); }).replace(/[^\d.-]/g, '');
const lag = parseInt(lagStr, 10) || 0;
// 発生日: 対象年月末日
const occurDate = new Date(cY, cM, 0);
// 決済予定日
const payDay = idxPayDay !== -1 ? (parseInt(String(row[idxPayDay]), 10) || 0) : 0;
var settleDate;
if (payDay > 0) {
const maxDay = new Date(cY, cM + lag, 0).getDate();
settleDate = new Date(cY, cM - 1 + lag, Math.min(payDay, maxDay));
} else {
settleDate = new Date(cY, cM + lag, 0);
}
405_rpa_adhoc.js L94-101(単発・アドホック予算):
var payDayRaw = col['支払基準日'] !== -1 ? (parseInt(String(row[col['支払基準日']]), 10) || 0) : 0;
var settleDate;
if (payDayRaw > 0) {
const maxDay = new Date(sY, sM, 0).getDate();
settleDate = new Date(sY, sM - 1, Math.min(payDayRaw, maxDay));
} else {
settleDate = new Date(oParts[0], oParts[1] + lag, 0);
}
406_rpa_pipeline.js L155-164(売上パイプライン / 入金):
function calcSettleDate(curYm) {
var sYm = Utils.addMonths(curYm, lag);
var sp = sYm.split('-').map(Number);
if (payDayRaw > 0) {
var maxDay = new Date(sp[0], sp[1], 0).getDate();
return new Date(sp[0], sp[1] - 1, Math.min(payDayRaw, maxDay));
}
return new Date(sp[0], sp[1], 0);
}
いずれも**「休日調整」を呼んでいない**。現状、Utils.adjustToBusinessDay(ymdStr, direction)(000_infra/004_utils.js L430)は実装済みだが、RPA 内部での呼び出し実例はなく、20 番台予算タブの「休日調整」列の値(例: 前営業日 / 翌営業日 / 空)は事実上読まれていない可能性が高い。本案件 Step 3 の改修対象。
既存マスタ DDL のパターン(100_config/101_sys_config.js)
L826-901 の schemas = { ... } 辞書で DDL を宣言的に定義。代表例:
'MST_ACCT': { headers: ["有効フラグ","主科目コード",...], color: "#666666" },
'MST_PART': { headers: [..., "標準決済手段","標準決済ラグ(月)","標準支払基準日","標準休日調整","標準CF計上区分"], color: "#666666",
validations: {
"標準決済ラグ(月)": { type: 'range', min: -1, max: 12 },
"標準支払基準日": { type: 'range', min: 1, max: 31 }
}
},
L769-824 の confSheet.appendRow(['MST_XXX', '', 'NN_xxx', '論理名']) パターンで 01_sys_config(Constants.CONFIG_SHEET)にシステムキーを登録する。本案件では MST_PMTM を同方式で追加する。
既存シート番号の割り当て状況(マスタ系 11_mst_* 〜 19_mst_*)
| 番号 | シート名 | ステータス |
|---|---|---|
| 11 | 11_mst_account | 実装済(MST_ACCT) |
| 12 | 12_mst_partner | 実装済(MST_PART) |
| 13 | 13_mst_organization | 実装済(MST_ORGN) |
| 14 | 14_mst_project | 実装済(MST_PROJ) |
| 15 | 15_mst_dictionary | 実装済(MST_DICT) |
| 16 | 16_wrk_master | 実装済(WRK_MAST:マスタ登録申請ワークフロー) |
| 17 | 17_mst_intellectual | 未実装(MAS-035 仕様書で予約) |
| 18 | 18_mst_tax_rate | 未実装(MAS-119 仕様書で予約) |
| 19 | 19_mst_loan_pattern | 未実装(MAS-121 仕様書で予約) |
シート番号の暫定割り当て: 本仕様書では 18_mst_payment_method を暫定案としているが、MAS-119(税率/保険料率マスタ)が同じ 18 番を予約済みのため番号衝突リスクあり。実装着手時に未着手仕様書との調整が必要(人間が検討すべき事項に記載)。候補は 17 / 18 / 19 / 20。
onEdit ハンドラの所在
100_config/101_sys_config.jsL409 に唯一のfunction onEdit(e)が存在し、内部からhandleUxAssist(e)を呼ぶ300_ui/301_ui_assist.jsL70handleUxAssistが実体(L75 のvalidSheets配列にシート名を登録)- MAS-120 実装で既に
applyPartnerPaymentTerms_ヘルパー(L42-66)が導入済み。対象シート判定マップPARTNER_TERMS_COL_MAP(L18-22)で21_bud_pipeline/23_bud_subscription/26_bud_adhocをカバー - 23_bud_subscription 分岐: L137-140(サービス名入力時の補完) + L158-161(取引先名後入力時の補完)
- 21_bud_pipeline 分岐: L333-336 + L347-350
- 26_bud_adhoc 分岐: L354-359
本案件では applyPartnerPaymentTerms_ 呼び出し後の残空欄に対して、同パターンで applyPaymentMethodTerms_ を呼ぶ 2 段フォールバック構造にする。
Repository パターン(200_data/202_repository.js)
L304-350 の AccountRepository が読み取り専用マスタ Repository の標準パターン:
var AccountRepository = {
_getSheet: function() { return Utils.getSheetByKey('MST_ACCT', '11_mst_account'); },
findAll: function() { return readSheetAsDtos_(AccountRepository._getSheet()); },
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: ..., cat: ... };
}
AccountRepository._cache = map;
return map;
},
_cache: null,
resetCache: function() { AccountRepository._cache = null; },
};
L356-406 の PartnerRepository(MAS-120 実装済)も同一パターンで、findPaymentTermsMap() が本案件の findAsMap() の直接の参考になる。
既存マイグレーションスクリプト
800_ops/ ディレクトリの使用番号: 801-809, 810, 811(810_migration_partner_payment_terms.js(MAS-120), 811_audit_checker.js)。次の空き番号は 812。
MAS-120 マイグレーション(810_migration_partner_payment_terms.js)は本案件の直接の参考実装で、以下のパターンを踏襲できる:
- 冒頭で
Repository.resetCache() - 対象シート群から決済条件を集計(最頻値抽出 + 同点は先出現優先)
Utils.auditLog('MIGRATE', ..., 'START'/'END')の監査ログSpreadsheetApp.getUi().alertでサマリ表示- 冪等性: 既存マスタ値が空欄の場合のみ setValue
修正方針
Step 1: DDL スキーマ追加(100_config/101_sys_config.js)
①confSheet.appendRow へのシステムキー登録(L818 付近、'SYS_TEST' の行の近傍に挿入):
if (!existKeys.includes('MST_PMTM')) confSheet.appendRow(['MST_PMTM', '', '18_mst_payment_method', 'マスタ_決済手段/決済条件']);
②schemas 辞書にエントリ追加(L835 MST_ORGN の前後、マスタ系がまとまって並んでいる位置に挿入):
'MST_PMTM': {
headers: ["有効フラグ","決済手段コード","決済手段名","標準決済ラグ(月)","標準支払基準日","標準休日調整","備考"],
color: "#666666",
validations: {
"標準決済ラグ(月)": { type: 'range', min: -1, max: 12, helpText: '-1〜12 の整数で入力してください(-1 = 前払い / 0 = 当月 / 正値 = 後払い月数)' },
"標準支払基準日": { type: 'range', min: 1, max: 31, helpText: '1〜31 の整数。月末の場合は 31 を入力(動的に末日に丸める)' }
}
},
③inputCols マッピング追加(L1189 MST_ACCT / L1190 MST_PART の近傍):
if (key === 'MST_PMTM') { inputCols = [1,2,3,4,5,6,7]; }
④プルダウン検証(setVali 群、L1485 の MST_PART の後に追加):
- 列 6(標準休日調整)→
UI休日調整(MAS-140 で名前付き範囲化予定。未定義時は前営業日 / 当日 / 翌営業日のハードコード値リストで暫定)
列定義の根拠:
決済手段コード: 英数 4 文字(例:JCB_,RKT_,BANK,CASH,DEPO)。将来マスタ間参照で使用決済手段名: 実データの表記に合わせる(JCB / 楽天カード / 口座振替 / 銀行振込 / 立替精算 / 現金 / 未定 等)。20 番台予算タブ・32_wrk_invoice の「決済手段」列の値と完全一致している必要あり(findAsMap()のキー)標準決済ラグ(月): MST_PART の標準決済ラグ(月)と同じ範囲-1〜12標準支払基準日: MST_PART の標準支払基準日と同じ範囲1〜31(31は動的に末日へ丸める)標準休日調整:前営業日/当日/翌営業日/ 空 の 4 値(Utils.adjustToBusinessDay のdirection引数との対応)
Step 2: PaymentMethodRepository / PaymentMethodDTO の新設
①000_infra/003_contracts.js に @typedef 追加(末尾、既存 PartnerDTO 等の後):
/**
* 18_mst_payment_method — 決済手段マスタ
* @typedef {Object} PaymentMethodDTO
* @property {boolean} 有効フラグ
* @property {string} 決済手段コード
* @property {string} 決済手段名
* @property {number} 標準決済ラグ(月)
* @property {number} 標準支払基準日
* @property {string} 標準休日調整
* @property {string} 備考
*/
②200_data/202_repository.js に PaymentMethodRepository を新設(PartnerRepository の直後・ファイル末尾に追加、既存 Repository は一切変更しない):
// =====================================================================
// PaymentMethodRepository — 18_mst_payment_method (読み取り専用マスタ)
// =====================================================================
var PaymentMethodRepository = {
/** @private */
_getSheet: function() {
return Utils.getSheetByKey('MST_PMTM', '18_mst_payment_method');
},
/**
* 全決済手段マスタレコードを DTO 配列で取得する。
* @returns {{ headers: string[], dtos: Object[] }}
*/
findAll: function() {
return readSheetAsDtos_(PaymentMethodRepository._getSheet());
},
/**
* 決済手段名をキーとする決済条件マップを返す(キャッシュ付き)。
* キー: 決済手段名(例: "JCB")
* 値: { lagMonths, baseDay, holidayDir, code }
* @returns {Object.<string, {lagMonths: number, baseDay: number, holidayDir: string, code: string}>}
*/
findAsMap: function() {
if (PaymentMethodRepository._cache) return PaymentMethodRepository._cache;
var result = PaymentMethodRepository.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) continue;
map[name] = {
code: String(dto['決済手段コード'] || '').trim(),
lagMonths: Number(dto['標準決済ラグ(月)']) || 0,
baseDay: Number(dto['標準支払基準日']) || 0,
holidayDir: String(dto['標準休日調整'] || '').trim(),
};
}
PaymentMethodRepository._cache = map;
return map;
},
/** @private */
_cache: null,
/** キャッシュをリセットする */
resetCache: function() {
PaymentMethodRepository._cache = null;
},
};
キャッシュ方針: AccountRepository / PartnerRepository と同一。GAS 実行単位でインメモリ保持。マイグレーション側では冒頭で resetCache() を呼ぶこと(MAS-003 失敗例回避)。
Step 3: 決済日計算ロジックの共通化 + フォールバック優先順位対応
①400_domain/400_rpa_common.js に共通ヘルパー RpaCommon.resolveSettlementTerms と RpaCommon.calcSettleDate を新設(ファイル末尾の resolveDefault の後に追加):
/**
* 決済条件をフォールバック順 (a)→(b)→(c) で解決する。
* @param {string} partnerName - 取引先名(UI用取引先名 or 取引先名_正式)
* @param {string} paymentMethod - 決済手段名
* @param {{lagMonths?: number, baseDay?: number, holidayDir?: string}} rowOverride - 行個別の手入力値
* @returns {{lagMonths: number, baseDay: number, holidayDir: string, source: string}}
* source: 'partner' | 'method' | 'row' | 'default'(デバッグ用)
*/
resolveSettlementTerms: function(partnerName, paymentMethod, rowOverride) {
var result = {
lagMonths: null,
baseDay: null,
holidayDir: '',
source: 'default',
};
var ov = rowOverride || {};
// (a) 取引先マスタ(S-48) — 最上位
var partnerKey = String(partnerName || '').trim();
if (partnerKey) {
try {
var pMap = PartnerRepository.findPaymentTermsMap();
var t = pMap[partnerKey];
if (t) {
if (result.lagMonths === null && t['決済ラグ月'] !== '' && t['決済ラグ月'] != null) {
result.lagMonths = Number(t['決済ラグ月']);
result.source = 'partner';
}
if (result.baseDay === null && t['支払基準日'] !== '' && t['支払基準日'] != null) {
result.baseDay = Number(t['支払基準日']);
result.source = 'partner';
}
if (!result.holidayDir && t['休日調整']) {
result.holidayDir = t['休日調整'];
result.source = 'partner';
}
}
} catch (e) { /* マスタ未整備時はフォールスルー */ }
}
// (b) 決済手段マスタ(本案件)
var methodKey = String(paymentMethod || '').trim();
if (methodKey) {
try {
var mMap = PaymentMethodRepository.findAsMap();
var m = mMap[methodKey];
if (m) {
if (result.lagMonths === null) { result.lagMonths = m.lagMonths; if (result.source === 'default') result.source = 'method'; }
if (result.baseDay === null) { result.baseDay = m.baseDay; if (result.source === 'default') result.source = 'method'; }
if (!result.holidayDir) { result.holidayDir = m.holidayDir; if (result.source === 'default') result.source = 'method'; }
}
} catch (e) { /* マスタ未整備時はフォールスルー */ }
}
// (c) 行個別の手入力値
if (result.lagMonths === null && ov.lagMonths !== undefined && ov.lagMonths !== '') {
result.lagMonths = Number(ov.lagMonths);
if (result.source === 'default') result.source = 'row';
}
if (result.baseDay === null && ov.baseDay !== undefined && ov.baseDay !== '') {
result.baseDay = Number(ov.baseDay);
if (result.source === 'default') result.source = 'row';
}
if (!result.holidayDir && ov.holidayDir) {
result.holidayDir = ov.holidayDir;
if (result.source === 'default') result.source = 'row';
}
// デフォルト (ラグ=0 / 末日 / 調整なし)
if (result.lagMonths === null) result.lagMonths = 0;
if (result.baseDay === null) result.baseDay = 0; // 0 = 月末指定
return result;
},
/**
* 発生年月・決済条件から決済予定日を計算する。
* @param {string} occurYm - 発生年月 "YYYY-MM"
* @param {{lagMonths: number, baseDay: number, holidayDir: string}} terms
* @returns {Date}
*/
calcSettleDate: function(occurYm, terms) {
if (!occurYm) return null;
var targetYm = Utils.addMonths(occurYm, terms.lagMonths || 0);
var parts = targetYm.split('-').map(Number);
var y = parts[0], m = parts[1];
var settle;
if (terms.baseDay && terms.baseDay > 0) {
var maxDay = new Date(y, m, 0).getDate();
var day = Math.min(terms.baseDay, maxDay);
settle = new Date(y, m - 1, day);
} else {
settle = new Date(y, m, 0); // 月末
}
// 休日調整
if (terms.holidayDir === '前営業日' || terms.holidayDir === '翌営業日') {
var dir = terms.holidayDir === '翌営業日' ? '後' : '前';
var ymdStr = Utilities.formatDate(settle, Session.getScriptTimeZone(), 'yyyy-MM-dd');
var adjusted = Utils.adjustToBusinessDay(ymdStr, dir);
var ap = adjusted.split('-').map(Number);
settle = new Date(ap[0], ap[1] - 1, ap[2]);
}
return settle;
},
②既存 RPA 3 ファイルの決済日計算箇所を共通ヘルパーに置き換え:
400_domain/402_rpa_subscription.jsL206-222 →RpaCommon.resolveSettlementTerms(ptnName, payMethodStr, { lagMonths: lag, baseDay: payDay, holidayDir: /* 該当列値 */ })+RpaCommon.calcSettleDate(curYm, terms)に置き換え400_domain/405_rpa_adhoc.jsL94-101 → 同様の置き換え400_domain/406_rpa_pipeline.jsL155-164(calcSettleDateインライン関数)→ 共通ヘルパー呼び出しに置き換え
互換性維持の観点:
- 既存 RPA のラグ計算に含まれる「全角数字→半角変換」「
[^\d.-]除去」は、文字列として入力された値をNumber()で受けた場合の挙動差に注意。resolveSettlementTermsの行個別値受け取り時に同変換を適用するか、呼び出し側で数値化してから渡す - 既存の
payMethodStr.includes('未定')で空文字化する分岐(402 L260)は本ヘルパー外部で引き続き適用
Step 4: onEdit 自動補完の追加(300_ui/301_ui_assist.js)
MAS-120 の applyPartnerPaymentTerms_ の直後に 2 段目フォールバックとして applyPaymentMethodTerms_ を呼び出す。
①マッピング追加(L18-22 PARTNER_TERMS_COL_MAP の直後に PAYMENT_METHOD_TERMS_COL_MAP を新設。同じ列構成で使い回し可能):
// 決済手段マスタから引く列。マスタの「標準〜」から取得し、決済手段列が未編集でも補完対象とする
var PAYMENT_METHOD_TERMS_COL_MAP = {
'21_bud_pipeline': { 決済ラグ月: '入金ラグ(月)', 支払基準日: '入金日', 休日調整: '休日調整' },
'23_bud_subscription': { 決済ラグ月: '決済ラグ(月)', 支払基準日: '支払基準日', 休日調整: '休日調整' },
'26_bud_adhoc': { 決済ラグ月: '決済ラグ(月)', 支払基準日: '支払基準日' }, // 休日調整 列なし
'32_wrk_invoice': { }, // INV には決済条件列なし(決済日_計画 のみ)→ 別処理
};
②ヘルパー関数新設(applyPartnerPaymentTerms_ の直後、L66 直後):
/**
* 決済手段マスタの標準決済条件を対象シートの空欄セルに転記する(S-48 補完の 2 段目)。
* - S-48 `applyPartnerPaymentTerms_` 実行後に呼ばれる想定
* - 「空欄のみ補完」原則。ユーザー手入力値は保護
* - マスタ未登録の決済手段は何もしない
* @param {GoogleAppsScript.Spreadsheet.Sheet} sheet
* @param {number} row
* @param {string[]} headers
* @param {string} paymentMethod - 決済手段名
*/
function applyPaymentMethodTerms_(sheet, row, headers, paymentMethod) {
if (!paymentMethod) return;
var sName = sheet.getName();
var mapKeyName = Object.keys(PAYMENT_METHOD_TERMS_COL_MAP).find(function(k) { return sName.indexOf(k) !== -1; });
if (!mapKeyName) return;
var colMap = PAYMENT_METHOD_TERMS_COL_MAP[mapKeyName];
var methodMap = PaymentMethodRepository.findAsMap();
var terms = methodMap[String(paymentMethod).trim()];
if (!terms) return;
var valueByKey = {
決済ラグ月: terms.lagMonths,
支払基準日: terms.baseDay,
休日調整: terms.holidayDir,
};
Object.keys(colMap).forEach(function(termKey) {
var colName = colMap[termKey];
var cIdx = headers.indexOf(colName);
if (cIdx === -1) return;
var cell = sheet.getRange(row, cIdx + 1);
if (!cell.isBlank()) return; // 既存値は保護(S-48 補完済を含む)
var v = valueByKey[termKey];
if (v === '' || v == null || v === 0) return; // マスタ値が空/0 は転記しない(意図的に無設定の可能性)
cell.setValue(v);
});
}
③呼び出し位置:
- 21_bud_pipeline / 23_bud_subscription / 26_bud_adhoc の各「取引先名」入力ブロック内、
applyPartnerPaymentTerms_(...)の直後に:var pmIdx = headers.indexOf('決済手段'); if (pmIdx !== -1) { applyPaymentMethodTerms_(sheet, row, headers, sheet.getRange(row, pmIdx + 1).getValue()); } - さらに「決済手段列が直接編集された場合」の分岐を新設(
colName === '決済手段' && val):if (colName === '決済手段' && val) { applyPaymentMethodTerms_(sheet, row, headers, val); } - 32_wrk_invoice では既存のマスタ補完ブロック(L269-281 付近)に準じて、「決済手段」編集時に
決済日_計画が空欄であればRpaCommon.calcSettleDate(発生日YM, terms)を使って補完するオプション追加(人間が検討すべき事項)
Step 5: マイグレーションスクリプト(800_ops/812_migration_payment_method.js 新規)
関数名: migrationS63PaymentMethod()
function migrationS63PaymentMethod() {
var FUNC = 'migrationS63PaymentMethod';
Utils.auditLog('MIGRATE', '', '', '', FUNC, '', '', 'START');
try {
if (PaymentMethodRepository.resetCache) PaymentMethodRepository.resetCache();
// 1. 32_wrk_invoice / 21_bud_pipeline / 23_bud_subscription / 26_bud_adhoc の
// 「決済手段」列から実在値を収集 + 各決済手段ごとに
// (決済ラグ, 支払基準日, 休日調整) の最頻値を抽出
// (26_bud_adhoc は休日調整列なし → スキップ)
// 2. PaymentMethodRepository.findAll() で既存 18_mst_payment_method を取得
// 3. 集計結果をプレビューダイアログで表示
// 「以下 N 件の決済手段をマスタに登録します。よろしいですか?」
// (Human-in-the-Loop: 承認された場合のみ書き込み)
// 4. 承認後、未登録の決済手段のみ appendRow で追加(冪等性:同名行があればスキップ)
// 既存行の値は一切上書きしない
// 5. Utils.logInfo + SpreadsheetApp.getUi().alert でサマリ表示
} catch (e) {
Utils.logError(FUNC, e);
SpreadsheetApp.getUi().alert('エラー', e.message, SpreadsheetApp.getUi().ButtonSet.OK);
}
}
メニュー登録(000_infra/002_constants.js L298-309 の MENU_DEFINITION の「📋 サイドバー: 🔧 マイグレーション」カテゴリの items 配列に、MAS-120 のエントリの直後に追加。101_sys_config.js の onOpen はこの配列を動的ループして生成するため、002_constants.js のみの編集で反映される):
{ label: 'S-63: 決済手段マスタ化', funcName: 'migrationS63PaymentMethod', description: 'S-63 既存データから決済手段別の最頻値をマスタに冪等投入' },
影響範囲
| 変更ファイル | 変更量 | 内容 |
|---|---|---|
100_config/101_sys_config.js | 約 10 行 | MST_PMTM スキーマ 1 ブロック追加、confSheet.appendRow 1 行、inputCols 1 行、setVali 1 行 |
000_infra/003_contracts.js | 約 15 行 | PaymentMethodDTO @typedef 追加のみ |
200_data/202_repository.js | 約 50 行 | PaymentMethodRepository の新設(_getSheet / findAll / findAsMap / _cache / resetCache) |
400_domain/400_rpa_common.js | 約 100 行 | resolveSettlementTerms + calcSettleDate の 2 ヘルパー追加 |
400_domain/402_rpa_subscription.js | 約 15 行(差し引き) | L206-222 のインライン計算を RpaCommon.resolveSettlementTerms + calcSettleDate 呼び出しに置き換え |
400_domain/405_rpa_adhoc.js | 約 10 行(差し引き) | L94-101 を同様に置き換え |
400_domain/406_rpa_pipeline.js | 約 10 行(差し引き) | L155-164 の calcSettleDate インライン関数を共通ヘルパーに置き換え |
300_ui/301_ui_assist.js | 約 60 行 | PAYMENT_METHOD_TERMS_COL_MAP + applyPaymentMethodTerms_ + 3-4 シートでの呼び出し追加(MAS-120 補完の直後・colName === '決済手段' 分岐) |
000_infra/002_constants.js | 1 行 | MENU_DEFINITION の「🔧 マイグレーション」カテゴリに 1 エントリ追加 |
800_ops/812_migration_payment_method.js | 約 150 行(新規) | プレビュー付き冪等 INSERT マイグレーション |
既存動作への影響:
setupAllSchemas実行後に18_mst_payment_methodシートが新規作成される(既存シートには影響なし)- MAS-120 の
applyPartnerPaymentTerms_は一切変更せず、その後に本案件の補完が走るため MAS-120 の挙動は不変 - RPA 3 ファイルの決済日計算結果は、マスタ未整備時は従来と同じ値を返す必要がある(互換性保持)。マスタ整備後は休日調整が新たに効くようになる(挙動変化あり)
32_wrk_invoiceの既存行は変更しない(マイグレーションは18_mst_payment_methodへの INSERT のみ)
注意事項
- onEdit 補完は「空欄のみ」を厳守 — ユーザーが手動設定した値を上書きしない。MAS-120 の
applyPartnerPaymentTerms_と同じくcell.isBlank()チェック必須 - フォールバック優先順位 (a)→(b)→(c) を全処理で徹底 —
resolveSettlementTermsを単一の参照点とし、RPA・onEdit の両方が同じ関数を呼ぶことで実装の一貫性を担保 - MAS-120 との協調 — 本案件は MAS-120 の次段フォールバック。MAS-120 で取引先マスタから補完済の列は空欄にならないため、
applyPaymentMethodTerms_は自動的にスキップされる(正しい挙動) - マスタキーは「決済手段名」の完全一致 —
findAsMap()のキーはString(dto['決済手段名']).trim()。20 番台予算タブ・32_wrk_invoice の「決済手段」列の表記(例:JCB/楽天カード)と完全一致している必要あり。表記ゆれは MAS-139(セル単位バリデーション)で防止する前提 - 「標準支払基準日 = 31」で月末を表現 — 動的に月末へ丸める(
Math.min(baseDay, maxDay)ロジック)。末日指定を意味するフラグは別途持たない - 休日調整の値域 —
前営業日/当日/翌営業日/ 空 の 4 値のみ。空欄(または当日)の場合はUtils.adjustToBusinessDayを呼ばない - マイグレーションは冪等 + Human-in-the-Loop — プレビューダイアログで承認された場合のみ書き込み。2 回目実行では既存行を全スキップ
- Repository キャッシュは GAS 実行単位 — マイグレーション冒頭で
PaymentMethodRepository.resetCache()を呼ばないと、直前の onEdit で読み込まれた古いマップが残る可能性あり(MAS-003 失敗例 #18) - MAS-120 未作成の場合の設計 — 本案件では MAS-120 は実装完了済として扱う。仕様書の前提案件テーブルにも記載の通り、
PartnerRepository.findPaymentTermsMapは既に利用可能な状態である。万が一 MAS-120 が dev 環境でのみ未反映の場合はtry/catchで優先順位 (a) をスキップし (b) から始める設計にしている - シート番号衝突の確認 —
18_mst_payment_methodは MAS-119(税率マスタ)が同じ 18 番を予約済。実装直前に MAS-119 実装状況を再確認し、必要なら 20〜25 の未使用番号に変更する
エッジケース
| 条件 | 挙動 | 理由 |
|---|---|---|
| 決済手段名がマスタ未登録 | 自動補完スキップ、手入力値をそのまま尊重。RPA は従来どおり行の手入力値で計算 | マスタ強制でユーザー入力を破壊しない |
| 標準支払基準日 = 31(月末) | Math.min(31, maxDay) で末日に動的に丸める(例: 2月は 28/29、4月は 30) | 月によって末日が異なるため |
| 休日調整方向が空欄 | Utils.adjustToBusinessDay を呼ばず調整なし | 未設定はユーザーの意図として尊重 |
| 標準決済ラグ(月) = 0 | 当月決済。Utils.addMonths(ym, 0) は同月を返す | 即時・当月決済の表現 |
| 標準決済ラグ(月) が負値(-1 等) | 前払い扱い。発生月より前の月を Utils.addMonths で算出(MST_PART の -1〜12 バリデーションに合わせる) | 前払金取引への対応 |
| 「現金」決済手段 | ラグ=0 / 支払基準日=0(= 発生日と同日扱い、new Date(y, m, 0) は末日になるため基準日 0 は別処理要件化)/ 休日調整=空 で登録 | 即時決済の慣習 |
| 「未定」決済手段 | マスタ登録しない(マイグレーション時のフィルタで除外)。RPA 402 L260 既存の .includes('未定') 分岐で空文字化される | 確定前状態はマスタ管理外 |
| onEdit 時に補完対象セルに既存値あり | 上書きしない(cell.isBlank() チェックを先行) | Human-in-the-Loop:ユーザー設定値を保護 |
| マイグレーションスクリプト 2 回目実行 | 同一「決済手段名」行をスキップ(冪等性)。プレビューダイアログの登録候補 0 件 | 重複挿入による不整合防止 |
| 優先順位 (a) と (b) が両方存在する | resolveSettlementTerms が (a) 取引先マスタ設定を優先して採用。source: 'partner' を返す | 取引先個別設定が最上位 |
| 優先順位 (a) が取引先マスタの一部項目のみ設定 | (a) で埋まらなかった項目のみ (b) から補完。1 行内で source 混在可 | 部分補完を許容(MAS-120 設計と整合) |
| マスタ名の表記ゆれ(半角スペース・全角/半角) | .trim() で前後空白のみ吸収。内部空白・全角半角は区別 | 厳密一致のほうが安全。MAS-139 バリデーションで入力時点で防ぐ |
Utils.adjustToBusinessDay の direction 引数 | '後' → 翌営業日、それ以外 → 前営業日。本仕様書では 翌営業日 → '後'、前営業日 → '前' を渡す | 既存ヘルパーの仕様に整合 |
| 複数マスタに同じ「決済手段名」が有効=TRUE で 2 行存在 | 後勝ち(for ループ最後の行で上書き)。マイグレーションは新規 INSERT のため発生しない | 運用上発生すべきでない。Utils.logWarn で警告を出す |
| onEdit で決済手段列のみ編集・取引先名未入力 | applyPaymentMethodTerms_ のみ発火(applyPartnerPaymentTerms_ はスキップ)、決済手段マスタからの補完のみ実行 | 決済手段単独でも補完が効く |
| RPA 実行中にマスタ未整備 | resolveSettlementTerms は try/catch で (b) をスキップ、行個別値 (c) にフォールバック。既存 RPA と同じ結果 | 段階導入時の互換性保持 |
| 決済手段マスタの「標準支払基準日」が "15" (文字列) | Number() で数値化。NaN の場合は 0 として扱い月末計算へ | DDL で range バリデーション済だが防御的に数値化 |
実データ検証(実装前に必須)
仕様書記述時および実装前に、以下を MCP / GAS エディタで確認すること(失敗パターン #18-#20 の轍を踏まないため):
32_wrk_invoiceの「決済手段」列の実データ — ユニーク値一覧(初期マスタ候補)。=UNIQUE(W:W)等で取得し、JCB/楽天カード/銀行振込/口座振替/立替精算/現金/未定以外の表記ゆれの有無を確認21_bud_pipeline/23_bud_subscription/26_bud_adhocの「決済手段」列 — 同様にユニーク値確認。20 番台タブは数十件〜数百件程度の想定01_sys_config(Constants.CONFIG_SHEET)のシステムキー命名規則 —MST_ACCT/MST_PART/MST_ORGN/MST_PROJ/MST_DICT等の 8 文字以内が既定パターン。本案件のMST_PMTMもこれに準拠- シート番号
18_mst_payment_methodの衝突確認 — 以下の未実装スペックとの競合確認:- MAS-119(
18_mst_tax_rate)—docs/dev/dev_mas-119_headcount_rate_master.md - MAS-121(
19_mst_loan_pattern)—docs/dev/dev_mas-121_capex_master_ref.md - MAS-035(
17_mst_intellectual)— 仕様書未作成 いずれかが先行実装されている場合は番号を再割り当て
- MAS-119(
- 既存 RPA の決済日計算の現在値 — 改修前後で結果が一致することを dev で確認するためのベースライン。代表 5〜10 件の
settleDateを改修前に記録 12_mst_partnerの「標準〜」列のデータ充足率 — MAS-120 マイグレーションで埋まった件数。空欄が多ければ (b) 決済手段マスタの利用頻度が高くなる18_dropdownシートの名前付き範囲 —UI休日調整/UI決済手段が存在するか(MAS-140 で追加予定)。存在しなければ本案件では「文字列リスト直指定」で暫定対応し、MAS-140 完了後に名前付き範囲参照に切替Utils.getSheetByKey('MST_PMTM', '18_mst_payment_method')のフォールバック —01_sys_configに MST_PMTM キーが登録される前の呼び出しで、物理名'18_mst_payment_method'で解決できることを dev で確認
関連ドキュメント
| 仕様書 | 関連箇所 |
|---|---|
| dev_mas-120_partner_payment_terms_autofill.md | 前提案件。取引先マスタ 5 列拡張・PartnerRepository.findPaymentTermsMap の実装。本案件のフォールバック優先順位 (a) を提供 |
| dev_mas-116_migration_framework.md | マイグレーション設計基盤(冪等性・Utils.auditLog・メニュー登録の統一パターン)。本案件 Step 5 の参考 |
| dev_mas-119_headcount_rate_master.md | 未実装だが 18_mst_tax_rate シート番号を予約済。番号衝突の確認対象 |
| dev_mas-121_capex_master_ref.md | 未実装だが 19_mst_loan_pattern シート番号を予約済。同上 |
| dev_mas-085_consistency_check.md | 整合性チェック系仕様書のフォーマット参考 |
| dev_mas-139_data_validation.md | セル単位バリデーション。決済手段列の表記ゆれをマスタ参照プルダウンで防ぐ前提 |
| dev_mas-140_partner_payment_terms_polish.md | MAS-120 の後追い整備。UI休日調整 等の名前付き範囲追加。本案件のプルダウンソースを共用する |
| CLAUDE.md | コーディング規約・マイグレーション運用ガイドライン・800_ops 番号付け(次は 812) |
人間が検討すべき事項
以下は TODO_future.md L244 の MAS-135 エントリで「人間が検討すべき事項」として列挙された項目をそのまま転記し、本仕様書での推奨回答を添えたもの:
| 検討事項(TODO_future.md 原文) | 本仕様書での推奨対応 | 未確定事項 |
|---|---|---|
| MAS-120(取引先マスタ標準決済条件)との優先順位設計 | (a) 取引先マスタ → (b) 決済手段マスタ → (c) 個別入力、で確定。resolveSettlementTerms が単一参照点 | — |
| カード会社の締日が月中改定された場合の扱い(発生日ベース or 決済予定日ベースで切替) | 発生日ベースを推奨。マスタ更新時点以降の発生分に新締日が適用、既存行は手動更新または個別マイグレーションで対応 | 発生日ベースか決済予定日ベースかを関係者と合意 |
| 「未定」「現金」等の決済手段の扱い(マスタ登録の要否) | 「未定」は登録しない(RPA 側で空文字化される)。「現金」は登録する(ラグ=0 / 基準日=0(当日)/ 休日調整=空) | 「現金」の基準日表現方式(0 を当日扱いにするか別フラグを設けるか) |
| 既存 INV のマイグレーション粒度(全 INV バックフィル or 新規分のみ) | 新規分のみ(既存 INV は一切触らない)。マスタ整備後の新規起票から新ロジックが効く段階導入方式 | 既存 INV のうち 決済日_計画 が空の行にバックフィルするか否か |
| 本案件のシート番号(18 or 他) | 暫定 18_mst_payment_method。MAS-119 / MAS-121 の実装順と調整。必要なら 20_mst_payment_method へ変更 | MAS-119 / MAS-121 / MAS-035 との番号調整の最終決定 |
| マイグレーション実行フローの承認方式 | プレビューダイアログ方式(登録候補一覧を表示 → OK 押下で書き込み)。Human-in-the-Loop 必須 | 承認 UI の詳細(HTML モーダル vs シンプル alert) |
onEdit の対象シートに 32_wrk_invoice を含めるか | 含めるが、INV には 決済ラグ(月) 等の列がないため「決済手段 → 決済日_計画 自動算出」のみ適用(オプション。デフォルト OFF が安全) | INV での onEdit 補完を本案件スコープに含めるか、別案件に切り出すか |
休日調整の値域(前営業日 / 当日 / 翌営業日 以外の選択肢要否) | 現状 3 値で十分。将来 T+2 決済等が必要になった段階で拡張 | — |
その他、実装着手前に関係者合意が必要な事項:
- RPA 改修の後方互換性テスト — 改修前後で同じ入力に対して同じ
settleDateが返ることを dev で 10 件以上の代表ケースで検証(マスタ未整備状態での互換性) - キャッシュ失効タイミング — マスタを手動編集した直後の onEdit では古いキャッシュを返す可能性。運用で許容するか、
resetCacheをメニュー化するか
実装プロンプト(Claude Code 用)
あなたはGAS会計システム(bizlp-gas-accounting)のシニア開発者です。
案件 MAS-135「決済手段マスタの新設(決済条件マスタ化)」を実装してください。
5 Step に段階実装し、各 Step 完了後に dev で動作確認してから次へ進むこと。
## 実行前タスク(必ず Read すること)
- `docs/dev/dev_mas-135_payment_method_master.md` — 本仕様書の全文
- `docs/dev/dev_mas-120_partner_payment_terms_autofill.md` — 前提案件(実装完了済)の全文。本案件は MAS-120 の直接的な拡張
- `docs/_internal/failure_patterns.md` — 特に #18-#20(固有名詞の Read 確認原則)
- `100_config/101_sys_config.js`
- L769-824 `confSheet.appendRow` のシステムキー登録パターン
- L826-901 `schemas = { ... }` 辞書(MST_PART の validations が参考)
- L1189-1190 `inputCols` 分岐
- L1485-1486 `setVali` プルダウン検証ブロック
- `000_infra/003_contracts.js` — 既存 `@typedef` 書式(ファイル末尾)
- `200_data/202_repository.js`
- L304-350 `AccountRepository` — キャッシュ付き Repository の参考
- L356-406 `PartnerRepository` — MAS-120 で追加された直接の参考(同パターンを踏襲)
- `400_domain/400_rpa_common.js` — 末尾 `resolveDefault` の後に新ヘルパーを追加する
- `400_domain/402_rpa_subscription.js` L206-222 — 決済日計算のインライン箇所
- `400_domain/405_rpa_adhoc.js` L94-101 — 同上
- `400_domain/406_rpa_pipeline.js` L155-164 — `calcSettleDate` インライン関数
- `300_ui/301_ui_assist.js`
- L18-22 `PARTNER_TERMS_COL_MAP`(本案件で `PAYMENT_METHOD_TERMS_COL_MAP` を同パターンで追加)
- L42-66 `applyPartnerPaymentTerms_`(直後に `applyPaymentMethodTerms_` を追加)
- L75 `validSheets` 配列
- L137-161 / L333-359 取引先名入力時の補完ブロック(直後に本案件の呼び出しを追加)
- `800_ops/810_migration_partner_payment_terms.js` — MAS-120 マイグレーションの完成形。本案件 Step 5 の直接のテンプレート
- `000_infra/002_constants.js` L298-309 — `MENU_DEFINITION` の「📋 サイドバー: 🔧 マイグレーション」カテゴリ(メニュー追加先)
- `000_infra/004_utils.js` L389 `addMonths` / L430 `adjustToBusinessDay` — 決済日計算で呼び出すユーティリティ
## 修正対象ファイル
1. `100_config/101_sys_config.js` — DDL 追加(既存コードへの追記のみ)
2. `000_infra/003_contracts.js` — `PaymentMethodDTO` `@typedef` 追加
3. `200_data/202_repository.js` — `PaymentMethodRepository` 新規追加(末尾)
4. `400_domain/400_rpa_common.js` — `resolveSettlementTerms` + `calcSettleDate` 新設
5. `400_domain/402_rpa_subscription.js` L206-222 — インライン計算を共通ヘルパー呼び出しに置換
6. `400_domain/405_rpa_adhoc.js` L94-101 — 同上
7. `400_domain/406_rpa_pipeline.js` L155-164 — 同上
8. `300_ui/301_ui_assist.js` — `PAYMENT_METHOD_TERMS_COL_MAP` + `applyPaymentMethodTerms_` + 呼び出し追加
9. `000_infra/002_constants.js` L298-309 — マイグレーションメニューに 1 項目追加
10. `800_ops/812_migration_payment_method.js` — 新規ファイル作成
## 実装内容
### Step 1: DDL スキーマ追加
実行前タスク:
- `100_config/101_sys_config.js` L826-901 の `schemas` 辞書を Read し、MST_ORGN / MST_PART の記述位置と書式を確認
- `000_infra/002_constants.js` の `CONFIG_SHEET` 値(`'01_sys_config'`)を Read で確認
実装内容:
- L818 付近に `if (!existKeys.includes('MST_PMTM')) confSheet.appendRow(['MST_PMTM', '', '18_mst_payment_method', 'マスタ_決済手段/決済条件']);` を追加
- `schemas` 辞書に `'MST_PMTM'` エントリを追加(本仕様書「修正方針 Step 1」の②の通り)
- L1189-1190 の inputCols 分岐に `if (key === 'MST_PMTM') { inputCols = [1,2,3,4,5,6,7]; }` を追加
- `setVali` でプルダウン検証を追加(標準休日調整 列 6 → `UI休日調整` 参照 or 文字列リスト暫定)
制約:
- 既存シートへの影響なし(新規シート作成のみ)
- 既存スキーマ定義(MST_ACCT / MST_PART 等)は触らない
- シート番号 `18` が MAS-119 と衝突する場合は関係者に確認してから別番号に変更
動作確認:
- `npm run push:dev` → GAS で `setupAllSchemas` を実行 → `18_mst_payment_method` シート新規作成
- `01_sys_config` に `MST_PMTM` 行が追加されている
- サンプル 2-3 行を手入力(JCB / 楽天カード / 銀行振込 等)し、バリデーションがかかること
### Step 2: PaymentMethodRepository / DTO 新設
実行前タスク:
- `200_data/202_repository.js` L304-406 を Read し、AccountRepository / PartnerRepository のパターンを完全理解
- `000_infra/003_contracts.js` の末尾 `@typedef` 群の書式を確認
実装内容:
- `003_contracts.js` 末尾に `PaymentMethodDTO` `@typedef` を追加
- `202_repository.js` 末尾(`PartnerRepository` L406 の直後)に `PaymentMethodRepository` を追加(本仕様書「修正方針 Step 2」の②の通り。5 メンバ: `_getSheet / findAll / findAsMap / _cache / resetCache`)
- `901_test_runner.js` に `PaymentMethodRepository.findAll().dtos.length >= 0` の簡易テストを追加
制約:
- `AccountRepository` / `PartnerRepository` のキャッシュパターンを忠実に踏襲
- `findAsMap` のキーは「決済手段名」を `.trim()` した文字列
- 有効フラグ=FALSE の行は除外
動作確認:
- GAS で `PaymentMethodRepository.findAll()` を実行 → Step 1 で手入力したサンプルが DTO 配列で返る
- `PaymentMethodRepository.findAsMap()['JCB']` が `{ code, lagMonths, baseDay, holidayDir }` を返す
- `901_test_runner.js` の新テストが合格
### Step 3: 決済日計算ロジックの共通化
実行前タスク:
- `400_domain/400_rpa_common.js` 全体を Read(既存 RpaCommon 名前空間の構造を把握)
- `400_domain/402_rpa_subscription.js` L200-230 を Read し、インライン計算の前後関係を把握
- `400_domain/405_rpa_adhoc.js` L85-110 / `400_domain/406_rpa_pipeline.js` L150-170 を同様に Read
- `000_infra/004_utils.js` L389 `addMonths` / L430 `adjustToBusinessDay` の引数仕様を再確認
実装内容:
- `400_rpa_common.js` の `RpaCommon` オブジェクト末尾に `resolveSettlementTerms` / `calcSettleDate` を追加(本仕様書「修正方針 Step 3」の①の通り)
- 402_rpa_subscription.js L206-222 を以下に置換:
`var terms = RpaCommon.resolveSettlementTerms(ptnName, payMethodStr, { lagMonths: lag, baseDay: payDay, holidayDir: /* 列値 */ });`
`var settleDate = RpaCommon.calcSettleDate(curYm, terms);`
- 405_rpa_adhoc.js / 406_rpa_pipeline.js も同様に置換
- 既存の「全角数字→半角変換」「`[^\d.-]` 除去」は呼び出し側に残すか、`resolveSettlementTerms` の受け取り時に吸収するかは、失敗テストがあれば呼び出し側維持を選択
制約:
- **互換性テスト必須**: 改修前後で同じ入力に対して同じ `settleDate` が返ることを dev で 10 件以上検証(マスタ未整備の状態で)
- マスタに該当エントリがない場合は `(c)` 行個別値にフォールバックするよう `try/catch` で防御
- `Utils.adjustToBusinessDay` の `direction` 引数は `'後'` or その他。本仕様書では `'翌営業日'` → `'後'`、`'前営業日'` → `'前'` にマッピング
動作確認:
- `runAllTests` で既存テストが回帰していないこと
- RPA 3 種(SaaS / Adhoc / Pipeline)を dev で実行 → 生成された `決済日_計画` が改修前と一致
- マスタに JCB を 15 日/前営業日 で登録 → 23_bud_subscription に JCB サブスクを追加 → 生成される `決済日_計画` が 15 日(土日祝日なら前営業日)になる
### Step 4: onEdit 自動補完の追加
実行前タスク:
- `300_ui/301_ui_assist.js` L18-22 / L42-66 / L137-161 / L333-359 を Read
- MAS-120 の `applyPartnerPaymentTerms_` の動作を完全理解(空欄判定・既定値上書き判定)
実装内容:
- L22 の `PARTNER_TERMS_COL_MAP` 直後に `PAYMENT_METHOD_TERMS_COL_MAP` を定義(本仕様書「修正方針 Step 4」の①の通り)
- L66 の `applyPartnerPaymentTerms_` 直後に `applyPaymentMethodTerms_` を新設(本仕様書「修正方針 Step 4」の②の通り)
- 各シートの取引先名入力ブロック(L139 / L335 / L356)に `applyPaymentMethodTerms_` の呼び出しを追加
- 各シートで新たに `colName === '決済手段' && val` 分岐を追加し、決済手段が直接編集された場合も補完
制約:
- **空欄のみ補完**(`cell.isBlank()` チェック必須)。MAS-120 で補完された値を上書きしない
- マスタ未登録の決済手段は何もしない(`return` 早期)
- `26_bud_adhoc` は休日調整列がないため `indexOf === -1` で自動スキップ
- `32_wrk_invoice` での onEdit 補完は、まず **OFF** でリリース(人間検討事項)
動作確認:
- マスタに JCB(ラグ=1 / 基準日=25 / 休日調整=前営業日)を登録
- 23_bud_subscription で新規行を作成 → 取引先名 "未マスタの取引先" を入力 → 決済手段 "JCB" を入力
- 決済ラグ(月)=1 / 支払基準日=25 / 休日調整=前営業日 が自動セット
- 既に決済ラグ(月)=2 が入っている行で決済手段を "JCB" に変更 → 2 が維持されること(上書きしない)
- MAS-120 登録済み取引先(標準決済手段=楽天カード)を入力 → applyPartnerPaymentTerms_ が先に発火 → applyPaymentMethodTerms_ は空欄がなくスキップされる
### Step 5: マイグレーションスクリプト
実行前タスク:
- `800_ops/810_migration_partner_payment_terms.js` 全体を Read(最頻値集計・冪等性保証の完成形)
- `000_infra/002_constants.js` L298-309 を Read(メニュー追加先の配列構造)
実装内容:
- `800_ops/812_migration_payment_method.js` を新規作成
- 関数名: `migrationS63PaymentMethod`
- 冒頭で `PaymentMethodRepository.resetCache()` + `Utils.auditLog('MIGRATE', ..., 'START')`
- 32_wrk_invoice / 21_bud_pipeline / 23_bud_subscription / 26_bud_adhoc の「決済手段」列から実値を収集
- 各決済手段ごとに (決済ラグ・支払基準日・休日調整) の最頻値を抽出(`810_migration_partner_payment_terms.js` の集計ロジックを流用)
- プレビュー文字列を組み立て → `SpreadsheetApp.getUi().alert(title, body, ButtonSet.YES_NO)` で承認
- 承認後、`PaymentMethodRepository.findAll()` の既存 `決済手段名` を取得して、**未登録の手段のみ appendRow**
- `Utils.logInfo` + サマリ alert + `Utils.auditLog('MIGRATE', ..., 'END')`
- `000_infra/002_constants.js` の `MENU_DEFINITION` の「🔧 マイグレーション」カテゴリ(L302-307 の items 配列)、MAS-120 エントリの直後に 1 行追加:
`{ label: 'S-63: 決済手段マスタ化', funcName: 'migrationS63PaymentMethod', description: 'S-63 既存データから決済手段別の最頻値をマスタに冪等投入' },`
制約:
- **冪等性必須** — 2 回目実行で登録候補 0 件になること
- **Human-in-the-Loop** — 承認ダイアログで YES を押さない限り書き込まない
- 「未定」「選定中」を含む決済手段名はマイグレーション対象外(集計時点でフィルタ)
- `PaymentMethodRepository.resetCache()` は冒頭必須(MAS-003 失敗例回避)
動作確認:
- dev でマイグレーション実行 → プレビュー表示 → YES で書き込み → サマリ alert
- 再度実行 → 登録候補 0 件のサマリ
- `18_mst_payment_method` シートで登録された内容を目視確認 → 不適切な値があれば手動で修正または無効化
## 制約(全 Step 共通)
- 列参照はヘッダー名ベース(`indexOf`)。列番号ハードコード禁止
- 既存 Repository(OrderRepository / InvoiceRepository / AccountRepository / PartnerRepository 等)には触らない
- MAS-120 の既存ロジック(`applyPartnerPaymentTerms_` / `PartnerRepository.findPaymentTermsMap` / `810_migration_partner_payment_terms.js`)は一切変更しない(本案件は後続レイヤーとして追加のみ)
- `setupAllSchemas` で MST_PMTM の既存データがクリアされないことを dev で事前確認
- **onEdit での既存値上書き禁止**(`cell.isBlank()` 必須)
- **マイグレーションの冪等性必須**(2 回目で書き込み 0 件)
## 動作確認フロー(統合テスト)
1. `setupAllSchemas` 実行 → `18_mst_payment_method` 生成、`01_sys_config` に MST_PMTM 登録
2. マスタに 5 件サンプル登録(JCB / 楽天カード / 銀行振込 / 口座振替 / 現金)
3. 23_bud_subscription で新規行 → 決済手段="JCB" 入力 → 決済ラグ/支払基準日/休日調整が JCB マスタ値に
4. 既に決済ラグ=2 の行で決済手段=JCB に変更 → 上書きされない(手動値保護)
5. MAS-120 設定済み取引先(取引先マスタに標準決済手段=楽天カード あり)の取引先名を入力 → 優先順位 (a) が効いて楽天カード補完
6. マスタ未登録の決済手段("PayPay" 等)を入力 → 何も補完されない
7. RPA `generateSaasInvoices` を実行 → 生成された `決済日_計画` に休日調整が効いていること
8. `migrationS63PaymentMethod` を実行 → プレビュー → YES → サマリ
9. 再実行 → 0 件サマリ(冪等性確認)
10. `runAllTests` で全テスト PASS
11. prod 環境にデプロイ前: CLAUDE.md の「変更時の動作確認テスト」に従い RPA テスト・マート更新テストを実施
### 拡張思考の使用状況
| フェーズ | 拡張思考 | 備考 |
|---------|:--------:|------|
| Step 1 DDL 追加 | なし | 既存 schemas 辞書へのエントリ追記・inputCols・setVali の 1 行ずつ追加 |
| Step 2 Repository 新設 | なし | AccountRepository / PartnerRepository パターンのコピー改変 |
| Step 3 決済日計算改修 | あり | 3 ファイルのインライン計算の抽出、フォールバック優先順位設計、互換性テスト |
| Step 4 onEdit 拡張 | あり | MAS-120 との呼び出し順序、決済手段列編集分岐の追加位置 |
| Step 5 マイグレーション | あり | 冪等性保証・プレビュー UI・最頻値集計・未登録フィルタ |
推奨実行モデル
| 工程 | 推奨モデル | 理由 |
|---|---|---|
| Step 1: DDL スキーマ追加 | Claude Haiku 4.5 | 既存 MST_PART / MST_ORGN の記述位置に 1 ブロック追記。判断要素少 |
| Step 2: PaymentMethodRepository 新設 | Claude Haiku 4.5 | AccountRepository / PartnerRepository のコピー改変でコード完全定義可能 |
| Step 3: 決済日計算改修 | Claude Opus 4.6 | 3 ファイル横断の抽出・優先順位フォールバック設計・互換性担保。設計判断が多い |
| Step 4: onEdit 拡張 | Claude Sonnet 4.6 | MAS-120 の直後パターンで機械的だが、呼び出し位置と colName === '決済手段' 分岐追加の判断あり |
| Step 5: マイグレーション | Claude Sonnet 4.6 | 810_migration_partner_payment_terms.js のテンプレート流用。プレビューダイアログ制御のみ新規設計 |
変更履歴
| 日付 | 変更内容 |
|---|---|
| 2026-04-22 | 初版作成。決済手段マスタ 18_mst_payment_method の DDL 設計・PaymentMethodRepository 新設・共通決済日計算ヘルパー RpaCommon.resolveSettlementTerms / calcSettleDate への集約・onEdit 補完の 2 段フォールバック拡張・冪等マイグレーションの 5 ステップ設計 |
仕様書作成プロンプト
展開して表示
<instruction>
【タイムアウト回避・実行原則(v1.7・必ず遵守すること)】
1. 拡張思考の使い分け: Phase 1(設計)では拡張思考をフル活用し、ファイル名・関数名・行番号・エッジケース一覧・Step 分割粒度を完全に確定させる。Phase 2(清書)の各 Step 内では拡張思考を最小限に抑え、Phase 1 で確定済みの内容の書き下しに徹する。出力途中で再考しない。
2. テキスト報告の禁止: 「〜を作成します」等の text のみで tool_use なしに turn を終了しない。説明は 1 文以内。直ちに tool を呼ぶ。
3. 4-5 分割の Write/Edit 実行: Step 2-1(骨格)/2-2(概要〜注意事項)/2-3a(エッジケース〜人間検討事項)/2-3b(実装プロンプト〜変更履歴)/2-4(<details>プロンプト記録) に分割。1 回の Write/Edit は約 300 行以内。
4. 各 Step で何を書くかを具体指示: Phase 2 実行時に設計判断を再考しない。Phase 1 で確定した内容をそのまま書き下す。
======================================================================
あなたはGAS会計システムのシニア開発者兼仕様書ライターです。
案件 MAS-135「決済手段マスタの新設(決済条件マスタ化)」の開発仕様書を作成してください。
作成後は `docs/_config.json` の `nav` 配列の適切なセクションに必ず追記してください。
---
## Phase 1: 実行前調査(テキスト報告禁止。即座にツール実行)
以下のファイルを順に Read/Grep し、Phase 2 で設計判断を再考しないよう全情報を確定させること。
**Grep は「どこにあるか」の発見まで。「どう書くか」の判断は必ず Read で裏取りしてから行う。推測で書かない。**
### 1-A: 案件要件の取得
- `docs/_internal/TODO_future.md` を Read し、MAS-135「決済手段マスタの新設」の概要・人間が検討すべき事項を取得する
### 1-B: プロジェクト規約の確認
- `CLAUDE.md` を Read し、マイグレーション番号ルール(804-808 使用済み・次は 809 から)・ファイル命名規則(`8XX_migration_*.js`)・コーディング規約を確認する
### 1-C: 仕様書テンプレートの参照
- `docs/dev/dev_mas-085_consistency_check.md` を Read し、整合性チェック系の仕様書フォーマットを把握(参考)
- `docs/dev/dev_mas-120_partner_payment_terms_autofill.md` について: まず `ls docs/dev/` で存在を確認してから Read する。ファイルが存在しない場合はスキップし、仕様書の注意事項に「MAS-120 仕様書未作成のため取引先マスタ連携設計は要確認」と記載する
### 1-D: 関連コードの調査(Grep → Read の順を守ること)
#### 1-D-1: 決済手段・決済日計算ロジックの特定
1. `Grep "決済手段" --include="*.js"` でヒットファイルと行番号を列挙する
2. `Grep "adjustToBusinessDay\|決済日\|calcPayment\|paymentDate" --include="*.js"` で決済日計算ヘルパー関数の所在を特定する
3. ヒットしたファイルを Read し、関数名・行番号・引数・呼び出し元を確定する
- `Utils.adjustToBusinessDay(ymdStr, direction)` は `000_infra/004_utils.js` に実在。`direction='後'` → 翌営業日方向に丸め、それ以外 → 前営業日方向に丸め
- `Utils.addMonths(ymStr, months)` は `000_infra/004_utils.js` に実在。戻り値は "YYYY-MM" 形式
- 上記以外に決済日を計算するカスタムヘルパーが存在する場合はファイル名・関数名・行番号を確定する
- 見つからない場合は「要調査: 決済日計算ヘルパーの所在未確定」として仕様書の注意事項に明記する
#### 1-D-2: DDL スキーマ定義パターンの把握
- `100_config/101_sys_config.js` を Read し、`setupAllSchemas` 内の既存マスタ(`11_mst_account` または `12_mst_partner`)の DDL 定義の実際の構造・列定義フォーマット・`Constants.CONFIG_SHEET`(値: `'01_sys_config'`)へのシステムキー登録方式を確認する
- 既存シート番号の一覧を確認し、`18_mst_payment_method` というシート番号が重複しないことを確かめる
#### 1-D-3: onEdit ハンドラの所在確認
1. `Grep "function onEdit\|onEdit_\|handleOnEdit" --include="*.js"` でハンドラの実在ファイル・行番号を特定する(`300_ui/301_ui_assist.js` または `100_config/101_sys_config.js` にある可能性が高いが、必ず Grep 結果で確認すること)
2. ヒットしたファイルを Read し、ハンドラ構造(シート名判定 → 列名判定 → 処理)を把握する
3. `21_bud_pipeline` / `23_bud_subscription` / `32_wrk_invoice` の「決済手段」列がハンドラの処理対象として既に扱われているか確認する(`000_infra/002_constants.js` の `SHEET_DEFAULTS` には `21_bud_pipeline` に `'決済手段': ''`、`23_bud_subscription` に `'決済手段': '未定'` が存在することは確認済みだが、実際の DDL 列定義も Read で確認すること)
#### 1-D-4: Repository パターンの把握
- `200_data/202_repository.js` を Read し、`AccountRepository` の実装(`findAll` / `findAsMap` / `_cache` / `resetCache`)を把握する。`PaymentMethodRepository` の設計ベースとして使用する
- `Utils.getSheetByKey(key, fallbackName)` の呼び出しパターンを確認する(key は `01_sys_config` に登録するシステムキー。例: `MST_ACCT` → `11_mst_account`)
- `readSheetAsDtos_` / `appendDtosToSheet_` 等のファイル内共通ヘルパーが存在することを確認する
#### 1-D-5: 既存マイグレーションスクリプトの確認
1. `ls 800_ops/` で使用済み番号の一覧を確認し、次の空き番号(CLAUDE.md では 809 から)を確定する
2. 最新番号のスクリプトを Read し、冪等性確保パターン(既存行チェック → スキップ)・`Utils.logInfo` と `SpreadsheetApp.getUi().alert` / `showModalDialog` の使い方を把握する
3. `docs/dev/dev_mas-116_migration_framework.md` を Read し、マイグレーション設計基盤の制約を把握する
### 1-E: Phase 2 着手前の確定チェックリスト(全て確定してから Phase 2 へ進むこと)
- [ ] 新マスタシート名: `18_mst_payment_method`(番号重複なし確認済み)
- [ ] 新マスタ列定義: 決済手段コード / 決済手段名 / 標準決済ラグ(月) / 標準支払基準日 / 休日調整方向 / 備考
- [ ] 新システムキー: 1-D-2 で命名規則を確認して決定(暫定案: `MST_PMTM`)
- [ ] `PaymentMethodRepository` 追加先: `200_data/202_repository.js`
- [ ] 決済日計算ヘルパーの関数名・ファイル名・行番号: 1-D-1 で確定
- [ ] onEdit ハンドラのファイル名・行番号: 1-D-3 で確定
- [ ] onEdit 拡張対象シート: `21_bud_pipeline` / `23_bud_subscription` / `32_wrk_invoice`(1-D-3 で実在確認済みのもの)
- [ ] マイグレーションスクリプトのファイル番号: 1-D-5 で確定(809〜次の空き番号)
- [ ] 取引先連携の優先順位: (a) 取引先マスタ(MAS-120 設定) → (b) 決済手段マスタ(本件) → (c) 個別手入力値
---
## Phase 2: 仕様書の分割作成
出力先: `docs/dev/dev_mas-135_payment_method_master.md`
**1 回の Write/Edit で全内容を出力しない。以下 5 Step に厳密に分割実行すること。**
### Step 2-1: 骨格の作成(Write, ~20行)
以下の見出しのみを書く。本文は空でよい:
# MAS-135: 決済手段マスタの新設(決済条件マスタ化)
## 概要
## 目的
## 現在のコード
## 修正方針
## 影響範囲
## 注意事項
## エッジケース
## 実データ検証
## 関連ドキュメント
## 人間が検討すべき事項
## 実装プロンプト(Claude Code 用)
## 推奨実行モデル
## 変更履歴
## 仕様書作成プロンプト
### Step 2-2: 概要〜注意事項の追記(Edit または Bash heredoc, ~300行)
**Phase 1 で確定した実在の関数名・行番号・ファイルパスのみ使うこと。推測で書かない。**
書く内容:
- **概要テーブル**: 案件ID=MAS-135, カテゴリ=マスタ整備, 対象ファイル=(Phase 1 で特定した全ファイル), 前提案件=MAS-120(未作成の場合はその旨を記載)
- **目的**: 決済手段ごとの決済条件(ラグ・支払基準日・休日調整)をマスタ管理し、手入力による設定不整合を解消する
- **現在のコード**: 1-D-1 で特定した決済日計算ロジックのコードスニペット(ファイル名 + 行番号を明記)。特定できなかった場合は「現状: 決済日計算ヘルパーの所在が未確定(要調査)」と記載する
- **修正方針**(5 Step に分割して記述):
- **Step 1: DDL スキーマ追加** — `100_config/101_sys_config.js` の `setupAllSchemas` に `18_mst_payment_method` のスキーマを追加(1-D-2 で確認した実際のフォーマットに準拠)。`Constants.CONFIG_SHEET`(値: `'01_sys_config'`)へのシステムキー登録(キー名: 1-E で確定した値)も含む
- **Step 2: PaymentMethodRepository の新設** — `200_data/202_repository.js` に `AccountRepository` の構造(`findAll / findAsMap / _cache / resetCache`)を踏襲して追加。内部ヘルパー `readSheetAsDtos_` を再利用。`findAsMap()` のキーは「決済手段名」、値は `{ lag: number, baseDay: string, holidayDir: string }`。`Utils.getSheetByKey(システムキー, '18_mst_payment_method')` で取得
- **Step 3: 決済日計算ロジックの改修** — 1-D-1 で特定したヘルパー関数(ファイル名・行番号を明記)に優先順位フォールバック `(a) 取引先マスタ(S-48) → (b) PaymentMethodRepository.findAsMap()[決済手段名] → (c) 個別手入力値` を追加。`Utils.addMonths(ymStr, months)` と `Utils.adjustToBusinessDay(ymdStr, direction)` を再利用(既存の呼び出し箇所との互換性を維持すること)
- **Step 4: onEdit 自動補完の追加** — 1-D-3 で特定したハンドラ(ファイル名・行番号を明記)に、「決済手段」列選択 かつ 対象セルが空 の場合のみ `PaymentMethodRepository.findAsMap()` から補完するロジックを追加。対象シート: `21_bud_pipeline` / `23_bud_subscription` / `32_wrk_invoice`(1-D-3 で実在確認済みのもの)。取引先マスタ(MAS-120)に設定がある場合は補完をスキップ
- **Step 5: マイグレーションスクリプト** — `800_ops/{次の空き番号}_migration_s63_payment_method.js` を新規作成。冪等性必須(同一「決済手段名」が `18_mst_payment_method` に既存行として存在する場合はスキップ)。`32_wrk_invoice` 等の「決済手段」列から最頻値を集計 → `SpreadsheetApp.getUi().alert` でプレビューをダイアログ表示 → 人間が確認・承認した場合のみシートへ書き込む
- **影響範囲**: 変更ファイルと各ファイルの追加行数見積もり
- **注意事項**:
- onEdit での自動補完は対象セルが空の場合のみ実行し、ユーザーが手動設定した値を上書きしない
- フォールバック優先順位 (a)→(b)→(c) を全処理で徹底すること
- MAS-120 が未作成の場合、優先順位 (a) の取引先マスタ連携は本案件スコープ外とする(人間が検討すべき事項で確認)
- `18_mst_payment_method` への直接書き込みは `setupAllSchemas` 実行後のみ有効
### Step 2-3a: エッジケース〜人間検討事項の追記(Edit または Bash, ~200行)
**エッジケーステーブル**(| 条件 | 挙動 | 理由 | 形式で全観点を網羅):
| 条件 | 挙動 | 理由 |
|------|------|------|
| 決済手段名がマスタ未登録 | 自動補完スキップ、手入力値をそのまま尊重 | マスタ強制でユーザー入力を破壊しない |
| 標準支払基準日 = "月末" | `new Date(y, m, 0).getDate()` で末日を動的計算 | 月によって末日が異なるため |
| 休日調整方向が空欄 | `Utils.adjustToBusinessDay` を呼ばず調整なし | 未設定はユーザーの意図として尊重 |
| 標準決済ラグ(月) = 0 | 当月決済(`Utils.addMonths(ym, 0)` は同月を返す) | 即時・当月決済の表現 |
| 標準決済ラグ(月) が負値 | DDL バリデーションでエラー。マスタ登録時に弾く | 遡及決済は仕様外の異常系 |
| 「現金」決済手段 | ラグ=0・支払基準日="当日"・休日調整方向=空でマスタ登録 | 即時決済の慣習 |
| 「未定」決済手段 | マスタ登録しない。ユーザー手入力に委ねる | 確定前状態はマスタ管理外 |
| onEdit 時に補完対象セルに既存値あり | 上書きしない(空セル判定を先行) | Human-in-the-Loop。ユーザー設定値を保護 |
| マイグレーションスクリプト 2 回目実行 | 同一「決済手段名」行をスキップ(冪等性) | 重複挿入による不整合防止 |
| 優先順位 (a) と (b) が両方存在する | (a) 取引先マスタ設定を優先して適用 | 取引先個別設定が最上位 |
**実データ検証**(実装前に MCP またはシート直読みで確認すべき項目):
- `32_wrk_invoice` の「決済手段」列に存在する実データのユニーク値(初期マスタデータの候補)
- `21_bud_pipeline` / `23_bud_subscription` の「決済手段」列の実在確認とユニーク値
- `01_sys_config`(`Constants.CONFIG_SHEET`)のシステムキー命名規則(`MST_ACCT` / `MST_PART` 等の形式から本件キー名を最終決定)
- `18_mst_payment_method` というシート番号が既存シートと重複しないことの最終確認
**関連ドキュメント**(テーブル形式):
- `docs/dev/dev_mas-120_partner_payment_terms_autofill.md`(存在する場合) — 取引先への決済条件自動補完(優先順位 (a) の前提)
- `docs/dev/dev_mas-116_migration_framework.md` — マイグレーション設計基盤
**人間が検討すべき事項**:
- TODO_future.md の MAS-135 記載事項をそのまま転記する
- マイグレーション実行フローの承認方式: プレビューダイアログ → 人間が「OK」を押した場合のみ書き込みを実行(Human-in-the-Loop 必須)
- `18` というシート番号が既存シートと衝突しないか(1-D-2 で調査済みの場合は結果を記載)
- MAS-120 が未実装の場合、優先順位 (a) の取引先マスタ連携を本案件スコープに含めるかどうかの判断
### Step 2-3b: 実装プロンプト〜変更履歴の追記(Edit または Bash, ~250行)
書く内容:
- **実装プロンプト(Claude Code 用)**: 行頭 4 スペースインデント形式(バッククォートで囲まない)で、Step 1〜5 それぞれの実装プロンプトを記載する。各 Step に「実行前タスク」(読むべきファイルと確認ポイント)・「修正対象ファイル」・「実装内容」・「制約」・「動作確認」を含める。「制約」に「onEdit での既存値上書き禁止」「マイグレーションの冪等性必須」を再掲する
- **推奨実行モデル**テーブル:
| 工程 | 推奨モデル | 理由 |
|------|-----------|------|
| Step 1: DDL スキーマ追加 | Claude Haiku 4.5 | 既存パターンの横展開。判断要素少 |
| Step 2: Repository 新設 | Claude Haiku 4.5 | AccountRepository パターンのコピー改変。コード完全定義可 |
| Step 3: 決済日計算改修 | Claude Sonnet 4.6 | 既存ヘルパーの特定と優先順位フォールバック追加 |
| Step 4: onEdit 拡張 | Claude Sonnet 4.6 | 複数シートへの条件分岐追加。既存ハンドラ構造の理解が必要 |
| Step 5: マイグレーション | Claude Sonnet 4.6 | 冪等性・最頻値集計・ダイアログ制御の設計判断 |
- **変更履歴**テーブル:
| 日付 | 変更内容 |
|------|---------|
| 2026-04-20 | 初版作成 |
### Step 2-4: 仕様書作成プロンプトの記録(Edit または Bash)
最重量工程のため必ず独立した Step で実行すること。仕様書末尾の `## 仕様書作成プロンプト` セクションに以下を追記する:
<details><summary>展開して表示</summary>
(この <instruction> タグの全文をそのまま記録)
</details>
---
## Phase 3: 保存・登録・コミット
### 3-A: `docs/_config.json` への登録(必須)
`nav` 配列の §E.2(バグ修正・バリデーション・マスタ整備)に追記:
```json
{ "file": "dev/dev_mas-135_payment_method_master.md", "title": "E.2.XX S-63 決済手段マスタの新設" }
```
追記後に JSON 構文チェックを実行する:
```bash
node -e "require('./docs/_config.json')" && echo "OK"
```
### 3-B: `docs/_internal/changelog.md` への追記
ヘッダー直後の先頭行に追記:
```
| 2026-04-20 | [dev_mas-135_payment_method_master.md](dev_mas-135_payment_method_master.md) | 初版作成。決済手段マスタ新設(S-63)の開発仕様書 |
```
### 3-C: コミット&プッシュ
```bash
git add docs/dev/dev_mas-135_payment_method_master.md docs/_internal/changelog.md docs/_config.json
git commit -m "docs: S-63 決済手段マスタ新設の開発仕様書を作成
18_mst_payment_method の DDL設計・PaymentMethodRepository 新設・
決済日計算改修・onEdit 拡張・マイグレーション方針を定義。
https://claude.ai/code/session_XXXXX"
git push -u origin $(git rev-parse --abbrev-ref HEAD)
```
</instruction>