BBS連携
概要
| 項目 | 内容 |
|---|---|
| ステータス | 🔵 提案中 |
| 開始日 | 2026/06/23 |
| 担当 | - |
提案内容
背景・課題
BBS(pub-api.optimize-business.com)が提供するAPIを使い、GMAC MEO管理画面からアカウント・ロケーションの管理とサイテーション状況の確認ができるようにする。
対象画面と画面遷移フロー
[1] BBSアカウント管理
├─ アカウント一覧(検索・ページング)
├─ アカウント新規作成
├─ [アカウント名クリック] → アカウント詳細・更新
└─ ["Location"クリック] → [2] ロケーション一覧
[2] ロケーション一覧(選択済みアカウント)
├─ [ロケーション名クリック] → ロケーション詳細・更新
│ └─ BBSロケーション ↔ Mappyロケーション マッピング設定
└─ ["Citation"クリック] → [3] サイテーション一覧
[3] サイテーション一覧(選択済みロケーション)
└─ 各プラットフォーム / AIリスティング / ボイスアシスタントの掲載状況| 画面名 | 概要 |
|---|---|
| BBSアカウント管理 | BBS上のアカウント一覧・検索・新規作成・編集 |
| ロケーション一覧 | 選択したアカウントのロケーション一覧(料金・連携状態・代理店など) |
| ロケーション詳細・編集 | ロケーション新規作成・編集フォーム(35項目)+Mappyロケーションとのマッピング設定 |
| サイテーション一覧 | ロケーション別のサイテーションページ掲載状況確認 |
技術設計
データ保存方針
BBSのデータはMappyに保存せず — 必要なときにAPIを呼び出すオンデマンド方式。
BBS側がアカウント・ロケーション・サイテーションのソースオブトゥルースである。Mappyに保存すると、BBS更新時の同期問題が発生し複雑度が増す。この画面は社内運用ツールであるため、APIの数百ms程度の遅延は許容範囲。
また、API仕様書にアクセストークンの有効期限は無期限と明記されており、トークンリフレッシュ機構は不要。
| データ | 保存先 | 理由 |
|---|---|---|
| BBSアカウント一覧・詳細 | APIオンデマンド呼び出し | BBSがソース |
| BBSロケーション一覧・詳細 | APIオンデマンド呼び出し | BBSがソース |
| サイテーション状況 | APIオンデマンド呼び出し | BBSがソース |
| BBSロケーション ↔ Mappyロケーション マッピング | Mappy DBに保存 | Mappy固有の情報、BBSは管理しない |
Mappy側のDB変更
新規テーブル mappy_bbs_accounts — BBSアカウントごとのログイン情報とトークンを保存:
| カラム | 型 | 備考 |
|---|---|---|
id | BIGINT UNSIGNED PK | |
bbs_account_id | BIGINT UNSIGNED | BBS側のアカウントID |
email | VARCHAR(255) | BBSログイン用メールアドレス |
password | VARCHAR(255) | 暗号化済みパスワード(encrypted) |
token | TEXT | アカウント作成後にBBSから取得したトークン |
created_at / updated_at / deleted_at | TIMESTAMP NULL |
- UNIQUE
(bbs_account_id) - APIキーは全アカウント共通 → ENV(
BBS_API_KEY)に保存、DBには保存しない passwordは復号可能な暗号化(LaravelのAES-256-CBCencrypt()/decrypt())で保存。アカウント作成後にBBSでパスワードを確認できないため- アカウント詳細画面ではパスワードを
••••••••で表示し、「表示」ボタンで確認可能 - アカウント新規作成時:
POST /v1/create-accounts→POST /v1/loginでトークン取得 →tokenカラムに保存
新規テーブル mappy_bbs_location_mappings — MappyロケーションとBBSロケーションのマッピング、既存システムとは完全に独立:
| カラム | 型 | 備考 |
|---|---|---|
id | BIGINT UNSIGNED PK | |
gbp_location_id | BIGINT UNSIGNED | Mappy側のロケーションID |
bbs_location_id | BIGINT UNSIGNED | BBS側のロケーションID |
memo | VARCHAR(255) NULL | 運用メモ |
created_at / updated_at | TIMESTAMP NULL |
- UNIQUE
(gbp_location_id)— Mappyロケーション1件につきBBSロケーション1件のみマッピング可 - BBS側への外部キー制約なし(BBSは外部システムのため)
gbp_locationsテーブルは変更しない
認証(Authentication)
| 操作種別 | 使用トークン | 保存先 |
|---|---|---|
| アカウント・ロケーション管理(ROOT) | ROOTトークン | ENV(BBS_ROOT_TOKEN) |
| アカウント別API呼び出し | ユーザートークン | mappy_bbs_accounts.token |
- APIキーはシステム共通 → ENV(
BBS_API_KEY) - ROOTトークンは
POST /v1/inside/loginで一度取得 → ENV保存、有効期限なし - ユーザートークンはアカウント新規作成時に
POST /v1/loginで自動取得 →mappy_bbs_accountsテーブルに保存
画面別API呼び出し
[1] BBSアカウント管理
| 操作 | API | トークン |
|---|---|---|
| 一覧読み込み | GET /v1/pub-accounts | ROOT |
| アカウント詳細表示 | GET /v1/pub-accounts/{account_id} | ROOT |
| アカウント新規作成 | POST /v1/create-accounts → POST /v1/login(トークン取得・保存) | ROOT |
| アカウント更新 | PUT /v1/update-accounts/{account_id} | ROOT |
アカウント新規作成時:
POST /v1/create-accounts成功後、POST /v1/loginを呼び出してトークンをmappy_bbs_accountsに保存する。
[2] ロケーション一覧
| 操作 | API | トークン |
|---|---|---|
| アカウント別ロケーション一覧読み込み | GET /v1/pub-locations(account_idでフィルター) | ROOT |
| ロケーション詳細表示 | GET /v1/pub-locations/{location_id} | ROOT |
| ロケーション新規作成 | POST /v1/create-locations | ROOT |
| ロケーション更新 | PUT /v1/update-locations/{location_id} | ROOT |
| BBS ↔ Mappyマッピング保存 | INSERT/UPDATE mappy_bbs_location_mappings | —(Mappy DB、BBS API呼び出しなし) |
[3] サイテーション一覧
| 操作 | API | トークン |
|---|---|---|
| ロケーション別サイテーション状況読み込み | GET /v1/pub_citation_pages/by-location/{location_id} | ユーザートークン(mappy_bbs_accounts.token) |
サイテーションはそのロケーションを所有するアカウントのユーザートークンを使用。ROOTトークンは使わない。
API対応表
エンドポイントベース: https://pub-api.optimize-business.com 認証: ROOT操作は POST /v1/inside/login で取得したトークン、ユーザー操作は POST /v1/login で取得したトークンを使用。
BBSアカウント管理
| 操作 | メソッド | URI | 認証 |
|---|---|---|---|
| アカウント一覧取得 | GET | /v1/pub-accounts | ROOT token |
| アカウント情報取得 | GET | /v1/pub-accounts/{account_id} | ROOT token |
| アカウント作成 | POST | /v1/create-accounts | ROOT token |
| アカウント更新 | PUT | /v1/update-accounts/{account_id} | ROOT token |
主なリクエストパラメータ(作成・更新): name, email, password, address_line_1〜3, telephone, account_representative, is_additional_line_notification_allowed, memo
ロケーション一覧・詳細・編集
| 操作 | メソッド | URI | 認証 |
|---|---|---|---|
| ロケーション一覧取得 | GET | /v1/pub-locations | ROOT token |
| ロケーション情報取得 | GET | /v1/pub-locations/{location_id} | ROOT token |
| ロケーション作成 | POST | /v1/create-locations | ROOT token |
| ロケーション更新 | PUT | /v1/update-locations/{location_id} | ROOT token |
主なリクエストパラメータ(作成・更新):
| パラメータ | 型 | 備考 |
|---|---|---|
name | String | ロケーション名 |
address_line_1〜3 | String | 郵便番号・都道府県・詳細住所 |
telephone | int | ハイフン区切り10〜13文字 |
location_person | String | ロケーション担当者 |
place_id | String | Google Place ID |
status | int | 1:契約 / 2:解約予定 / 3:解約 / 4:準備中 / 5:一時停止 |
service_id | int | 1:インスタ連携 / 2:Google管理 / 3:インスタ×Google / 4:CMS専用 / 5:IG運用 / 6:IM運用 / 7:リクルート / 8:Synup |
contract_start | timestamp | YYYY-MM-DD HH:MM:SS |
contract_update_interval | int | 契約期間(ヶ月)。status=1,2の場合必須 |
contract_end | timestamp | 省略時は当月末日 |
initial_cost / monthly_cost | int | 初期・月額費用 |
initial_transfer_amount / monthly_transfer_amount | int | 仕切り(初期・月額) |
initial_back_amount / monthly_back_amount | int | バック(初期・月額) |
agency_id | int | 代理店(初期値:1=なし) |
payment_method | int | 0:未設定 / 1:カード / 2:口座振替 / 3:請求書 / 4:請求書代行 |
billing_destination | String | 請求先 |
is_initial_configuration | int | サイテーション: 0:なし / 1:あり / 2:ハイプラン |
is_splan / is_owlet / is_onerank / is_win / is_hitosara | int | CMSオプション(0:なし / 1:あり) |
is_synup | int | 0:なし / 1:あり / 2:あり(飲食業/宿泊業) |
synup_serial_number | String | Synupシリアル番号 |
is_pc_block | int | 口コミクッションページPCブロック(0:なし / 1:あり) |
target_keywords | JSON | ターゲットキーワード(最大10個) |
memo | String | メモ |
サイテーション一覧
| 操作 | メソッド | URI | 認証 |
|---|---|---|---|
| サイテーションページ情報取得 | GET | /v1/pub_citation_pages/by-location/{location_id} | token |
レスポンスにはAIリスティング・ボイスアシスタント・プラットフォームごとの掲載状況(同期済み/準備中/要連携)とインデックス有無・リンクURLが含まれる。
画面モック
BBSアカウント管理
BBSアカウント管理
| ID | アカウント名 | adminユーザー | 住所 | 電話番号 | インスタ連携 | GBP管理 | インスタ × GBP | 合計契約数 | 月額料金合計 | メモ | 操作 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 51420 | tanaka@gmail.com | 東京都港区赤坂3丁目21−15 | 03-4500-7451 | 3 | 5 | 2 | 10 | ¥48,000 | |||
| 51383 | h.sato@company.co.jp | 東京都新宿区西新宿2-8-1 | 080-2345-6789 | 1 | 2 | 1 | 4 | ¥16,000 | |||
| 51441 | suzuki@gmail.com | 東京都豊島区東池袋1-1-1 | 090-3456-7890 | 5 | 8 | 4 | 17 | ¥85,000 | |||
| 51298 | misaki.t@outlook.com | 神奈川県横浜市西区みなとみらい2-2 | 045-567-8901 | 0 | 1 | 0 | 1 | ¥4,800 | 退会検討中 | ||
| 51247 | kenta.n@company.jp | 東京都品川区大崎1-2-2 | 03-2345-6789 | 2 | 3 | 2 | 7 | ¥34,000 | |||
| 51203 | akane.k@mappy-admin.jp | 東京都千代田区秋葉原1-1 | 03-3456-7890 | 8 | 12 | 6 | 26 | ¥130,000 | VIP顧客 | ||
| 51187 | yuji.ito@ymail.co.jp | 東京都台東区上野4-1-1 | 070-4567-8901 | 2 | 4 | 1 | 7 | ¥33,600 | |||
| 51152 | sachiko.y@hotmail.com | 東京都武蔵野市吉祥寺本町1-1 | 0422-12-3456 | 1 | 1 | 0 | 2 | ¥9,600 | 長期未ログイン |
アカウント詳細・編集
ロケーション一覧(アカウント別)
ロケーション一覧
| 基本情報 | 料金 | 代理店・支払い | FB連携 | GBP連携 | LINE公式連携 | IG API連携 | — | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ID | ロケーション | 住所 | 契約期間 | 電話番号 | ステータス | 契約サービス | 初期費用 | 月額費用 | 仕切り (初期) | 仕切り (月額) | バック (初期) | バック (月額) | サイテーション | 自動更新 システム | 自動更新 (月額) | 代理店 | 支払い方法 | 請求先 | ステータス | インスタID | ステータス | 接続メール | ステータス | アクセストークン | ステータス | ロギングID | メモ |
| 33944 | 株式会社H2Technology | 107-0052, 東京都港区赤坂3丁目21−15 東都赤坂ビル 2階A号室 | 2026/04/01 〜 2027/03/31 | 03-4500-7451 | 契約 | インスタ連携 × GBP管理 | なし | なし | なし | 未選択 | なし | なし | なし | なし | なし | H2 | — | — | 連携済み | h2technologytest | 連携済み | h2tec12131234@gmail.com | 連携済み | h2technologytest | H2 | — | |
| 33945 | 渋谷サンプル店 | 150-0041, 東京都渋谷区神南1丁目2−3 | 2026/01/01 〜 2026/12/31 | 03-1234-0001 | 契約 | GBP管理 | ¥50,000 | ¥9,800 | ¥30,000 | ¥5,000 | なし | なし | あり | あり | ¥2,000 | Agency A | クレジット | 本社 | 未連携 | — | 連携済み | shibuya@sample.jp | 未連携 | — | 未連携 | — | テスト中 |
| 33946 | 新宿テスト法人 | 160-0023, 東京都新宿区西新宿2丁目8−1 | 2025/07/01 〜 2026/06/30 | 03-5678-9012 | 解約 | インスタ連携 | ¥30,000 | ¥4,800 | 未選択 | 未選択 | なし | なし | なし | なし | なし | — | 銀行振込 | 担当者 | 連携済み | shinjuku_test | 未連携 | — | 未連携 | — | 未連携 | — | 解約済み |
ロケーション詳細・編集
サイテーション一覧
サイテーション一覧
AIリスティング
| AI |
|---|
⬡openai.com |
✦gemini.google.com |
◈perplexity.ai |
⬡copilot.microsoft.com |
◈intellychat.com |
◈myndmeld.com |
ボイスアシスタントリスティング
| アシスタント | 連携ステータス |
|---|---|
CCortana | ⏳ 進行中 |
AAlexa | ⏳ 進行中 |
SSiri | ⏳ 進行中 |
プラットフォームリスティング
| プラットフォーム | 連携ステータス | インデックス | リンク |
|---|---|---|---|
HHotfrog | ✔ 同期済み | 🌐 Yes | 🔗 アクティブ |
BBeLocalFocussed | ✔ 同期済み | 🌐 Yes | 🔗 アクティブ |
Aarrivebusiness | ✔ 同期済み | 🌐 Yes | 🔗 アクティブ |
GGoLocalPages | ✔ 同期済み | 🌐 Yes | 🔗 アクティブ |
BBrownBook | ✔ 同期済み | 🌐 Yes | 🔗 アクティブ |
iiGlobal | ✔ 同期済み | 🌐 Yes | 🔗 アクティブ |
OOpenDi.us | ✔ 同期済み | 🌐 Yes | 🔗 アクティブ |
PPassPages | ✔ 同期済み | 🌐 Yes | 🔗 アクティブ |
SSpeedy Local | ✔ 同期済み | 🌐 Yes | 🔗 アクティブ |
LLocalizedListings | ✔ 同期済み | 🌐 Yes | 🔗 アクティブ |
NNAVITIME | ✔ 同期済み | — | |
MMapion | ✔ 同期済み | — | |
TTabelog | ✔ 同期済み | — | |
PPayPay | ✔ 同期済み | — | |
AAmazon | ✔ 同期済み | — | |
YYouTube | ✔ 同期済み | — | |
RRakuten Market | ✔ 同期済み | — | |
DDiDi | ✔ 同期済み | — | |
WWaze | ✔ 同期済み | — | |
UUber | ✔ 同期済み | — | |
LLife360 | ✔ 同期済み | — | |
MMapFan | ✔ 同期済み | — | |
LLUUP | ✔ 同期済み | — | |
◉Pokemon GO | ✔ 同期済み | — | |
TToyota | ✔ 同期済み | — | |
HHonda | ✔ 同期済み | — | |
BBMW | ✔ 同期済み | — | |
MMercedes Benz | ✔ 同期済み | — | |
BBaidu | ✔ 同期済み | — | |
TTomTom | プラットフォーム側準備中 | 🌐 No | |
HHere | プラットフォーム側準備中 | 🌐 No | |
BBing | プラットフォーム側準備中 | 🌐 No | |
MMG | プラットフォーム側準備中 | 🌐 No | |
◆Apple Maps | プラットフォーム側準備中 | 🌐 No | 🔗 アクティブ |
◉TripAdvisor | アカウント連携が必要 | 🌐 No |
概算工数(AI前提)
体制
| 役割 | 人数 | 担当内容 |
|---|---|---|
| 設計者 | 1名 | 要件確認 → AIに設計書作成指示 → レビュー → 製造へ指示 |
| 製造者 | 1名 | ISSUEを元にAIに作成指示 → コードレビュー → テスト実施 → デプロイ |
工数内訳
| # | 作業項目 | AIリテイク | レビュー | 工数(人日) | 担当 |
|---|---|---|---|---|---|
| 1 | 要件確認・設計書作成 | — | — | 1.0 | 設計者 |
| 2 | ROOT認証・APIクライアント基盤 | 2回 | 0.5日/回 | 1.0 | 製造者 |
| 3 | BBSアカウント管理(一覧・検索・ページング) | 4回 | 0.5日/回 | 2.0 | 製造者 |
| 4 | アカウント詳細・編集フォーム | 3回 | 0.5日/回 | 1.5 | 製造者 |
| 5 | ロケーション一覧(グループヘッダー付きテーブル) | 4回 | 0.5日/回 | 2.0 | 製造者 |
| 6 | ロケーション作成・編集フォーム(35項目・バリデーション) | 5回 | 0.5日/回 | 2.5 | 製造者 |
| 7 | サイテーション一覧(3セクション表示) | 2回 | 0.5日/回 | 1.0 | 製造者 |
| 8 | 結合テスト・デプロイ | 3回 | 0.5日/回 | 1.5 | 製造者 |
| 9 | 設計レビュー・製造指示 | — | — | 1.0 | 設計者 |
| 合計 | 13.5 | 設計者2.0日 / 製造者11.5日 |
スケジュール
| タスク | 担当 | 日数 | 6/23 | 6/24 | 6/25 | 6/26 | 6/27 | 6/28 | 6/29 | 6/30 | 7/1 | 7/2 | 7/3 | 7/4 | 7/5 | 7/6 | 7/7 | 7/8 | 7/9 | 7/10 | 7/11 | 7/12 | 7/13 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 火 | 水 | 木 | 金 | 土 | 日 | 月 | 火 | 水 | 木 | 金 | 土 | 日 | 月 | 火 | 水 | 木 | 金 | 土 | 日 | 月 | |||
| 要件確認・設計書作成 | 設計者 | 1d | |||||||||||||||||||||
| ROOT認証・APIクライアント基盤 | 製造者 | 1d | |||||||||||||||||||||
| 設計レビュー・製造指示 | 設計者 | 1d | |||||||||||||||||||||
| BBSアカウント管理(一覧・検索) | 製造者 | 2d | |||||||||||||||||||||
| アカウント詳細・編集フォーム | 製造者 | 2d | |||||||||||||||||||||
| ロケーション一覧 | 製造者 | 2d | |||||||||||||||||||||
| ロケーション作成・編集フォーム | 製造者 | 3d | |||||||||||||||||||||
| サイテーション一覧 | 製造者 | 1d | |||||||||||||||||||||
| 結合テスト・デプロイ | 製造者 | 2d |
PART 2 — 実装タスク詳細
開発チーム向けのセクション。
技術概要
| 項目 | 内容 |
|---|---|
| リポジトリ | mappy-laravel-docker/mappy/laravel(GitLab h2t/mappy、Laravel 5.7 / PHP 7.1) |
| データ戦略 | BBS APIをオンデマンド呼び出し、キャッシュなし |
| 新規テーブル | mappy_bbs_accounts、mappy_bbs_location_mappings |
| 追加ENV | BBS_API_KEY、BBS_ROOT_TOKEN、BBS_API_BASE_URL |
| 想定工数 | 約13.5人日(2名:設計者1名 + 製造者1名) |
ENV変数
.envと.env.exampleに追加:
BBS_API_BASE_URL=https://pub-api.optimize-business.com
BBS_API_KEY= # 全アカウント共通のx-api-key
BBS_ROOT_TOKEN= # POST /v1/inside/login で取得したBearerトークン(有効期限なし)実装チェックリスト
実装順序: A → (B, C, D 並行) → E → F
A. 基盤(最初に実施 — 他の全タスクが依存)
- [ ]
mappy_bbs_accountsテーブルのマイグレーション — カラム:id、bbs_account_id(UNIQUE)、email、password(encrypted)、token(TEXT)、created_at、updated_at、deleted_at - [ ]
mappy_bbs_location_mappingsテーブルのマイグレーション — カラム:id、gbp_location_id(UNIQUE)、bbs_location_id、memo、created_at、updated_at - [ ] モデル
app/Models/Mappy/BbsAccount.php—fillable、encrypt()/decrypt()でpasswordをキャスト、SoftDeletes - [ ] モデル
app/Models/Mappy/BbsLocationMapping.php—fillable、belongsTo(GbpLocation::class)リレーション - [ ] サービス
app/Services/Mappy/BbsApiService.php— BBS API呼び出しのHTTPクライアントラッパー:- デフォルトヘッダー:
x-api-key: env('BBS_API_KEY')、Content-Type: application/json rootToken()—env('BBS_ROOT_TOKEN')を返すuserToken($accountId)—bbs_account_idでBbsAccountからtokenを取得get($uri, $token)、post($uri, $data, $token)、put($uri, $data, $token)- レスポンスステータス >= 400 の場合
BbsApiExceptionをスロー
- デフォルトヘッダー:
B. バックエンド — アカウント管理(C、Dと並行)
- [ ]
app/Http/Controllers/Mappy/BbsAccountController.php:index()—GET /v1/pub-accounts(ROOTトークン)→ 一覧を返すshow($bbsAccountId)—GET /v1/pub-accounts/{id}+mappy_bbs_accountsからdecryptしたpassword取得 →storedEmail、storedPassword(マスク済み)を追加で返すstore(Request $request)— バリデーション →POST /v1/create-accounts→POST /v1/loginでトークン取得 →mappy_bbs_accountsにINSERTupdate(Request $request, $bbsAccountId)— バリデーション →PUT /v1/update-accounts/{id}revealPassword($bbsAccountId)— 平文パスワードを返す(decrypt)、「表示」ボタン押下時のみ呼び出し
- [ ] バリデーション(
store/update):namerequired|max:255、emailrequired|email、passwordrequired|min:8、telephonenullable|regex:/^\d{2,4}-\d{2,4}-\d{4}$/ - [ ] ルート定義:php
Route::prefix('bbs/accounts')->group(function () { Route::get('/', 'BbsAccountController@index'); Route::post('/', 'BbsAccountController@store'); Route::get('/{id}', 'BbsAccountController@show'); Route::put('/{id}', 'BbsAccountController@update'); Route::get('/{id}/password', 'BbsAccountController@revealPassword'); });
C. バックエンド — ロケーション一覧・詳細(B、Dと並行)
- [ ]
app/Http/Controllers/Mappy/BbsLocationController.php:index($bbsAccountId)—GET /v1/pub-locations(account_idでフィルター)+mappy_bbs_location_mappingsをJOINしてマッピング済みか判定show($bbsLocationId)—GET /v1/pub-locations/{id}+ マッピング情報があれば取得store(Request $request)— バリデーション →POST /v1/create-locationsupdate(Request $request, $bbsLocationId)— バリデーション →PUT /v1/update-locations/{id}mapping(Request $request, $bbsLocationId)—gbp_location_idをバリデーション →mappy_bbs_location_mappingsをupsert
- [ ] バリデーション(
store/update):namerequired、address_line_1required、location_personrequired、statusrequired|in:1,2,3,4,5、service_idrequired|in:1,2,3,4,5,6,7,8、contract_update_intervalrequired_if:status,1,2 - [ ] ルート定義:php
Route::prefix('bbs/accounts/{accountId}/locations')->group(function () { Route::get('/', 'BbsLocationController@index'); Route::post('/', 'BbsLocationController@store'); Route::get('/{id}', 'BbsLocationController@show'); Route::put('/{id}', 'BbsLocationController@update'); Route::post('/{id}/mapping', 'BbsLocationController@mapping'); });
D. バックエンド — サイテーション一覧(B、Cと並行)
- [ ]
app/Http/Controllers/Mappy/BbsCitationController.php:index($bbsLocationId)— ロケーションからbbs_account_idを取得 →mappy_bbs_accountsからユーザートークンを取得 →GET /v1/pub_citation_pages/by-location/{id}
- [ ] ルート定義:php
Route::get('bbs/locations/{locationId}/citations', 'BbsCitationController@index');
E. フロントエンド(A完了後)
- [ ]
resources/js/mappy/views/bbs/AccountList.vue— アカウント一覧、検索、ページング; 「新規作成」「編集」ボタン、LocationListへのリンク - [ ]
resources/js/mappy/views/bbs/AccountForm.vue— アカウント作成・編集フォーム; パスワードフィールドは••••••••表示、「表示」ボタンでGET /{id}/passwordを呼び出し - [ ]
resources/js/mappy/views/bbs/LocationList.vue— グループヘッダー付き多カラムテーブル、AccountListへのパンくずリスト、「新規作成」ボタン、CitationListへのリンク - [ ]
resources/js/mappy/views/bbs/LocationForm.vue— 35項目フォーム + Mappyロケーションマッピングセクション(gbp_location_idのドロップダウン) - [ ]
resources/js/mappy/views/bbs/CitationList.vue— 3セクション(AIリスティング・ボイスアシスタント・プラットフォーム)、各行に掲載状況とリンクURLを表示
F. QA・運用(最後に実施)
- [ ] ユニット
BbsApiService: U1(ROOTトークンのヘッダーが正しい)、U2(4xxレスポンス → BbsApiExceptionをスロー)、U3(bbs_account_idで正しいuserTokenを取得) - [ ] ユニット
BbsAccount: U4(保存時にpasswordがencryptされる)、U5(revealPasswordが正しい平文を返す) - [ ] 結合テスト: I1(アカウント作成 → mappy_bbs_accountsにトークンが保存される)、I2(ロケーションマッピング → 正しくupsertされる)、I3(サイテーションがROOTトークンでなくユーザートークンを使用)、I4(BBS APIエラー → FEに明確なエラーを返す)
- [ ] リグレッション: R1(既存画面に影響なし)、R2(gbp_locationsテーブルに変更なし)
- [ ]
BBS_API_KEY、BBS_ROOT_TOKEN、BBS_API_BASE_URLを.env.exampleとCI/CDのシークレットに追加