ValueOS 業務フロー
位置づけ: クライアントERP(ValueOS)
ValueOSは案件(cases)に対して1つの決済区分(case_settlements.settlement_type)を紐付け、決済区分ごとに宣言された条件(SETTLEMENT_RULES)をWorkflowEngineが解釈して発注可否(canOrder)・請求可否(canInvoice)・現在の状態(currentState)・次アクション(nextAction)・担当(assignee)を機械的に導出する。判定ロジックはすべてlib/workflow配下の純関数に集約し、画面はこの判定結果を表示するレイヤーに徹する。if/elseの分岐をUIや各フォームに直接書かず、決済区分を追加・変更する場合はSETTLEMENT_RULESという設定オブジェクトを増やすことで対応する設計である。
決済区分が「3社間決済」の案件は、発注・請求とは別に、信販会社からの入金(finance_receipts)・販売店への仕切精算(dealer_settlements)・仕入先への支払(supplier_payments)という3つの金銭実体を持つ。これらはexecute_three_party_moneyという冪等なRPC経路を通じてのみ書き込まれ、three_party_money_requestsテーブルが実行結果を記録する。販売店発注フォーム(app/dealer/orders/new)による案件起票は、この金銭フローとは別の独立した登録経路であり、本ページで両者を区別して扱う。
スコープ/対象
Section titled “スコープ/対象”| 項目 | 内容 |
|---|---|
| 対象 | WorkflowEngine(canOrder/canInvoice/現在状態の判定)、決済区分別の工程進行、三社間金銭フロー(信販入金・仕切精算・仕入先支払)、販売店発注フォームの登録経路 |
| 対象外 | ダッシュボード集計基準(valueos/overviewを参照)、テーブル定義の網羅(valueos/data-modelを参照) |
| 情報源 | ValueOS正本(github.com/stanaka-blip/valueos)のlib/workflow・lib/threeParty・app/dealer/orders/new・supabase/migrations |
| 関連ページ | features/wholesale-settlement、redesign/valueos-gap、glossary |
データ(エンティティ)
Section titled “データ(エンティティ)”| エンティティ | 主なフィールド | 役割 |
|---|---|---|
cases | case_no, dealer_id, status, construction_completed_date | 案件本体。construction_completed_dateが3社間決済の請求可否判定に使われる |
case_settlements | case_id(1:1), settlement_type, fee_rate/fee_amount, deposit_rate/deposit_amount, payment_terms, card_brand/card_status/card_status_updated_at, finance_company/approval_number, loan_status/loan_status_updated_at | 決済区分と、区分ごとの詳細項目を1レコードに集約 |
orders + order_items | supplier_id, status, delivered_date, order_amount | 発注実体。全発注の納品状況が売掛の請求可否を決める |
invoices / payments | status, invoice_amount / payment_amount | 請求・入金実体。前金の入金確認判定にpaymentsの確認済み合計を使う |
three_party_money_requests | request_id(PK), action, case_id, resource_id, status, payload_hash, response | 3社間金銭アクションの冪等リクエスト表。同一request_idの再送を安全に処理する |
finance_receipts | case_id, finance_company, scheduled_date/scheduled_amount, actual_date/actual_amount, status, corrects_id | 信販会社からの入金予定・実績 |
dealer_settlements + dealer_settlement_lines | dealer_id, finance_receipt_id, invoice_id, credit_received_amount, ve_share_amount, adjustment_total_amount, payout_amount, scheduled_payout_date/actual_payout_date/actual_payout_amount, status | 販売店への仕切清算書兼支払。明細(line_kind)で調整額を積み上げる |
supplier_payments | case_id, supplier_id, order_id, due_date/scheduled_amount, paid_date/paid_amount, status | 仕入先への支払予定・実績。発注(orders)に対して1:N |
case_registration_requests | request_id(PK), case_id, status, payload_hash, response | create_case_registrationRPC(service_role専用)の冪等リクエスト表。現行の販売店発注フォームからは未接続(後述) |
決済区分と正規化
Section titled “決済区分と正規化”case_settlements.settlement_typeの正式値は4つ。旧値は読み取り互換のエイリアスとしてresolveSettlementRuleが吸収する。
| 正式値 | エイリアス(読取互換の旧値) |
|---|---|
| 前金 | 前金 |
| 売掛 | 売掛、掛売 |
| 3社間決済 | 3社間決済、ローン、三社間決済、3社間、三社間 |
| カード | カード |
「その他」はレガシー値として保持されるが正式区分には含まれない。settlementTypeがいずれの正式値・エイリアスにも一致しない場合、WorkflowEngineはruleKey: null・currentState: "決済条件未設定"・canOrder: false・canInvoice: falseを返し、警告に「未対応の決済区分です」または「決済区分が未設定です」を積む。
当方のWholesaleCaseは決済区分を前金/掛売/三社間/カード/その他の5値で管理しており、ValueOSの正式値(前金/売掛/3社間決済/カード)とは表記が異なる。対応は本ページ末尾の対応表を参照。
WorkflowEngineの判定モデル
Section titled “WorkflowEngineの判定モデル”evaluateWorkflow(ctx: WorkflowContext)は決済区分ごとの設定(SETTLEMENT_RULES)から次を導出し、WorkflowResultとして返す。
| フィールド | 内容 |
|---|---|
canOrder | 発注可否。canOrderWhen条件配列がすべて真のとき真 |
canInvoice | 請求可否。canInvoiceWhen条件配列がすべて真のとき真 |
currentState / assignee / nextAction | 現在の工程表示。phases配列を先頭から走査し、completeWhenが未達成の最初のフェーズを返す(canOrder/canInvoiceとは別ロジック) |
warnings | 発注・請求がブロックされている理由の文言(複数可、重複排除) |
billingClosingDate / paymentDueDate | 売掛のみ算出する請求締め日・支払期日 |
canOrder/canInvoiceとcurrentStateは同じ条件セットを参照するが、評価の入口が異なる独立したロジックである。settlement_confirmed条件は決済区分が正式値に解決できた時点で常に真になる(別途「確定」操作を要しない)。
決済区分別の発注可否・請求可否条件
Section titled “決済区分別の発注可否・請求可否条件”| 決済区分 | canOrder条件 | canInvoice条件 |
|---|---|---|
| 前金 | 入金確認(payment_confirmed_from_billing) | 決済区分の解決(実質常時true) |
| 売掛 | 決済区分の解決(実質常時true) | 案件内の全発注が納品済(all_orders_delivered) |
| 3社間決済 | loan_statusが「承認済」 | construction_completed_date(完工日)が設定済 |
| カード | card_statusが「決済成功」 | card_statusが「決済成功」(発注と同一条件) |
前金は請求可否が実質常時trueになる点、カードは発注と請求が同一条件で同時に解放される点が、区分間で構造が異なる箇所である。
入金確認(payment_confirmed_from_billing)は、案件に紐づく入金(payments)のうち確認済みステータスの金額を合算し、deposit_amount(頭金予定額)が設定されていれば合計がそれ以上か、未設定なら合計が0円超かで判定する。全発注納品済(all_orders_delivered)は、キャンセル等を除いたアクティブな発注(lib/status/activeRecords.tsと同一の判定)が1件以上あり、かつ全件のstatusが「納品済」かつdelivered_dateが入力済みであることを要求する。発注が0件の案件は未達とみなす。
決済区分別の工程(phases)
Section titled “決済区分別の工程(phases)”| 決済区分 | STEP1 | STEP2 | STEP3 | STEP4 |
|---|---|---|---|---|
| 前金 | 決済条件未設定(経理) | 入金確認待ち(経理) | 発注可能(発注担当) | — |
| 売掛 | 決済条件未設定(経理) | 発注可能(発注担当、全納品まで) | 請求可能(経理) | — |
| 3社間決済 | 決済条件未設定(経理) | ローン承認待ち(経理) | 完工報告待ち(営業事務) | 請求可能(経理) |
| カード | 決済条件未設定(経理) | カード決済待ち(経理) | 発注・請求可能(発注担当) | — |
「決済条件未設定」フェーズはsettlement_confirmedが常時真であるため実質的に即時通過し、UI上で長く滞在することはない。
発注・請求ブロック時の警告文言
Section titled “発注・請求ブロック時の警告文言”| 状況 | 警告文言 |
|---|---|
| 前金・入金未確認で発注不可 | 前金の入金確認前のため発注できません(請求・入金データで判定) |
| 3社間決済・ローン未承認で発注不可 | ローン未承認のため発注できません |
| カード・決済未成立で発注不可 | カード決済前のため発注できません |
| カード・決済未成立で請求不可 | カード決済前のため請求できません |
| 3社間決済・完工日未登録で請求不可 | 完工日登録前のため請求できません |
売掛・納品済だがdelivered_date欠損 | 納品日が登録されていません |
| 売掛・未納品の発注が残っている | 売掛の請求は、案件内の全発注が納品済になってから可能です |
売掛の請求不可は上記の個別メッセージのみを出し、汎用メッセージ(「現在の決済区分ルールでは請求できません」)は出さない実装になっている。
売掛の請求締め日・支払期日
Section titled “売掛の請求締め日・支払期日”売掛(datePolicy.trigger: all_orders_delivered)は、案件内の全発注が納品済となった時点の最終納品日(アクティブな発注のdelivered_dateの最大値)を起点に、月末締め・翌月末払いでbillingClosingDate・paymentDueDateを自動算出する。他の決済区分にはこの日付ポリシーはない。
販売店発注(app/dealer/orders/new)の登録経路
Section titled “販売店発注(app/dealer/orders/new)の登録経路”販売店発注フォームは4ステップ(案件情報→商品選択→決済区分選択→確認)で入力を受け付け、送信時にsaveDealerOrder.tsが次の順でSupabaseへ直接INSERTする。
casesへ案件本体を作成する。ステータスは常に「新規受付」固定、case_noはVE-{timestamp}形式で発番する- パッケージ発注なら
case_packages+case_package_items(パッケージ構成のスナップショット・仕入価格)、部材のみ発注ならcase_productsを作成する case_settlementsに選択された決済区分(settlement_type)を保存する- いずれかのステップが失敗した場合は
cleanupCaseが作成済みの行を逆順で削除し、中間状態の案件を残さない
この経路はブラウザから直接複数テーブルへ書き込む非トランザクションな実装であり、失敗時のクリーンアップで整合性を保っている。
STEP3(決済区分選択)の入力値とWorkflowEngine正式値の対応
Section titled “STEP3(決済区分選択)の入力値とWorkflowEngine正式値の対応”STEP3で選択できる決済区分はDEALER_ORDER_SETTLEMENT_TYPES(掛売/ローン/現金/カード/その他の5値)であり、WorkflowEngineの正式値(前金/売掛/3社間決済/カード)とは選択肢の構成そのものが異なる。入力値はそのままcase_settlements.settlement_typeにINSERTされ、以降resolveSettlementRuleが正式値へ解決する。
| STEP3の選択肢 | resolveSettlementRuleでの解決 |
|---|---|
| 掛売 | 売掛(エイリアス一致) |
| ローン | 3社間決済(エイリアス一致) |
| カード | カード(正式値) |
| 現金 | 未対応(ruleKey: null、canOrder/canInvoiceとも常時false) |
| その他 | 未対応(ruleKey: null、canOrder/canInvoiceとも常時false) |
「前金」はSTEP3の選択肢に存在せず、この販売店発注フォームからは前金の案件を作成できない。「現金」「その他」を選択して作成した案件はresolveSettlementRuleがいずれの正式値・エイリアスにも一致せずruleKey: nullを返すため、発注・請求ともにブロックされた状態(警告「未対応の決済区分です: 現金」等)で登録される。案件詳細側で決済区分を正式値へ手動修正しない限りこの状態は解消しない。
これとは別に、DB側には冪等な案件登録用のcreate_case_registrationRPC(SECURITY INVOKER・service_role専用実行権限・request_idとpayload_hashによる冪等性)と、その結果を記録するcase_registration_requestsテーブルが用意されている。この経路はservice_role経由のトランザクション登録用として設計されており、現行のapp/dealer/orders/new画面からは呼び出されていない。案件起票の正本は現時点で「フォーム→直接INSERT」であり、RPC経路は未接続のバックエンド機能として存在する。
三社間の金銭フロー(信販入金・仕切精算・仕入先支払)
Section titled “三社間の金銭フロー(信販入金・仕切精算・仕入先支払)”3社間決済の案件は、発注・請求可否のワークフローとは独立に、次の3系統の金銭実体を持つ。いずれもexecute_three_party_moneyRPCへのアクションとして実行され、moneyActionsLogic.tsが入力検証・正規化を行う。
| アクション | 対象テーブル | 主な操作 |
|---|---|---|
finance_receipt.* | finance_receipts | create(入金予定登録)→confirm(実入金確認:実績日・実績額)。cancel/correctで取消・訂正 |
dealer_settlement.* | dealer_settlements + dealer_settlement_lines | create(仕切清算書作成)→confirm(確定)→pay(実績支払日・実績支払額)。cancel/correctで取消・訂正 |
supplier_payment.* | supplier_payments | create(支払予定登録)→pay(実績支払日・実績支払額)。cancel/correctで取消・訂正 |
想定される進行順序は「ローン承認(loan_status=承認済)→発注→工事完了(construction_completed_date)→請求→信販会社からの入金(finance_receipt)→販売店への仕切精算(dealer_settlement)/仕入先への支払(supplier_payment)」である。信販入金・仕切精算・仕入先支払の3系統は互いに独立したアクション列であり、dealer_settlements.finance_receipt_id・invoice_idで該当する信販入金・請求と任意に紐付けられる。
仕切精算の金額計算
Section titled “仕切精算の金額計算”dealer_settlement.create時、払戻額(payout_amount)は次の式で自動計算される。
payout_amount = credit_received_amount − ve_share_amount − Σ(調整明細のamount)調整明細(dealer_settlement_lines.line_kind)はtransfer_fee(振込手数料)・discount(値引)・offset(相殺)・other(その他控除)の4種で、控除額を正数で保持する。credit_in(信販入金額行)・ve_share(当社取り分行)は明細に計上できるが調整合計には含めない。計算結果payout_amountが負になる登録・訂正はAPI側で拒否される。
ステータス(DB値と表示値)
Section titled “ステータス(DB値と表示値)”DB上のステータスは最小集合とし、期限超過などの表示状態は登録時の日付から都度導出する。
| エンティティ | DB値 | 表示値 |
|---|---|---|
finance_receipts | 予定 / 入金済 / 取消 | 未入金 / 入金予定 / 入金済 / 期限超過 / 取消 |
dealer_settlements | 下書き / 確定 / 支払済 / 取消 | 下書き / 支払予定 / 支払済 / 期限超過 / 取消 |
supplier_payments | 予定 / 支払済 / 取消 | 支払予定 / 支払済 / 期限超過 / 取消 |
期限超過は「予定日が当日より前」で判定し、当日中は超過扱いにしない。取消済み行は集計から除外する。
冪等性と訂正の仕組み
Section titled “冪等性と訂正の仕組み”すべての3社間金銭アクションはrequest_id(クライアント発行のUUID)を伴い、three_party_money_requestsにpayload_hash(キー順正規化したJSONのハッシュ)とともに記録される。同一request_idの再送は冪等に処理される。確定済み金額の直接UPDATEは扱わず、訂正はcorrectアクション(新しい内容で作り直し、corrects_idで元レコードを参照)、取消はcancelアクション(cancel_reasonを記録)という形で、常に監査可能な履歴として残す設計である。
当方の決済フローとの対応
Section titled “当方の決済フローとの対応”| 観点 | 当方(WholesaleCase) | ValueOS |
|---|---|---|
| 決済区分の値 | 前金 / 掛売 / 三社間 / カード / その他(5値) | 前金 / 売掛 / 3社間決済 / カード(正式4値、旧値はエイリアス吸収) |
| 発注可否・請求可否の判定 | wholesaleFlow(工程配列上の位置関係から導出) | WorkflowEngine.evaluateWorkflow(決済区分別の条件配列canOrderWhen/canInvoiceWhen) |
| 承認番号・審査情報 | WholesaleCase.approvalNo(単一・三社間とカードで共用) | case_settlements.finance_company/approval_number(3社間決済)、card_brand/card_status(カード)に分離 |
| 入金消込 | 案件のpayments[]を残高計算方式で合算 | 前金はpayments確認済み合計とdeposit_amount比較、売掛は納品完了トリガーで締め日算出、3社間決済はfinance_receiptsが信販入金を個別管理 |
| 三社間の下流精算 | 未実装(案件メモでの運用) | dealer_settlements(販売店への仕切精算)・supplier_payments(仕入先への支払)として構造化 |
| 販売店発注の起票 | DealerIntakeForm送信→WholesaleCaseをクライアント側で生成 | app/dealer/orders/new→saveDealerOrder.tsが直接INSERT。冪等RPC(create_case_registration)はDB側に存在するが未接続 |
差分の全体像はredesign/valueos-gapを参照。
- redesign/valueos-gapの「ValueOSには決済区分でフローを制御するロジックが無い」という記述は、本ページで確認した
WorkflowEngineの実装内容(決済区分別のcanOrder/canInvoice宣言的判定)と齟齬がある。記述の更新要否を確認する create_case_registrationRPC(冪等な案件登録経路)をapp/dealer/orders/newから呼び出す設計へ移行する要否。現行はsaveDealerOrder.tsによる直接INSERTで運用されている- 3社間金銭アクション(
finance_receipt/dealer_settlement/supplier_payment)の呼び出し導線(社内のどの画面・どの担当者が実行するか)の確認 - 販売店発注STEP3で「現金」「その他」を選択した案件が発注・請求ともに永続ブロックされる状態を仕様として許容するか、STEP3の選択肢自体をWorkflowEngine正式値(前金/売掛/3社間決済/カード)に合わせて見直すかの確認
- features/wholesale-settlement — 当方の決済区分・工程順序の正本
- redesign/valueos-gap — ValueOSとの対応・差分の全体像
- valueos/data-model — ValueOSのテーブル定義
- valueos/overview — ValueOSの概要・アーキテクチャ
- glossary