ValueOS 概要・アーキテクチャ
位置づけ: クライアントERP(ValueOS)
ValueOSは、住宅設備商社向けにクライアントが自社開発しているERPである。正本は github.com/stanaka-blip/valueos。Next.js(App Router)+ Supabase(Postgres / Auth / Storage)で構成し、開発環境は localhost:3001 で稼働する。
案件(cases)を単一の軸として、受注=発注(orders)・請求(invoices)・入金(payments)・タスクの5本柱で受発注〜請求〜入金の一気通貫を管理する。案件ごとの発注可否・請求可否は WorkflowEngine が決済区分(settlement_type)に基づいて機械判定し、各画面はその判定結果を表示するレイヤーに徹する。
当方CRMは案件獲得〜見積〜催事という前段に強く、ValueOSは受発注〜請求〜入金という後段に強い。両者は相補的な関係にあり、詳細な機能差分・項目突合は redesign/valueos-gap を正本とする。
スコープ/対象
Section titled “スコープ/対象”本ページはValueOSそのものの構造(アーキテクチャ・データモデル・業務ロジック)を扱う。当方CRMとの機能差分・移行方針は対象外とし、以下を参照する。
| 論点 | 参照先 |
|---|---|
| 当方CRMとの機能差分・項目突合 | redesign/valueos-gap |
| ValueOSのデータモデル詳細 | valueos/data-model |
| WorkflowEngineの判定ロジック詳細 | valueos/workflow |
| 当方CRM側のスコープ・フェーズ計画 | redesign/scope-phasing |
技術スタック
Section titled “技術スタック”| 領域 | 採用技術 |
|---|---|
| フロントエンド/サーバー | Next.js(App Router)、React |
| データベース | Supabase Postgres |
| 認証 | Supabase Auth(社内認証。staff_profiles でアカウント有効性・管理者権限を管理) |
| ストレージ | Supabase Storage(case_attachments はDirect-to-Storageでアップロード) |
| スタイリング | Tailwind CSS |
| 開発環境 | next dev --port 3001(localhost:3001) |
| テスト | tsx によるロジック単体テスト(WorkflowEngine・入金ステータス・三社間計算・粗利計算・ダッシュボード集計など領域ごとに個別スクリプト) |
データ(5本柱+周辺エンティティ)
Section titled “データ(5本柱+周辺エンティティ)”ValueOSは主要テーブル28本で構成する。中核は次の5本柱である。
| 柱 | 主テーブル | 役割 |
|---|---|---|
| 案件 | cases | 案件番号・販売店・顧客・現場住所・受注日・希望納期・工事日・ステータス・部門・担当・優先度を保持する起点エンティティ |
| 受注=発注 | orders(+ order_items) | 仕入先ごとの発注書番号・発注日・納期回答・納品日・発注金額・ステータスを個別に保持する |
| 請求 | invoices(+ invoice_line_items) | 請求書番号・請求日・支払期日・請求金額・税区分・ステータスを個別に保持する |
| 入金 | payments | 入金日・入金額・確認ステータスを個別に保持する(管理用に拡張済み) |
| タスク | タスクエンティティ(案件紐付) | 案件配下の対応事項をステータス・期日・担当・優先度で管理する |
5本柱を支える主要エンティティは以下のとおりである。
| エンティティ群 | 主テーブル | 役割 |
|---|---|---|
| 明細 | case_products | 案件配下の商品・パッケージ明細。line_type・product_id・package_id・supplier_id・数量・仕入価格・販売価格・粗利をスナップショットで保持し、発注/請求の共通ソースとなる |
| パッケージ | case_packages、case_package_items | 複数商品を束ねたパッケージ単位の明細構成 |
| 決済 | case_settlements | 決済区分(settlement_type。正式値は前金/売掛/3社間決済/カード。掛売・三社間決済は旧称で、2026-08-01のnormalizeで掛売→売掛、ローン/三社間決済→3社間決済に統一済み。「その他」は正式区分外だが保持可)・手数料率/額・頭金率/額・支払条件・カードブランド/ステータス・ローン会社/承認番号/ステータスを保持する |
| 三社間 | three_party_money_requests、finance_receipts、dealer_settlements(+明細)、supplier_payments | ローン会社を介する三社間決済のリクエスト・入金・販売店精算・仕入先支払を個別テーブルで管理する |
| 販売店発注 | ― | 販売店フォーム(app/dealer/orders/new)の saveDealerOrder が cases/case_products/case_settlements へ直接INSERTする。case_registration_requests は経由せず、人による承認ステップも無い |
| 社内案件登録 | case_registration_requests | 社内の案件登録画面(/cases/new)が申請〜RPCで案件化する。処理状態は PROCESSING/COMPLETED/FAILED で管理し、同期実行する |
| マスタ | products、packages、contractors(施工店)、company_settings、staff_profiles | 商品・パッケージ・施工店・自社設定・スタッフ権限の基礎マスタ |
| 申請系(RPC) | product_setup_requests、supplier_purchase_price_bulk_requests、dealer_sales_price_bulk_requests、package_bulk_setup_requests、case_line_append_requests | マスタ変更・価格一括更新・明細追加を申請〜承認の形で処理する |
| 添付 | case_attachments | 案件に紐づくファイルをSupabase StorageへDirect-to-Storageで保存する |
| 機能領域 | 概要 |
|---|---|
| 案件管理 | 案件の登録・編集・ステータス管理。cases を起点に明細・発注・請求・入金・決済・タスクを紐付ける |
| 発注管理 | 仕入先別の発注登録・進捗管理(発注済/納期回答待ち/納期確定/一部納品/納品済) |
| 請求管理 | 請求書の発行・ステータス管理(未請求/作成済/請求済/入金待ち/一部入金/入金済) |
| 入金管理 | 入金の記録・消込。summarizeInvoicePayments() で請求に対する入金状況を集計する |
| 決済区分管理 | 案件ごとの決済区分(前金/売掛/3社間決済/カード等。掛売・三社間はレガシー別名)と、区分に応じた手数料・頭金・承認情報の管理 |
| 三社間精算 | ローン会社を介した三社間決済における請求・入金・販売店精算・仕入先支払の一連の処理 |
| 販売店発注受付 | 販売店が直接入力する発注フォーム(app/dealer/orders/new)の saveDealerOrder が cases/case_products/case_settlements へ直接INSERTする(人による承認ステップは無い) |
| 経営ダッシュボード | 期間内の売上・実粗利・粗利率・未入金額の集計と、未発注/未請求の業務アラート表示(詳細は次節) |
業務ルール/ワークフロー
Section titled “業務ルール/ワークフロー”WorkflowEngine
Section titled “WorkflowEngine”WorkflowEngine(lib/workflow/WorkflowEngine.ts)は、案件の決済区分(settlementType)から決済ルールを解決し、発注可否(canOrder)・請求可否(canInvoice)・現在の業務状態・次アクション・担当・警告メッセージを共通ロジックで判定する。画面はこの判定結果を表示するレイヤーであり、各フォームが独自にステータスを分岐させることはない。
判定の主なルールは次のとおりである。
| 判定 | 内容 |
|---|---|
| 決済区分未確定 | ルールを解決できない場合、canOrder・canInvoice ともに false とし、担当を「経理」、次アクションを「決済条件を確定してください」とする |
| 発注可否 | 決済区分ごとの条件(例: 前金の入金確認、ローン承認、カード決済確定)を満たさない場合は canOrder = false とし、区分別の警告文を返す |
| 請求可否(売掛) | 案件内の全発注が納品済(delivered_date 登録済)になって初めて canInvoice = true となる。納品日未登録または未納品の発注が残る場合は警告文を返す |
| 与信日算出 | 決済ルールの datePolicy.trigger が全発注納品済を起点とする場合、請求締日・支払期日を発注データから算出する |
WorkflowEngine は詳細ページ valueos/workflow を参照する。
ダッシュボード集計基準(Ver1.0)
Section titled “ダッシュボード集計基準(Ver1.0)”| 指標 | 集計基準 |
|---|---|
| 売上 | 期間内に cases.order_received_date(顧客が当社へ正式発注した日)を持つ有効案件の case_products.sales_price 合計 |
| 実粗利 | 同条件での case_products.gross_profit 合計 |
| 粗利率 | 実粗利 ÷ 売上 |
| 未入金額 | summarizeInvoicePayments().unpaidAmount(期間非連動の全期間集計) |
受注日は cases.order_received_date を用い、orders.order_date や created_at は用いない。キャンセル案件は lib/status/activeRecords.ts の有効判定により集計から除外する。
業務アラート
Section titled “業務アラート”| アラート | 条件 |
|---|---|
| 未発注 | canOrder = true かつ、その案件に紐づく有効発注が0件 |
| 未請求 | canInvoice = true かつ、その案件に紐づく有効請求が0件 |
canOrder・canInvoice が false の案件はアラート集計の対象外とする。現時点の業務アラートは未発注/未請求の2種のみであり、未入金・期限超過(支払期日超過)を自動検知するアラートは含まない。未入金額自体はダッシュボード集計基準の指標として別途表示する(前節参照)。
社内ユーザーの認証はSupabase Authが担う。ログイン成功後、staff_profiles テーブルでアカウントの有効性(is_active)と管理者権限(is_admin)を確認する。プロフィール未登録・非アクティブ・認証失敗はそれぞれ個別のエラーコードで区別する。販売店発注フォーム(app/dealer/orders/new)は社内認証の外側にあり、saveDealerOrder が cases/case_products/case_settlements へ直接INSERTする。case_registration_requests は経由せず、人による承認ステップも無い。
当方CRMとの棲み分け
Section titled “当方CRMとの棲み分け”| 観点 | 当方CRM | ValueOS |
|---|---|---|
| 強い領域 | 案件獲得〜見積〜催事(前段) | 受発注〜請求〜入金(後段) |
| 案件の呼称 | WholesaleCase | cases |
| 卸金額の呼称 | WholesalePrice(dealer_sales_prices / supplier_purchase_prices) | sales_prices / purchase_prices |
| 決済区分の呼称 | WSettlement(前金/掛売/三社間/カード/その他) | case_settlements.settlement_type(正式値: 前金/売掛/3社間決済/カード) |
| 販売店発注の呼称 | DealerIntakeForm | app/dealer/orders/new(saveDealerOrder が直接INSERT・承認ステップ無し) |
| 発注/請求/入金 | 卸案件のフラグ集約(差) | 独立エンティティ(orders/invoices/payments) |
| 決済区分別ワークフロー | wholesaleFlow で機械判定(上位) | WorkflowEngine で機械判定 |
両者の統合方針・段階的な機能差分の埋め方は redesign/valueos-gap を正本とする。
- redesign/valueos-gap — 当方CRMとの機能差分・項目突合の正本
- redesign/scope-phasing — 当方CRM側のフェーズ分類・機能×フェーズ管理表
- redesign/meeting-log — 決定経緯の一次情報
- redesign/terminology — 当方CRMとValueOSの用語対応表