コンテンツにスキップ

チャット・通知

位置づけ: 後続フェーズ

チャット・通知基盤は、営業・事務・施工店・代理店の連絡を CRM 上のチャットに一元化し、社内向けには Slack 通知を併用するハイブリッド構成である。会話は案件(Deal)に紐づくルームとして存在し、雑談チャンネルは対象外とする「文脈必須」原則をとる。

試作実装(crm_app、React + TS)には案件単位のチャット機能が実装済みである。ルームは相手スコープ(社内/施工店/代理店)で固定分割され、案件詳細画面のチャットタブおよび受信箱型の一覧ページから閲覧する。Slack通知は、設定画面のイベント×宛先マトリクスとして定義済みであり、タスク依頼フローでは Incoming Webhook による実送信も動作する。

一方、バックエンド永続化・リアルタイム配信・チャットメッセージ発火のSlack通知配線は未実装である。永続化は現状ブラウザの localStorage(キー crm:chats)に限られ、試作段階のモックデータとして扱う。

第1弾(先行リリース: 催事・アイテム(商品マスタ)・商社(卸))には含まれない。本ページはその後続フェーズの仕様である。

出典は3系統に分かれる。混同を避けるため下表で整理する。

対象内容実装状況
旧システム向け拡張見積(BT社「チャットシステム拡張開発」)顧客ごとのチャットルーム。Pusherでリアルタイム配信未実装(旧システム側の見積案件)
ChatworkService社内ツール ChatWork への通知連携実装済(本件のCRM内チャットとは別物)
新CRM試作の案件チャット案件(Deal)×相手スコープでルーム分割実装済(フロント・localStorage 永続化のみ)
Slack Incoming Webhook 通知タスク依頼・通知マトリクスから Slack へ送信実装済(設定画面から Webhook URL を登録して送信)
リアルタイム配信基盤(Pusher/WebSocket)メッセージのプッシュ配信未実装

会話は案件(Deal)×スコープの組み合わせごとに1ルームとし、1案件につき最大3ルームとする。トピック分けはメッセージ本文側の運用に委ねる。

エンティティ主なフィールド紐付け先実装状況
ChatThread(ルーム)id, dealId, scope, members, messages, unreadDeal × RoomScope実装済(フロントのみ)
ChatMessageid, author, role, text, atChatThread実装済(フロントのみ)
ChatMembername, role(表示用 ChatRole:営業/事務/施工店/代理店)ChatThread実装済(フロントのみ)
ReadReceipt(ユーザー別既読)userId, threadId, lastReadAtChatThread未実装(現状はルーム単位の unread カウンタのみ)
添付ファイルファイル種別・保存先・紐付け先ChatMessage未実装

ChatThreaddealIdscope を主キー的に持つ。メンバーごとの既読管理ではなく、ルーム単位の単純な未読カウンタで運用する。

画面/機能内容実装状況
案件詳細「チャット」タブ(DealChatTab案件に紐づく最大3ルームをタブ切替で閲覧実装済
/chat 受信箱一覧(ChatPage案件を1行に畳み、ルーム・未読・最新メッセージを横断表示実装済
ロールベース可視スコープ(visibleScopes()施工店ロールは施工店ルームのみ、代理店ロールは代理店ルームのみ、社内ロールは3スコープすべてを閲覧実装済
Slack通知マトリクス(SettingsPageイベント×宛先の一覧表示とON/OFF切替実装済
アプリ内通知センター(ベルアイコン・未読一覧)チャットタブ内バッジ表示と /chat の未読集計で代替未実装

モバイル対応の要否・優先度は、催事現場からの利用ニーズに応じて判断する。

案件ステータスが変化した際、useDeals から createRoomsFor が呼ばれ、成約時に社内ルーム(代理店経由の場合は代理店ルームも)、施工着手時に施工店ルームを自動作成する。既定メンバーはスコープに応じて defaultMembers() が自動セットする。社内ルームは営業担当者本人、代理店ルームは営業担当者と代理店窓口、施工店ルームは営業担当者と施工店名を初期メンバーとする。

第三者を既存ルームへ追加招待する機能は未実装である。内部ロールは未作成のルームをボタン一つで作成できるが、これは招待ではなくルーム作成にとどまる。

src/lib/notifications.ts に23件の通知ルール(NOTIFY_RULES)が定義されており、SettingsPage の通知マトリクスで宛先・タイミングを一覧・ON/OFF切替する。宛先は3系統に整理する。

  1. 担当DM — 割当・催促など「その人が動く」通知
  2. 機能チャンネル — #商談前確 #成約 #施工 #発注 #申請 #催事 などチームで拾う通知
  3. 顧客チャンネル — 成約時に案件ごとへ自動作成する

実送信が動作するのはタスク依頼(前確・太陽光調査設計、TaskRequestSheet)のみで、設定画面に保存した Incoming Webhook URL へ POST する。Webhook未設定時は「Slack未設定」のトースト表示にフォールバックする。それ以外の通知ルールは、設定UI・ルール定義のレベルにとどまり、バックエンドからの自動発火(cronやイベントトリガー)は行わない。

CRM内チャットのメッセージ送信とSlack通知は未接続である。notifications.ts には chat-message ルールが定義されているが、ChatPanel の送信処理からSlack送信を呼び出すコードはない。

イベントグループ代表イベント宛先実装状況
架電(前確)担当割当・リマインド・結果・不出再架電担当DM/#商談前確/営業DMルール定義・設定UIのみ
商談結果入力の催促、保留の再連絡リマインド営業DMルール定義・設定UIのみ
成約・契約後成約時の顧客チャンネル自動作成、審査結果#成約/顧客チャンネル/営業DMルール定義・設定UIのみ
施工現地写真格納漏れ、完了報告・完工書督促、入金超過#施工/担当DM/営業DMルール定義・設定UIのみ
発注納期回答メールの案件紐付け(order-reply担当DMルール定義・設定UIのみ
発注欠品・納期遅延アラート(order-stock#発注ルール定義・設定UIのみ
申請印鑑証明期限、申請期限、連携結果未着#申請ルール定義・設定UIのみ
催事開始/終了報告未提出、日次ファネル集計#催事/担当DMルール定義・設定UIのみ
タスク依頼(前確・太陽光調査設計)依頼→担当割振→通知→結果/成果物担当DM実送信まで実装済(TaskRequestSheet
チャットCRMチャット新着(Slack併用期間)担当DMルール定義のみ(送信処理は未配線)

部門ごとの質問窓口スレッドを常設する運用は、コード上に該当概念(区分・専用チャンネル等)を持たない構想段階の機能である。実装するにはスレッドにステータス(未回答/解決済等)を持たせるスキーマ拡張が必要になる。解決済みQ&Aをナレッジとして蓄積し、AIエージェントが一次回答する構想は将来構想とし、AIエージェント構想の方針と接続する。

催事モジュール(催事モジュール仕様)との接続では、通知ルール ev-start-missing(開始報告未提出)・ev-end-missing(終了報告未提出)・ev-daily(日次ファネル集計)が #催事 チャンネル向けに定義済みである。催事単位のチャットルーム自動生成は未実装である。

商社(卸)業務(商社(卸)モジュール仕様)との接続では、通知ルール order-reply(納期回答メールの案件紐付け)が担当DM向け、order-stock(欠品・納期遅延アラート)が #発注 チャンネル向けに、それぞれ定義済みである。発注管理・決済フローとの詳細な状態遷移(発注→入荷→請求等)への通知拡張は今後の検討課題とする。

各モジュールは通知イベントを発行するだけとし、配信先の解決は notifications.ts のルールテーブルで一元管理する設計原則をとる。ルールがモジュール横断で1ファイルに集約されている現状は、この原則に沿う。

現状は Step0 に位置づけられる。チャットはフロントの状態管理(zustand + localStorage)のみで、ページを開いている間の表示更新はできるが、他ユーザー・他端末へのリアルタイム配信・プッシュ通知の仕組みはない。

段階配信方式できること実装状況
Step0(現状)zustand + localStorage(フロントのみ)案件チャットの閲覧・送信・未読表示。Slack通知はタスク依頼のみ実送信実装済(試作範囲)
Step1バックエンド永続化+ポーリング複数端末・複数ユーザーでの状態同期未着手
Step2Pusher等リアルタイム配信新着メッセージ・通知のプッシュ配信未着手(採用可否を再評価)
Step3双方向同期・AI一次応答Slack↔CRM相互反映、質問窓口のAI回答将来構想

Pusher採用は旧システム向け見積時点の前提であり、新CRM試作では未採用である。自前WebSocketやSupabase Realtime等との比較は未実施とする。メッセージと通知ログの保持期間は未定である。

ロール別の可視スコープは visibleScopes() により自動的に絞り込む。権限判定に使うのは既存CRMのロール体系(lib/permissions.tsRole:管理者/営業/事務(BO)/発注・申請担当/代理店/代理店(メンバー)/施工店の7種)のみであり、チャット専用の権限ロールは追加しない。これとは別に、ChatMember.rolelib/chat.tsChatRole:営業/事務/施工店/代理店の4種)は発言者アイコン・ラベルを出し分けるための表示専用の型で、権限判定には関与しない。

ロール閲覧できるルーム
管理者・営業・事務・発注/申請担当(社内ロール)社内/施工店/代理店の3スコープすべて
代理店/代理店(メンバー)代理店ルームのみ
施工店施工店ルームのみ

外部(商社・代理店)ユーザーのログイン主体・アカウント発行方式は、役割・権限で定める所属・組織軸(Google Workspace正)の設計と合わせて別途定める。

  • チャットメッセージ送信時のSlack通知(chat-messageルール)を配線するかどうか
  • バックエンド永続化(Supabase等)への移行時期
  • 第三者を既存ルームへ追加する招待フローのUI設計
  • ユーザー別既読モデル(ReadReceipt)への拡張要否
  • 質問窓口スレッドの新規実装可否とスケジュール
  • Pusher採用可否の再評価、および自前WebSocket・Supabase Realtime等との比較
  • メッセージ・通知ログの保持期間