Commerce と CPQ
製品から確定した金額までの道筋。ポリシー、明細の価格決定方式を決めるプロファイル、価格表、仕入原価、そして見積バージョンを扱います。
ここのすべてのエンドポイントは cpq モジュールを必要とします。流れは一方向です。ワークスペースのポリシーとプロファイルが何が可能かを決め、価格表と仕入原価が数値を供給し、見積バージョンが結果を凍結します。
まずポリシー
GET /settings/commercial はすべての見積が従う算術を返します。ワークスペースごとに 1 つのオブジェクトでリビジョンを持ち、見積の側からこれを上書きすることはできません。
| 設定 | 既定 | 決めるもの |
|---|---|---|
baseCurrency |
JPY |
金額を報告する通貨 |
currencies |
{} |
他にどの通貨を許すか、どの条件で許すか |
currencyScale |
0 |
金額の小数桁数、0〜4。既定値は既定の通貨に合わせたものです |
rounding |
half_up |
計算された価格の丸め方。half_up、half_even、toward_zero、floor、ceil |
taxRounding |
floor |
同じ選択を税に独立して適用 |
taxCalculation |
per_rate_total |
税を per_line で計算するか、見積全体で税率ごとに一度計算するか |
calculationOrder |
discount_before_tax |
割引が税の前に入るか後に入るか |
pricesIncludeTax |
false |
カタログ価格が税込みかどうか |
fiscalYearStartMonth |
4 |
会計年度の開始月 |
timezone |
Asia/Tokyo |
日付を解釈するタイムゾーン |
ポリシーの変更はリビジョン付きの書き込みです。 PUT は読み取り時のリビジョンを取り、古い値は settings_stale で拒否します。既に書かれた見積は作成時のポリシーを保持します。各バージョンが policySnapshot を持つためです。
プロファイルが明細の価格決定方式を決める
GET /cpq/configuration は profile という 1 つのフィールドを返し、それが見積明細で使える 5 つの価格決定方式を決めます。
| 方式 | catalog |
procurement |
hybrid |
仕入原価が必要 |
|---|---|---|---|---|
catalog |
✓ | ✓ | ||
cost_plus |
✓ | ✓ | ✓ | |
gross_margin |
✓ | ✓ | ✓ | |
resale |
✓ | ✓ | ✓ | |
manual |
✓ | ✓ |
catalog のワークスペースは価格表からのみ価格を決めます。procurement のワークスペースは catalog を一切使えません。 ユーザーインターフェースで方式を提示する前にプロファイルを読んでください。プロファイルに含まれない方式は無視されるのではなく拒否されます。
各方式の計算
率はパーセントではなく小数の割合で、結果はすべてポリシーの rounding で丸められます。
| 方式 | 算術 |
|---|---|
catalog |
価格表のエントリ。計算はありません |
cost_plus |
cost × (1 + markup) |
gross_margin |
cost ÷ (1 − margin) |
resale |
retailPrice に対し、downstreamMargins(1〜10 個)の各率で × (1 − rate) を順に適用 |
manual |
与えられた unitPrice。1〜500 文字の reason も必須です |
原価を使う 3 つの方式は、原価エントリが存在しないか負の場合 purchase_cost_required で拒否します。manual は原価も利益も報告しません。他は unitProfit を unitPrice − unitCost として報告します。
manual は逃げ道であり、逃げ道として記録されます。 必須の reason が明細に保存されるため、手で価格を付けた見積はその理由を述べています。
製品・価格表・価格合意
製品は販売対象です。価格表は 1 つの通貨の名前付き価格一覧で、価格は 1 件ずつではなく POST /price-books/{id}/entries で 1〜500 件ずつまとめて入ります。
価格合意は 1 つの取引先を 1 つの価格表に期間付きで結び付けます。明細に複数該当する場合、priority が高いものが勝ち、最小数量の大きい方が同点を破ります。両方が同じ場合は恣意的に解決せず price_agreement_ambiguous で拒否します。矛盾する 2 つの合意は価格の問題ではなく設定の問題です。
仕入原価は事業が支払った額で、POST /purchase-costs で記録し、製品ごとに GET /products/{id}/purchase-costs で読みます。原価から価格を決める明細は costEntryId でエントリを指定するため、見積は今日の原価ではなく使った過去の原価を記録します。
見積・バージョン・明細
見積は number、取引先、任意で商談、そして裏付けとなる CRM レコードを持ちます。金額自体は持ちません。それはバージョンにあります。
バージョンは見積の価格が付いた 1 つの状態です。currency、subtotal、taxableAmount、tax、discount、total、価格決定時の cpqProfile と policySnapshot、customerSnapshot、contentHash、そして draft・submitted・approved・rejected・accepted・superseded のいずれかの state を持ちます。
commerce のエンドポイントはその状態を報告し、設定はしません。バージョンをその状態の間で動かすのは承認側で、見積のレコードに対して申請されます。commerce が制御するのはバージョンが凍結されているかどうかで、これは状態とは別のフラグです。
バージョンの明細は quantity、unit、unitPrice、unitCost、netAmount、discountAmount、taxRate、使われた pricingMethod、priceSnapshot、そして数値の出所である sourcePriceEntryId か sourceCostEntryId を持ちます。2 つの列挙がこれを分類します。chargeType は one_time・recurring・milestone、componentKind は product・hardware・software・service・option・package です。
各明細はスケジュールを持てます。金額をどう期間に配分して請求するかで、chargeType と同じ 3 種類、月単位の間隔、マイルストーンのラベルを持ちます。これは価格決定ではなく請求の関心事で、形はリファレンスにあります。
ドラフトと改訂
2 つの経路があり、同じではありません。
POST /quotes は見積を作成し、最初のバージョンを凍結します。POST /quotes/drafts は同じものを、そのバージョンを凍結しない状態で作成し、PUT /quotes/{id}/draft がそれをその場で編集します。凍結されたバージョンは編集できません。quote_version_frozen が代わりに改訂を作るよう告げます。
POST /quotes/{id}/versions はバージョンを追加して見積を改訂します。知っておく価値のある 2 つの拒否があります。
quote_stale— 送ったリビジョンが現在のものではありません。読み直して再試行してください。quote_draft_open— 最新のバージョンがまだ凍結されていません。改訂の前にドラフトを完了してください。 ドラフトと改訂は同じ見積を変える 2 つの方法で、同時に進められるのは一方だけです。quote_approval_pending— その見積に承認が開いています。改訂の前に取り下げてください。
POST /quotes/preview は何も作らずに見積の価格を計算します。利用者が入力している間に合計を表示するのはこれです。
原価の履歴がない状態で試す
procurement または hybrid のワークスペースは、その製品の仕入原価が存在するまで cost_plus の明細に価格を付けられません。先に POST /purchase-costs で 1 件記録するか、原価履歴を読み込んでいる間は理由を添えて manual を使ってください。