Sales CRM 値オブジェクト定義 / Value Objects
エンティティではないが、ドメイン上重要な意味を持つ不変の値の型定義。 値オブジェクトは同一性 (ID) を持たず、値の等価性で比較される。
→ 対応ドメイン:
docs/ddd/pms/06-value-objects.md(PMS 側の値オブジェクト) → 知識ベース:knowledge/06-crm-fundamentals/crm-strategy.md(CLV, セグメント)
DealAmount (案件金額)
案件の金額と確度を組み合わせた値オブジェクト。 加重パイプライン (Weighted Pipeline) の計算基礎。
interface DealAmount {
/** 金額 (円) — 税抜 */
amount: number;
/** 成約確度 (0-100%) */
probability: number;
/** 加重金額 = amount × (probability / 100) */
weightedAmount: number;
}
| 業務用語 | English | 使用箇所 |
|---|---|---|
| 案件金額 | Deal Amount | Deal.amount |
| 確度 | Probability | Deal.probability |
| 加重金額 | Weighted Amount | パイプライン分析 (→ Reporting BC)、フロントエンド計算 |
| 成約予定日 | Expected Close Date | Deal.expectedCloseDate |
ルール:
amount≥ 0 (nonnegative)probabilityは 0-100 の整数weightedAmount=amount×probability/ 100 (フロントエンドで計算)- 通貨は JPY 固定 (現行)
ActivityDuration (活動時間)
営業活動の所要時間を表す値オブジェクト。
interface ActivityDuration {
/** 所要時間 (分) */
minutes: number;
}
| 業務用語 | English | 使用箇所 |
|---|---|---|
| 所要時間 | Duration | Activity.duration |
ルール:
minutes> 0 (正の数)- 省略可能 (optional)
- 単位は「分」固定
Address (住所)
日本の住所体系に基づく値オブジェクト。 Account と CompanySettings で使用。
interface Address {
/** 郵便番号 (XXX-XXXX) */
postalCode?: string;
/** 住所テキスト (Account) or 都道府県+市区町村+番地 (CompanySettings) */
address?: string;
/** 地理座標 — 地図表示用 */
coordinates?: {
lat: number;
lng: number;
};
}
Account の住所
| 業務用語 | English | 変数名 |
|---|---|---|
| 郵便番号 | Postal Code | postalCode |
| 住所 | Address | address |
| 座標 | Coordinates | coordinates (Point 型) |
CompanySettings の住所
| 業務用語 | English | 変数名 |
|---|---|---|
| 郵便番号 | Postal Code | postal_code |
| 都道府県 | Prefecture | prefecture |
| 市区町村 | City | city |
| 番地・建物名 | Street Address | street_address |
ルール:
postalCode/postal_codeは/^\d{3}-?\d{4}$/形式coordinatesは地図 API でジオコーディング後に設定
PhoneNumber (電話番号)
type PhoneNumber = string; // /^\+?[\d\s\-()]+$/
| 業務用語 | English | 使用箇所 |
|---|---|---|
| 代表電話 | Phone | Account.phone |
| 電話番号 | Phone | Contact.phone |
| 携帯番号 | Mobile | Contact.mobile |
ルール:
- 数字、ハイフン、括弧、スペース、先頭の
+のみ許可 - 最大 20 文字
- 国際電話形式 (
+81-3-xxxx-xxxx) も許可
Email (メールアドレス)
type Email = string; // /^[^\s@]+@[^\s@]+\.[^\s@]+$/
| 業務用語 | English | 使用箇所 |
|---|---|---|
| メールアドレス | Contact.email, User.email |
ルール:
- RFC 5322 簡易パターン
- 最大 255 文字
PipelineStage (パイプラインステージ)
案件の進行段階を表す値オブジェクト。現在は DealType として実装。
type PipelineStage = "lead" | "inquiry" | "negotiation";
| 値 | 日本語 | 営業プロセスの位置 | 典型的な確度 |
|---|---|---|---|
lead | リード | 初期接点。見込み客の発掘 | 10-20% |
inquiry | 引合 | 顧客から問い合わせ。ニーズ確認 | 30-50% |
negotiation | 商談 | 具体的な提案・交渉段階 | 50-80% |
ルール:
- 値は DEAL_TYPE_VALUES から取得 (SSOT)
- ステージの進行方向に制約なし (現在の実装)
→ 知識ベース参照:
knowledge/07-sales-management/sales-process.md(標準的な営業パイプラインは 5-7 段階だが、現在は 3 段階の簡易版)
DealStatus (案件ステータス)
案件の最終結果を表す値オブジェクト。
type DealStatus = "open" | "won" | "lost";
| 値 | 日本語 | 説明 |
|---|---|---|
open | 進行中 | 案件が活動中 |
won | 成約 | 受注確定。PMS 連携のトリガー |
lost | 失注 | 失注。理由の記録を想定 |
ルール:
- デフォルト値は
open won→ PMS に CreateOrderRequest を送信 (PMS 連携有効時)- 値は DEAL_STATUS_VALUES から取得 (SSOT)
BusinessHours (営業時間)
interface BusinessHours {
/** 開始時刻 (HH:MM) */
start: string;
/** 終了時刻 (HH:MM) */
end: string;
}
| 業務用語 | English | 使用箇所 |
|---|---|---|
| 営業時間開始 | Business Hours Start | CompanySettings.business_hours_start |
| 営業時間終了 | Business Hours End | CompanySettings.business_hours_end |
ルール:
HH:MM形式 (/^([01]\d|2[0-3]):([0-5]\d)$/)start<end(開始は終了より前)
UserRole (ユーザーロール)
type UserRole = "admin" | "manager" | "sales_rep" | "executive";
| 値 | 日本語 | 権限レベル |
|---|---|---|
admin | 管理者 | 全操作可能 |
manager | マネージャー | 全データ閲覧 + 編集 (限定) |
sales_rep | 営業担当 | 自分の担当分のみ |
executive | 経営層 | 全データ閲覧 (読取専用) |
ActivityType (活動タイプ)
営業活動の種別を表す値オブジェクト。
type ActivityType = "call" | "meeting" | "inquiry" | "email" | "email_received" | "other";
| 値 | 日本語 | 説明 |
|---|---|---|
call | 電話発信 | 発信による電話営業 |
meeting | 面談 | 対面またはオンライン面談 |
inquiry | 電話受信 | 顧客からの受信 |
email | メール送信 | メールでの営業・フォロー |
email_received | メール受信 | 顧客からの受信メール |
other | その他 | その他の営業活動 |
ルール:
- 値は ACTIVITY_TYPE_VALUES から取得 (SSOT)
- Activity.activityType で使用
beforeValidateで値の検証を実施
FileType (ファイルタイプ)
営業資料の種別を表す値オブジェクト。
type FileType = "proposal" | "quote" | "contract" | "business_card" | "other";
| 値 | 日本語 | 営業プロセスでの位置 |
|---|---|---|
proposal | 提案書 | 商談段階で提出する提案資料 |
quote | 見積書 | 見積段階で提出する価格提示 |
contract | 契約書 | 成約後の契約文書 |
business_card | 名刺 | 担当者情報のデジタル保存 |
other | その他 | 議事録、カタログ等 |
ルール:
- 値は FILE_TYPE_VALUES から取得 (SSOT)
- File.fileType で使用
GroupSlug (グループ識別子)
type GroupSlug = string; // StaffGroups.slug
StaffGroups コレクションから動的に取得される識別子。
以前はハードコードされていた (sales-1, sales-2, sales-3, marketing, cs) が、
現在は StaffGroups コレクションで動的管理。
注:
GROUP_LABELS定数は deprecated。StaffGroups コレクションを使用すること。
Version (楽観ロックバージョン)
interface OptimisticLock {
/** バージョン番号 (0 から開始、更新ごとにインクリメント) */
version: number;
}
| 操作 | version の挙動 |
|---|---|
| create | version = 0 |
| update (正常) | version = currentVersion + 1 |
| update (競合) | 409 Conflict + latestData を返却 |
全主要コレクション (Account, Contact, Deal, Activity, File, CompanySettings, CustomFieldConfig) で共通適用。
TaxMode (税区分)
見積書の税計算方式を表す値オブジェクト。
type TaxMode = "exclusive" | "inclusive";
| 値 | 日本語 | 計算方式 |
|---|---|---|
exclusive | 外税 | taxAmount = subtotal × 税率、totalAmount = subtotal + taxAmount |
inclusive | 内税 | taxAmount = subtotal - subtotal / (1 + 税率)、totalAmount = subtotal |
ルール:
- QuoteTemplate.taxMode で使用
- 値は 2 値のみ (exclusive / inclusive)
→ 参照:
03-aggregates/quote-management.md§QuoteTemplate
QuoteLineItem (見積明細行)
見積書の個別明細行を表す値オブジェクト。
interface QuoteLineItem {
/** 品目名 (最大 50 文字) */
itemName: string;
/** 数量 (正の数) */
quantity: number;
/** 単価 (0 以上) */
unitPrice: number;
/** 単位 (式、個、セット等) */
unit?: string;
/** 明細詳細 (最大 200 文字) */
description?: string;
/** 行合計 = quantity × unitPrice */
lineTotal: number;
}
| 業務用語 | English | 使用箇所 |
|---|---|---|
| 品目名 | Item Name | QuoteDocument.lineItems[].itemName |
| 数量 | Quantity | QuoteDocument.lineItems[].quantity |
| 単価 | Unit Price | QuoteDocument.lineItems[].unitPrice |
| 単位 | Unit | QuoteDocument.lineItems[].unit |
| 行合計 | Line Total | 計算値: quantity × unitPrice |
ルール:
itemNameは空文字不可、最大 50 文字quantity> 0 (正の数)unitPrice≥ 0 (非負)lineTotal=quantity×unitPrice(計算値)descriptionは最大 200 文字
→ 参照:
03-aggregates/quote-management.md§QuoteDocument
GoalPeriod (目標期間)
目標の集計期間種別を表す値オブジェクト。
type GoalPeriod = "monthly" | "quarterly" | "yearly";
| 値 | 日本語 | 説明 |
|---|---|---|
monthly | 月次 | 月単位での目標管理 |
quarterly | 四半期 | 四半期 (3 ヶ月) 単位 |
yearly | 年次 | 年度単位 |
ルール:
- Goal.period で使用
- 会計年度の開始月は CompanySettings.fiscal_year_start_month に準拠
→ 参照:
03-aggregates/goal-tracking.md§Goal
DuplicateScore (類似度スコア)
重複検出における名前の類似度を表す値オブジェクト。
interface DuplicateScore {
/** 類似度スコア (0-100) — 高いほど類似 */
score: number;
/** 検出アルゴリズム */
algorithm: "levenshtein" | "trigram";
}
| 業務用語 | English | 使用箇所 |
|---|---|---|
| 類似度 | Similarity Score | DuplicateCandidate.similarityScore |
ルール:
scoreは 0-100 の範囲 (0 = 完全不一致、100 = 完全一致)- 検出閾値は設定可能 (デフォルト: 70)
- 全角・半角、大文字・小文字を正規化した上で比較
→ 参照:
03-aggregates/sales-pipeline.md§DuplicateDetection
WeightedAmount (加重金額)
パイプライン分析で使用される、案件金額に確度を掛けた計算値。 Reporting BC の PipelineReport で集計に使用する。
interface WeightedAmount {
/** 元の案件金額 (円) */
amount: number;
/** 成約確度 (0-100%) */
probability: number;
/** 加重金額 = amount × (probability / 100) */
weighted: number;
}
| 業務用語 | English | 使用箇所 |
|---|---|---|
| 加重金額 | Weighted Amount | PipelineReport.stageBreakdown, repBreakdown |
| 加重パイプライン合計 | Total Weighted Pipeline | PipelineReport.totalWeightedAmount |
ルール:
weighted=amount×probability/ 100-amount≥ 0、probabilityは 0-100 (元の Deal バリデーションに準拠)- 通貨は JPY 固定
- フロントエンドで個別計算。サーバー側集計は Reporting BC で提供
→ 参照:
03-aggregates/reporting.md§PipelineReport
DateRange (日付範囲)
レポートの集計期間を表す値オブジェクト。
interface DateRange {
/** 開始日 (ISO 8601) */
startDate: string;
/** 終了日 (ISO 8601) */
endDate: string;
}
| 業務用語 | English | 使用箇所 |
|---|---|---|
| 集計期間 | Report Period | PipelineReport.period, ActivitySummary.period |
ルール:
startDate≤endDate(開始は終了以前)- ISO 8601 日付形式- レポートリクエスト時に必須