Trigger.*(new/newMap/old/oldMap)の活用事例（標準オブジェクト）

## **`Trigger.new`、`Trigger.newMap`、`Trigger.old`、`Trigger.oldMap` の活用事例（標準オブジェクト）**  

Apexトリガーでは、レコードの **挿入・更新・削除時のデータを取得するために** `Trigger.new` や `Trigger.old` などの変数が利用されます。  
それぞれの用途を理解し、標準オブジェクト（商談や取引先）を例に活用事例を紹介します。

---

## **1. `Trigger.new` の活用例**（商談作成時にデフォルトのフォローアップタスクを作成）  

🔹 `Trigger.new` は **新しく作成されたレコードのリスト** です。  
🔹 `before insert` / `after insert` のタイミングで利用できます。  

**📌 事例: 商談が作成されたとき、自動でフォローアップタスクを作成する**  

```apex
trigger CreateFollowUpTask on Opportunity (after insert) {
    List<Task> tasksToInsert = new List<Task>();

    for (Opportunity opp : Trigger.new) {
        Task newTask = new Task(
            Subject = 'フォローアップ',
            WhatId = opp.Id,
            OwnerId = opp.OwnerId,
            ActivityDate = Date.today().addDays(30), // 30日後のタスク
            Status = 'Not Started',
            Priority = 'High'
        );
        tasksToInsert.add(newTask);
    }

    if (!tasksToInsert.isEmpty()) {
        insert tasksToInsert;
    }
}
```
✅ **ポイント**  
- `Trigger.new` を使い、新しく作成された商談のリストを取得  
- `after insert` トリガーなので、**レコードが保存された後** にタスクを作成  

---

## **2. `Trigger.newMap` の活用例**（取引先更新時に関連する商談の「取引先名」を更新）  

🔹 `Trigger.newMap` は **更新後のレコードを ID をキーにして取得できる `Map<Id, SObject>`** です。  
🔹 **大量データ処理（Bulk処理）** の場合、レコードを ID で参照できるため **効率が良い** です。  

**📌 事例: 取引先の「取引先名」が変更されたら、関連する商談の「取引先名」も更新する**  

```apex
trigger UpdateOpportunityAccountName on Account (after update) {
    List<Opportunity> oppsToUpdate = new List<Opportunity>();

    for (Account acc : Trigger.new) {
        Account oldAcc = Trigger.oldMap.get(acc.Id);
        if (acc.Name != oldAcc.Name) { // 取引先名が変わった場合
            for (Opportunity opp : [SELECT Id, Name FROM Opportunity WHERE AccountId = :acc.Id]) {
                opp.Name = acc.Name + ' 商談';
                oppsToUpdate.add(opp);
            }
        }
    }

    if (!oppsToUpdate.isEmpty()) {
        update oppsToUpdate;
    }
}
```

✅ **ポイント**  
- `Trigger.oldMap.get(acc.Id)` を使い、更新前のデータと比較  
- 取引先名 (`Name`) が変更されたら、関連する商談の `Name` も変更  
- `after update` で実行し、関連レコードの更新を許可  

---

## **3. `Trigger.old` の活用例**（商談のステージが「成立（Closed Won）」から変更されたら警告）  

🔹 `Trigger.old` は **更新前のレコードのリスト** を取得できます。  
🔹 `before update` などで活用し、**データ変更の制限** に使えます。  

**📌 事例: 「成立」済みの商談のステージが変更されそうになったらエラーを出す**  

```apex
trigger PreventStageChange on Opportunity (before update) {
    for (Integer i = 0; i < Trigger.new.size(); i++) {
        Opportunity newOpp = Trigger.new[i];
        Opportunity oldOpp = Trigger.old[i];

        if (oldOpp.StageName == 'Closed Won' && newOpp.StageName != 'Closed Won') {
            newOpp.addError('成立した商談のステージを変更できません。');
        }
    }
}
```

✅ **ポイント**  
- `Trigger.old` を使い、更新前のデータを取得  
- **`Closed Won` だった商談のステージを変更させない** ように制御  
- `before update` の `addError` を使うことで **画面上でエラーメッセージを表示** 可能  

---

## **4. `Trigger.oldMap` の活用例**（取引先削除時に関連する商談をクローズする）  

🔹 `Trigger.oldMap` は **削除されるレコードの ID をキーとした `Map<Id, SObject>`** です。  
🔹 **大量データ処理でも高速に関連レコードを検索** できます。  

**📌 事例: 取引先が削除されたら、関連する商談のステージを「Closed Lost」にする**  

```apex
trigger CloseOpportunitiesOnAccountDelete on Account (before delete) {
    List<Opportunity> oppsToUpdate = new List<Opportunity>();

    for (Account acc : Trigger.oldMap.values()) {
        for (Opportunity opp : [SELECT Id, StageName FROM Opportunity WHERE AccountId = :acc.Id]) {
            opp.StageName = 'Closed Lost';
            oppsToUpdate.add(opp);
        }
    }

    if (!oppsToUpdate.isEmpty()) {
        update oppsToUpdate;
    }
}
```

✅ **ポイント**  
- `Trigger.oldMap.values()` を使い、削除対象の `Account` のリストを取得  
- 関連する商談 (`Opportunity`) を検索し、ステージを `"Closed Lost"` に変更  
- `before delete` で実行し、取引先削除前に商談データを更新  

---

## **まとめ**

| **変数** | **用途** | **活用例** |
|----------|--------|------------|
| `Trigger.new` | **新しく作成された or 更新後のレコードのリスト** | 商談作成時にタスクを追加 (`after insert`) |
| `Trigger.newMap` | **新しく作成・更新後のレコードを ID で取得できる Map** | 取引先名変更時に商談の取引先名も更新 (`after update`) |
| `Trigger.old` | **更新前 or 削除前のレコードのリスト** | 商談の成立済みステージ変更を制限 (`before update`) |
| `Trigger.oldMap` | **更新前 or 削除前のレコードを ID で取得できる Map** | 取引先削除時に関連商談をクローズ (`before delete`) |

### **使い分けポイント**
✅ **`Trigger.new` / `Trigger.newMap`** → **新規作成・更新後のデータ処理**  
✅ **`Trigger.old` / `Trigger.oldMap`** → **更新前・削除前のデータチェックや制約**  
✅ **大量データを扱う場合** は `Map` を使うと **効率的に ID 参照できる**  

---

SalesforceのApexトリガーでは、これらの変数を使い分けることで、データの整合性を保ちつつ柔軟なビジネスロジックを実装できます！