Fab Forward Dev/

DDD ドキュメント

Sales CRM 集約: 目標管理 / Aggregate: Goal Tracking

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

知識ベース: knowledge/07-sales-management/performance-management.md (KPI)


集約ルート (Aggregate Roots)

1. Goal (目標項目)

Goal (集約ルート)
├── name: string                (目標名)
├── description: string         (説明)
├── entityType: GoalEntityType  (deals / activities)
├── aggregationMethod: AggregationMethod  (count / sum / average)
├── targetField: string         (集計対象フィールド — sum/average 時)
├── filterConditions[]          (フィルタ条件)
│   ├── field: string           (フィルタ対象フィールド)
│   ├── operator: string        (equals / in / gte / lte)
│   └── value: string | string[] (フィルタ値)
├── period: GoalPeriod          (monthly / quarterly / yearly)
├── isActive: boolean           (有効フラグ)
├── displayOrder: number        (表示順)
├── createdBy: → User           (作成者)
├── updatedBy: → User           (最終更新者)
└── version: number             (楽観ロック用)
プロパティ必須説明
namestring目標名 (最大 100 文字)
descriptionstring目標の説明 (最大 500 文字)
entityTypeGoalEntityTypedeals / activities — 集計対象エンティティ
aggregationMethodAggregationMethodcount / sum / average
targetFieldstring条件付集計対象フィールド名 (sum/average 時必須: 例 amount, duration)
filterConditionsFilterCondition[]フィルタ条件配列 (任意)
periodGoalPeriodmonthly / quarterly / yearly
isActiveboolean有効フラグ (デフォルト: true)
displayOrdernumber表示順序 (デフォルト: 0)
createdBy→ User作成者 (読取専用)
updatedBy→ User最終更新者 (読取専用)
versionnumber楽観ロック用

フィルタ条件の例:

// 例: 商談の成約金額を集計
{
  entityType: "deals",
  aggregationMethod: "sum",
  targetField: "amount",
  filterConditions: [
    { field: "dealType", operator: "equals", value: "negotiation" },
    { field: "status", operator: "equals", value: "won" }
  ],
  period: "monthly"
}

// 例: 電話活動件数を集計
{
  entityType: "activities",
  aggregationMethod: "count",
  filterConditions: [
    { field: "activityType", operator: "in", value: ["call", "inquiry"] }
  ],
  period: "monthly"
}

不変条件 (Invariants):

  • name は空文字不可
  • entityTypedeals / activities のいずれか
  • aggregationMethodcount / sum / average のいずれか
  • aggregationMethodsum / average の場合、targetField は必須
  • targetField は対象エンティティの数値フィールド名のみ
  • periodmonthly / quarterly / yearly のいずれか
  • filterConditions[].field は対象エンティティの有効なフィールド名
  • 楽観ロック: バージョン不整合で 409 Conflict
  • admin のみ作成・更新・削除可能

2. GoalValue (目標値)

GoalValue (エンティティ — Goal の子)
├── goal: → Goal                (親目標項目)
├── user: → User                (対象ユーザー、任意 — 全体目標時は null)
├── group: string               (対象グループ、任意)
├── periodStart: Date           (期間開始日)
├── periodEnd: Date             (期間終了日)
├── targetValue: number         (目標値)
└── version: number             (楽観ロック用)
プロパティ必須説明
goal→ Goal親目標項目
user→ User対象ユーザー (個人目標時)
groupstring対象グループ (グループ目標時)
periodStartDate期間開始日
periodEndDate期間終了日
targetValuenumber目標値 (0 以上)
versionnumber楽観ロック用

不変条件 (Invariants):

  • goal は必須
  • periodStart < periodEnd
  • targetValue ≥ 0
  • 同一 goal + user + periodStart の組み合わせはユニーク
  • 楽観ロック: バージョン不整合で 409 Conflict

読取専用投影: GoalProgress (目標進捗)

GoalProgress はデータベースに永続化しない、都度計算される読取専用の投影。 Goal の定義に基づき、対象エンティティから実績値を集計する。

interface GoalProgress {
  /** 目標項目 */
  goal: Goal;
  /** 対象期間 */
  period: { start: Date; end: Date };
  /** 目標値 */
  targetValue: number;
  /** 実績値 (集計結果) */
  actualValue: number;
  /** 達成率 (%) = actualValue / targetValue × 100 */
  achievementRate: number;
  /** 差分 = actualValue - targetValue */
  variance: number;
}

計算ロジック:

  1. Goal.entityType に基づき対象コレクション (deals / activities) を選択
  2. Goal.filterConditions でフィルタリング
  3. Goal.aggregationMethod に基づき集計:
    • count: レコード件数
    • sum: targetField の合計値
    • average: targetField の平均値
  4. RBAC スコーピング適用 (sales_rep は自分の担当分のみ)

トランザクション境界

操作同一トランザクション結果整合性 (Eventual)
Goal 作成Goal のみ
GoalValue 設定GoalValue のみ
GoalProgress 取得読取専用 (集計クエリ)

関連図

┌──────────────────┐
│      Goal        │
│  (目標項目定義)    │
│                  │
│  entityType      │
│  aggregation     │
│  filterConditions│
│  period          │
└────────┬─────────┘
         │ 1
    ┌────┼────┐
    │         │
   N│        N│
┌───┴──────┐ ┌┴───────────────┐
│GoalValue │ │ GoalProgress   │
│(目標値)   │ │ (実績 — 読取専用)│
│          │ │                │
│ user     │ │ actualValue    │
│ target   │ │ achievementRate│
│ period   │ │ variance       │
└──────────┘ └────────────────┘
                    │
         集計元 ────┤
                    │
         ┌──────────┴──────────┐
         │                     │
    ┌────┴─────┐         ┌────┴─────┐
    │  Deal    │         │ Activity │
    │ (案件)   │         │ (活動)   │
    └──────────┘         └──────────┘
  • Goal : GoalValue = 1 : N
  • Goal : GoalProgress = 1 : N (読取専用投影、都度計算)