通知概要

説明

通知システムコンポーネントは、ウィッシュリスト製品およびグループの売上データ変更に関するリアルタイム通知を管理します。このシステムはLaravelの通知システムを活用して、コンソールデータベース(gb_console)とアナライザーデータベース(gb_analyzer)からデータを処理し、ユーザー定義のしきい値(比率型または金額型)に基づいて重要な変更を特定し、データベース保存とリアルタイムPusherサービスの両方を通じて通知を配信します。このコンポーネントにより、ユーザー定義の基準に基づいて製品および製品グループの売上パフォーマンスの変化を自動的に監視し、エンドユーザーに重要なビジネスメトリクスをタイムリーに認識させることができます。

システム概要図

---
config:
  theme: base
  layout: dagre
  flowchart:
    curve: linear
    htmlLabels: true
  themeVariables:
    edgeLabelBackground: "transparent"
---
flowchart TB
    %% External services
    PusherAPI((Pusher API))
    
    %% Commands
    SendNotification[notification:sale-one-month]
    
    %% Database tables grouped by database
    subgraph ConsoleDB["Console Database (gb_console)"]
        direction TB
        NotificationSettings[(notification_settings)]
        Notifications[(notifications)]
        Groups[(groups)]
        GroupMembers[(group_members)]
        Users[(users)]
        WishlistProducts[(wishlist_products)]
        WishlistGroups[(wishlist_groups)]
        Subscriptions[(subscriptions)]
    end
    
    subgraph AnalyzerDB["<div style='width: 300px'>Analyzer Database (gb_analyzer)</div>"]
        direction TB
        Products[(products)]
        ProductDetails[(product_details)]
    end
    
    subgraph Commands["Scheduled Commands"]
        SendNotification
    end
    
    subgraph JobProcessing["Job Processing"]
        SendNotificationJob[SendNotificationJob]
    end
    
    SendNotification --- Step1[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>1</span>
            <p style='margin-top: 8px'>Retrieve Settings</p>
        </div>
    ]
    Step1 --> NotificationSettings
    
    SendNotification --- Step2[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>2</span>
            <p style='margin-top: 8px'>Dispatch Jobs</p>
        </div>
    ]
    Step2 --> SendNotificationJob
    
    SendNotificationJob --- Step3[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #99cc66 !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>3</span>
            <p style='margin-top: 8px'>Get Product Data</p>
        </div>
    ]
    Step3 --> Products
    Step3 --> ProductDetails
    
    SendNotificationJob --- Step4[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #99cc66 !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>4</span>
            <p style='margin-top: 8px'>Get Group Members</p>
        </div>
    ]
    Step4 --> GroupMembers
    
    SendNotificationJob --- Step5[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #99cc66 !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>5</span>
            <p style='margin-top: 8px'>Store Notifications</p>
        </div>
    ]
    Step5 --> Notifications
    
    SendNotificationJob --- Step6[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #99cc66 !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>6</span>
            <p style='margin-top: 8px'>Real-time Delivery</p>
        </div>
    ]
    Step6 --> PusherAPI
    
    PusherAPI --- Step7[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #cc66cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>7</span>
            <p style='margin-top: 8px'>WebSocket</p>
        </div>
    ]
    Step7 --> Users
    
    %% Implicit relationships
    NotificationSettings -.-> WishlistProducts
    NotificationSettings -.-> WishlistGroups
    Groups -.-> Subscriptions
    
    %% Database styles
    style ConsoleDB fill:#d9f2d9,stroke:#339933,stroke-width:2px
    style AnalyzerDB fill:#d9d9f2,stroke:#6666cc,stroke-width:2px
    
    %% Table styles
    classDef consoleTable fill:#e6ffe6,stroke:#339933,stroke-width:1px
    classDef analyzerTable fill:#e6e6ff,stroke:#6666cc,stroke-width:1px
    
    %% Apply table styles
    class NotificationSettings,Notifications,Groups,GroupMembers,Users,WishlistProducts,WishlistGroups,Subscriptions consoleTable
    class Products,ProductDetails analyzerTable
    
    %% Other styles
    style PusherAPI fill:#fcd9d9,stroke:#cc6666,stroke-width:2px
    style SendNotification fill:#d9f2d9
    style Commands fill:#f9f9f9
    style JobProcessing fill:#f0e6ff,stroke:#9966cc,stroke-width:1px
    style SendNotificationJob fill:#f5e6ff
    
    %% Transparent connection steps
    style Step1 fill:transparent,stroke:transparent,stroke-width:1px
    style Step2 fill:transparent,stroke:transparent,stroke-width:1px
    style Step3 fill:transparent,stroke:transparent,stroke-width:1px
    style Step4 fill:transparent,stroke:transparent,stroke-width:1px
    style Step5 fill:transparent,stroke:transparent,stroke-width:1px
    style Step6 fill:transparent,stroke:transparent,stroke-width:1px
    style Step7 fill:transparent,stroke:transparent,stroke-width:1px

詳細なデータフロー依存関係

通知システムコンポーネントは、以下のステップによる順次データフローに従います:

  1. 設定の取得: notification:sale-one-monthコマンドはデータベースから通知設定を取得します:

    • notification_settingsテーブルからアクティブな設定をクエリ
    • whereHas('group.activeSubscription')を使用してアクティブなグループサブスクリプションでフィルタリング
    • チャンク単位で設定を処理(デフォルト:チャンクあたり100レコード)
    • chunkDataSendNotification()メソッドを持つNotificationSettingRepositoryInterfaceを使用
  2. ジョブのディスパッチ: 通知設定の各チャンクに対して:

    • 設定コレクションデータを含むSendNotificationJobをディスパッチ
    • 信頼性の高いバックグラウンド処理のためにLaravelキュー設定を適用
    • 監視とデバッグのためにディスパッチイベントをログに記録
  3. 製品データの取得: ジョブは関連する製品と売上データを取得します:

    • 個別製品通知の場合:特定のウィッシュリスト製品と対応するアナライザー製品を取得
    • グループ通知の場合:ウィッシュリストグループ内の複数の製品にわたる集計データを取得
    • 日付範囲を使用してproduct_detailsテーブルから現在および過去の売上データを取得
    • リポジトリインターフェースを通じてデータにアクセス:ProductRepositoryProductDetailRepositoryWishlistProductRepository
  4. 条件の評価: システムは通知設定に基づいてデータを分析します:

    • 比率ベースの通知:calculate_percentage_change()を使用して現在と過去の期間の間のパーセンテージ変化を計算
    • 金額ベースの通知:固定しきい値に対して絶対的な売上値を比較
    • 売上計算:売上値決定のためのsales_one_month * priceを使用
    • 比較タイプに基づいて通知基準が満たされているかを判断:
      • 増加/減少(パーセンテージしきい値を持つ比率タイプの場合)
      • 超過/下回る(絶対値しきい値を持つ金額タイプの場合)
  5. グループメンバーの取得: 条件が満たされた場合、システムは:

    • group_idを通じて通知設定に関連付けられたグループメンバーを特定
    • GroupRepositoryを使用してグループメンバー関係を通じてユーザーレコードを取得
    • ユーザー固有のコンテキストでパーソナライズされた通知データを準備
  6. 通知の保存: 条件を満たす各通知に対して:

    • Laravelの通知システムを使用してnotificationsテーブルに新しいレコードを作成
    • 比較値、エンティティ参照、タイムスタンプを含む構造化JSONデータを保存
    • 適切なデータフォーマットでデータベース保存のためにSendNotificationクラスを使用
    • 監査と既読追跡のための配信ステータスを維持
  7. リアルタイム配信: 最後に、システムは通知を配信します:

    • toPusher()メソッドを使用してPusher WebSocketsを介してリアルタイム更新を送信
    • Laravel通知イベントリスナーを通じて配信ステータスを追跡
    • エラーを処理し、データベースのみの配信へのフォールバックを提供
    • 監視のために成功および失敗した通知試行をログに記録

データベーススキーマ

コンソールデータベーステーブル (gb_console)

erDiagram
    notification_settings {
        bigint id PK
        string notifiable_type "ポリモーフィックタイプ(ジョブ処理でのエンティティタイプ識別に使用)"
        bigint notifiable_id "エンティティを参照するポリモーフィックID(ジョブ処理でのエンティティルックアップに使用)"
        bigint group_id FK "groupsテーブルへの外部キー(グループメンバー通知とサブスクリプションフィルタリングに使用)"
        string type "通知タイプ:ratio、amount(処理ロジック選択に使用)"
        string frequency "通知頻度:previous_day、one_week_ago(日付範囲計算に使用)"
        string comparison_type "比較タイプ:increase、decrease、exceed、fall_below(しきい値評価に使用)"
        decimal comparison_value "比較のためのしきい値(通知条件チェックに使用)"
        timestamp created_at
        timestamp updated_at
    }
    
    notifications {
        uuid id PK
        string type "通知クラス名(通知タイプ識別に使用)"
        string notifiable_type "ポリモーフィックタイプ(Pusher配信でのユーザー識別に使用)"
        bigint notifiable_id "ユーザーを参照するポリモーフィックID(通知ターゲティングに使用)"
        text data "設定と比較情報を含むJSON通知データ(Pusherペイロードに使用)"
        timestamp read_at "通知が読まれた時間(既読ステータス追跡に使用)"
        timestamp created_at
        timestamp updated_at
    }
    
    groups {
        bigint id PK
        string name "グループ名(通知コンテキストに使用)"
        timestamp created_at
        timestamp updated_at
    }
    
    group_members {
        bigint id PK
        bigint group_id FK "groupsテーブルへの外部キー(通知配信でのユーザールックアップに使用)"
        bigint user_id FK "usersテーブルへの外部キー(通知ターゲティングに使用)"
        timestamp created_at
        timestamp updated_at
    }
    
    users {
        bigint id PK
        string name "ユーザー名(通知パーソナライゼーションに使用)"
        string email "ユーザーメール(通知配信に使用)"
        timestamp created_at
        timestamp updated_at
    }
    
    subscriptions {
        bigint id PK
        bigint group_id FK "groupsテーブルへの外部キー(アクティブサブスクリプションフィルタリングに使用)"
        string status "サブスクリプションステータス(chunkDataSendNotificationでアクティブ用にフィルタリング)"
        timestamp created_at
        timestamp updated_at
    }
    
    wishlist_products {
        bigint id PK
        bigint wishlist_group_id FK "wishlist_groupsテーブルへの外部キー(グループ関連付けに使用)"
        text summary_product "製品入力情報を含むJSONデータ(製品ID抽出に使用)"
        timestamp created_at
        timestamp updated_at
    }
    
    wishlist_groups {
        bigint id PK
        string name "ウィッシュリストグループ名(通知コンテキストとグループ処理に使用)"
        timestamp created_at
        timestamp updated_at
    }
    
    notification_settings ||--o{ groups : "belongs to"
    groups ||--o{ group_members : "has many"
    groups ||--o{ subscriptions : "has many"
    group_members ||--o{ users : "belongs to"
    notifications ||--o{ users : "notifiable"
    notification_settings ||--o{ wishlist_products : "notifiable (polymorphic)"
    notification_settings ||--o{ wishlist_groups : "notifiable (polymorphic)"
    wishlist_products ||--o{ wishlist_groups : "belongs to"

アナライザーデータベーステーブル (gb_analyzer)

erDiagram
    products {
        bigint id PK
        integer mall_id "モール識別子(製品フィルタリングとマッチングに使用)"
        string mall_product_id "モールからの製品ID(入力による製品ルックアップに使用)"
        string unique_key "一意の識別子(製品重複排除に使用)"
        timestamp created_at
        timestamp updated_at
    }
    
    product_details {
        bigint id PK
        bigint product_id FK "productsテーブルへの外部キー(売上データ関連付けに使用)"
        decimal price "製品価格(売上値計算に使用:sales_one_month * price)"
        integer sales_one_month "1ヶ月間の売上数(売上値計算に使用)"
        date metrics_date "メトリクスの日付(過去比較での日付範囲フィルタリングに使用)"
        timestamp created_at
        timestamp updated_at
        timestamp crawl_created_at "データがクロールされた時間(最新データ選択に使用)"
    }
    
    products ||--o{ product_details : "has many"

通知コマンドロジックフィールド

通知設定の取得:

コマンドレベル(notification:sale-one-month):

  • notification_settings.id - チャンク処理のための主キー
  • notification_settings.group_id - whereHas('group.activeSubscription')によるアクティブサブスクリプションフィルタリングに使用

ジョブレベル(SendNotificationJob):

  • notification_settings.notifiable_type - エンティティがWishlistProductかWishlistGroupかを判断するために使用
  • notification_settings.notifiable_id - エンティティルックアップ(getEntity()メソッド)に使用
  • notification_settings.type - 処理ロジックの選択(比率vs金額)に使用
  • notification_settings.frequency - 日付範囲計算(getDateRangeForFrequency())に使用
  • notification_settings.comparison_type - しきい値評価ロジックに使用
  • notification_settings.comparison_value - 通知条件チェックに使用
  • notification_settings.group_id - グループメンバーのルックアップと通知配信に使用

製品データ処理:

製品ルックアップ:

  • products.mall_product_id - getByMallProductId()による製品マッチングに使用
  • products.id - 製品詳細関連付けに使用

売上データ計算:

  • product_details.product_id - 製品関連付けに使用
  • product_details.sales_one_month - 売上値計算に使用
  • product_details.price - 売上値計算に使用(sales_one_month * price)
  • product_details.metrics_date - 過去比較での日付範囲フィルタリングに使用
  • product_details.crawl_created_at - 最新データ選択に使用

グループメンバー通知:

グループ処理:

  • groups.id - findById()によるグループルックアップに使用
  • group_members.group_id - メンバー関連付けに使用
  • group_members.user_id - ユーザールックアップに使用
  • users.id - 通知ターゲティングとPusher配信に使用
  • users.name - 通知パーソナライゼーションに使用
  • users.email - 通知配信に使用

通知保存と配信:

データベース保存:

  • notifications.id - 通知識別のための生成されたUUID
  • notifications.type - 通知クラス名に設定
  • notifications.notifiable_type - 'App\Models\User'に設定
  • notifications.notifiable_id - ターゲティングのためのユーザーIDに設定
  • notifications.data - 設定と比較データを含むJSONペイロードを格納
  • notifications.read_at - 既読ステータス追跡に使用

エンティティコンテキスト:

  • wishlist_products.summary_product - 製品入力抽出に使用
  • wishlist_groups.name - 通知コンテキストに使用

売上値計算ロジック

通知システムは売上監視のために以下の計算を使用します:

売上値 = product_details.sales_one_month * product_details.price

比率タイプ通知:

  • 現在期間と過去期間の売上値を比較
  • calculate_percentage_change()を使用してパーセンテージ変化を計算
  • 増加/減少しきい値に基づいて通知をトリガー

金額タイプ通知:

  • 現在の売上値を絶対的なしきい値と比較
  • 値が設定された金額を超過または下回った場合に通知をトリガー

日付範囲処理

システムはproduct_details.metrics_dateを以下のために使用します:

  • 現在期間フィルタリング(現在の月)
  • 過去期間フィルタリング(前月)
  • 日付範囲内の最新データ選択

サブスクリプションフィルタリング

アクティブサブスクリプションフィルタリングは以下を通じて実装されています:

whereHas('group.activeSubscription')

これにより、アクティブなサブスクリプションを持つグループのみが通知を受け取ります。

頻度概要

タイムライン

timeline
    title 通知システムスケジュール
    section 売上通知
        毎日<br>(例:00.00) : notification sale-one-month
                            : 通知設定を処理しアラートをトリガー

期待される結果

これらのコマンドが正常に実行されると、システムは以下を提供します:

  • 自動売上監視: ユーザー定義のしきい値に基づいたウィッシュリスト製品およびグループの売上パフォーマンス変化の継続的な監視
  • リアルタイム通知配信: データベース保存とPusher WebSocketサービスの両方を通じた即時通知配信によるユーザーへの瞬時の認識
  • 設定可能なしきい値管理: 比率ベース(パーセンテージ)と金額ベース(絶対値)の両方の通知基準を柔軟な比較タイプでサポート
  • グループベースの通知配布: サブスクリプションベースのフィルタリングを持つグループメンバーシップ関係を通じた関連ユーザーへの効率的な配信
  • 永続的な通知履歴: 既読ステータス追跡と構造化JSONデータ保存を備えたすべての通知の完全な監査証跡
  • バックグラウンドジョブ処理: システムパフォーマンスをブロックせずに大量の処理を扱うための信頼性の高い非同期通知チャンク処理
  • エラー処理とフォールバック: 外部サービスが失敗した場合のデータベースのみの配信へのフォールバックを持つ堅牢なエラー処理
  • データ駆動型ビジネスインテリジェンス: 重要な売上変化と市場動向に対する迅速な対応を可能にするタイムリーなアラート

バッチリスト

名前 説明
売上通知 アクティブなサブスクリプションを持つグループの通知設定を処理し、ウィッシュリスト製品およびグループの売上変化を検出するコマンド