概要

項目内容
案件 IDMAS-048
カテゴリシミュレーション
優先度P1.5 ★★★(Jr 採用 D-180 = 2026-10 入社想定の最優先案件)
対象ファイル(変更あり)400_domain/412_hiring_tco_simulator.js(新規・namespace HiringTcoSimulator
100_config/101_sys_config.js03_sys_params に法定福利費率等の初期値設定支援)
000_infra/002_constants.jsMENU_DEFINITION📋 サイドバー: 📊 マート更新 カテゴリに 1 項目追加)
301_ui_assist.js または新規サイドバー HTML(採用 TCO 入力フォーム)
出力先シート69_report_hiring_tco(新規・DDL 管理外・動的上書き)
前提案件MAS-044(テンプレートマスタ・入力源として使用)、MAS-012(目標売上 → 必要人員数逆算・相補関係)
後続案件MAS-049(賃上げ促進税制シミュレーター・本案件の TCO を入力として受取)、MAS-042(Go/No-Go 判定・本案件の TCO/BEP を閾値照合に使用)

「給与 600 万 → 実コスト 900 万」の可視化が本案件のコア価値。Jr 採用 D-180(2026-10 入社想定)に向けた採用可否の財務判断を TCO(Total Cost of Ownership)BEP(損益分岐点売上) の 2 指標で定量化する。

入力(想定年収 / 雇用形態 / 採用チャネル費用)→ 計算(法定福利費 15.68% + 採用費 + 研修費 + 設備按分)→ 出力(年間 TCO + 月次 TCO + 採用者が稼ぐべき最低粗利月額 = BEP)を 1 画面で完結させる。

D.9「一人法人 1 人目採用 財務シミュレーション完全ガイド」§2 / §5 で整理された計算フレームを実装する位置付け。

目的

  • 採用可否の財務判断を定量化: 「年収 X 万の採用に対し実コスト Y 万・BEP 月 Z 万円」という数字で Go/No-Go 議論を土台化
  • Jr 採用 D-180(2026-10 入社想定)への準備: 業務委託 → 契約社員 → 正社員の段階ごとに TCO 比較可能にして実雇用タイミングを最適化
  • MAS-012(目標売上 → 必要人員逆算)との相補: MAS-012 が「何人必要か」、MAS-048 が「1 人いくらかかるか」。両者を組み合わせて採用計画を構築
  • MAS-042(Go/No-Go ラベル付与)の判断エンジン: MAS-042 は判定ラベル(Go / グレー / No-Go)、MAS-048 は判定に使う TCO/BEP の数値計算。両者で役割分担

現在のコード

400_domain/ の採番状況(2026-04-23 時点)

400/401/402/403/404/405/406/407/410/413/420/430 が使用中。空き番号は 408, 409, 411, 412, 414-419, 421-429, 431-439。本案件は 412_hiring_tco_simulator.js を採用(MAS-011 の 430 / MAS-042 予定の 431 とは別番号で、ドメイン分類上「採用関連」として 412 を確保)。

22_bud_headcountBUD_HC schema、101_sys_config.js L943)

既存ヘッダー 41 列: 有効フラグ / 管理ID / 氏名・ポジション / 雇用形態 / 科目名 / 取引先名 / 適用年度 / 入社年月 / 退職年月 / 開始年月 / 終了年月 / 月額給与・報酬 / 決済手段 / ... / 採用エージェント費 / PC等初期費用 / ... / 売上貢献(MAS-012 / PR #337 で追加された boolean 列)/ ...

本案件は 月額給与・報酬 / 採用エージェント費 / PC等初期費用 / 社保料率群(健保料率 / 厚年料率 / 雇用保険料率 / 子ども・子育て拠出金率)を参照して既存採用者の実績平均を算出し、シミュレーション入力のプリロードに使う。loadActualAverages では 売上貢献 = FALSE 行を除外(MAS-012 と同じ判定ロジック): 顧問会計士・顧問社労士等の「コストではあるが売上を生まない」HC を採用 TCO の平均から外し、「今後採用する売上貢献型 HC」の想定コスト平均を算出する。

18_tmpl_hc_positionMST_HC_TMPL schema、MAS-044 / PR #339 で実装済)

MAS-044 実装済の HC テンプレートマスタ。14 列構成:

説明MAS-048 での使用
有効フラグBooleanfindAsMap でスキップ判定
管理IDPOS_001テンプレ ID(サイドバー dropdown のキー)
ポジション名「Sr エンジニア」等UI 表示名・結果ラベル
想定雇用形態正社員/業務委託/副業/パートTCO 計算時の法定福利費適用判定
標準月額給与数値(円)年収 = × 12 でプリロード
想定月次売上貢献数値(円)BEP 判定時の粗利貢献想定値
想定変動費比率0〜1BEP 月次売上の粗利率計算
採用費デフォルト数値(円)TCO 計算の採用費
PC費デフォルト数値(円)TCO 計算の設備按分
月次追加固定費数値(円)本案件で新規反映: 席料・福利厚生等、1 人増加に伴う月次固定費増分
立ち上がり月数0〜60本案件で新規反映: 入社〜売上貢献開始までのオンボーディング期間
売上貢献Boolean本案件で新規反映: FALSE の場合は BEP 判定を「コスト回収のみ」モードに変更(売上貢献なし HC の扱い)
稼働率0〜1本案件で新規反映: BEP 月次売上を稼働率で割り戻す拡張の入力源(MVP は考慮せず、Phase 2 拡張で対応)
備考任意

200_data/202_repository.jsPositionTemplateRepository.findAsMap()(MAS-044 / PR #339 実装済、L430-497)

戻り値は 11 フィールド:

map[id] = {
  positionName,       // ポジション名
  employmentType,     // 想定雇用形態
  monthlySalary,      // 標準月額給与
  monthlyRevenue,     // 想定月次売上貢献
  variableCostRate,   // 想定変動費比率
  defaultRecruitFee,  // 採用費デフォルト
  defaultPcCost,      // PC費デフォルト
  monthlyFixedCost,   // 月次追加固定費(F-44 新規)
  rampUpMonths,       // 立ち上がり月数(F-44 新規)
  revenueContributing,// 売上貢献(F-44 新規、boolean)
  utilization,        // 稼働率(F-44 新規、0〜1)
  note,               // 備考
}

MAS-048 の入力 UI でテンプレ選択時、これら 11 フィールドを一括でフォームに反映する。

03_sys_paramsConstants.getParam(key, defaultVal)002_constants.js L147-167)

法定福利費率・採用費・研修費・設備按分の既定値を 03_sys_params で管理する(ハードコード禁止)。本案件で使うパラメータキー:

キーデフォルト根拠
TCO_STATUTORY_WELFARE_RATE0.1568協会けんぽ福井・40 歳未満(健保 4.97% + 介護 0 + 厚年 9.15% + 子育て 0.36% + 雇用 0.90% + 労災 0.30% = 15.68%)。D.9 §2.1 準拠
TCO_STATUTORY_WELFARE_RATE_40PLUS0.1647540 歳以上(介護 0.795% 追加)
TCO_COMMUTE_COST_MONTHLY10000通勤費月額
TCO_RETIREMENT_DEPOSIT_MONTHLY10000中退共月 1 万円
TCO_WELFARE_ANNUAL30000健診・慶弔年 3 万円
TCO_LABOR_MANAGEMENT_ANNUAL280000社労士月 2 万 × 12 + 給与ソフト年 4 万
TCO_EQUIPMENT_TOTAL600000PC + モニター + チェア + デスク
TCO_EQUIPMENT_AMORT_YEARS3設備按分年数
TCO_OFFICE_COST_MONTHLY30000コワーキング月 3 万
TCO_TRAINING_ANNUAL80000教育研修年 8 万(中央値)
TCO_RECRUIT_FEE_RATE0.30人材紹介料率(年収の 30%)
TCO_RECRUIT_AMORT_YEARS3採用コスト按分年数
TCO_TURNOVER_RATE_3Y0.5273 年以内離職率(厚労省・小規模法人 5-29 人)。D.9 §2.6 準拠

000_infra/002_constants.jsMENU_DEFINITION

📋 サイドバー: 📊 マート更新 カテゴリ(L231-241)の items 配列に追加する:

{ label: '💼 採用 TCO & BEP 試算', funcName: 'openHiringTcoSidebar', description: '想定年収から TCO(実コスト)と BEP(損益分岐点売上)を試算' },

69_report_hiring_tco(新規・DDL 管理外)

MAS-013 の 67_report_investment_analysis と同じく DDL 管理外・動的上書き方式。CLAUDE.md 末尾の「DDL (setupAllSchemas) で管理されないタブ」リストに 69_report_hiring_tco を追加する。

列構成(案):

  • A: 試算 ID(タイムスタンプ + 想定年収)
  • B: 実行日時
  • C: 想定年収
  • D: 雇用形態
  • E: 年齢区分(40 歳未満 / 40 歳以上)
  • F: 法定福利費(円/年)
  • G: 採用費(円/年、按分後)
  • H: 研修費(円/年)
  • I: 設備按分(円/年)
  • J: オフィス按分(円/年)
  • K: 労務管理費(円/年)
  • L: 退職金積立(円/年)
  • M: 福利厚生(円/年)
  • N: 通勤費(円/年)
  • O: 年間 TCO 合計
  • P: 月次 TCO
  • Q: BEP 月次粗利(採用者が稼ぐべき最低粗利)
  • R: BEP 月次売上(粗利率想定値で割戻し)
  • S: 粗利率想定値(ユーザー入力、デフォルト 62%)
  • T: 実効 Payback(離職率調整・D.9 §2.6 準拠、月数)
  • U: 備考(MAS-042 判定ラベル候補 / MAS-012 必要人員との比較メモ)

修正方針

Step 1: DDL 外シート生成 + パラメータ整備

CLAUDE.md69_report_hiring_tco を DDL 管理外リストに追記。03_sys_params に 13 パラメータキーの初期値を手動投入(シート直接編集 or MCP add_rows)。

注意: 69_report_hiring_tcosetupAllSchemas で自動生成されない。400_domain/412_hiring_tco_simulator.jsrun() 関数内で SpreadsheetApp.insertSheet('69_report_hiring_tco') を実行し、存在しなければ自動生成する設計。

Step 2: 計算エンジン実装(412_hiring_tco_simulator.js 新規)

namespace HiringTcoSimulator を IIFE で定義。公開 API:

var HiringTcoSimulator = (function() {
  /**
   * @param {Object} input
   * @param {number} input.annualSalary       想定年収(円)
   * @param {string} input.employmentType    'SEISHAIN' | 'KEIYAKU' | 'GYOUMU_ITAKU' | 'FUKUGYOU'
   * @param {number} input.ageGroup          40 or 40 以上(介護保険料率の切替)
   * @param {number} [input.recruitFeeRate]  採用費率(未指定で 0.30)
   * @param {number} [input.grossMarginRate] 粗利率想定(未指定で 0.62)
   * @returns {Object} { tco, bep, payback, breakdown }
   */
  function simulate(input) { /* ... */ }

  /**
   * 22_bud_headcount の有効行から実績平均をプリロード
   * **売上貢献 = FALSE 行を除外**(F-12 PR #337 で追加された列。顧問会計士・顧問社労士等のコスト型 HC を除外)
   * @returns {{ avgAnnualSalary, avgRecruitFee, avgPcCost, employmentTypeMix, excludedCount }}
   */
  function loadActualAverages() {
    var result = HeadcountRepository.findAll();
    var activeRows = result.dtos.filter(function(dto) {
      var flag = dto['有効フラグ'];
      if (flag === false || String(flag).toUpperCase() === 'FALSE') return false;
      // 売上貢献 = FALSE を除外(F-12 と同じ判定)
      var rev = dto['売上貢献'];
      return !(rev === false || String(rev).toUpperCase() === 'FALSE');
    });
    // 平均年収・採用エージェント費・PC等初期費用・雇用形態割合を算出...
  }

  /**
   * シミュレーション結果を 69_report_hiring_tco に追記
   * @param {Object} result  simulate() の戻り値
   */
  function writeToReport(result) { /* ... */ }

  /**
   * サイドバーから呼ばれる統合関数(calc → write の 1 セット)
   */
  function runHiringTcoSimulation(input) { /* ... */ }

  return {
    simulate: simulate,
    loadActualAverages: loadActualAverages,
    writeToReport: writeToReport,
    runHiringTcoSimulation: runHiringTcoSimulation,
  };
})();

function openHiringTcoSidebar() {
  var html = HtmlService.createHtmlOutputFromFile('hiring_tco_sidebar')
    .setTitle('💼 採用 TCO & BEP 試算');
  SpreadsheetApp.getUi().showSidebar(html);
}

Step 3: 計算ロジック詳細

TCO 計算式(年間、円):

法定福利費 = 年収 × TCO_STATUTORY_WELFARE_RATE(40 歳以上は _40PLUS)
採用費 = 年収 × TCO_RECRUIT_FEE_RATE ÷ TCO_RECRUIT_AMORT_YEARS
研修費 = TCO_TRAINING_ANNUAL
設備按分 = TCO_EQUIPMENT_TOTAL ÷ TCO_EQUIPMENT_AMORT_YEARS
オフィス按分 = TCO_OFFICE_COST_MONTHLY × 12
労務管理費 = TCO_LABOR_MANAGEMENT_ANNUAL
退職金積立 = TCO_RETIREMENT_DEPOSIT_MONTHLY × 12
福利厚生 = TCO_WELFARE_ANNUAL
通勤費 = TCO_COMMUTE_COST_MONTHLY × 12

年間 TCO 合計 = 年収 + 上記合計

雇用形態別の補正:

  • GYOUMU_ITAKU(業務委託): 法定福利費 = 0、採用費率 = 0.15(エージェント経由なら、直接契約なら 0)、オフィス按分 = 0(在宅前提)
  • FUKUGYOU(副業): 法定福利費 = 0、設備按分 = 0、研修費 = 0
  • KEIYAKU(契約社員): 正社員と同じ(雇用保険は 1 年未満でも適用)
  • SEISHAIN(正社員): 上記フル適用

BEP 計算式:

BEP 月次粗利 = 月次 TCO = 年間 TCO ÷ 12
BEP 月次売上 = BEP 月次粗利 ÷ 粗利率想定値(デフォルト 0.62 = 70% ライス + 30% バリュー ≒ D.9 §5.2 の 62%)

MAS-044 テンプレ連携時の BEP 補正(MVP はなし、Phase 2 拡張候補):

MAS-044 テンプレの 稼働率(0〜1、例: 80% = 0.8)を考慮する場合、BEP 月次売上を稼働率で割り戻す:

BEP 月次売上(稼働率考慮版)= BEP 月次粗利 ÷ 粗利率想定値 ÷ 稼働率

例: 稼働率 80% のポジションなら、BEP 売上必要額は 1 / 0.8 = 1.25 倍 に増加。MVP では稼働率を無視して「フル稼働前提」で計算するが、業務委託・副業等で稼働率が 1.0 未満のポジションを試算する場合は Phase 2 で対応。「人間が検討すべき事項 #11」に拡張候補として明記。

MAS-044 テンプレの 売上貢献 = FALSE ポジション扱い:

revenueContributing = false のテンプレ(顧問会計士・顧問社労士等の想定)が選択された場合、BEP 月次売上は計算せず、UI に「このポジションは売上貢献なし → BEP 判定は不可。TCO 回収はクライアント売上全体から行う」と表示。月次粗利ベースの判定は行わない。

実効 Payback(離職率調整):

理論 Payback(月)= 年間 TCO ÷ (月次粗利貢献想定 × 12) × 12

実効 Payback = 理論 Payback ÷ (1 - TCO_TURNOVER_RATE_3Y × (36 - 理論 Payback) / 36)
  * 離職率調整: 3 年以内離職率 52.7% を線形に配分。Payback が 36 ヶ月より長ければ完全ロスト扱い(`Infinity` 返却)

Step 4: UI 実装(templates/hiring_tco_sidebar.html 新規)

入力フォーム:

  • MAS-044 テンプレート選択(MAS-044 / PR #339 実装済、選択時に以下フィールドを自動入力)
  • 想定年収(数値、プリセット: 400 万 / 500 万 / 600 万 / 800 万 / 1,000 万、テンプレ選択時は monthlySalary × 12 で自動入力
  • 雇用形態(dropdown: 正社員 / 契約社員 / 業務委託 / 副業、テンプレ選択時は employmentType で自動入力
  • 年齢区分(40 歳未満 / 40 歳以上)
  • 採用費率(デフォルト 30%、調整可、テンプレ選択時は defaultRecruitFee ÷ monthlySalary ÷ 12 で逆算
  • PC・設備費(テンプレ選択時は defaultPcCost で自動入力、従来の TCO_EQUIPMENT_TOTAL デフォルトを上書き)
  • 月次追加固定費(テンプレ選択時は monthlyFixedCost で自動入力、TCO 計算の「その他固定費」に加算)
  • 立ち上がり月数(テンプレ選択時は rampUpMonths で自動入力、実効 Payback 計算の「売上貢献開始までのオフセット」として減算)
  • 稼働率(テンプレ選択時は utilization で自動入力、MVP では表示のみで計算未反映・Phase 2 で BEP 補正対応)
  • 粗利率想定(デフォルト 62%、調整可、テンプレ選択時は 1 - variableCostRate で自動入力

テンプレ選択の実装方針:

MAS-044 実装の getHcTemplateValues(templateId)430_what_if_simulator.js に MAS-044 PR #339 で追加、同等機能)を MAS-048 でも呼び出す or MAS-048 専用に getHiringTcoTemplateValues(templateId) を新設するかを Step 2 実装時に判断。推奨: 共通 API PositionTemplateRepository.findAsMap() を MAS-048 の 412_hiring_tco_simulator.js から直接呼ぶ(MAS-044 依存を避け、Repository 層のみに依存)。

  • 月次粗利貢献想定(任意、離職率調整 Payback 計算用)

出力表示:

  • 年間 TCO 合計(強調表示)
  • 月次 TCO(= BEP 月次粗利)
  • BEP 月次売上
  • 実効 Payback(月、警告色で 24 ヶ月超を赤表示)
  • 内訳テーブル(13 項目)
  • MAS-042 判定ヒント(Go: BEP < 月商の 30%、グレー: 30-50%、No-Go: 50% 超)

「シートに保存」ボタンで runHiringTcoSimulation 実行 → 69_report_hiring_tco に追記。

Step 5: MENU_DEFINITION 追記

📋 サイドバー: 📊 マート更新 カテゴリの items 末尾(MAS-011 What-if の直後)に追加:

{ label: '💼 採用 TCO & BEP 試算', funcName: 'openHiringTcoSidebar', description: '想定年収から TCO(実コスト)と BEP(損益分岐点売上)を試算' },

影響範囲

変更ファイル一覧

ファイル変更種別内容
400_domain/412_hiring_tco_simulator.js新規namespace HiringTcoSimulator + 計算 / 書込 / 統合関数(約 300 行)
templates/hiring_tco_sidebar.html新規入力フォーム + 結果表示(約 250 行)
000_infra/002_constants.js追加のみMENU_DEFINITION に 1 エントリ追加
CLAUDE.md追加のみDDL 管理外リストに 69_report_hiring_tco 追記
03_sys_paramsデータ追加のみ13 パラメータキーの初期値投入
docs/_config.json追加のみnav 登録

既存動作への影響

  • MAS-011 What-if MVP: 影響なし(別 namespace / 別サイドバー)
  • MAS-012 人員計画: 仕様書段階、MAS-048 完成後に「MAS-012 逆算人員数 × MAS-048 単位 TCO = 採用総投資額」を計算する統合シミュレーションを検討
  • MAS-042 Go/No-Go: 仕様書完了済(PR #319)。MAS-048 の TCO/BEP 出力を MAS-042 の採用スクリーニング判定に入力として接続する

運用・デプロイ手順

  1. 03_sys_params に 13 パラメータキーの初期値を手動投入
  2. CLAUDE.md69_report_hiring_tco 追記 → PR マージ
  3. npm run push:dev → サイドバー 💼 採用 TCO & BEP 試算 起動
  4. テストケース実行: 年収 600 万 / 正社員 / 40 歳未満 → 年間 TCO ≒ 873 万円 / BEP ≒ 117 万 / 月(D.9 §2.2 と一致確認)
  5. 69_report_hiring_tco シートが自動生成され結果が追記される
  6. npm run push:prod → 本番同手順

注意事項

  • ⚠️ failure_patterns #18-#20(命名造語禁止): namespace HiringTcoSimulator / ファイル名 412_hiring_tco_simulator.js / シート名 69_report_hiring_tco / パラメータキー TCO_* を記述前に再確認
  • ⚠️ failure_patterns #3(DDL コード値 vs 実データ乖離): 法定福利費率は 2025 年度料率ベース。年次更新(毎年 4 月)必須。03_sys_params で管理すれば年次更新はマスタ変更のみで対応可能
  • ⚠️ failure_patterns #26(oauthScopes: 本案件は SpreadsheetApp / HtmlService のみ使用。追加スコープ不要(該当なし)
  • ⚠️ 雇用形態コードの命名: 'SEISHAIN' | 'KEIYAKU' | 'GYOUMU_ITAKU' | 'FUKUGYOU' は独自列挙だが、15_mst_dictionaryUI雇用形態 カテゴリ値と文字列として一致させる必要あり。マッピングテーブルを 412_hiring_tco_simulator.js 冒頭に定数として定義
  • ⚠️ 設備按分の共有: 複数人採用時に TCO_EQUIPMENT_TOTAL を 1 人に全額按分すると過大になる。シミュレーション時にユーザーが「共有 or 専用」を選択できるようにする(Phase 2 拡張余地)
  • ⚠️ 実効 Payback 計算の線形近似: D.9 §2.6 の離職率 52.7% を単純線形配分している。実務では最初 6 ヶ月での離職が多い指数分布に近いが、MVP は線形で簡略化
  • ⚠️ MAS-044 連携: MAS-044 / PR #339 で既に実装完了。PositionTemplateRepository.findAsMap() 経由で 11 フィールド(monthlySalary / monthlyRevenue / variableCostRate / defaultRecruitFee / defaultPcCost / monthlyFixedCost / rampUpMonths / revenueContributing / utilization / employmentType / positionName)を取得してフォーム自動入力に使用
  • ⚠️ 売上貢献 = FALSE 行の除外: loadActualAverages22_bud_headcount売上貢献 列が FALSE の行を除外(MAS-012 PR #337 と同じ判定)。顧問会計士・顧問社労士等のコスト型 HC を「今後採用する売上貢献型 HC」の想定コスト平均から外す
  • ⚠️ Human-in-the-Loop: TCO / BEP は判断補助であり、最終的な採用決定は人間が行う。仕様書・サイドバー UI にその旨を明記

エッジケース

#条件検知方法期待される挙動ログ出力
1想定年収 0 or 負値input.annualSalary <= 0入力バリデーションエラー・計算中断Utils.persistLog('WARN', 'simulate', 'invalid salary', '')
203_sys_params にパラメータ未投入Constants.getParam('TCO_STATUTORY_WELFARE_RATE') がデフォルト値(0.1568)返却デフォルト値で計算実行・結果にヒント表示「03_sys_params に初期値を投入してください」Utils.logInfo('simulate', 'using default params')
3雇用形態が定義外定義外文字列(例: 'ALBAITO'入力バリデーションエラー・UI で dropdown 範囲外を拒否Utils.persistLog('WARN', 'simulate', 'invalid employmentType: ' + type)
422_bud_headcount が空(実績平均プリロード不可)loadActualAverages で有効行 0プリロードをスキップし MAS-044 テンプレート or 手動入力にフォールバックUtils.logInfo('loadActualAverages', 'no active rows')
5粗利率想定値 0 or 負値input.grossMarginRate <= 0BEP 月次売上計算でゼロ除算 → Infinity 返却 → UI で「粗利率要確認」赤表示Utils.persistLog('WARN', ...)
640 歳以上指定だが介護保険料率 03_sys_params 未定義Constants.getParam('TCO_STATUTORY_WELFARE_RATE_40PLUS') でフォールバックデフォルト 0.16475 で計算Utils.logInfo(...)
7業務委託(GYOUMU_ITAKU)で法定福利費を計算しようとする雇用形態分岐で 0 強制法定福利費 = 0 で計算継続ログ出力なし(正常系)
8実効 Payback が Infinity(離職率で完全ロスト扱い)理論 Payback ≥ 36UI で「3 年以内離職リスク大・採用見送り推奨」赤色警告Utils.persistLog('WARN', 'calcEffectivePayback', 'payback > 36 months')
969_report_hiring_tco シート書き込み中に他処理が編集LockService.tryLock(5000) 失敗「別の処理が実行中」Toast 表示Utils.persistLog('WARN', 'runHiringTcoSimulation', 'lock failed')
10サイドバー起動中にマスタ (03_sys_params) 編集キャッシュ未更新次回計算から反映(Constants._paramsCacheGAS 実行単位でリセット)ログ出力なし(正常系)
11MAS-044 未実装時にテンプレート選択を試行PositionTemplateRepository 存在チェックdropdown 非表示または「MAS-044 未実装」メッセージ表示ログ出力なし
12年収が 3,000 万超の高額想定input.annualSalary > 30000000警告表示「一人法人想定範囲外・計算は継続」Utils.persistLog('WARN', 'simulate', 'high salary', '')
13採用費率が 1.0 超(年収の 100% 超)input.recruitFeeRate > 1.0警告表示「採用費率が異常値」・計算は継続Utils.persistLog('WARN', ...)
14同時に複数ユーザーがサイドバー起動LockService で 1 ユーザーのみ計算実行2 人目は「別処理実行中」ToastUtils.persistLog('WARN', ...)
15Web アプリ(doGet)から実行SpreadsheetApp.getUi() が throwMAS-013 実装の _notifyUser_ パターンで alert → toast → console フォールバックログ出力なし

冪等性・再実行の設計

Gemini レビュー 🟡 Major 指摘対応(MAS-045 との挙動統一): 69_report_hiring_tco への書き込みは 純粋な追記方式。同一条件で複数回実行すれば複数行が追加される(MAS-045 予算転記と同一方針)。

  • 試算 ID はタイムスタンプベース(HTCO_YYYYMMDD_HHMMSS)で毎回一意
  • 過去試算との比較はユーザーがシート上で手動比較 or 将来の Phase 2 で「試算履歴ビューワー」を提供
  • MVP で上書き方式を採用しない理由: MAS-045 予算転記と挙動が異なると「What-if 系の機能は追記だが、採用 TCO 系は上書き」とユーザーが混乱するリスク。類似機能は原則統一(追記方式)

Human-in-the-Loop

  • TCO / BEP は判断補助であり、採用決定は人間が行う(仕様書・サイドバー UI に明記)
  • MAS-042 との連携で「Go / グレー / No-Go」ラベルを表示するが、背景色のみの視覚警告(自動ブロックはしない)

テスト要件(900_test/901_test_runner.js

テスト関数合格基準
test_HiringTcoSimulator_simulate_seishain_40under年収 600 万 / 正社員 / 40 歳未満 → 年間 TCO = 約 873 万(D.9 §2.2 一致誤差 1% 未満)
test_HiringTcoSimulator_simulate_gyoumuItaku業務委託 → 法定福利費 = 0、TCO = 年収 + 諸費用のみ
test_HiringTcoSimulator_calcEffectivePayback理論 Payback 12 ヶ月 × 離職率 52.7% → 実効 Payback の手計算一致
test_HiringTcoSimulator_loadActualAverages_emptyMaster22_bud_headcount 空 → avgAnnualSalary = null
test_HiringTcoSimulator_writeToReport_newRow新規試算 → 最終行追加
test_HiringTcoSimulator_writeToReport_duplicateId同一試算 ID → 既存行上書き

実データ検証

実装前に MCP で以下を確認:

  1. 22_bud_headcount の実ヘッダー行: BUD_HC schema(101_sys_config.js L943)との一致確認、特に 雇用形態 / 月額給与・報酬 / 採用エージェント費 / PC等初期費用 / 健保料率
  2. 03_sys_params の既存キー一覧: TCO_* プレフィックスの 13 キーが未登録であること
  3. 15_mst_dictionaryUI雇用形態 カテゴリ: 現行値域(正社員 / 契約社員 / 業務委託 / 副業 / パート 等)の確認
  4. 69_report_hiring_tco シートが未作成であること
  5. CLAUDE.md の DDL 管理外リスト: 現状 03_sys_params / 75_ss_equity_changes / 76_notes / 77_pj_raw / 78_pj_pl / 91_fs_bs / 92_fs_pl / 93_kpi_dashboard / 94_fs_longterm_forecast / 90_test_results を列挙中。本案件で 69_report_hiring_tco / MAS-013 で 67_report_investment_analysis 追記済

関連ドキュメント

仕様書・ドキュメント関連箇所
dev_mas-012_headcount_simulation.md目標売上 → 必要人員数逆算。MAS-048 の「1 人の TCO」と組み合わせて「X 人採用の総投資額」を計算
dev_mas-042_investment_hurdle_rate.mdGo/No-Go 判定エンジン。MAS-048 の TCO/BEP 出力を採用スクリーニング判定に接続
dev_mas-044_hc_template_master.mdMAS-048 の入力源。PositionTemplateRepository からテンプレート年収・雇用形態・初期費用を参照
dev_mas-049_wage_increase_tax_credit_simulator.mdMAS-048 の TCO 計算結果を入力として、賃上げ促進税制の税額控除を試算
ref_boutique_first_hire_simulation.mdD.9 調査レポート。§2 採用 TCO 完全分解・§5 BEP / Payback 計算フレーム・§7 Exit Cost が本案件の根拠
CLAUDE.mdコーディング規約(ヘッダー名ベース列参照・Human-in-the-Loop・DDL 管理外タブリスト)

人間が検討すべき事項

  1. 法定福利費率の年次更新フロー: 毎年 4 月料率改定への追従。03_sys_params での管理は良いが、更新忘れ防止のアラート(4 月になったら「料率更新を確認してください」Toast)を実装するか
  2. 業務委託との比較モードの追加: 現案は単一雇用形態の試算。「正社員 vs 業務委託」の横並び比較モード(Phase 2 拡張)の優先度
  3. 定着率リスク(3 年以内離職率 52.7%)の感応度分析: 現案はパラメータ固定。職種別・年齢別の離職率を 03_sys_params で複数キーに分解するか
  4. オンボーディング工数按分ルール: 現案は TCO_TRAINING_ANNUAL 年 8 万で固定。代表者の時間単価 × OJT 時間での動的計算も検討(D.9 §2.6 の「オンボーディングコスト年収の 20-30%」反映)
  5. MAS-012 との統合シミュレーション: 「必要人員数 × 単位 TCO = 採用総投資額」を 1 画面で表示する統合 UI を MAS-048 内に作るか、別案件で起票するか
  6. MAS-042 Go/No-Go 連携の実装タイミング: MAS-042 実装時に MAS-048 API を呼ぶ形 or MAS-048 UI に MAS-042 判定ラベルを直接表示。UI 密結合は避けるべきだが、ユーザー体験は密結合の方が良い
  7. Web アプリ対応: MAS-013 と同様 _notifyUser_ フォールバックを実装。スマホから採用検討中に試算できる価値は高い
  8. 69_report_hiring_tco シートの保持期間: 過去の試算履歴は全件保持 or 100 件上限で古いものを自動削除するか
  9. 税務・社労士との連携: 計算結果の年次監査(4 月料率改定後の整合確認)を顧問社労士にレビュー依頼する運用ルール
  10. D.9 §11 GO/WAIT/NO-GO 判定マトリクス: MAS-048 実装時に「WAIT 推奨ライン」(月商 300 万円未満は採用しない等)を計算結果画面に表示するか
  11. 稼働率(utilization)の BEP 補正対応タイミング(Phase 2 拡張候補): MAS-044 テンプレの utilization(0〜1)を BEP 月次売上計算に反映する機能。MVP では表示のみで計算は未反映(フル稼働前提)。業務委託・副業・パートタイムの試算が増えた時点で Phase 2 対応。補正式: BEP 月次売上 ÷ utilization(稼働率 80% なら売上必要額が 1.25 倍に増加)
  12. 立ち上がり月数(rampUpMonths)の実効 Payback への反映: MAS-044 テンプレの rampUpMonths(入社〜売上貢献開始までの月数)を Payback 計算の「売上貢献開始までのオフセット」として減算する設計。例: 立ち上がり 3 ヶ月で理論 Payback 12 ヶ月 → 実質 15 ヶ月(入社から 15 ヶ月経過で回収完了)。離職率調整と組み合わせた最終 Payback 計算の優先順位を検討
  13. 売上貢献フラグ FALSE ポジションの TCO 試算モード: revenueContributing = false テンプレ(顧問会計士等)の場合、BEP 判定不可のまま TCO のみ表示する運用で良いか。あるいは「クライアント売上からの按分費用」として間接的に BEP を計算する拡張を入れるか

実装プロンプト(Claude Code 用)

あなたは GAS 会計システム (bizlp-gas-accounting) のシニア開発者です。
案件 MAS-048「採用 TCO & BEP シミュレーター」を以下の 5 Step で実装してください。

## 実行前タスク(必須・5 件)
1. `100_config/101_sys_config.js` の `BUD_HC` schema(L943)を Read し `22_bud_headcount` のヘッダー構成を確認
2. `000_infra/002_constants.js` の `Constants.getParam`(L147)と `MENU_DEFINITION`(L206 起点)を Read
3. `docs/arch/ref_boutique_first_hire_simulation.md`(D.9)の §2 / §5 を Read し計算式を確認
4. `docs/dev/dev_mas-013_investment_simulation.md` の `_notifyUser_` パターンを確認(Web アプリ対応)
5. MCP で `69_report_hiring_tco` シート未作成を確認、`03_sys_params` に `TCO_*` キー未登録を確認

## Step 1: `03_sys_params` パラメータ投入 + CLAUDE.md 更新(推奨モデル: Haiku)
- 13 パラメータキー(`TCO_STATUTORY_WELFARE_RATE` 等)を `03_sys_params` に MCP `update_cells` で投入
- `CLAUDE.md` の DDL 管理外リストに `69_report_hiring_tco` 追記

## Step 2: `412_hiring_tco_simulator.js` 新設(推奨モデル: Sonnet)
- namespace `HiringTcoSimulator` を IIFE で定義
- `simulate(input)` / `loadActualAverages()` / `writeToReport(result)` / `runHiringTcoSimulation(input)` の 4 公開関数
- `openHiringTcoSidebar()` グローバル関数(MENU_DEFINITION の funcName と一致)
- `LockService.tryLock(5000)` で排他制御、`_notifyUser_` で Web アプリ対応
- 離職率調整 Payback は D.9 §2.6 の線形近似で実装

## Step 3: サイドバー UI 実装(`templates/hiring_tco_sidebar.html` 新規、推奨モデル: Sonnet)
- 入力フォーム(想定年収プリセット / 雇用形態 dropdown / 年齢区分 / 採用費率 / 粗利率想定)
- 出力: 年間 TCO / 月次 TCO / BEP 月次売上 / 実効 Payback
- 内訳テーブル 13 項目
- MAS-044 テンプレ dropdown(MAS-044 完成前は非表示)
- 「シートに保存」ボタン → `runHiringTcoSimulation` 呼出

## Step 4: MENU_DEFINITION 追記(`002_constants.js`、推奨モデル: Haiku)
- `📋 サイドバー: 📊 マート更新` カテゴリに 1 エントリ追加
- `funcName: 'openHiringTcoSidebar'` と Step 2 のグローバル関数名一致確認

## Step 5: テスト追加(`900_test/901_test_runner.js`、推奨モデル: Sonnet)
- 6 テスト関数(正社員 40 歳未満 / 業務委託 / Payback / プリロード / 追記 / 重複 ID)
- 合格基準: D.9 §2.2 の年収 600 万 → 873 万円 TCO との誤差 1% 未満

## 制約
- `appsscript.json` の `oauthScopes` を変更しない
- 列番号ハードコード禁止(`headers.indexOf` で動的取得)
- 架空の関数名・シート名を使わない(failure_patterns #18-#20)
- MAS-044 未実装時も単体で動作する(テンプレ dropdown は非表示 or グレーアウト)
- 計算ロジックは純粋関数(`simulate` は入出力のみで副作用なし、`SpreadsheetApp` を呼ばない)

## 動作確認
1. サイドバー起動 → 想定年収 600 万 / 正社員 / 40 歳未満
2. 年間 TCO ≒ 873 万円(D.9 §2.2 一致)
3. BEP 月次売上 ≒ 117 万円(粗利率 62%)
4. 実効 Payback 表示
5. 「シートに保存」→ `69_report_hiring_tco` に追記される
6. Web アプリ URL からも実行可能(`_notifyUser_` フォールバック)

推奨実行モデル

工程推奨モデル理由
Step 1: パラメータ投入 + CLAUDE.md 更新Claude Haiku 4.5定型作業、判断要素なし
Step 2: 計算エンジン実装Claude Sonnet 4.6D.9 計算式の忠実実装 + 雇用形態分岐の判断
Step 3: サイドバー UIClaude Sonnet 4.6HTML + JS + google.script.run 連携
Step 4: MENU_DEFINITION 追記Claude Haiku 4.51 行追記、判断なし
Step 5: テスト追加Claude Sonnet 4.6合格基準の D.9 §2.2 との数値一致検証

変更履歴

日付変更内容
2026-04-23初版作成。D.9「一人法人 1 人目採用 財務シミュレーション完全ガイド」§2 / §5 の計算フレームを実装する仕様。Jr 採用 D-180(2026-10 入社想定)向け P1.5 ★★★ 最優先案件。namespace HiringTcoSimulator400_domain/412_hiring_tco_simulator.js 新規)で simulate(input) / loadActualAverages() / writeToReport(result) / runHiringTcoSimulation(input) の 4 公開関数。13 パラメータを 03_sys_params で管理(ハードコード禁止)。69_report_hiring_tco(DDL 管理外・動的上書き)に試算履歴を追記。MAS-044 テンプレ連携・MAS-042 Go/No-Go 連携・MAS-049 税制連携のフック点を確保。エッジケース 15 件・人間検討事項 10 件・推奨実行モデル 5 工程(Haiku×2 / Sonnet×3)を定義
2026-04-23Gemini レビュー(PR #335)指摘を反映。🟡 Major 対応: 冪等性設計を「同一 ID 上書き」から「純粋追記」に変更し、MAS-045 予算転記の挙動と統一。類似機能の挙動差異によるユーザー混乱を回避。試算 ID はタイムスタンプベース(HTCO_YYYYMMDD_HHMMSS)で毎回一意、過去比較は Phase 2 で「試算履歴ビューワー」として拡張予定
2026-04-23不整合修正: (1) 出力シート番号 68 → 69 に変更(MAS-042 PR #336 で 68_report_investment_gonogo が使用中のため衝突回避、仕様書内 21 箇所を一括置換)、(2) MAS-044 実装(PR #339)で 18_tmpl_hc_position に追加された列(月次追加固定費 / 立ち上がり月数 / 売上貢献 / 稼働率)の MAS-048 での参照方法を明記。PositionTemplateRepository.findAsMap() の 11 フィールド戻り値(monthlyFixedCost / rampUpMonths / revenueContributing / utilization を含む)のフォーム自動反映設計を追加。loadActualAverages に売上貢献フラグ FALSE 除外ロジック(MAS-012 と同じ判定)を追記。人間検討事項 #11〜#13 を追加(稼働率 BEP 補正 / 立ち上がり月数 Payback 反映 / 売上貢献 FALSE ポジション試算モード)