Net Zero Cloud 連携アプリケーションを2GPで開発する

本記事では、Net Zero Cloudに対応した開発環境を取得し、Net Zero Cloud連携アプリケーションを第二世代管理パッケージ（通称2GP）で作成してリリースするまでの一連の流れをご紹介します。


## 前提
以下Trailheadをご参照ください。
 - [Net Zero Cloud](https://trailhead.salesforce.com/ja/users/atait0/trailmixes/net-zero-cloud)
 - [Salesforce DX を使用したアプリケーション開発](https://trailhead.salesforce.com/ja/content/learn/modules/sfdx_app_dev)
 - [第二世代管理パケージ](https://trailhead.salesforce.com/ja/content/learn/modules/second-generation-managed-packages)

## リリースまでの一連の流れ
### 1. Net Zero Cloud 開発環境の取得
2GPで開発するので、作業は全てローカル & スクラッチ組織上で行います。

#### 1-1. DevHub
開発に必要なDevHub組織を認証します。
##### - DevHubを準備
参考：[Trailhead - Quick Start Lightning Web Component](https://trailhead.salesforce.com/content/learn/projects/quick-start-lightning-web-components/)
##### - DevHub組織を認証
```
sfdx force:auth:web:login -d -a [YOUR DEV HUB ORG ALIAS]
```

#### 1-2. SFDXプロジェクト
Net Zero Cloudが有効化されたスクラッチ組織を作成します。
##### - SFDXプロジェクトを作成
```
sfdx force project create -n devCustomAppWithNzc
```
> プロジェクト名：devCustomAppWithNzcの場合
##### - 作成したプロジェクトディレクトリに移動
```
cd devCustomAppWithNzc
```
##### - スクラッチ組織の定義ファイルを編集

```json:project-scratch-def.json
{
  "orgName": "My Dev company",
  "edition": "Developer",
  "features": ["EnableSetPasswordInApi","SustainabilityApp", "TCRMForSustainability","RecordTypes","DevelopmentWave"],
  "settings": {
    "lightningExperienceSettings": {
      "enableS1DesktopEnabled": true
    },
    "mobileSettings": {
      "enableS1EncryptedStoragePref2": false
    },
    "industriesSettings": {
      "enableSCCarbonAccounting":true,
      "enableSustainabilityCloud":true
    }
  }
}
```
> "features"で、"SustainabilityApp"、"TCRMForSustainability"を指定することで、Net Zero Cloud用の権限セットを割り当てることができるようになります

##### - スクラッチ組織を作成
```
sfdx force:org:create -s -f config/project-scratch-def.json -a devNzcScratch
```
> 前手順で作成した定義ファイルを指定することで、Net Zero Cloudが有効化されたスクラッチ組織を取得します


##### - スクラッチ組織の確認
```
sfdx force:org:open -u devNzcScratch
```  
上記コマンドにてスクラッチ組織を開き、

設定 -> 機能設定 -> Net Zero 設定
 - Net Zero Cloud: オン
 - カーボンアカウンティングを管理: オン

になっていることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3112543/e4cbcf60-a454-c098-036b-07a1056e2259.png)




### 2. 開発・テスト
手順1で作成したスクラッチ組織にて、Net Zero Cloud連携機能を作成します。Net Zero CloudオブジェクトへアクセスするApexクラスの一例として、[Githubリポジトリ Fuel Gas Eater](https://github.com/SalesforceLabs/Fuel-Gas-Eater) より一部抜粋でご紹介します。

#### 2-1. Apexクラス

##### 例）Apexクラス FuelGasEaterUtils.cls

https://github.com/SalesforceLabs/Fuel-Gas-Eater/blob/main/force-app/main/default/classes/FuelGasEaterUtils.cls

```apex
List<AirTravelEmssnFctr> aefs = Security.stripInaccessible(
    AccessType.READABLE, 
    [SELECT DistanceUnit, ShortHaulMaximumDistance, MediumHaulMaximumDistance, Co2PsgrKmLongHaulInKg, Co2PsgrKmMediumHaulInKg, Co2PsgrKmShortHaulInKg, Co2PsgrMileLongHaulInKg, Co2PsgrMileMediumHaulInKg, Co2PsgrMileShortHaulInKg FROM AirTravelEmssnFctr WHERE Id=:aefId LIMIT 1]
).getRecords();  
```

> 以下 Net Zero Cloud オブジェクトレコードを取得します
> - [AirTravelEmssnFctr](https://developer.salesforce.com/docs/atlas.en-us.netzero_cloud_dev_guide.meta/netzero_cloud_dev_guide/sforce_api_objects_airtravelemssnfctr.htm)

```apex
List<GroundTravelEmssnFctr> gefs = Security.stripInaccessible(
    AccessType.READABLE,
    [SELECT DistanceUnit, TaxiEmssnInKgCo2eDstnUnit, PersCarEmssnInKgCo2eDstnUnit, TrainEmssnInKgCo2eDstnUnit FROM GroundTravelEmssnFctr WHERE Id=:gefId LIMIT 1]
).getRecords();
```

> 以下 Net Zero Cloud オブジェクトレコードを取得します
> - [GroundTravelEmssnFctr](https://developer.salesforce.com/docs/atlas.en-us.netzero_cloud_dev_guide.meta/netzero_cloud_dev_guide/sforce_api_objects_groundtravelemssnfctr.htm)


#### 2-2. Apexテストクラス

##### 例）Apexテストクラス FuelGasEaterUtilsTest.cls

https://github.com/SalesforceLabs/Fuel-Gas-Eater/blob/main/force-app/main/default/classes/FuelGasEaterUtilsTest.cls

```apex
AirTravelEmssnFctr atef1 = new AirTravelEmssnFctr(
    Name = 'Air Plane #1',
    DistanceUnit = 'Miles',
    Co2PsgrKmShortHaulInKg = 2000
);
insert atef1;

//

Decimal em = 0;
Decimal distance = 0;
Decimal expected = 0;

//

distance = 1;
em = FuelGasEaterUtils.getEmission(atef1.Id, null, distance);
expected = distance * 2000;
System.assertEquals(expected, em);
```


### 3. パッケージング
作成した成果物を管理パッケージとしてパッケージングしリリースします。

#### 3-1. SFDXプロジェクト設定

##### - sfdx-project.json ファイル
:::note warn
別途、名前空間の取得・設定は必要になります
:::

Apexテスト実行時にNet Zero Cloud関連オブジェクトにアクセスできるよう、テスト実行ユーザに権限セットを指定します。

> - apexTestAccess
>     - permissionSets: "NetZeroManager"
>     - permissionSetLicenses: "NetZeroCloudUserPsl"

```json:sfdx-project.json
{
  "packageDirectories": [
    {
      "〜〜〜": "〜〜〜", 
      "〜〜〜": "〜〜〜", 
      "〜〜〜": "〜〜〜", 
      "apexTestAccess": {
        "permissionSets": [
          "NetZeroManager"
        ],
        "permissionSetLicenses": [
          "NetZeroCloudUserPsl"
        ]
      }
    }
  ],
  "〜〜〜": "〜〜〜", 
  "〜〜〜": "〜〜〜", 
  "〜〜〜": "〜〜〜"
}
```

#### 3-2. 管理パッケージの作成

管理パッケージ作成以降は、通常のパッケージング作業と特に変わりはないです。


##### - パッケージの作成 
```
sfdx force:package:create --name [パッケージ名] --path force-app --packagetype Managed
```
> パッケージ作成が成功すると、パッケージIDが表示されます


##### - パッケージバージョンの作成 

```
sfdx force:package:version:create --package [パッケージID] --definitionfile config/project-scratch-def.json --codecoverage --installationkeybypass --wait 10
```
> パッケージバージョン作成が成功すると、パッケージバージョンIDが表示されます


##### - パッケージバージョンのリリース
```
sfdx force:package:version:promote -p [パッケージバージョンID]
```
> テスト組織にてベータ版をしっかりテストしてからリリースするのがおすすめです


以上で、Net Zero Cloud連携アプリケーションの第二世代管理パッケージが出来上がります。
ざっと一連の流れを見ると、Net Zero Cloud連携するためには、特別な設定・作業等は意外に少なく、
ポイントさえ抑えてしまえば、通常のSFDX開発と大して変わらないですね。

今後、環境に配慮した社会を実現するために、
ますますカーボンアカウンティング業務が大事になってきます。
是非お試しください。


## リファレンス
Net Zero Cloud連携アプリケーションのサンプルです。

##### AppExchangeリスティング（無償にて公開中）

https://appexchange.salesforce.com/appxListingDetail?listingId=8adc53d0-d5b9-40e0-9683-66b594961fc5

##### ソースコード
https://github.com/SalesforceLabs/Fuel-Gas-Eater