Sales CRM 集約: カスタムフィールド / Aggregate: Custom Fields
バウンデッドコンテキスト: Configuration (設定)
集約ルート
CustomFieldConfig (カスタムフィールド設定)
CustomFieldConfig (集約ルート)
├── entity_type: EntityType (account / contact / deal)
├── field_name: string (システム名、snake_case)
├── display_name: string (ユーザー表示名)
├── field_type: FieldType (text/number/date/dropdown/checkbox)
├── description: string (説明)
├── is_required: boolean (必須フラグ)
├── display_order: number (表示順)
├── is_system_field: boolean (システム項目フラグ)
└── type_properties: JSON (タイプ固有設定)
├── options: DropdownOption[] (dropdown 時)
├── min_value: number (number 時)
├── max_value: number (number 時)
├── decimal_places: number (number 時)
└── default_value: string (date 時)
| プロパティ | 型 | 必須 | 説明 |
|---|---|---|---|
| entity_type | EntityType | ✓ | account / contact / deal |
| field_name | string | ✓ | システム名 (/^[a-z_][a-z0-9_]*$/) |
| display_name | string | ✓ | ユーザー表示名 |
| field_type | FieldType | ✓ | text / number / date / dropdown / checkbox |
| description | string | 項目の説明 | |
| is_required | boolean | 必須フラグ (デフォルト: false) | |
| display_order | number | ✓ | 表示順序 (デフォルト: 0、小さい値が先) |
| is_system_field | boolean | システム標準項目フラグ (読取専用) | |
| type_properties | JSON | タイプ固有の設定プロパティ | |
| createdBy | → User | 作成者 (読取専用) | |
| updatedBy | → User | 最終更新者 (読取専用) | |
| version | number | 楽観ロック用 |
不変条件 (Invariants):
entity_type + field_nameの組み合わせはユニーク制約field_nameはFIELD_NAME_PATTERNに一致:^[a-z_][a-z0-9_]*$field_nameは予約語禁止:id,created_at,updated_at,created_by,updated_by,version,deleted_at,deleted_by- dropdown タイプの場合、
type_properties.optionsに最低 1 つのオプションが必要 - number タイプの場合、
min_value≤max_value(両方指定時) - admin のみ全操作可能
- 楽観ロック: バージョン不整合で 409 Conflict
対応するフィールドタイプ
| FieldType | 日本語 | Payload 型 | type_properties |
|---|---|---|---|
text | テキスト | text | — |
number | 数値 | number | min_value, max_value, decimal_places |
date | 日付 | date | default_value |
dropdown | ドロップダウン | select | options: [{value, label, order}] |
checkbox | チェックボックス | checkbox | — |
標準フィールド (Standard Fields)
各エンティティには予め定義された標準フィールドがあり、カスタムフィールドと区別される:
| EntityType | 標準フィールド |
|---|---|
| account | name, website, phone, postalCode, address, coordinates, group, salesRep, dealCount, activityCount, lastActivityAt, nextActivityAt |
| contact | firstName, lastName, email, phone, position, department, account |
| deal | title, amount, stage, probability, expectedCloseDate, account, contact, salesRep |
拡張性設計
┌──────────────────┐ ┌──────────────────┐
│ CustomFieldConfig │ │ Account/Contact │
│ (メタデータ) │───────▶│ /Deal │
│ │ 動的 │ (実データ) │
│ entity_type │ フィールド│ │
│ field_name │ 追加 │ custom_fields: │
│ field_type │ │ { [key]: val } │
│ type_properties │ │ │
└──────────────────┘ └──────────────────┘
CustomFieldConfig はメタデータ (フィールド定義) を管理し、 実際の値は各エンティティの JSON フィールドに格納される構造。 これにより、スキーマ変更なしに動的な項目追加が可能。
影響件数カウント / Affected Record Count
カスタムフィールド削除前に、そのフィールドを使用しているレコード件数を表示する。
仕様
削除確認ダイアログ表示時に、対象フィールドが使用されているレコード数をカウントする。
クエリ仕様:
対象コレクション = CustomFieldConfig.entity_type に対応するコレクション
(account → accounts, contact → contacts, deal → deals)
カウント条件:
WHERE custom_data->>'{field_name}' IS NOT NULL
AND custom_data->>'{field_name}' != ''
API エンドポイント:
GET /api/settings/custom-fields/:id/impact-count
→ { affectedRecordCount: number }
不変条件 (Invariants):
- カウントは都度計算 (永続化しない)
- 削除確認ダイアログでユーザーに件数を表示してから削除実行
- RBAC: admin のみアクセス可能 (カスタムフィールド操作に準拠)