Fab Forward Dev/

DDD ドキュメント

Sales CRM 集約: レポート・分析 / Aggregate: Reporting

バウンデッドコンテキスト: Operations (オペレーション)

知識ベース: knowledge/07-sales-management/performance-management.md (KPI) → 知識ベース: knowledge/06-crm-fundamentals/crm-strategy.md (パイプライン分析)


設計方針

Reporting は 読み取り専用のプロジェクション (Read Model) であり、新しいコレクションは作成しない。 既存の Deal, Activity, Account データを集計・投影する API エンドポイントとして実装する。

┌──────────┐     ┌──────────┐     ┌──────────────────┐
│  Deal    │────▶│          │────▶│ PipelineReport   │
│          │     │  集計    │     │ (読取専用投影)    │
└──────────┘     │  ロジック │     └──────────────────┘
┌──────────┐     │          │     ┌──────────────────┐
│ Activity │────▶│          │────▶│ ActivitySummary  │
│          │     │          │     │ (読取専用投影)    │
└──────────┘     └──────────┘     └──────────────────┘

集約ルート (Read Models)

1. PipelineReport (パイプラインレポート)

ステージ別・担当者別のパイプライン集計を提供する読み取り専用プロジェクション。

PipelineReport (読取専用プロジェクション)
├── period: DateRange           (集計期間)
├── stageBreakdown[]            (ステージ別集計)
│   ├── stage: DealType         (lead / inquiry / negotiation)
│   ├── count: number           (案件数)
│   ├── totalAmount: number     (合計金額)
│   └── weightedAmount: number  (加重金額)
├── statusBreakdown[]           (ステータス別集計)
│   ├── status: DealStatus      (open / won / lost)
│   ├── count: number           (案件数)
│   └── totalAmount: number     (合計金額)
├── repBreakdown[]              (担当者別集計)
│   ├── salesRep: → User        (営業担当)
│   ├── count: number           (案件数)
│   ├── totalAmount: number     (合計金額)
│   └── weightedAmount: number  (加重金額)
├── totalDeals: number          (全案件数)
├── totalAmount: number         (合計金額)
├── totalWeightedAmount: number (加重金額合計)
└── winRate: number             (成約率: won / (won + lost))
プロパティ説明
periodDateRange集計対象期間 (開始日-終了日)
stageBreakdownArrayDealType 別の案件数・金額集計
statusBreakdownArrayDealStatus 別の案件数・金額集計
repBreakdownArray営業担当者別の案件数・金額・加重金額
totalDealsnumber対象期間の全案件数
totalAmountnumber合計金額 (円)
totalWeightedAmountnumber加重金額合計 (amount x probability / 100)
winRatenumber成約率 (0-100%)

ルール:

  • PipelineReport は永続化しない。リクエスト時に Deal データから動的に集計
  • weightedAmount = amount x probability / 100
  • winRate = won件数 / (won件数 + lost件数) x 100。open のみの場合は 0
  • 期間フィルタ: expectedCloseDate または createdAt で絞り込み
  • グループフィルタ: group (StaffGroups.slug) で絞り込み可能

API エンドポイント (計画):

  • GET /api/reports/pipeline — パイプライン集計
    • クエリパラメータ: startDate, endDate, group, salesRep

2. ActivitySummary (活動サマリー)

活動タイプ別・担当者別の活動集計を提供する読み取り専用プロジェクション。

ActivitySummary (読取専用プロジェクション)
├── period: DateRange              (集計期間)
├── typeBreakdown[]                (タイプ別集計)
│   ├── activityType: ActivityType (call / meeting / etc.)
│   ├── count: number              (件数)
│   └── totalDuration: number      (合計時間・分)
├── repBreakdown[]                 (担当者別集計)
│   ├── salesRep: → User           (営業担当)
│   ├── count: number              (件数)
│   └── totalDuration: number      (合計時間・分)
├── dailyTrend[]                   (日別推移)
│   ├── date: Date                 (日付)
│   └── count: number              (件数)
├── totalActivities: number        (全活動件数)
└── totalDuration: number          (全合計時間・分)
プロパティ説明
periodDateRange集計対象期間 (開始日-終了日)
typeBreakdownArrayActivityType 別の件数・合計時間
repBreakdownArray営業担当者別の件数・合計時間
dailyTrendArray日別の活動件数推移
totalActivitiesnumber対象期間の全活動件数
totalDurationnumber全合計所要時間 (分)

ルール:

  • ActivitySummary は永続化しない。リクエスト時に Activity データから動的に集計
  • 期間フィルタ: activityDate で絞り込み
  • グループフィルタ: group (StaffGroups.slug) で絞り込み可能
  • totalDurationduration が設定されている活動のみ合算

API エンドポイント (計画):

  • GET /api/reports/activities — 活動サマリー
    • クエリパラメータ: startDate, endDate, group, salesRep, activityType

RBAC

レポートのアクセスは以下のロールモデルに従う:

ロールパイプラインレポート活動サマリー
admin全データ全データ
manager全データ (チーム管理用)全データ (チーム管理用)
sales_rep自分の担当分のみ自分の活動のみ
executive全データ (閲覧専用)全データ (閲覧専用)

レポートの RBAC は、元データ (Deal, Activity) の RBAC スコーピングを集計時に適用する。 → 参照: iam.md §RBAC データアクセスマトリクス


関連図

┌──────────┐          ┌──────────────────┐
│  Deal    │─集計───▶ │ PipelineReport   │
│ (案件)   │          │ (ステージ×金額×   │
│          │          │  担当者)          │
└──────────┘          └──────────────────┘

┌──────────┐          ┌──────────────────┐
│ Activity │─集計───▶ │ ActivitySummary  │
│ (活動)   │          │ (タイプ×件数×     │
│          │          │  担当者)          │
└──────────┘          └──────────────────┘