Adhoc(経費・その他)自動起票 — 26_bud_adhoc
1. 基本情報
焦点質問: 臨時経費・その他費用からどのようなINVを生成するか?
26_bud_adhoc(単発予算マスタ)の各有効行に対し、科目名・発生日・税込金額を検証したうえで 1行1INV を 32_wrk_invoice へ一括起票 する。HC/SaaS/CAPEXと異なり月次ループは行わず、対象月指定も不要。ORD自動作成は行わない(手動紐づけ)。申請種別は決済手段キーワードから自動判定される。
| 項目 | 内容 |
|---|---|
| 関数名 | generateAdhocInvoices(targetOverride, _silent) |
| ファイル | 401_bat_rpa.js |
| 入力 | 26_bud_adhoc |
| 出力 | 32_wrk_invoice(末尾追記)。ORD 自動作成なし |
| メニュー | 「📒 経理業務 > 📥 単発経費の自動起票」 |
| 一括実行 | generateAllRpaInvoices から generateAdhocInvoices(null, true) で呼出 |
2. 前提条件・依存関係
| 項目 | 内容 |
|---|---|
| SSOT | 32_wrk_invoice(起票先・重複チェック用) |
| 入力元タブ | 26_bud_adhoc |
| マスタ依存 | 11_mst_account(writeInvRows_ 内で諸表区分・大分類を科目マスタから自動付与) |
| 前提 | 有効フラグ=TRUE の行のみ処理対象。空セル・未定義値は FALSE 扱い |
| 前提 | 科目名・発生日・税込金額(税抜+消費税の再計算値)がすべて有効であること |
| 重複制御 | 摘要 【RPA:Adhoc】{mgrId} {取引名} で isDuplicate_() 判定 → 既存時 SKIP |
| ヘルパー | buildInvRow_, writeInvRows_, isDuplicate_, generateInvId_ |
| 後続処理 | Action A → TRN/STL 自動作成 → Action B(消込・決済仕訳) |
3. 入力スキーマ
26_bud_adhoc カラム定義
DDL定義元: 101_sys_config.js — BUD_ADHOC
| # | 列 | カラム名 | 型 | 入力/自動 | 説明 | 制約 |
|---|---|---|---|---|---|---|
| 1 | A | 有効フラグ | checkbox | 入力 | FALSE→SKIP | 空セルもFALSE扱い。プルダウン=TRUE/FALSE |
| 2 | B | 管理ID | string | 自動(RPA) | ADH_NNNN(空なら自動発番) | 空の場合RPAが全行スキャン最大番号+1で自動採番 |
| 3 | C | 取引名 | string | 入力 | PC購入、出張費等。摘要に転記 | — |
| 4 | D | 取引先名 | string | 入力(pulldown) | INV Rowに転記 | プルダウン=UI取引先名(E列) |
| 5 | E | 科目名 | string | 入力(pulldown) | INV Rowに転記。11_mst_accountに未登録の科目はエラー | プルダウン=UI科目名(F列) |
| 6 | F | 税抜金額_計画 | number | 入力 | INV生成時に taxExcl + taxAmt で税込を再計算 | #,##0書式 |
| 7 | G | 消費税額_計画 | number | 入力 | 0も可(対象外の場合) | #,##0書式 |
| 8 | H | 税込金額_計画 | number | 自動(数式) | =F+G (DDL設定の数式)。コード上はF+Gを再計算して使用 | #,##0書式。DDL自動設定 |
| 9 | I | 税区分 | string | 入力(pulldown) | 空の場合「対象外」をデフォルト | プルダウン=UI税区分(B列) |
| 10 | J | 発生日(P/L計上日) | date | 入力 | 日付型→そのまま使用。YYYY-MM文字列→月末日に変換 | yyyy-mm-dd書式。空→SKIP |
| 11 | K | 収支区分 | string | 入力(pulldown) | 支出/収入。空の場合「支出」をデフォルト | プルダウン=UI収支区分(A列) |
| 12 | L | 決済手段 | string | 入力(pulldown) | 申請種別の自動判定に使用 | プルダウン=UI決済手段(C列) |
| 13 | M | 決済ラグ(月) | number | 入力 | 0=当月。全角数字→半角自動変換 | — |
| 14 | N | 支払基準日 | number | 入力 | 日(1-31)。0=月末。月末日より大きい場合キャップ | — |
| 15 | O | PJ名 | string | 入力(pulldown) | INV Rowに転記。空の場合 buildInvRow_ がデフォルト「指定なし_共通費など」を設定 | プルダウン=UIPJ名(H列) |
| 16 | P | 組織名 | string | 入力(pulldown) | INV Rowに転記 | プルダウン=UI組織名(G列) |
| 17 | Q | 備考 | string | 入力 | 自由記述。INVには転記されない | — |
4. 処理ロジック(マトリクス)
共通INVフィールド(
buildInvRow_が自動設定): 有効フラグ=true, 請求ID=INV_YYYYMMDD_NNNN(自動発番), 起票日時=now, 起票者="RPA自動起票", 請求ステータス="未処理", 通貨="JPY", 未決済残高=税込金額_計画HC/SaaSとの違い: Adhocは月次ループなし・対象月指定なし・ORD自動作成なし。1入力行あたり1INVのみ生成。
| 項番 | 処理フェーズ | 入力(論理名) | 入力(物理名: タブ.列) | 処理詳細 / 変換ロジック | 出力(論理名) | 出力(物理名: タブ.列) | 例外処理 |
|---|---|---|---|---|---|---|---|
| S1.1 | 初期化: シート取得 | — | — | 26_bud_adhoc と 32_wrk_invoice を取得 | adhocSheet, invSheet | — | ⚠️ 26タブ未検出 → ui.alert で中断 |
| S1.2 | 初期化: データ読込 | 全行データ | 26_bud_adhoc, 32_wrk_invoice | ヘッダー行をパースし col マップを構築。INV全行も読込(重複チェック用) | adhocData, invData, col | 変数 | ⚠️ データ1行以下 → ui.alert("Adhocデータがありません") で終了 |
| S1.3 | 初期化: 管理ID最大値取得 | 管理ID | 26_bud_adhoc.B列 | 全行スキャンし ADH_ プレフィックスの最大番号を取得 | mgrIdMax | 変数: mgrIdMax | — |
| S2.1 | ループ開始 | — | 26_bud_adhoc 全行 | FOR EACH 行 — 以下を各行に対して実行 | — | — | — |
| S2.2 | スキップ判定① | 有効フラグ | 26_bud_adhoc.A列 | !== true かつ String().toUpperCase() !== 'TRUE' → SKIP | — | — | ⚠️ 空セル・未定義値もFALSE扱い |
| S2.3 | 管理ID自動発番 | 管理ID | 26_bud_adhoc.B列 | 空 → ADH_ + (mgrIdMax+1) を4桁ゼロ埋め(padStart)で付与。adhocUpdates に書き戻し情報を蓄積 | 管理ID | 26_bud_adhoc.B列 (書き戻し予約) | — |
| S3.1 | 変数: 基本情報取得 | 取引名〜備考 | 26_bud_adhoc.C〜Q列 | 各列から文字列/数値を String().trim() / Number() || 0 で取得 | 各変数 | 変数: txnName, vendorName, accName, taxExcl, taxAmt, totalIncTax 等 | ⚠️ 収支区分空→'支出'。⚠️ 税区分空→'対象外' |
| S3.2 | 変数: 税込金額再計算 | 税抜金額_計画, 消費税額_計画 | 26_bud_adhoc.F列, G列 | totalIncTax = taxExcl + taxAmt で再計算(H列の数式値は使わない) | totalIncTax | 変数 | — |
| S3.3 | スキップ判定② | 発生日, 科目名, 税込金額 | 26_bud_adhoc.J列, E列, 変数 | occurYmが空 OR 科目名が空 OR totalIncTax === 0 → SKIP | — | — | ※1 |
| S3.4 | 変数: 発生日決定 | 発生日(P/L計上日) | 26_bud_adhoc.J列 | parseDateToYm() で YYYY-MM を取得。日付型(Date)ならそのまま使用。YYYY-MM文字列なら月末日(new Date(year, month, 0))に変換 | occurDate | 変数: occurDate (Date) | ⚠️ 日付でもYYYY-MMでもない文字列 → parseDateToYm が null → S3.3でSKIP |
| S3.5 | 変数: 決済日_計画算出 | 決済ラグ(月), 支払基準日, 発生日 | 26_bud_adhoc.M列, N列 | ラグ文字列を全角→半角変換しパース。支払基準日 > 0 なら 発生月 + ラグ月の支払基準日(月末日キャップ)。支払基準日 = 0 なら 発生月 + ラグ月の月末日 | 決済日_計画 | 変数: settleDate (Date) | ⚠️ 全角数字→半角変換(charCodeAt - 0xFEE0)。⚠️ 支払基準日 > 月末日 → Math.min でキャップ |
| S4.1 | 重複チェック | 摘要 | 32_wrk_invoice.摘要列 | isDuplicate_() で "【RPA:Adhoc】{mgrId} {取引名}" を完全一致検索 → 存在すれば SKIP | — | — | — |
| S4.2 | 申請種別の自動判定 | 決済手段 | 26_bud_adhoc.L列 | 判定順序(先勝ち): ①振込含む→"手動振込" ②クレカor振替含む→"自動引落" ③立替含む→"経費精算(社員立替)" ④その他→"請求書受領(AP)" | appType | 変数: appType | ※2 |
| S4.3 | INV行生成 | 全変数 | — | buildInvRow_ で INV行を構築。PJ名が空の場合は "指定なし_共通費など" がデフォルト設定される | INV行 | drafts配列に追加 | — |
| W1.1 | 一括書き込み: INV | drafts | — | writeInvRows_() で 32タブ末尾に追記。諸表区分・大分類を loadAcctMapForRpa_() 経由で科目マスタから自動付与 | — | 32_wrk_invoice | — |
| W1.2 | 管理ID書き戻し | adhocUpdates | — | 自動発番したIDを adhocSheet.getRange(r, c).setValue(val) で 26タブに個別書き戻し | — | 26_bud_adhoc.B列 | — |
脚注:
- ※1: 仕様上は
税込金額_計画=0だが、コード上はtotalIncTax = taxExcl + taxAmtで再計算した値が0かチェック(H列の数式値ではなくF+Gの合計)- ※2: 判定順序が重要。
振込→クレカ/振替→立替の順。例:"口座振替_福井銀行"は振替を含むので"自動引落"。"立替振込"は振込が先にマッチするので"手動振込"
5. 出力サマリー
生成される INV 行
Adhoc RPAは1入力行あたり最大1行のINVを生成する(HC RPAのような派生Rowは発生しない)。
| 出力フィールド | 値の決定方法 | ソース |
|---|---|---|
| 有効フラグ | true (固定) | — |
| 請求ID(INV) | INV_YYYYMMDD_NNNN | generateInvId_ 自動発番 |
| 起票日時 | 実行時刻 | new Date() |
| 起票者 | "RPA自動起票" (固定) | — |
| 申請種別 | 決済手段キーワードから自動判定 | S4.2 参照 |
| 発生日(P/L計上日) | 入力日付 or YYYY-MM→月末日 | 26_bud_adhoc.J列 |
| 決済日_計画 | 発生月+ラグ月の支払基準日 or 月末日 | S3.5 参照 |
| 請求ステータス | "未処理" (固定) | — |
| 収支区分 | 入力値。空→"支出" | 26_bud_adhoc.K列 |
| 取引先名 | 入力値をそのまま転記 | 26_bud_adhoc.D列 |
| PJ名 | 入力値。空→"指定なし_共通費など" | 26_bud_adhoc.O列 |
| 科目名 | 入力値をそのまま転記 | 26_bud_adhoc.E列 |
| 税区分 | 入力値。空→"対象外" | 26_bud_adhoc.I列 |
| 通貨 | "JPY" (固定) | — |
| 税抜金額_計画 | 入力値 | 26_bud_adhoc.F列 |
| 消費税額_計画 | 入力値 | 26_bud_adhoc.G列 |
| 税込金額_計画 | taxExcl + taxAmt (再計算) | F列 + G列 |
| 未決済残高(自動計算) | totalIncTax と同値 | — |
| 決済手段 | 入力値をそのまま転記 | 26_bud_adhoc.L列 |
| 組織名 | 入力値をそのまま転記 | 26_bud_adhoc.P列 |
| 摘要 | 【RPA:Adhoc】{mgrId} {取引名} | 26_bud_adhoc.B列 + C列 |
| 諸表区分 | 科目マスタから自動付与 | 11_mst_account |
| 大分類 | 科目マスタから自動付与 | 11_mst_account |
6. 業務ルール
6.1 Adhoc RPAの位置づけ
Adhoc RPAは、HC・SaaS・CAPEX・FINのいずれにも該当しない 臨時経費・その他費用 を一括起票するための汎用RPAである。月次の繰返しではなく、1行1回限りの単発起票を前提とする。
6.2 HC/SaaS/CAPEX/FIN との違い
| 項目 | HC/SaaS/CAPEX | FIN | Adhoc |
|---|---|---|---|
| 対象月指定 | 必要 | 必要 | 不要(全行一括) |
| 月次ループ | あり | なし | なし |
| ORD自動作成 | あり | あり | なし(手動紐づけ) |
| 最終起票年月日 | あり | あり | なし(単発のため不要) |
| 申請種別 | 固定値 | 固定値 | 決済手段キーワードから自動判定(S4.2参照) |
| PJ名・組織名 | デフォルト値 | デフォルト値 | 入力値をそのまま反映 |
| 消費税 | 内税/なし | なし | 税抜+消費税を個別入力(F列+G列) |
| 収支区分 | 固定(支出) | 入力 | 入力値を反映(支出/収入) |
6.3 申請種別の自動判定ルール
決済手段の文字列に含まれるキーワードで申請種別を先勝ちで判定する。
| 優先順 | 決済手段に含むキーワード | 判定結果(申請種別) | 例 |
|---|---|---|---|
| 1 | 振込 | 手動振込 | 口座振込、銀行振込 |
| 2 | クレカ or 振替 | 自動引落 | クレカ決済、口座振替_福井銀行 |
| 3 | 立替 | 経費精算(社員立替) | 社員立替 |
| 4 | 上記以外 | 請求書受領(AP) | 現金、その他 |
注意: 判定は
String.includes()による部分一致で、先勝ちのif-else構造。立替振込は「振込」が先にマッチするため「手動振込」と判定される。
6.4 税込金額の算出
税込金額_計画 = 税抜金額_計画 + 消費税額_計画 — totalIncTax = taxExcl + taxAmt
コード上はH列の数式値(=F+G)を参照せず、F列+G列を直接再計算して使用する。これにより数式の破損・未反映があっても正しい値でINVを生成できる。
6.5 決済日_計画の算出
決済日_計画 = 発生月 + 決済ラグ月 の 支払基準日 — settleDate
- 支払基準日 > 0: 当該月の指定日(月末日を超える場合はキャップ)
- 支払基準日 = 0 or 未指定: 当該月の月末日
6.6 PJ名のデフォルト
buildInvRow_ 内で PJ名が空の場合は "指定なし_共通費など" が自動設定される。これはAdhoc固有ではなく全RPA共通の挙動である。
7. 冪等性(二重起票防止)
| 保証項目 | メカニズム | 詳細 |
|---|---|---|
| INV重複防止 | isDuplicate_() | 摘要 【RPA:Adhoc】{mgrId} {取引名} を 32_wrk_invoice の有効行(有効フラグ=TRUE)から完全一致検索。一致すればSKIP |
| 管理ID一意性 | ADH_NNNN 自動発番 | 全行スキャンで最大番号を取得し +1 で採番。4桁ゼロ埋め |
| 請求ID一意性 | generateInvId_() | INV_YYYYMMDD_NNNN 形式。同一日付内でオフセットにより一意性を保証 |
再実行時の挙動: 同一データで2回実行した場合、全行が重複チェックによりSKIPされ、起票件数=0となる。ただし、管理IDが書き戻された後に26タブの取引名を変更すると、摘要が異なるため二重起票される可能性がある。
8. エラーハンドリング
| エラー条件 | 処理 | ユーザー通知 |
|---|---|---|
| 26_bud_adhoc タブが存在しない | 処理中断 | ui.alert("🚨 26_bud_adhoc が見つかりません。") |
| データが0行(ヘッダーのみ) | 処理中断 | ui.alert("✅ Adhocデータがありません。") |
| 有効フラグ=FALSE | 行スキップ(正常動作) | 通知なし |
| 科目名が空 | 行スキップ(正常動作) | 通知なし |
| 発生日が空 or パース不可 | 行スキップ(parseDateToYm が null を返す) | 通知なし |
| 税込金額(再計算)=0 | 行スキップ(正常動作) | 通知なし |
| 重複検出(摘要一致) | 行スキップ(正常動作) | 通知なし |
| 全角数字の決済ラグ | 半角変換して処理続行 | 通知なし |
| 支払基準日 > 月末日 | Math.min で月末日にキャップして処理続行 | 通知なし |
| 起票対象なし(全行スキップ) | 正常終了 | ui.alert("✅ 起票対象なし — 新たに起票すべきAdhocはありませんでした。") |
| 起票成功 | 正常終了 | ui.alert("🎉 Adhoc起票完了 — N件 のINV行を生成しました。") |
| 予期しない例外 | try-catch で捕捉 | ui.alert("🚨 generateAdhocInvoices でエラーが発生しました — {e.message}") |
_silent=true(一括実行経由) | ダイアログ非表示 | 通知なし(戻り値で件数を返却) |
9. テスト仕様
| テストID | テスト名 | 前提条件 | 期待結果 |
|---|---|---|---|
| T1 | 立替精算の経費 | 決済手段=「社員立替」 | 申請種別=経費精算(社員立替) |
| T2 | 口座振込の支払 | 決済手段=「口座振込」 | 申請種別=手動振込 |
| T3 | クレカ決済 | 決済手段=「クレカ決済」 | 申請種別=自動引落 |
| T4 | 口座振替 | 決済手段=「口座振替_福井銀行」 | 申請種別=自動引落(「振替」にマッチ) |
| T5 | 決済手段が「その他」 | 決済手段=「現金」 | 申請種別=請求書受領(AP) |
| T6 | 管理ID空欄 | B列が空 | ADH_NNNN が自動付与され、26タブに書き戻し |
| T7 | 日付型の発生日 | J列=2026-04-15(Date型) | INVの発生日=2026-04-15 |
| T8 | YYYY-MM形式の発生日 | J列=「2026-04」(文字列) | INVの発生日=2026-04-30(月末日) |
| T9 | PJ名指定あり | O列=「PJ_Alpha」 | INVのPJ名=PJ_Alpha |
| T10 | PJ名未指定 | O列=空 | INVのPJ名=指定なし_共通費など |
| T11 | 同データで2回実行 | 1回目で起票済 | 2回目は重複スキップ(0件) |
| T12 | B/S科目(工具・器具) | 科目名=「工具・器具」 | INV生成OK(諸表区分=BS、大分類=資産が自動付与) |
| T13 | 科目名空欄 | E列=空 | 行スキップ |
| T14 | 税込金額=0 | F列=0, G列=0 | 行スキップ |
| T15 | 有効フラグ=FALSE | A列=FALSE | 行スキップ |
| T16 | 決済ラグ=全角数字 | M列=「2」 | 半角変換され、ラグ2ヶ月で決済日算出 |
| T17 | 支払基準日>月末日 | N列=31, 発生月=2月 | 支払基準日=28(or 29)にキャップ |
| T18 | 収支区分=収入 | K列=「収入」 | INVの収支区分=収入 |
付録
付録A: 変更履歴
| 日付 | 変更内容 |
|---|---|
| 2026-04-12 16:06 | Template A に準拠しリライト。コードリーディングに基づき §2前提条件、§5出力サマリー、§7冪等性、§8エラーハンドリングを新規追加。§6に業務ルール統合 |
付録B: 関連仕様書
- spec_engine — Action A / Action B(後続の仕訳転記・消込処理)
- spec_rpa_hc — HC RPA(月次ループ・派生Row・ORD自動作成あり)
- spec_rpa_saas — SaaS RPA(月次ループ・ORD自動作成あり)
- spec_rpa_finance — FIN RPA(申請種別固定・ORD自動作成あり)