最終更新: 2026/06/22 18:56
MAS-074: 給与INVの未決済残高に仕訳振替分を反映
概要
| 項目 | 内容 |
|---|---|
| 案件ID | MAS-074 |
| カテゴリ | 経費・仕訳 |
| Phase | P1 |
| 優先度 | ★★★ |
| 所要時間 | 1-2時間 |
| 対象ファイル | 400_domain/403_subledger_engine.js |
目的
給与INV(月額給与・報酬)の未決済残高計算に、同一ORD配下の仕訳振替INV(源泉所得税・社保預り等)を仮想消込として含め、残高表示を適正化する。
背景
現在の問題
HC RPA が生成する給与INV群の構造:
ORD (EMP_0001|2025-08)
├─ INV1: 月額給与・報酬 ¥500,000 (決済手段: 口座振込)
│ └─ STL: ¥400,000 (差引支給額 = ¥500,000 − 天引き¥100,000)
├─ INV2: 源泉所得税預り ¥30,000 (決済手段: 仕訳振替) → Action Aで即残高0
├─ INV3: 住民税預り ¥10,000 (決済手段: 仕訳振替) → Action Aで即残高0
└─ INV4: 社保預り ¥60,000 (決済手段: 仕訳振替) → Action Aで即残高0
STL消込後の残高:
| INV | 税込金額 | STL決済額 | 仕訳振替額 | 現在の残高 | あるべき残高 |
|---|---|---|---|---|---|
| INV1(給与) | 500,000 | 400,000 | — | 100,000 | 0 |
| INV2(源泉) | 30,000 | — | 30,000 | 0 | 0 |
| INV3(住民税) | 10,000 | — | 10,000 | 0 | 0 |
| INV4(社保) | 60,000 | — | 60,000 | 0 | 0 |
INV1の残高¥100,000は未払いに見えるが、実際には仕訳振替(INV2-4)で消化済み。天引き額 = ¥30,000 + ¥10,000 + ¥60,000 = ¥100,000 がSTLの差引計算で既に控除されている。
未決済残高の現在の計算ロジック(403_subledger_engine.js L571-608)
// STLからINV別の消込合計を集計
const settledByInv = {};
for (各STL行) {
if (決済ステータス !== '消込済') continue;
if (!自動仕訳JNL_ID) continue; // Action B処理済のみ
settledByInv[invId] += 税込金額_決済;
}
// INV別に残高再計算
newBal = |税込金額_計画| - settledByInv[invId];
// ★ 仕訳振替による仮想消込が含まれていない
修正方針
Action Bの残高再計算セクション(L571-608)に、仕訳振替INVの金額を仮想消込として加算するロジックを追加する。
Step 1: 仕訳振替INVの天引きマップ構築
settledByInv の集計(L573-585)の直後に、32_wrk_invoiceから仕訳振替INVの天引きマップを構築する。
// S-02: 仕訳振替INVの天引き額をORD別に集計(仮想消込用)
const jvDeductByOrd = {};
const iOrdCol = invIdx['親発注ID(ORD)'];
const iPayMethod = invIdx['決済手段'];
const iMemo = invIdx['摘要'];
const iTotalAmt = invIdx['税込金額_計画'];
for (var ji = 1; ji < invData.length; ji++) {
var flag = invData[ji][invIdx['有効フラグ']];
if (flag === false || String(flag).toUpperCase() === 'FALSE') continue;
var pm = String(invData[ji][iPayMethod] || '').trim();
if (pm !== '仕訳振替') continue;
var amt = Number(invData[ji][iTotalAmt]) || 0;
if (amt <= 0) continue; // 正の額(預り計上側)のみ対象。負の額(支払側)は除外
var ordId = String(invData[ji][iOrdCol] || '').trim();
if (ordId) {
jvDeductByOrd[ordId] = (jvDeductByOrd[ordId] || 0) + amt;
}
}
Step 2: メインINVの残高計算に仮想消込を適用
残高再計算ループ(L592-608)で、メインINVの settled に仮想消込額を加算する。
// 既存: L598
var settled = settledByInv[invId] || 0;
// S-02追加: 仕訳振替の仮想消込
var ordIdForJv = String(invSheet.getRange(upd.row, invIdx['親発注ID(ORD)'] + 1).getValue()).trim();
var pmForJv = String(invSheet.getRange(upd.row, iPayMethod + 1).getValue()).trim();
if (pmForJv !== '仕訳振替' && ordIdForJv && jvDeductByOrd[ordIdForJv]) {
settled += jvDeductByOrd[ordIdForJv];
}
var newBalAbs = totalAbs - settled;
仮想消込の適用条件
| 条件 | 理由 |
|---|---|
| 対象INVの決済手段 ≠ 仕訳振替 | 仕訳振替INV自身は Action A で即残高0。仮想消込はメインINVにのみ適用 |
| 同一ORD配下に仕訳振替INVが存在 | ORDで親子関係を紐付け |
| 仕訳振替INVの金額が正(> 0) | 預り計上側(給与日の天引き)のみ集計。負の額(納付期限の支払)は除外 |
| 有効フラグ = TRUE | 論理削除されたINVは除外 |
なぜ「正の額のみ」か
HC RPAは天引きINVをペアで生成する:
源泉所得税預り ¥30,000(正: 給与支給日に預り金計上)源泉所得税 -¥30,000(負: 納付期限に預り金解消)
STL自動作成時の天引き計算(deductMap)も正の額のみを集計している(401_bat_rpa.js L148-173)。仮想消込も同じロジックに合わせ、正の額のみを対象にする。
影響範囲
- 変更ファイル:
403_subledger_engine.jsのprocessSettlementClearings()内(Action B) - 変更量: 約15行追加
- 既存ロジックへの影響: 残高計算の settled に仮想消込を加算するのみ。STL集計ロジックは変更なし
- 84_cf_daily_plan: 未決済残高を参照しているため、残高が正しくなることでCF計画の精度も向上
注意事項
- invData のスコープ: Action B の processSettlementClearings 内で
invDataがどのスコープで参照可能か確認すること。invSheet.getDataRange().getValues() で取得されているはず - invBalUpdates の対象行: 残高再計算は
invBalUpdatesに含まれる行のみ。Action B で処理されなかったINVの残高は更新されない - 二重減算防止: 仮想消込は
pmForJv !== '仕訳振替'ガードで、仕訳振替INV自身には適用されない。仕訳振替INVは Action A で既に残高0 - シート読み取り回数:
invSheet.getRange(upd.row, ...)でループ内に getRange が増える。パフォーマンスが問題なら invData 配列から直接読み取る方式に変更
関連ドキュメント
| 仕様書 | 関連箇所 |
|---|---|
| CLAUDE.md | 未決済残高は請求総額から再計算(減算方式ではなく全STL合計から逆算) |
| CLAUDE.md | STL天引き計算は摘要「月額給与・報酬」を含むINVのみ |
| CLAUDE.md | P/L INV消込の未払金解消は期ずれあり(pYm≠sYm)の場合のみ(二重減算防止) |
| B.3 統合テスト手順 | Action A → Action B テスト |
人間が検討すべき事項
- 仮想消込のルール(全額 or 部分): 本仕様では全額(同一ORD配下の正の仕訳振替INV全額を仮想消込)を採用。部分消込(例: 一部の天引き項目のみ)が必要なら条件を追加
- 対象ORDの範囲: 本仕様ではORD単位で集計するため、給与INV以外のORDにも仕訳振替INVがあれば同様に仮想消込される。給与INVのみに限定する場合は摘要フィルタ(「月額給与・報酬」)の追加が必要
実装プロンプト(Claude Code 用)
あなたはGAS会計システム(bizlp-gas-accounting)のシニア開発者です。
CLIエージェントである「Claude Code」として、以下の指示に従い、案件 S-02「給与INVの未決済残高に仕訳振替分を反映」を実装してください。
## 実行前タスク(コンテキストの読み込み)
実装前に**必ず**以下のファイルを読み込んで、現在の実装を正確に把握してください。
1. 修正対象: `400_domain/403_subledger_engine.js` — `processSettlementClearings()` の全体構造。特に以下を確認:
- L571-608: 未決済残高の再計算セクション(settledByInv集計 → INV別残高更新)
- L287-293: Action Aでの仕訳振替INV即決済処理
- invData, invIdx の変数スコープ
2. 参考(天引きロジック): `400_domain/401_bat_rpa.js` — L148-173の deductMap 構築パターン(正の額のみ集計)
3. プロジェクト規約: `CLAUDE.md` — 未決済残高の計算ルール、天引き計算の条件
4. 開発仕様書: `docs/dev/dev_mas-074_jv_virtual_settlement.md`
## 修正対象ファイル
`400_domain/403_subledger_engine.js` の `processSettlementClearings()` のみ。
## 実装内容
### A: 仕訳振替天引きマップの構築(L585の直後に追加)
settledByInv の集計ループ完了直後に、32_wrk_invoice の invData から仕訳振替INVの天引き額をORD別に集計するループを追加。
**集計条件:**
- 有効フラグ = TRUE
- 決済手段 === '仕訳振替'
- 税込金額_計画 > 0(正の額のみ。預り計上側)
- 親発注ID(ORD) が非空
**出力:** `jvDeductByOrd` = { ordId: 天引き合計額 }
### B: 残高計算への仮想消込の適用(L598付近を修正)
残高再計算ループ内で、`settled` に仮想消込額を加算:
1. 対象INVの親発注ID(ORD)を取得
2. 対象INVの決済手段を取得
3. 決済手段 ≠ '仕訳振替' かつ ORDに仮想消込がある場合: `settled += jvDeductByOrd[ordId]`
**重要:** invSheet.getRange() でループ内にシート読み取りが増えるのを避けるため、invData 配列から直接読み取ることを推奨。invBalUpdates の各 upd.row は1始まり行番号なので、invData のインデックスは `upd.row - 1`。
## 制約
- settledByInv の集計ロジック(L573-585)は変更しない
- Action A の仕訳振替即決済処理(L287-293)は変更しない
- 仕訳振替INV自身の残高は変更しない(既に Action A で 0)
- 負の額の仕訳振替INV(納付側)は集計に含めない
## 動作確認
`npm run push:dev` 後:
1. HC RPA を実行して給与INV群を生成
2. 32タブで給与INVを「承認済」に変更
3. Action A を実行(仕訳振替INVが即決済完了になること)
4. 33タブでSTLに決済日入力+「消込済」に変更
5. Action B を実行
6. **検証**: INV1(月額給与・報酬)の未決済残高が 0 になっていること
7. **検証**: 仕訳振替INV(源泉・社保等)の残高は引き続き 0 であること
### 拡張思考の使用状況
| フェーズ | 拡張思考 | 備考 |
|---------|:--------:|------|
| ファイル読み込み・構造理解 | あり | invData/invIdx のスコープ確認、invBalUpdates の行番号体系 |
| 天引きマップ構築 | なし | deductMap パターンの踏襲 |
| 残高計算への統合 | あり | invData からの直接読み取り、二重減算防止ガード、符号処理の確認 |
推奨実行モデル
| 工程 | 推奨モデル | 理由 |
|---|---|---|
| 仕様書作成(本ドキュメント) | Claude Opus 4.6 | 給与INVの親子関係、天引きペアの符号ルール、二重減算防止の分析に高い推論力が必要 |
| 実装 | Claude Sonnet 4.6 | 仕様書で挿入コードが概ね定義済みだが、invData スコープ確認と行番号変換に中程度の判断力が必要 |
| 動作確認 | ユーザー手動 | HC RPA → Action A → STL消込 → Action B の一連の手動操作が必要 |
変更履歴
| 日付 | 変更内容 |
|---|---|
| 2026-04-14 | 初版作成 |