cpq-builder について
CPQ Builder は、構造化された入力に業務ルールを適用し、レビューや承認に回す成果物を作るツールのプロトタイプ向けスキルです。製品の見積もりや計算・受付ワークフローに適応できるパターンを提供します。
主な機能
- 01見積もり明細のインライン編集
- 02製品バンドルと制約の表示
- 03割引計算の透明な表示
- 04合計のリアルタイム更新とブランド付き出力
- 05承認ルーティングとロール別表示
- 06見積もりの保存・読み込み・複製・管理
活用シーン
- 01表計算ベースの見積もり業務の置き換え
- 02製品構成・価格設定ツールの構築
- 03適格性や保険の見積もりツール作成
- 04レビュー可能な業務提案の試作
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ customware-ai/ skills --skill cpq-builderインストール後、Claude Code で/cpq-builderを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/config-schema.mdexample-config.jsonvertical-presets.md詳細
CPQ ビルダースキル
このスキルの概要
このスキルでは、Configure-Price-Quote 型のツールを構築するためのパターンを定義します。ユーザーが入力を設定し、システムがルールを適用して結果を計算し、レビューや承認が必要になる場合もある、書式が整った成果物を出力するシステムです。
CPQ は製品の価格設定に限りません。同じ構造パターンは、次のような分野にも当てはまります。
| 分野 | 「設定」 | 「計算」 | 「出力」 |
|---|---|---|---|
| 設備販売 | 製品を選択し、オプションを選ぶ | マークアップを適用し、合計を計算する | 販売見積書の PDF |
| 法律関連の計算ツール | 事案の詳細(収入、期間)を入力する | ガイドラインの計算式を適用する | 見積もりを含む概要レポート |
| 保険見積もりツール | 補償内容を入力する | 料率表を適用する | 保険料の見積もり書類 |
| ローン審査資格 | 財務情報を入力する | 融資基準を適用する | 資格通知書 |
| 給付金の受給資格 | 個人情報を入力する | 受給資格のルールを適用する | 給付金の概要 |
| サービス提案 | サービスを選択し、範囲を設定する | 作業料金を適用する | サービス提案書 |
ビルダーはこのスキルを読み、特定ドメインの用語やルールが記載された DOMAIN.md を読み込んで、動作するプロトタイプを生成します。DOMAIN.md によって、ツールがクレーンの見積もりを扱うのか、離婚に関する計算を扱うのかが決まります。このスキルは、どちらにも適用できる構造パターンを提供します。
このスキルのパターンはデフォルトであり、必須ではありません。 実際のワークフローが標準的な CPQ の形式と異なり、段階が少ない場合や、レイアウトが異なる場合、異なる出力を生成する場合は、パターンを適応させてください。各主要セクションでは、そうした相違点を明示しています。
顧客の状況
Customware の CPQ 顧客は、産業機器の販売店、カスタム衣料品・看板ショップ、食品・飲料の卸売業者、法律・コンサルティング・デザインなどの専門サービス企業、IT・マネージドサービスプロバイダー、建設・職人事業者、製造業者、販売業者など、さまざまな分野にわたります。CPQ パターンは、これらすべてに適用できます。
このスキルの例では、複数の分野を入れ替えながら取り上げています。産業機器、サービス、消費財、ソフトウェア、カスタム製品などです。これは意図的なものです。パターンはドメインに依存せず、例は類推によって説明しています。このスキルを適用する際は、各例に登場する特定のドメインではなく、構造パターンを取り出してください。構築するツールの具体的な語彙、製品、ルール、役割は DOMAIN.md によって決まります。
「シングルガーダークレーンにはモーターが必要」というルールも、「カスタムパーカーには印刷方法が必要」や「マネージドサービス契約にはティアが必要」、「犬用おやつの注文には包装サイズが必要」というルールも、同じ形をしています。つまり、「親製品には子コンポーネントの選択が必要」というルールです。そのパターンを構築し、具体的な用語は DOMAIN.md に反映させてください。
顧客プロファイル
Customware の CPQ を利用する顧客は、成長に伴う課題に直面している**中小企業(従業員 5~50 名)**が一般的です。別の CPQ システムから移行しているわけではありません。次のようなものから移行しています。
- 扱いにくくなった Excel スプレッドシート(複数のタブ、コピー&ペーストのミス、壊れた数式)
- 顧客ごとに手作業で編集する Word の見積もりテンプレート
- 上司が全員返信のスレッドで見積もりを承認する、メールベースの承認ワークフロー
- どの製品にどの付属品が必要かという、ベテラン営業担当者の頭の中にしかない暗黙知
- 手入力の価格設定。一貫性のない値引きによって利益率が損なわれています
このプロトタイプの役割は、スプレッドシートより格段に優れていると感じられ、エンタープライズ向けの複雑さを感じさせないことです。5 年間 Excel で見積もりを作成してきた小規模なチームがプロトタイプを見て、「これはずっと速い」とすぐに思えるようにしてください。「これは複雑そうだ」と思わせてはいけません。
この位置付けは、このスキルにおけるすべての設計判断に影響します。
- 明細項目のインライン編集が比較の基準です。Excel のユーザーは、グリッドを直接編集できることを期待しています。
- 合計金額がリアルタイムで更新されることが重要です。顧客は数式で計算してきたため、入力を変更すると数値も更新されることを期待しています。
- 役割に応じた制限は、顧客にとって印象的です。顧客は「5 万ドルを超える場合はオーナーのみが承認できる」というルールをソフトウェアで徹底した経験がありません。口頭で決めたルールは破られていました。
- ブランドに合わせた PDF 出力も印象的です。顧客は Word 文書の書式を手作業で整えてきました。
- 顧客向けポータル、AI による提案、電子署名の連携は、この段階では印象的ではありません。これらは、顧客がまだ抱えていない問題を解決するための、エンタープライズ向けの複雑な機能です。
壊れた Excel の数式にうんざりしている顧客のために構築してください。Salesforce から移行する顧客のためではありません。
これは本当に CPQ ですか?
このスキルのパターンを適用する前に、そのワークフローが本当に CPQ に当てはまるか確認してください。次の 4 つすべてに当てはまる場合、CPQ のパターンが適しています。
- ユーザーが、結果を決める構造化された入力を収集します(構成の選択肢、顧客情報、要件、財務データ、案件の詳細)。
- ビジネスルールまたは計算ロジックが入力を変換し、成果物を作成します(マークアップの数式、ガイドラインの計算、料率表、適格性ルール)。
- 入力から最終確定までの間に確認または承認のゲートがあるか、または成果物が何らかの関係者レビューを受けます(作成者/確認者のパターン)。
- 作成物が引き渡されるものとして扱われます。顧客、社内の関係者、規制当局、後続システムなどが引き渡し先です。
基準 1 に当てはまらない場合 → ダッシュボードまたは表示ツールであり、CPQ ではありません。ここでは対象外です。
基準 2 に当てはまらない場合 → データ入力フォームであり、CPQ ではありません。ここでは対象外です。
基準 3 に当てはまらない場合 → 「受付して納品する」タイプです。CPQ のパターンを適用しますが、「承認」セクションは省略してください。
基準 4 に当てはまらない場合 → 個人用の計算機/ユーティリティであり、CPQ ではありません。ここでは対象外です。
よくある誤判定:
- 「株価の見積もりビューア」—「見積もり」という言葉は含まれていますが、表示ツールです(基準 1 に不適合)。
- 確認手順のない「税金計算機」—ユーティリティであり、CPQ ではありません(基準 3 と 4 に不適合)。
- 価格を掲載した「製品カタログ」—表示ツールであり、CPQ ではありません(基準 2 と 3 に不適合)。
- 「フィードバックフォーム」—データ入力であり、CPQ ではありません(基準 2 に不適合)。
4 つの基準を満たさない場合は、以下のパターンを無理に当てはめないでください。代わりに、タスクの説明と DOMAIN.md に基づき、frontend-design の原則を使って構築してください。
ドメインタイプ
CPQ に似たワークフローの大半は、次の 2 つのドメインタイプのいずれかに分類されます。パターンを適用する前に、ビルドがどちらのタイプかを特定してください。
製品ドメイン。 ユーザーは販売可能な製品やサービスを設定します。価格が中心となる計算です。出力は、明細、合計、税金、条件を含む見積書です。例:機器販売、カスタムアパレルの注文、食品・CPG の卸売、サービスの提案(コンサルティングの入札、マネージドサービス)、ソフトウェアライセンス、カスタムパッケージ。
計算/インテークドメイン。 ユーザーは案件や申請者の詳細を入力します。ガイドライン/ルール/料率表に基づいて計算します。出力は、入力値、計算値、免責事項を含むサマリーレポートです。例:配偶者扶養費の計算ツール(Clarity Legal)、保険料の見積もり、ローン審査、給付の受給資格判定。
このスキルのパターンは、どちらのタイプにも適応します。特定のドメインに固有のセクションやルールがある場合は、このスキルで明示します。
最低基準
すべての CPQ ビルドで Tier 1 基準を満たす必要があります。Tier 2 基準は、DOMAIN.md で必要性が示されている場合に実装します。Tier 3 の機能は、プロトタイプでは実装せず、今後の作業として完了サマリーに記載します。
Tier 1 — 必須(すべての CPQ ビルド)
これらの機能によって、プロトタイプは Excel と Word の組み合わせよりも格段に優れたものになります。どれか 1 つでも欠けていれば、UI がどれほど洗練されていても、ビルドは未完成です。
1. 明細を直接インライン編集できること。 ユーザーが行を追加し、任意のセルを編集でき、合計がリアルタイムで更新されるスプレッドシート形式のテーブルです。「フォームで設定 → 見積もりに追加 → 見積もりテーブルを作成 → 編集」という往復ではありません。明細テーブル自体が作業スペースです。標準的な実装については、以下の「セクションパターン」を参照してください。
2. バンドル/必須子製品に適切なコンフィギュレーターのパターンを使用すること。 親製品に子コンポーネントが必要な場合(例:「産業用ユニットにはモーターの選択が必要」「カスタムパーカーにはプリント方法の選択が必要」「マネージドサービス契約にはティアの選択が必要」「犬用おやつの注文には包装サイズの選択が必要」)、子製品の選択は親製品の設定に含めます。明細では親製品と選択した子製品を、まとまりのある 1 つの項目として表示します。ユーザーが子製品を選び忘れる可能性があるような、別々の明細 2 行にしてはいけません。設定属性が 4 つ以上ある製品や、依存関係が段階的に連なる製品(一般的な産業機器、カスタム製品、階層型サービスでは、3~4 段階にわたることがよくあります)には、適切なコンフィギュレーターのパターンを使用します。インライン展開、サイドドロワー、全ページ表示の選択については、以下の「製品コンフィギュレーターパターン」を参照してください。
3. 制約ルールをユーザーに見える形で提示すること。 DOMAIN.md の必須/除外/推奨ルールを、黙って適用するだけでなく、ユーザーに見えるようにします。ユーザーがクレーンを追加するときは、保存する前に「モーターの選択が必要です(BR-001)」と UI に表示します。除外される組み合わせを追加しようとした場合は、ルールとその根拠を表示します。Excel に慣れた顧客は、ルールが適用される体験をこれまでまったくしたことがありません。ルールを見えるようにすること自体が、価値の半分を占めます。
4. 計算が明示された割引の積み重ね。 割引が適用される場合は、段階的な計算を表示します。
List Price: $15,000.00
Volume Discount (5%): -$750.00
Promotional Discount (3%): -$427.50
─────────────────────────────────────
Net Price: $13,822.50
割引ごとに行を設け、計算を透明にします。監査記録のないメールのやり取りで割引交渉をしてきた顧客には、価格がどのように算出されたのかを正確に示す必要があります。
5. 見積もりのライブサマリー。 小計、税金、合計が、ユーザーによる明細の編集に合わせてリアルタイムに更新されます。「計算」ボタンをクリックする必要はありません。Excel を使ってきた顧客が最も驚くポイントです。合計がその場で更新されます。
6. ブランドに合わせた見積書。 顧客のロゴ、明細テーブル、合計、条件、必要な免責事項を含む、PDF または印刷用の表示を生成します。手作業で書式を整えていた Word 文書に代わるものです。品質基準として、実際の企業が顧客に送る見積書に見える必要があります。 7. 複数階層の承認ルーティング。 ほとんどの中小企業のワークフローには、2 段階以上の承認プロセスがあります(担当者が設定 → マネージャーが確認 → オーナーが承認)。単純なケースでも、少なくとも 1 人の承認者と、最終承認を担う役割が必要です。プロトタイプでは、DOMAIN.md のステークホルダーマップに沿った、役割ベースのルーティングを示す必要があります。ルーティングはリクエストの種類によって分岐することもよくあります。たとえば、ある会社では「カスタム設定は上級レビュー担当者、検査はサービスマネージャー、保守はオペレーションマネージャーに回し、どの経路でもオーナーが最終承認者となる」といったルーティングが考えられます。このような条件付きの複数階層ルーティングは必須です。
8. 複数見積もりの管理。 ユーザーは複数の見積もりを同時に進行します。プロトタイプでは、ステータス表示付きの見積もり一覧を示し、フィルタリングと並べ替えに対応し、ユーザーが任意の見積もりをクリックして編集できるようにする必要があります。「保存済み見積もり」のサイドバー一覧があるだけの、単一見積もり用ワークスペースでは不十分です。
9. 見積もりの保存/読み込み/複製。 localStorage を使用します。ユーザーは新しい見積もりを作成して保存したり、保存済みの見積もりを読み込んだり、既存の見積もりを複製して類似の見積もりの下書きにしたりできます。Excel ユーザーはシートをコピーしてこれを行います。プロトタイプでは[複製]ボタンを用意します。
10. 役割ベースの表示とアクションの制御。 役割によって表示される内容は異なります。承認者には[承認]ボタンが表示されますが、作成担当者には表示されません。利益率や原価などの機密性の高い数値は、承認者以外には表示されません。これは顧客にも直感的に理解されているものの、これまで強制されてこなかった「利益率を見られるのは上司だけ」というパターンです。
Tier 2 — DOMAIN.md に根拠がある場合に実装
これらは有用な機能ですが、DOMAIN.md に明確な根拠がある場合にのみ実装する価値があります。
- ガイド付き販売(複雑な設定向けの段階的な Q&A)— DOMAIN.md に顧客との要件確認フローが記載されている場合
- 数量/段階別価格設定 — DOMAIN.md に数量による価格区分、数量階層、または大量購入割引について記載されている場合
- 顧客向けの読み取り専用見積もりリンク — DOMAIN.md に顧客への見積もりのメール送信や共有について記載されている場合
- サブスクリプション/更新への対応 — ドメインが継続収益を伴う SaaS に近い場合
- 1 つのビルドで複数の価格設定モデルに対応(コストプラス方式+カタログ方式+カスタム方式)— DOMAIN.md に複数の価格設定戦略の併用が記載されている場合
- 顧客タイプ別の見積もり文書テンプレート — DOMAIN.md に対象者ごとに異なる出力形式が記載されている場合
Tier 3 — 今後の作業(完了サマリーに記載し、実装しない)
これらはプロトタイプではなく、本番環境向けのビルドに含める機能です。顧客が次に何が提供されるのかを把握できるよう、完了サマリーで明記してください。
- CRM/メール/通話のコンテキストに基づく AI 提案見積もり
- 見積もりのバージョン管理と変更履歴の追跡
- サブスクリプションの請求ロジックと日割り計算
- CRM/ERP 連携(フルスタックフェーズで対応)
- 電子署名連携(DocuSign、HelloSign など)
- 税務エンジン連携(Avalara、Vertex)
- 動的な為替レートを使用する複数通貨への対応
- セルフサービス型の顧客設定ポータル
- 商談ルーム/ブランド化した提案用マイクロサイト
- ネイティブモバイルアプリ
完了サマリーのテンプレート
すべての CPQ ビルドの完了サマリーには、以下を含める必要があります。
## What this prototype includes
**Tier 1 (always built):**
- [confirm each Tier 1 capability is present, or note why a specific one was omitted]
**Tier 2 (built for this domain):**
- [list any Tier 2 capabilities that were built and why]
## What this prototype does NOT include
This is a frontend prototype demonstrating the core CPQ workflow. The following capabilities
would come in production:
- [list relevant Tier 3 items based on the customer's likely future needs]
To move from prototype to production, add: real authentication, CRM/ERP integration,
e-signature, real PDF generation, and any Tier 3 capabilities listed above.
これにより、誠実な期待値を設定し、提供済みの内容を明確にしながら、今後さらに機能が追加されることを顧客に示せます。
このスキルを使用するタイミング
「これって本当に CPQ?」の4つの基準を満たし、かつ顧客の DOMAIN.md に次の内容が含まれる場合に使用します。
従来型の CPQ を示す兆候:
- 顧客向けに見積もりや価格設定を行う製品またはサービス
- 構成オプション(サイズ、モデル、バリエーション、素材)
- 製品間の依存関係(必須、推奨、除外)
- マークアップまたは粗利ベースの価格設定(原価加算、仕入先価格表+割合)
- 見積もりまたは提案書のワークフロー(下書き → レビュー → 承認 → 送信)
より広義の「構成・計算・出力」を示す兆候:
- レビューまたは引き継ぎのステップがある計算ツール、見積もりツール、評価ツール
- 入力に基づいて計算結果が生成される、ガイド付きの受付フォーム
- ルールを適用して結果を生成する、複数ステップのデータ収集
- 出力文書(レポート、要約、見積もり、提案書)
- 作成者とレビュアーによるワークフロー(顧客が入力 → 専門家がレビュー)
このドメインが主に在庫追跡(ERP スキルを使用)、現場の進捗追跡と支払いを伴う継続的なプロジェクト遂行(trades-builder を使用)、オンラインでの製品販売(e-commerce スキルを使用)、または顧客関係管理(CRM スキルを使用)に関する場合は、このスキルを使用しないでください。
テンプレートの契約内容
構築を始める前に、テンプレートが提供する機能と、このスキルが追加する機能を把握してください。
テンプレート(app/layouts/MainLayout.tsx)に含まれるもの:
SidebarProvider、Sidebar、SidebarContent、SidebarInset、SidebarTrigger— すでに接続済みSidebarContentは 空 です — ここが実装箇所です- ヘッダー内のブランド枠(ロゴのプレースホルダー+会社名)
- ヘッダー右側のグループにある
ModeToggleとユーザーメニュー
このスキルで実装するもの:
SidebarContent— 選択したレイアウトに適したセクションナビゲーション- ブランド枠 — DOMAIN.md に記載されたクライアントのロゴと会社名
- ヘッダー右側のグループ — ワークフローに複数のロールがある場合、既存のユーザーメニューの前にロール切り替え用の
DropdownMenuを追加 <main>内の<Outlet />— 各セクションのルートコンポーネント経由で表示
このスキルで行わないこと:
- 2つ目の
Sidebarコンポーネントを追加すること。サイドバーは1つです。 SidebarContent内にブランドタイルを配置すること。ブランド表示はヘッダーのみです。- ルートコンポーネント内に MainLayout をマウントすること。ルートは
<Outlet />内にレンダリングされ、レイアウトは親要素になります。ルート内に MainLayout をマウントすると、サイドバーとヘッダーが重複します。 SidebarProviderを再接続したり、折りたたみの動作を置き換えたりすること。
ワークフローがサイドバーレイアウトに適さない場合(下記の「レイアウトパターン」の代替案を参照)、別のシェルを使用してもかまいません。完了サマリーに、その変更内容を記録してください。
セクションパターン
標準的な CPQ ワークフローには、入力の構成、レビュー/承認、文書の提供という3つの論理フェーズがあります。ユーザーが「レビュー/明細の編集」段階を別に設けるメリットがあるかどうかに応じて、標準 UI ではこれらを3つまたは4つのセクションに分けます。
標準のセクション構成(SMB の直接編集モデル)
1つのロールが見積もりの作成から承認までを担当する SMB 向け CPQ(最も一般的なケース)では、標準は3つのセクションです。
- 見積もりを編集 — すべての明細と顧客情報を直接インライン編集します。ユーザーが時間の90%を費やす主要な作業スペースです。明細の追加、編集、削除はインラインで行います。顧客情報、条件、メモもインラインで編集します。合計金額は右側または下部にリアルタイムで表示します。
- 承認 — レビューと承認の操作を行います。最終状態を表示し、承認に必要なチェックを実行して、承認操作を行います。見積もりが以前に承認または変更されている場合は、変更履歴を表示してもかまいません。
- 見積もり文書 — 提供する成果物です。読み取り専用で、印刷可能なブランド書式にします。
これにより、v4.3 の「構成 → 見積もり作成」という往復の工程が、1つの直接編集画面にまとまります。ほとんどの SMB 向け CPQ では、この3セクションモデルを使用してください。
4 セクション構成(役割間の引き継ぎがある場合)
設定と明細の組み立てを別々の人が行う場合(例:エンジニアが設定 → 営業担当者が価格を設定 → マネージャーが承認)は、4 つのセクションが適切です。
- 設定 — エンジニアまたは技術担当者が製品を指定します
- 見積もり作成 — 営業担当者が価格、条件、顧客情報を追加します
- 承認 — マネージャーが承認します
- 見積書 — 納品物です
各段階で役割間の実際の引き継ぎがあることを DOMAIN.md が示している場合に限り、これを使用してください。ほとんどの SMB CPQ では、この構成は不要です。1 人で設定、作成、承認を行えます。3 つのセクションを使用してください。
計算ドメインのセクション構成
計算/受付ドメインの場合(Clarity Legal パターン):
- 提出内容 — 受付フォーム(クライアント向け)
- 計算 — 算出された結果(入力内容から自動生成)
- 弁護士レビュー — レビュアー向けの承認(弁護士向け)
- 最終レポート — 提供する成果物
構造パターンは同じです。ラベルと構成要素はドメインに合わせて調整してください。
例外
ワークフローにレビューゲートがない場合(セルフサービスのフロー)は、「承認」を省略します。 見積もり編集 → ドキュメント。 成果物がドキュメントでない場合(システムへのプッシュ、インライン結果、確認ページ)は、「見積書」を省略します。 設定の前に要件確認フェーズがある場合は、「見積もり編集」の前に「発見/受付」を追加します。 実際のワークフローに合ったセクション数を選んでください。 4 つに合わせて水増ししないでください。収まるように切り詰めないでください。
見積もり編集セクション — インラインで直接編集(Tier 1 必須)
見積もり編集セクションでは、Excel のような明細テーブルを主要な作業領域として使用します。これは、製品 CPQ では譲れない要件です。
必須の動作:
- 各明細項目がテーブルの行になります
- セルはインラインで編集できます。セルをクリックして値を編集すると、合計が更新されます
- テーブルの下にある「+ Add Line」ボタンから新しい行を追加します(または、ユーザーが空のプレースホルダー行をクリックしたときに自動で追加します)
- 行アクションメニュー(ゴミ箱アイコン、「Remove」オプション)から行を削除します
- 行アクションメニュー(「Duplicate」オプション)から行を複製します
- 行ごとに合計を計算します(数量 × 単価 − 割引)
- フッター行で全明細項目の小計を計算します
- 割引の内訳は小計の下に表示します(該当する場合)
- 税額は割引の下に表示します(DOMAIN.md に税に関する記載がある場合)
- 一番下に総合計を太字で表示します
必須の列(製品ドメイン):
| # | 説明 | 構成 | 数量 | 定価 | 割引 | 正味価格 | 行合計 | アクション |
|---|
「説明」列には製品名を表示します。「構成」列には選択したオプションを表示します(例:「プレミアムティア — 50 ユーザー」または「トライブレンド、DTG プリント」)。必須構成がある製品(バンドル/必須子製品パターン)の場合、行をクリックするとコンフィギュレーターのドロワーまたはポップオーバーが開き、行が確定する前にユーザーがオプションを選択できます。選択後は構成がインラインで表示され、再度クリックすると編集できます。
バンドル/必須子製品の必須動作:
DOMAIN.md に、親製品に子コンポーネントが必須であると記載されている場合(例:「産業用ユニットにはモーターの選択が必要」、「カスタムパーカーにはプリント方法の選択が必要」、「マネージドサービス契約にはティアの選択が必要」、「犬用おやつの注文には包装サイズの選択が必要」など):
- 親製品を追加すると、必須の子製品を選択するよう自動的に促します
- 明細項目をひとまとまりの項目として表示します:「[親製品] — [必須の子製品] — [バリアント]」
- 価格は親製品の基本価格と子製品の追加料金を合算します
- 必須の子製品を選択するまで、ユーザーは明細項目を保存できません
- ルールを示すインジケーターを見える形で表示します:「[コンポーネント名] の選択が必要です(BR-001)」
制約ルールの必須動作:
DOMAIN.md に requires/excludes/recommends ルールがある場合:
- 「Requires」ルールは、条件が満たされるまで保存をブロックします。インラインで「必須:[説明]」と表示します
- 「Excludes」ルールは、無効な組み合わせをブロックします。インラインで「[理由] のため、X と Y を組み合わせることはできません」と表示します
- 「Recommends」ルールは、ソフトな提案として表示します。「お客様は Z をよく一緒に追加しています。追加しますか?」と表示します
- 各ルールにはルール ID(BR-001、BR-002)を表示し、ユーザーが出典をたどれるようにします
ルールが目に見える形で適用されることは、Excel から移行するお客様にとって最大級の「驚き」の一つです。目立つようにしてください。
製品コンフィギュレーターのパターン
製品に複数の構成属性(3 つ以上の選択肢)がある場合や、構成が連鎖する場合(レベル 1 の選択によってレベル 2 の選択肢が決まり、さらにレベル 3 が決まるなど)は、セル内のインラインドロップダウンパターンでは不十分です。ユーザーには本格的なコンフィギュレーターが必要です。
実際の製品構成では、多くの分野で 3〜4 レベルにわたることがよくあります。
- 産業機器:種類 → 容量 → モーター → ホイスト → 制御装置
- カスタムアパレル:衣服のスタイル → 生地 → サイズ展開 → プリント/刺繍方法 → 仕上げ
- IT サービス:サービスプラン → ユーザー数 → モジュール → SLA レベル → インテグレーション
- 食品/CPG 卸売:製品ファミリー → フレーバーまたはバリエーション → 包装サイズ → ケース数量 → 冷蔵/常温での配送
- プロフェッショナルサービス:契約の種類 → スコープのプラン → チーム構成 → 期間 → 成果物の形式
- カスタム看板/包装:基材 → 寸法 → 仕上げ → 印刷方法 → 取り付け金具
各レベルによって、次のレベルの選択肢が制限されます。5 トンの産業用ユニットを選ぶと、適合するモーターが限られ、さらに組み合わせ可能な制御装置も限られます。トライブレンドのパーカー生地を選ぶと、対応する印刷方法が限られ、さらに選択可能な仕上げも限られます。Premium サービスプランを選ぶと、特定のモジュールが利用可能になり、より上位の SLA が必要になります。どの分野でも構造は同じです。実際に何を構成するのかは、DOMAIN.md がエージェントに伝えます。
このように階層の深い構成には、構成の複雑さに応じて、次の 3 つのパターンが適しています。
パターン A — インラインで展開する行(属性 2〜4 個、連鎖なし)
製品に少数の独立した属性(数量、色、サイズなど、または構成の選択肢が 1 つ)がある場合、明細行をインラインで展開し、属性を表示します。行をクリック → 展開して属性セレクターを表示 → 入力 → 「構成」列に構成の概要を表示して行を折りたたみます。
┌─────────────────────────────────────────────────────────────┐
│ 1 [Product Name] [Variant ▾] 1 $X,XXX.XX ... │ ← collapsed
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 1 [Product Name] [Variant ▾] 1 $X,XXX.XX ... │
│ ┌───────────────────────────────────────────────────┐ │ ← expanded
│ │ Variant: ( ) Option A ( ) Option B │ │
│ │ Quantity: [ 1 ] │ │
│ │ Description: [ ] │ │
│ └───────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
次の場合に使用します。
- 属性の合計が 2〜4 個
- 属性が独立している(連鎖する依存関係がない)
- 展開時に、すべての属性が約 200px の縦方向のスペースに視覚的に収まる
パターン A に適した製品の例:サイズと色を選ぶ T シャツ、時間数と料金を選ぶサービスアドオン、ソフトウェアライセンスのシート数、卸売のケース数量、仕上げオプションが 1 つある印刷バナー。
パターン B — 垂直ステッパー付きサイドドロワー(属性が4〜7個で、連動選択が可能な場合)
設定項目に連動する依存関係がある場合、または属性が4〜7個ある場合は、行をクリックすると右側からサイドドロワーがスライドして表示され、画面の約40%を覆います。ドロワーの左側には、設定の各段階を示す垂直ステッパーがあります。
┌────────────────────────────────┐
│ Configure [Product] │
│ │
│ ●━━━ Step 1: Foundation │
│ │ [Selected value] │
│ │ │
│ ●━━━ Step 2: Sizing │
│ │ [Selected value] │
│ │ │
│ ◉━━━ Step 3: Core Component │
│ │ [ Option A ] [ Option B ] │
│ │ │
│ ○━━━ Step 4: Dependent Choice │
│ │ (Complete Step 3 first) │
│ │ │
│ ○━━━ Step 5: Finishing │
│ │
│ [Cancel] [Save] │
└────────────────────────────────┘
ドロワーの動作:
- ドロワー内の左側に垂直ステッパーを表示します(メインアプリのサイドバーには表示しません)
- 依存関係が満たされるとステップをクリックできるようになり、満たされていない場合はグレー表示されます
- 各ステップの内容は、ドロワー内のステッパーの右側に表示されます
- 連動する依存関係:上流の選択を変更すると、下流の選択が無効になってクリアされます(確認トースト「[upstream] を変更すると、[downstream] の選択がリセットされます」が表示されます)
- 「Save」をクリックすると設定が明細行に反映され、「Cancel」をクリックすると破棄されます
- 明細行の「Configuration」列に、組み立てられた設定の概要が表示されます
これは、本当に連動する設定に適したパターンです。パターン B に適した例として、種類/容量/モーター/制御装置を選ぶ産業機器、衣類/生地/印刷方法/仕上げを選ぶカスタムアパレル、プラン/ユーザー数/モジュール/SLA を選ぶ IT サービス、基材/寸法/印刷/取り付け方法を選ぶカスタムサインがあります。ドロワーを使うと、見積もりワークスペースのコンテキストからユーザーを移動させることなく、設定ツールに十分なスペースを確保できます。ドロワー内の垂直ステッパーにより、アプリレベルのナビゲーションを占有せずに、連動関係を視覚化できます。
モーダルではなくドロワーを使う理由:
- ドロワーはモーダルよりも作業を中断させません
- 左側に明細行テーブルが表示されるため、ユーザーはコンテキストを保てます
- 外側をクリックしてドロワーを閉じられます(モーダルのように「閉じる前に保存」する煩わしさを避けられます)
- ドロワーは React Router と相性がよく、ルートとして開き、閉じると親に戻ります
パターン C — 全ページの設定画面(属性が8個以上で、連動関係が複雑な場合)
設定が本当に複雑な場合(属性が8個以上、複数段階の連動関係がある、図や視覚化が必要など)は、設定画面に独自のページを用意するのが適切です。「Configure」をクリックすると /quotes/{id}/lines/{lineId}/configure に移動し、上部に横型のステップインジケーター、中央に設定フォーム、右側に概要/プレビュー用のレールを配置した全ページが表示されます。
┌──────────────────────────────────────────────────────────────────┐
│ ← Back to Quote │
│ │
│ ●━━━━━━●━━━━━━●━━━━━━◉━━━━━━○━━━━━━○ │
│ Step 1 Step 2 Step 3 Step 4 Step 5 Review │
│ │
│ ┌─────────────────────────────────────┬──────────────────────┐ │
│ │ │ Selected so far: │ │
│ │ Configuration content for │ │ │
│ │ current step │ Step 1: [value] │ │
│ │ │ Step 2: [value] │ │
│ │ │ Step 3: [value] │ │
│ │ │ Step 4: (selecting) │ │
│ │ │ │ │
│ │ │ Running price: │ │
│ │ │ $X,XXX.XX │ │
│ └─────────────────────────────────────┴──────────────────────┘ │
│ │
│ [Back] [Continue →] │
└──────────────────────────────────────────────────────────────────┘
本当に複雑な設定に対応できるのは、全ページを使うパターンだけです。専用のウィザード形式のフローでは、ユーザーが次に進む前に実際に一つずつ手順を進めるため、上部の横型ステップインジケーターが適しています。見積もり詳細レベルで使うのは適切ではありません。
次の場合に使用します:
- 属性が8個以上ある
- 設定に視覚要素(図、寸法、写真、カラースウォッチ、レイアウトのプレビュー)が含まれる
- 設定に30秒以上かかり、専用の作業画面を用意する価値がある
- 設定結果が重要で、「確定前の確認」ステップを設ける価値がある
パターン C に適した例として、キャビネット、表面材、家電、仕上げを数多く選ぶカスタムキッチン、フレーム、駆動系、ホイール、ブレーキ、アクセサリー、色を選ぶカスタマイズ可能な自転車、モジュール、ユーザー層、連携機能、サポートレベル、契約期間を選ぶエンタープライズソフトウェアの契約、基材、寸法、構造設計、印刷、仕上げ、数量、配送方法を選ぶカスタム包装の注文があります。
パターンの選び方
IF product has 2-4 independent attributes, no cascading:
→ Pattern A: Inline expandable row
IF product has 4-7 attributes, cascading dependencies, configuration takes <30s:
→ Pattern B: Side drawer with vertical stepper
IF product has 8+ attributes, visual/diagram component, takes >30s:
→ Pattern C: Full-page configurator with horizontal step indicator
WHEN IN DOUBT:
→ Pattern A for simple-looking products
→ Pattern B for industrial equipment, services with options
→ Pattern C reserved for genuinely complex configurators
連鎖する依存ルール
パターン B と C で設定が連鎖する場合:
- 上流の選択が行われるまで、下流のステップは無効として表示します。ステップ 2 が空のときに、ステップ 4 をクリックできないようにします。
- 上流の選択が変更されたとき、下流の選択をクリアし、確認メッセージを表示します:「容量を 5 ton から 10 ton に変更すると、モーターとホイストの選択がリセットされます。続行しますか?」
- 各ステップでルールの根拠を表示します:「使用可能なモーターは、選択した容量 5 ton に基づいて絞り込まれています(BR-007)。」絞り込みルールを見えるようにします。
- 選択肢が 1 つだけの場合は自動選択します:連鎖によって有効な選択肢が 1 つに絞られた場合は、それを事前に選択し、「(前の選択に基づき、利用可能な選択肢はこれだけです)」と注記します。
こうすることで、連鎖設定がわかりやすく、直感的に感じられます。Excel に慣れた顧客は、「サイズが大きい場合、基本コンポーネントは使えない」「プレミアムサービスプランには組み込みサポートが含まれる」「食品対応基材の場合、水性インクのみ使用できる」といったルールを頭の中に持っていることがよくあります。そのルールを明示するほうが、何も説明せずに適用するよりも印象的です。
明細行の設定概要
コンフィギュレーターの確定後(ドロワーで保存、または全画面ページで確定)、明細行の「設定」列に組み立てた設定が表示されます。設定が 3~4 階層になると、長くなる場合があります。
[Industrial equipment example]
Industrial Lift — 5 ton, 40ft span
└─ Standard motor, Type 2 hoist, 480V controls, festoon system
[Custom apparel example]
Premium Hoodie — Tri-blend, M-XL run
└─ DTG print, 4-color front, sleeve embroidery, polybag
[IT services example]
Managed Services — Premium Tier, 50 users
└─ Security module, Backup module, 4-hr SLA, Slack integration
これを簡潔な概要テキストとして表示し、コンフィギュレーターを再度開く「設定を編集」リンクを付けます。明細行テーブルに各属性を個別の列としてすべて収めようとしないでください。属性が 2~3 個を超えると、拡張できなくなります。
参照実装パターン:
<table>
<thead>
<tr>
<th>#</th>
<th>Description</th>
<th>Configuration</th>
<th>Qty</th>
<th className="text-right">List Price</th>
<th className="text-right">Discount</th>
<th className="text-right">Net Price</th>
<th className="text-right">Line Total</th>
<th></th>
</tr>
</thead>
<tbody>
{lineItems.map((item, i) => (
<tr key={item.id}>
<td>{i + 1}</td>
<td>
<ProductPicker value={item.productId} onChange={(p) => updateItem(item.id, { productId: p })} />
</td>
<td>
<ConfigurationCell item={item} onChange={(config) => updateItem(item.id, { configuration: config })} />
{item.requiredRules.map(rule => (
<RuleIndicator key={rule.id} rule={rule} satisfied={item.satisfiedRules.includes(rule.id)} />
))}
</td>
<td>
<Input type="number" value={item.qty} onChange={(e) => updateItem(item.id, { qty: e.target.value })} />
</td>
<td className="text-right">{formatCurrency(item.listPrice)}</td>
<td className="text-right">
<DiscountCell item={item} onChange={(d) => updateItem(item.id, { discount: d })} />
</td>
<td className="text-right">{formatCurrency(item.netPrice)}</td>
<td className="text-right font-medium">{formatCurrency(item.lineTotal)}</td>
<td>
<RowActions onClone={() => cloneItem(item.id)} onRemove={() => removeItem(item.id)} />
</td>
</tr>
))}
</tbody>
<tfoot>
<tr><td colSpan={7} className="text-right">Subtotal:</td><td className="text-right">{formatCurrency(subtotal)}</td><td /></tr>
{discountRows.map(d => (
<tr key={d.id}><td colSpan={7} className="text-right text-muted-foreground">{d.label}:</td><td className="text-right">-{formatCurrency(d.amount)}</td><td /></tr>
))}
{taxRate > 0 && (
<tr><td colSpan={7} className="text-right">{taxName} ({taxRate}%):</td><td className="text-right">{formatCurrency(taxAmount)}</td><td /></tr>
)}
<tr className="font-bold text-lg"><td colSpan={7} className="text-right">Total:</td><td className="text-right">{formatCurrency(grandTotal)} {currency}</td><td /></tr>
</tfoot>
</table>
<Button onClick={addNewLine}>+ Add Line</Button>
顧客情報、支払条件、有効期限、メモは、明細行テーブルの下のセクションに表示します。同じページ内にインラインで表示し、別のルートやステップにはしません。
割引の積み上げパターン(割引が適用される場合、Tier 1 で必須)
DOMAIN.md に何らかの割引(数量割引、プロモーション割引、手動割引、個別交渉による割引)が記載されている場合、ビルドでは割引を段階的で透明性のある計算として表示する必要があります。
必須の表示計算:
List Price (5 × $15,000): $75,000.00
─────────────────────────────────────────
Volume Discount (5%): -$3,750.00
Promotional Discount (3%): -$2,137.50
Manual Discount ($1,000): -$1,000.00
─────────────────────────────────────────
Net Price: $68,112.50
HST (13%): $8,854.63
─────────────────────────────────────────
Total: $76,967.13 CAD
必須の動作:
- 合計欄では、割引ごとに独立した行を表示します
- 各行には、割引の種類、割合または金額、および差し引かれた金額を表示します
- 割引は積み上げ順(数量割引 → プロモーション割引 → 手動割引)に適用します
- 手動割引が DOMAIN.md のしきい値を超える場合、承認ルーティングを開始します
- ユーザーには、差し引かれた内容とその理由を表示します。計算式の中に隠してはいけません
割引の承認しきい値:
DOMAIN.md に割引の承認ルール(「15%を超える割引にはマネージャーの承認が必要」など)が記載されている場合、プロトタイプでそのルールを適用します。
- 割引がしきい値未満 → ユーザーは承認なしで適用できます
- 割引がしきい値以上 → ユーザーは適用できますが、見積もりは「承認待ち」ステータスになります
- 承認ルーティングでは、その割引レベルで承認権限を持つ役割に申請します
これは、中小企業で最もよくある「利益率が下がる」という不満です。UI でルールを明示することには大きな価値があります。
複数階層の承認チェーンパターン(Tier 1 で必須)
ほとんどの中小企業の CPQ ワークフローには、2 段階以上の承認レベルがあります。プロトタイプにはこれを反映する必要があります。
承認チェーンの定義
DOMAIN.md では、ステークホルダーマップに承認者を記載します。プロトタイプでは、このマップから承認チェーンを導き出します。
- 単一の承認者 → シンプルなゲート(「[Owner] の承認待ち」)
- 順次承認する承認者 → チェーン(「[Sales Manager] の承認後、[Owner] の承認待ち」)
- 条件付き承認者 → 見積もりの属性に基づいてルーティング(「標準構成は [Reviewer A]、サービス依頼は [Reviewer B]、メンテナンスは [Reviewer C] にルーティング」)
承認チェーン UI
チェーンを明示的に表示し、見積もりがどの段階にあり、次に何が起こるのかをユーザーが理解できるようにします。
Quote Status: Pending Approval
─────────────────────────────────────────
✓ Submitted by [Sales Rep] (May 5, 2:30 PM)
✓ Approved by [Sales Manager] (May 5, 3:15 PM)
○ Pending approval from [Finance Lead]
○ Pending final signoff from [Owner]
各承認者は次の操作ができます。
- 自分のキューで見積もりを確認できます(フィルターされたリストビュー:「自分の承認待ち」)
- 承認、却下、または変更を依頼できます
- 操作によってチェーンが進むか、停止します
- 却下または変更された見積もりは、コメントとともに前の承認者に戻ります
ビルドに必要な要件:
- 承認チェーンは、DOMAIN.md のステークホルダーマップから自動的に導き出されます
- ロール切り替え機能を使うと、ユーザーは任意の承認者として表示を切り替え、キューの見え方を確認できます
- 複数見積もりのリストにある「自分の承認待ち」フィルターには、現在のロールが承認待ちの見積もりが表示されます
- 承認操作によってチェーンの状態が更新され、トースト通知が表示されます
- 却下や変更の際にコメントを記録でき、そのコメントは次または前のロールに表示されます
承認ルーティングのルール
DOMAIN.md にルーティングルールが記述されている場合(たとえば、「メンテナンス依頼はサービスマネージャーに、点検依頼は現場監督者にルーティングする」など)、プロトタイプにそのルーティングを実装します。例のロジック(DOMAIN.md で置き換える仮名を使用):
// Example routing logic derived from DOMAIN.md stakeholder map:
// - Standard quotes: route to [Sales Manager]
// - Inspection requests: route to [Field Supervisor]
// - Maintenance requests: route to [Service Manager]
// - All quotes finalized by [Owner]
function getApprovalChain(quote) {
const chain = [];
if (quote.requestType === 'inspection') {
chain.push({ role: 'inspection-reviewer', name: '[Field Supervisor]' });
} else if (quote.requestType === 'maintenance') {
chain.push({ role: 'maintenance-reviewer', name: '[Service Manager]' });
} else {
chain.push({ role: 'sales-reviewer', name: '[Sales Manager]' });
}
chain.push({ role: 'final-approver', name: '[Owner]' }); // Always final-signoff at end
return chain;
}
実際のビルドでは、プレースホルダーの名前を DOMAIN.md のステークホルダーマップにある実際の名前に置き換えます。プロトタイプでは、承認セクションにチェーンを明示的に表示し、ユーザーがルーティングロジックを確認できるようにします。これは中小企業のお客様にとって最も価値の高い機能の一つです。これまで自動ルーティングを利用したことがないからです。
レイアウトパターン
デフォルトのレイアウトはリスト/詳細です。中小企業の CPQ ユーザーは、常に複数の見積もりを進行させているためです。自分のキューを確認し、個々の見積もりを掘り下げて確認する必要があります。
デフォルト:リスト/詳細レイアウト
+----------+--------------------------------+
| | [List of quotes] |
| Filters | row (status badge) |
| Quick | row |
| filters | row |
| | |
| | + New Quote |
+----------+--------------------------------+
ユーザーが見積もりをクリックすると、詳細ルートに移動します。
+--------------------------------------------------------------+
| Header: [Company Name] | Q-2026-0001 | Status: Draft |
| ← All Quotes |
+--------------------------------------------------------------+
| [Edit Quote] [Approve] [Quote Document] tabs |
| ──────────────────────────────────────────────────────────── |
| |
| [Active section content — line items table by default] |
| |
| [Live totals on right or below — collapsible] |
+--------------------------------------------------------------+
リスト/詳細をデフォルトにする理由:
- お客様は、異なる見積もりごとに複数のタブやファイルを使う Excel の利用に慣れています
- 進行中のすべての見積もりを一目で確認する必要があります(キュービュー)
- ステータス、顧客、承認者、日付でフィルターする必要があります
- 1件の見積もりを掘り下げて確認しても、キューのコンテキストを失わないようにする必要があります(戻るボタンは常に機能します)
- 承認キューは本質的にリスト形式です(「自分の承認待ちのすべてを表示する」)
リストビューのサイドバー: フィルター、ロール切り替え機能、保存済み見積もりへのショートカット、「+ 新しい見積もり」へのリンク。ワークフローステッパーは含めません(アクティブな見積もりがないため)。
詳細ビューのサイドバー: 4 セクション/3 セクションのナビゲーション(見積もりを編集/承認/見積書)。または、サイドバーの代わりに詳細ビューで上部タブを使ってもかまいません。どちらも適切です。視覚的な密度に応じて選んでください。
右レール/ライブサマリー: 折りたたみ可能にします。見積もりを編集ではデフォルトで展開します(合計額は重要なコンテキストです)。見積書ではデフォルトで折りたたみます(書類自体がサマリーです)。
代替案:単一見積もりレイアウト
DOMAIN.md で、ユーザーが一度に1件の見積もりしか扱わないワークフローが説明されている場合(CPQ ではまれですが、一部の計算ツールでは有効です)、リストビューのない単一ページレイアウトを使用します。見積もりそのものがページになります。
代替案:計算ツール型レイアウト(計算ツールのドメイン)
計算が主要な機能となる計算ツール/受付ドメインでは、次のようにします。
+--------------------------------------------------------------+
| [Single-column form] |
| |
| Personal details |
| [field rows] |
| |
| Financial details |
| [field rows] |
| |
| ───────────────────────────────────── |
| |
| Calculated result |
| [inline output panel — updates as user types] |
| |
| [Submit for review] |
+--------------------------------------------------------------+
Clarity Legal の顧客向けフローでは、この形式を使用しています。弁護士向けのレビュー用フローでは、リスト/詳細を使用しています。
レイアウトの選択ルール
IF the user manages multiple in-flight workflows in parallel (almost all CPQ):
→ List/Detail layout (DEFAULT)
IF the calculation is the primary feature AND can be shown inline with inputs:
→ Calculator-Style layout
IF the user only ever works on one item at a time (rare):
→ Single-Page layout
IF in doubt:
→ List/Detail layout
サイドバーの動作
リスト/詳細を使う場合、ユーザーがリストビューにいるか詳細ビューにいるかに応じてサイドバーを切り替えます。
リストビュー: フィルター、ロール切り替え機能、「+ 新しい見積もり」ボタン、任意の保存済みフィルターへのショートカット。
詳細ビュー: セクションナビゲーション(見積もりを編集 → 承認 → 見積書)、上部のリストに戻るリンク。
どちらにも SidebarContent を使用します。ルートに応じて内容を切り替え、サイドバーを2つ追加しないでください。これはよくある実装バグです。エージェントが詳細ルート内に MainLayout をマウントし、サイドバーが重複して表示されます。これは避けてください。
右側の折りたたみパネル
見積概要パネルは固定パネルではなく、折りたたみ可能な右サイドバーです。shadcn の Sidebar コンポーネントに side="right" を指定するか、オフキャンバス動作には Sheet を使用します。
セクションごとのデフォルト状態:
- 見積の編集:展開(合計金額は重要です)
- 承認:展開(最終確認にはコンテキストが必要です)
- 見積書:折りたたみ(見積書自体が概要です)
ユーザーはヘッダーのトリガーボタンから、いつでも切り替えられます。
見積のライフサイクルインジケーター
ユーザーが見積の詳細画面に入ったら、現在のライフサイクル上の位置と、異なるビュー(編集、見積書、承認)間の移動方法を把握できる必要があります。
この2つは別々の課題であり、それぞれに異なる操作手段が必要です。
課題1 — ワークフローの状態(「この見積はライフサイクルのどの段階にあるか?」)
見積は、下書き → 承認待ち → 承認済み → 送信済み(または却下)という状態を遷移します。ユーザーは常に現在の状態を確認できる必要があります。
デフォルトのパターン:ページタイトルの近くにステータスバッジを配置します。
見積参照番号の横に Badge を配置し、現在の状態を表示します。状態に応じて色分けします:
- 下書き → アウトライン/グレー
- 承認待ち → デフォルト/アンバー
- 承認済み → セカンダリ/グリーン
- 却下 → destructive/レッド
- 送信済み/確定済み → セカンダリ/ブルー
これが最小構成です。v4.5 のビルドにはすでに含まれており、正常に動作します。
任意の拡張:横方向のステータスフロー。
ライフサイクルに表示可能な状態が4つ以上あり、進捗をひと目で把握できることが顧客にとって有益なワークフローでは、ページタイトルの下に横方向のステータス行を追加します:
●━━━━━━━━━━━━━●━━━━━━━━━━━━━◉━━━━━━━━━━━━━○━━━━━━━━━━━━━○
Draft [Reviewer] [Approver] Approved Sent
(complete) (complete) (current)
完了した状態には塗りつぶした円、現在の状態には塗りつぶしを含むアウトラインの円、今後の状態には空の円を使用します。承認待ちの段階では承認者名を表示し、誰のところで見積が保留されているかをユーザーが確認できるようにします。
ライフサイクルがシンプルな場合(状態が3つ以下)は追加しません。ステータスバッジだけで十分です。3段階のステータスフローは情報ではなく装飾です。
課題2 — ビュー間の移動(「編集ビューと見積書ビューを切り替えるには?」)
ユーザーは、編集可能なワークスペース、読み取り専用の顧客向け見積書、その他のビュー(承認キュー、履歴)間を移動できる必要があります。これらは連続するフェーズではなく、同じ見積の並列ビューです。
デフォルトのパターン:詳細ページの上部にタブを配置します。
ページタイトルの下、メインコンテンツ領域の上に Tabs を配置します:
[Edit Quote] [Document] [Approval] [History]
═══════════
アクティブなタブには下線を付けるか、塗りつぶします。非アクティブなタブはクリックできます。このパターンが適切な理由は次のとおりです:
- タブは「並列ビュー」を示し、順序があることを暗示しません
- 切り替えは1クリックで済み、モーダルやページ遷移はありません
- 各タブに件数やステータスバッジを表示できます(「承認(1件保留中)」、「履歴(5件)」)
- 無効状態にも意味があります。明細項目が追加されるまで「見積書」を無効にできます
- タブは6個まで無理なく増やせます。それ以上必要な場合は、ワークフローのフェーズが多すぎる可能性があります
タブの表示ルール:
- 編集 — 常に利用可能
- 見積書 — 明細項目が1つ以上追加されるまで無効(それ以外の場合、見積書は空です)
- 承認 — 見積が承認状態にある場合、または承認履歴がある場合のみ表示
- 履歴 — 見積に何らかの状態変更(編集、承認、却下)がある場合に表示
空のタブは表示しません。「近日公開」タブも表示しません。
タブを使わないほうがよい場合 — 代わりに垂直ステッパーを使う
垂直ステッパー(v4.3 のビルドのように、左側のレールに番号付きのステップを並べる形式)が適しているのは、次の場合です。
- ワークフローに、順番どおりに進める必要がある4 つ以上のステップがある
- ユーザーが次へ進む前に各ステップを一度ずつ実行する(ワークスペースではなく、ウィザードである)
- 自然な終点がある — ユーザーが N 番目のステップを終えると、見積もりも完成する
ほとんどの CPQ は、これらの条件を満たしません。見積もりはワークスペースです。ユーザーはそこに戻って編集し、後から再び開きます。この考え方にはタブが合っています。アプリレベルで垂直ステッパーを使うと、ワークスペース型のワークフローにウィザードの考え方を無理に当てはめることになり、その副作用として、ステップ名が詰まる、サイドバーのスペースが使いにくくなるといった視覚的な問題も生じます。このスキルの初期のイテレーションでは、この誤りを犯していました。現在のパターンでは、垂直ステッパーをアプリシェルではなく、コンフィギュレーターのドロワーに限定しています。
垂直ステッパーは、本物のウィザードに限定してください。たとえば、オンボーディングのフロー、一度限りのセットアップ、各ステージを別の担当者が受け持つエンタープライズ向けの複数段階の取引などです。
タブもステッパーも使わないほうがよい場合 — パンくずリストだけを使う
パンくずリストが示すのは階層や現在地であり、ワークフローのフェーズではありません。ユーザーがツリーを下っていく場合(Quotes › Q-2026-0007 › Line Items)はパンくずリストを使いますが、フェーズ間の移動の代わりとして使ってはいけません。
実際には、両方を併用できます。一番上に現在地を示すパンくずリストを置き、その下に現在の項目の同階層ビューを示すタブを置きます。
ワークフローが単純すぎて、どちらも必要ない場合
ワークフローによっては、画面が 1 つだけです(電卓のような単一ページのレイアウト)。タブは必要ありません。ページそのものが作業画面です。ステータスバッジだけで状態を伝えられます。依頼があった場合は、別のルートまたはモーダルで見積もりドキュメントを開きます。
レイアウトを埋めるためだけにタブバーを追加してはいけません。タブが 1 つだけなら、タブはありません。
まとめ
| ワークフローの形態 | パターン |
|---|---|
| 複数ビューのワークスペース(編集/ドキュメント/承認) | 詳細画面の上部にタブ+タイトル付近にステータスバッジ |
| 複数ビューのワークスペース+複雑なライフサイクル(4 つ以上の状態) | タブ+ステータスバッジ+水平ステータスフロー行 |
| 順次ステップに沿って進む本物のウィザード | 左側のレールに垂直ステッパー |
| 階層型ナビゲーション | パンくずリスト(同階層のビューもある場合はタブを併用) |
| 単一ページのワークフロー | ステータスバッジのみ |
製品 CPQ の大半は、1 行目のパターン、つまり複数ビューのワークスペースを使用します。編集/ドキュメント/承認にはタブを使い、タイトル付近にステータスバッジを置きます。
見積もりドキュメント(最終成果物)
納品物です。製品ドメインでは、顧客向けの見積もり PDF です。電卓ドメインでは、サマリーレポートです。
サマリーカードではなく、実際のドキュメントとして扱ってください。品質基準:「見積もり/レポート」として顧客にメールで送るのが気恥ずかしいと思うなら、まだ完成していません。
レイアウト(上から下へ)
1. ドキュメントヘッダー — 2 列:
- 左:ブランドロゴ(onError 時は色付きのイニシャル入り四角形にフォールバックします。img タグのみの使用は禁止です)。会社名。会社住所。
- 右:ドキュメントのタイトル(「見積書」「概算見積書」「概要レポート」など)。参照番号(自動生成。例:「Q-2026-0001」)。ドキュメントの日付。該当する場合は有効期限。
2. 宛先ブロック — 受取人の名前、連絡先メールアドレス、顧客の会社名。視覚的に目立たせます。
3. コンテンツブロック:
製品ドメインの場合:明細テーブル。 | # | 説明 | 構成 | 数量 | 単価 | 明細合計 |
計算ツールドメインの場合:入力テーブル+結果テーブル。(Clarity Legal のパターンを参照してください。)
4. 合計/概要ブロック:
製品ドメイン — 右揃えの合計欄に、割引の計算内容をすべて表示します:
Subtotal: $75,000.00
Volume Discount (5%): -$3,750.00
Promotional Discount (3%): -$2,137.50
─────────────────────────────────────
Net Subtotal: $69,112.50
HST (13%): $8,984.63
─────────────────────────────────────
Total: $78,097.13 CAD
計算ツールドメイン — 主な計算値または値の範囲を目立つように表示します。範囲を表示する場合は、3 カードレイアウト(低/中/高)で主な値を強調すると効果的です。
5. 条件/免責事項ブロック:
製品:支払い条件、通貨、有効期間。 計算ツール:DOMAIN.md に記載された必須の法的/規制上の免責事項。
6. 承認履歴ブロック — 承認履歴を表示します:
Approved by:
✓ [Reviewer Name] (Sales Manager) — May 5, 2026
✓ [Reviewer Name] (Finance) — May 6, 2026
✓ [Reviewer Name] (Owner) — May 6, 2026
これは顧客に好印象を与えます。見積もりが適切な手順で承認されたことの証明になります。
7. ステータスバッジ — 下書き/レビュー待ち/承認済み/確定済み。常に表示します。
8. フッター — 注記、連絡先情報、ドメインで必要な場合は署名欄を小さく表示します。
読み取り専用
ドキュメントビューに編集コントロールは表示しません。利用できる操作は「見積書の編集に戻る」「印刷」「PDF をダウンロード」(プロトタイプではトーストを表示するプレースホルダー操作)のみです。
RBAC の動作
ワークフローに複数のロールがある場合:
- DOMAIN.md のユーザーロールまたはステークホルダーマップに記載されたロールを localStorage にシードします
- ロール切り替え機能は、ヘッダーに配置する単一の
DropdownMenuとします。トリガーには現在のロールとバッジを表示します - 表示の制御: ロールごとに、デフォルトで異なるリストフィルターを表示します(承認者には「自分の承認待ち」、作成者には「自分の下書き」)
- 操作の制御: 承認ボタンは、承認権限を持つロールにのみ表示します
- フィールドの制御: 機密性の高い数値(コスト、利益率)は、承認者以外には表示しません
- ルーティング情報の表示: ロールが特定の作業タイプを担当する場合、アクティブなロールに応じた関連ルーティング情報を表示します
DOMAIN.md にロールが 1 つだけ記載されている場合、またはロールの記載がない場合は、ロール切り替え機能を省略します。UI を埋めるためにロールを捏造してはいけません。
ロールに権限がない場合の、操作を促すメッセージ:
- ❌ 無効化されたボタン(理由が分からず、ユーザーに伝わりません)
- ✓ 「[承認者ロール] ロールに切り替えて、[操作]してください」(ロール切り替え機能があるプロトタイプの場合)
- ✓ 「この操作には [承認者ロール] の権限が必要です。承認については [名前] にお問い合わせください。」(本番環境の場合)
shadcn/ui コンポーネントのマッピング
以下の shadcn/ui コンポーネントを使用してください。~/components/ui/* からインポートします。カードは例外として扱い、デフォルトでは使用しないでください。ビジュアル品質の基準については frontend-design スキルを参照してください。
| CPQ 要素 | コンポーネント | 備考 |
|---|---|---|
| 明細テーブル | Table と TableHeader、TableBody、TableFooter | セルはインライン編集可能です。合計の積み上げ表示には TableFooter を使用します。 |
| 編集可能なセル(数値) | Input type="number" | セル内で幅いっぱいに表示します。ぼかし時または変更時に更新します。 |
| 編集可能なセル(セレクト) | Select | テーブルセル内のドロップダウンに使用します。 |
| 構成セル | カスタムのポップオーバー/ドロワー | クリックするとコンフィギュレーターが開き、概要がインラインで表示されます。 |
| 行のアクション | DropdownMenu | トリガーにはゴミ箱アイコンを使用し、オプションは編集/複製/削除です。 |
| 明細追加ボタン | Button variant="outline" | テーブルの下に配置します。空の行を追加するか、ピッカーを開きます。 |
| ステータスバッジ | Badge | outline は下書き、default は承認待ち、secondary は承認済みです。 |
| ロール切り替え | DropdownMenu | ヘッダーに配置します。現在のロールとバッジを表示します。 |
| 右サイドバー(折りたたみ可能) | Sidebar side="right" | または、画面外から表示する場合は Sheet を使用します。ヘッダーから切り替えます。 |
| 承認チェーンの表示 | ステータスアイコン付きのカスタムリスト | チェックマーク/保留中の円形アイコンで、ステップごとに視覚的に表示します。 |
| 見積もりリスト | Table または行リスト | 上部にステータスフィルターチップを配置します。行をクリックすると詳細ルートに移動します。 |
| フィルター | チップグループ/Select | 見積もりリストの上に配置します。ステータス、顧客、承認者で絞り込みます。 |
| 確認ダイアログ | AlertDialog | 削除や却下などの破壊的な操作に使用します。 |
| トースト通知 | Sonner/toast() | 保存、承認、却下、複製の後に表示します。 |
| 見積書 | 印刷用スタイルの記事 | print:border-0、ブランドヘッダー、合計の積み上げ表示を使用します。 |
| 積み上げ表示の値引き行 | インラインのラベル/値 | 値引き行には控えめな色を使用します。 |
構成スキーマ
TypeScript インターフェイスの全文は references/config-schema.md を参照してください。概要:
config
├── app ← Branding, theme
├── sections[] ← Sections (3 default for SMB direct-editing)
├── layout ← list-detail | calculator-style | single-page
├── data
│ ├── products[] ← Catalog with options, required-children
│ ├── inputSections[] ← Calculator domain inputs
│ ├── quotes[] ← All quotes (multi-quote management)
│ └── quoteSettings ← Currency, tax, terms, markup
├── rules[] ← Constraint rules + business rules + discount rules
├── approvalChain ← Multi-tier approval routing
└── roles[] ← Roles with permissions and view filters
決定論的なマッピングルール
ドメインタイプの判定
INSPECT DOMAIN.md:
IF Entity Registry has products with prices/options/accessories:
→ DOMAIN TYPE: product
ELSE IF Entity Registry has input fields with rules and DOMAIN.md has guidelines/formulas:
→ DOMAIN TYPE: calculator
ELSE IF both:
→ DOMAIN TYPE: hybrid (rare — pick dominant)
ELSE:
→ AMBIGUOUS — note in completion summary, default to product
セクション数の決定
EVALUATE workflow handoffs:
IF same role does configure + line management + approval:
→ 3 sections: Edit Quote, Approve, Quote Document (DEFAULT for SMB)
IF different roles for configure vs line management:
→ 4 sections: Configure, Build Quote, Approve, Quote Document
IF no review gate exists:
→ Skip Approve section
IF deliverable isn't a document:
→ Replace Quote Document with appropriate output (confirmation, push-to-system, inline result)
レイアウトの決定
PICK based on workflow:
IF user manages multiple quotes in parallel (almost all CPQ):
→ List/Detail layout (DEFAULT)
IF calculation is primary feature, simple inputs/outputs:
→ Calculator-Style layout
IF single-item workflow (rare):
→ Single-Page layout
エンティティから構成可能な項目へのマッピング
FOR EACH entity in DOMAIN.md Entity Registry:
PRODUCT DOMAIN:
WHERE entity is sellable product/service/part:
→ CREATE config.data.products[] entry
→ SET id, name, category, basePrice, pricingSource
→ SET options[] from entity's "what varies" attributes
→ SET requiredChildren[] from "must include" relationships (e.g., crane requires motor)
→ SET optionalChildren[] from "may include" relationships
CALCULATOR DOMAIN:
WHERE entity is input field/parameter:
→ CREATE config.data.inputSections[] entry
→ GROUP related inputs into sections
→ SET field id, label, type, required, validation
関係からルールへのマッピング
FOR EACH relationship:
"requires" → config.rules[] (type: requires, severity: error, surface visibly)
"recommends" → config.rules[] (type: recommends, severity: info, surface as suggestion)
"excludes" → config.rules[] (type: excludes, severity: error, block invalid combo)
"includes child" → config.products[].requiredChildren[] (bundle pattern)
値引きの積み上げ表示へのマッピング
FOR EACH discount type in DOMAIN.md:
→ CREATE config.data.discountTypes[] entry
→ SET id, label, type (percentage|amount), rate, conditions
→ IF discount has approval threshold:
→ CREATE config.rules[] entry (type: approval-required, threshold: X)
EXAMPLES:
"5% volume discount over 10 units" → percentage discount with quantity condition
"Promotional 3% in Q4" → percentage discount with date condition
"Discounts over 15% require manager approval" → approval-required rule, threshold 0.15
承認チェーンへのマッピング
FROM DOMAIN.md Stakeholder Map and routing rules:
→ CREATE config.approvalChain entry per quote type
→ IF routing rules exist (e.g., "inspections to Dre, maintenance to Manish"):
→ CREATE conditional routing in approvalChain
→ ALWAYS append final approver if DOMAIN.md describes one
→ SURFACE the chain visually in the Approve section
状態モデルからワークフローへのマッピング
IF DOMAIN.md State Models contain workflow statuses:
→ MAP to quote.status enum (Draft, Awaiting Approval, Approved, Rejected, Finalized)
→ MAP transitions to action availability
ブランディングからテーマへのマッピング
→ SET config.app.companyName from DOMAIN.md Project Overview
→ SET config.app.theme.primaryColor from brandfetch
→ SET config.app.theme.accentColor from brandfetch
→ SET config.app.theme.logoUrl from brandfetch (with onError fallback in BrandMark)
→ SET config.app.theme.mode = "light"
見積もり設定へのマッピング
Product domain:
→ SET currency, taxEnabled (only if DOMAIN.md mentions tax), taxLabel, taxRate
→ SET defaultTerms, markup, quoteFormat
Calculator domain:
→ SET formulas from DOMAIN.md guidelines
→ SET outputFormat per deliverable type
→ SET disclaimers from DOMAIN.md mandatory text
ロールへのマッピング
FOR EACH role in DOMAIN.md User Roles:
→ CREATE config.roles[] entry
→ SET id, label, permissions, viewFilters, fieldVisibility
→ IF role appears in approval chain → mark as approver
→ IF only one role or no roles → omit role switcher in UI
エッジケース
→ IF entity has no price → SET pricingSource = "tbd", ADD to openQuestions
→ IF relationship rationale missing → SET message = "[source] [rel] [target] — rationale not captured"
→ IF entity unclassifiable → SKIP, ADD to openQuestions
→ IF DOMAIN.md has Open Questions → COPY to config.metadata.openQuestions
→ IF only one role → CREATE default role, OMIT role switcher
→ IF no pricing AND domain is product → SET markup = 0, ADD to openQuestions
→ IF no calculation formulas AND domain is calculator → BUILD with placeholder formulas, ADD to openQuestions
→ IF DOMAIN.md mentions discounts but no approval thresholds → use 15% default for "requires approval"
ビジネスルールのテンプレート
製品の依存関係(必須要件)
{
"id": "BR-XXX",
"type": "requires",
"trigger": "addItem",
"condition": { "item.category": "[source_category]" },
"action": { "suggest": "[target_product_id]", "matchField": "[matching_attribute]" },
"message": "[rationale from DOMAIN.md]",
"severity": "error",
"surfaceVisibly": true
}
製品の推奨(任意)
{
"id": "BR-XXX",
"type": "recommends",
"trigger": "addItem",
"condition": { "item.category": "[source_category]" },
"action": { "suggest": "[target_product_id]" },
"message": "[rationale from DOMAIN.md]",
"severity": "info",
"surfaceVisibly": true
}
製品の除外
{
"id": "BR-XXX",
"type": "excludes",
"trigger": "addItem",
"condition": { "item.category": "[source_category]" },
"action": { "block": "[target_product_id]" },
"message": "[rationale from DOMAIN.md]",
"severity": "error",
"surfaceVisibly": true
}
バンドル/必須の子項目
{
"id": "BR-XXX",
"type": "requires-child",
"parent": "[parent_product_id]",
"child": "[child_product_id_or_category]",
"selectionMode": "required-one-of",
"message": "[rationale]",
"severity": "error"
}
値引きしきい値による承認ゲート
{
"id": "BR-XXX",
"type": "approval-required",
"trigger": "discountApplied",
"condition": { "discount.percentage": { "$gte": 0.15 } },
"action": { "requireApproval": "[approver_role_id]" },
"message": "Discounts over 15% require [approver name] approval",
"severity": "warning"
}
複数段階の承認チェーン
{
"id": "BR-XXX",
"type": "approval-chain",
"trigger": "submitForApproval",
"chain": [
{ "role": "sales-reviewer", "name": "[Sales Manager]", "condition": { "quote.requestType": "standard" } },
{ "role": "inspection-reviewer", "name": "[Field Supervisor]", "condition": { "quote.requestType": "inspection" } },
{ "role": "maintenance-reviewer", "name": "[Service Manager]", "condition": { "quote.requestType": "maintenance" } },
{ "role": "final-approver", "name": "[Owner]" }
],
"message": "Routed through reviewer based on request type, finalized by [Owner]"
}
実際の構成では、プレースホルダー名を DOMAIN.md の Stakeholder Map に記載されている実際の名前に置き換えてください。
計算式
{
"id": "BR-XXX",
"type": "computes",
"trigger": "inputChange",
"condition": { "fields": ["incomeA", "incomeB", "duration"] },
"action": { "compute": "supportLow = (incomeB - incomeA) * 0.015 * yearsOfMarriage" },
"message": "[formula basis from DOMAIN.md]",
"severity": "info"
}
業種別プリセット
| 業種 | ドメインタイプ | 一般的なレイアウト | 主な Tier 1 機能 |
|---|---|---|---|
| 製造/BOM | 製品 | リスト/詳細 | バンドル(親項目+アクセサリー)、値引きの積み上げ表示、複数段階の承認 |
| 卸売/流通 | 製品 | リスト/詳細 | 数量別価格帯(Tier 2)、値引きの積み上げ表示、顧客別価格設定 |
| サービス/インテグレーター | 製品 | リスト/詳細 | 機器+労務+材料のバンドル、承認チェーン |
| 法律/コンプライアンス | 計算機 | 計算機スタイル+リスト/詳細 | 数式による計算、必須の免責事項、弁護士による確認キュー |
| 金融/保険 | 計算機 | 計算機スタイル+リスト/詳細 | レートテーブル、適格性ルール、範囲での出力 |
| 評価/適格性判定 | 計算機 | 計算機スタイル | スコアリングモデル、しきい値ルール、推奨の出力 |
完了前の検証
構築を完了する前に、Tier 1 の標準をすべて満たしていることを確認してください。
[ ] Direct inline editing — line items table with editable cells, no Configure-then-Build round trip
[ ] Bundle / required-child — parent products with required children handled in single line; configurator pattern matches complexity (inline / drawer / full-page)
[ ] Constraint rules visible — requires/excludes/recommends surfaced with rationale and rule IDs
[ ] Discount stack — visible math, layered calculation, no hidden formulas
[ ] Live quote summary — totals update in real-time as user edits
[ ] Branded quote document — logo, line items, totals, terms, approval chain, professional print layout
[ ] Multi-tier approval routing — chain derived from DOMAIN.md, surfaced visually
[ ] Multi-quote management — list view with filters, drill into detail
[ ] Save / load / clone — all persisted to localStorage
[ ] Role-based gating — view filters, action gating, sensitive field hiding
[ ] Quote lifecycle indicator — tabs for view navigation + status badge for state; horizontal status flow when 4+ states
Tier 1 の標準に不足がある場合、構築は未完了です。完了前に修正してください。
[ ] No duplicate sidebars — verify by routing through to detail view, count Sidebar components (should be 1)
[ ] No mounted MainLayout inside route — routes render in <Outlet />
[ ] Light mode set in BOTH app.css AND ThemeProvider default
[ ] BrandMark component used everywhere a logo appears (no bare <img>)
[ ] Currency uses Intl.NumberFormat with thousands separators
[ ] Footer text appears once, not duplicated by layout nesting
これらは、npm run build は通過してもユーザーエクスペリエンスを損なう、よくある実装上のバグです。
マッピングログ
マッピングルールを実行した後、マッピングログを生成します。
## Mapping Log
**Skill:** cpq-builder v4.7
**DOMAIN.md:** [company name]
**Domain type:** [product / calculator / hybrid / ambiguous]
**Vertical preset:** [manufacturing / wholesale / services / legal / financial / assessment / none]
**Section count:** [3 / 4 / 5] (deviations: [list])
**Layout:** [list-detail / calculator-style / single-page]
### Tier 1 standards: [all met / list any gaps]
- [confirm or note gap]
### Tier 2 capabilities built: [N]
- [list with rationale]
### Tier 3 capabilities mentioned in completion summary: [N]
- [list]
### Items mapped: [N]
- [entity name] → config.data.products[0] (with [N] required children, [N] options)
### Rules mapped: [N]
- BR-001: [source] [rel] [target] → [severity, action]
### Approval chain configured:
- [chain description]
### Discount stack configured:
- [list discount types and thresholds]
### Configurator pattern used:
- [inline-expand / drawer-with-stepper / full-page] — [rationale based on attribute count and cascading]
### Lifecycle indicator pattern:
- Tabs: [Edit / Document / Approval / History — list which are present]
- Status flow: [included / omitted — rationale]
### Skipped entities: [N]
- [entity name] — [reason]
### Open questions carried forward: [N]
- [question from DOMAIN.md]
参照ファイル
references/config-schema.md— CPQ 設定の構造を定義する TypeScript インターフェイスの全容references/vertical-presets.md— 製品および計算機ドメインの詳細なプリセットreferences/example-config.json— 設定例を完全に記入したファイル