---
sidebar_position: 13
title: "完全技術ガイド"
---

# カスタマーポータル — 技術運用ガイド

カスタマーポータルがWHMCS、Salesforce、その他のシステムとどのように連携するかを説明する包括的なガイドです。

---

## システムアーキテクチャ

ポータルは2つのメインコンポーネントで構成されています：

- **フロントエンド**：顧客UIを提供するNext.jsアプリケーション
- **BFF（Backend-for-Frontend）**：外部システムへの呼び出しを調整するNestJS API

### 接続システム

| システム | 役割 | 連携方法 |
| --- | --- | --- |
| **WHMCS** | 請求の管理システム | REST API |
| **Salesforce** | CRMと注文管理 | REST API + Change Data Capture (CDC) |
| **Freebit** | SIM/MVNOプロビジョニング | REST API |
| **SFTP (fs.mvno.net)** | 通話/SMS明細レコード | SFTPファイルダウンロード |
| **PostgreSQL** | ポータルユーザーアカウントとIDマッピング | 直接接続 |
| **Redis** | キャッシュとリアルタイムイベント用pub/sub | 直接接続 |

### IDマッピング

ポータルはPostgreSQLの`id_mappings`テーブルで以下のマッピングを管理：

- `user_id`（ポータルUUID）↔ `whmcs_client_id`（整数）↔ `sf_account_id`（Salesforce 18文字ID）

---

## データ所有権とフロー

| データ | 管理システム | ポータルの動作 |
| --- | --- | --- |
| ユーザー認証情報 | Portal (PostgreSQL) | Argon2でハッシュ化、WHMCS/SF認証情報の保存なし |
| クライアントプロフィール & 住所 | WHMCS | ポータルがWHMCSに読み書き、更新時にキャッシュクリア |
| 商品カタログ & 価格 | Salesforce (Pricebook) | ポータル価格表から読み取り |
| 注文 & 注文ステータス | Salesforce (Order) | ポータルが注文作成、Salesforce CDCがフルフィルメントをトリガー |
| 請求書 & 支払い方法 | WHMCS | ポータルは読み取りのみ、WHMCS SSO経由で支払い |
| サブスクリプション/サービス | WHMCS (tblhosting) | ポータルは読み取りのみ |
| サポートケース | Salesforce (Case) | ポータルがOrigin = "Portal Website"でケース作成/読み取り |
| SIM詳細 & 使用量 | Freebit | ポータルがFreebit API経由で読み書き |

---

## アカウント作成とリンク

### 新規顧客サインアップ

**検証ステップ：**

1. ポータル`users`テーブルにメールが存在するか確認
2. Customer Number（`SF_Account_No__c`）でSalesforce Accountを検索
3. `WH_Account__c`フィールドが既に設定されているか確認
4. WHMCS `GetClientsDetails`でメールが存在するか確認

**作成ステップ（検証通過時）：**

1. WHMCS `AddClient` APIアクションでWHMCSクライアントを作成
2. PostgreSQLにポータルユーザーレコードを作成（Argon2ハッシュ）
3. 同一トランザクションでIDマッピングを作成
4. Salesforce Accountをポータルフィールドで更新

---

## プロフィールと住所管理

- すべてのプロフィール/住所データはWHMCS `GetClientsDetails` API経由で読み取り
- プロフィール更新はWHMCS `UpdateClient` API経由で書き込み
- キャッシュは更新成功後に即座に無効化
- Salesforceは注文作成時のみ住所スナップショットを受信

---

## パスワード管理

- ポータルパスワードはPostgreSQLにArgon2ハッシュで保存
- WHMCS認証情報とは完全に別管理
- パスワードリセットは時間制限付きトークンを使用
- リセット後、既存セッションはすべて無効化
- レート制限：IPあたり15分で5回まで

---

## 商品カタログと利用資格

- 商品は`PORTAL_PRICEBOOK_ID`で設定されたSalesforce Pricebookから取得
- ポータル表示対象の商品のみ表示
- カテゴリ：Internet、SIM/Mobile、VPN
- カタログはTTLなしでRedisにキャッシュ、Salesforce CDC `PricebookEntry`変更時に無効化

### SIMファミリープラン

- WHMCSにアクティブなSIMサブスクリプションが存在する場合、ファミリー/割引SIMプランを表示
- アクティブなSIMがない場合、ファミリープランは非表示

---

## 注文作成

### 事前チェックアウト検証

1. 有効なIDマッピングの存在確認
2. WHMCSに少なくとも1つの支払い方法の存在確認
3. インターネット注文：WHMCSにアクティブなインターネットサービスがないこと

---

## 注文フルフィルメントとプロビジョニング

### トリガー

- Salesforce CDCが注文ステータス変更を検出
- べき等キーによる重複処理防止

### ステップ

1. Salesforce `Activation_Status__c` = "Activating" に更新
2. OrderItemsをWHMCS商品にマッピング
3. WHMCS `AddOrder` APIアクション呼び出し
4. SIM注文：Freebit APIアクティベーション
5. SalesforceをWHMCS Order ID等で更新
6. リアルタイムイベントを公開

---

## 請求と支払い

- 請求書はWHMCS `GetInvoices`/`GetInvoice` API経由で取得
- 一覧は90秒、個別は5分キャッシュ
- 支払い方法はWHMCS `GetPayMethods` API経由で取得、15分キャッシュ
- WHMCS SSO経由で請求書支払い用リンクを生成

---

## SIM管理

SIM商品として識別されたサブスクリプションに対し、Freebit API経由で追加管理が可能。

### 利用可能な操作

| 操作 | Freebit API | タイミング |
| --- | --- | --- |
| データチャージ | `addSpec` / `eachQuota` | 即時またはスケジュール |
| プラン変更 | `changePlan` | 翌月1日 |
| 音声機能更新 | `talkoption/changeOrder` | 即時 |
| ネットワークタイプ更新 | `contractline/change` | 即時 |
| SIMプラン解約 | `releasePlan` | スケジュール |
| eSIM再発行 | `reissueEsim` | スケジュール |

### 操作タイミング制約

重要ルール：以下の操作間には**30分の最小間隔**が必要：
- 音声機能変更
- ネットワークタイプ変更
- プラン変更

---

## サポートケース

| フィールド | API名 | 値 |
| --- | --- | --- |
| AccountId | `AccountId` | マッピングから |
| Origin | `Origin` | "Portal Website" |
| Subject | `Subject` | 顧客入力（必須） |
| Description | `Description` | 顧客入力（必須） |
| Status | `Status` | "New" |

ケースは顧客のリンク済みAccountに厳密にフィルタリングされます。

---

## ダッシュボードとサマリーデータ

| メトリック | ソース | クエリ |
| --- | --- | --- |
| 最近の注文 | Salesforce | アカウントの過去30日の注文 |
| 未払い請求書 | WHMCS | Unpaid/Overdue請求書 |
| 有効サービス | WHMCS | Active状態のサブスクリプション |
| 未解決ケース | Salesforce | Status ≠ Closedのケース |

---

## リアルタイムイベント

### SSEエンドポイント

- 単一エンドポイント：`GET /api/events`
- Server-Sent Events (SSE) 接続
- 認証が必要
- マルチインスタンス配信用にRedis pub/subをバックエンドに使用
