Review Summary

会員検索がヒットしない

OPEN PR #858 Issue #857 2026-03-24 by Nissho Chao
01 問題の概要

松戸八柱店から「テンマネの会員タブで会員名検索してもヒットしない」と問合せ。報告者(Masaru Suzuki)自身も確認し、2名の会員が会員名検索でヒットしないことを確認。購入履歴タブからは検索可能。

店舗 松戸八柱店
報告 門馬 恵里香 様 / 天野 真里奈 様 の2名が検索不可
影響 同様の現象が 47名 で発生していることが判明
02 Chaoさんの対応(PR #858)
16:12
確認着手
17:45
原因特定・PR作成完了(約1.5時間で対応)
Issue #857 を作成し、影響ユーザー47名のリストもまとめた

/api/users/search の検索ロジックを修正。RECURRING 指定時に、最新1件の type 判定ではなく EXISTS サブクエリで「履歴に RECURRING があるか」で判定するように変更。

03 原因のメカニズム

フロントエンドが送信する固定フィルタと、バックエンドの「最新1件のみ判定」ロジックの組み合わせにより、過去に定期会員だったが現在は単発のユーザーが除外される。

Frontend (fe-admin)
会員一覧の検索リクエストに
membershipType: 'RECURRING'常に固定送信
POST /api/users/search
Backend (users.service.ts)
ROW_NUMBER() PARTITION BY user_id ORDER BY id DESC
最新メンバーシップ1件のみを取得し、type = 'RECURRING' で判定
最新が ONE_SHOT の場合
結果
過去に RECURRING 履歴があっても、最新が ONE_SHOT なら
RECURRING フィルタで除外 → 検索にヒットしない
04 なぜ RECURRING 固定なのか 設計意図あり

RECURRING 固定は偶然ではなく、意図的な設計であることがコードとコミット履歴から確認できた。

1 会員一覧=定期会員の管理画面

会員タブは「定期課金ユーザー」の管理を目的として設計されている。チケット(ONE_SHOT)はサブスク編集フォームでも「チケット」として別セクションに分離表示。

2 FE側フィルタ → API移行の経緯

もともとフロントエンド側で userMemberships.find(m => m.type == 'RECURRING') でフィルタしていた。2025-02-27 のコミットでAPIレベルに移行しただけで、フィルタ自体は初期設計から存在。

3 UI上に切替は存在しない

会員一覧画面のフィルタに定期/単発の切り替えUIは存在しない。検索キーワード・スタジオ・ステータス・トライアルのみ。

4 CSV出力も同様

CSV出力時も membershipType: 'RECURRING' を固定送信。さらにCSV生成ユーティリティ側でも RECURRING でフィルタしている二重構造。

05 PR #858 の懸念点
仕様の非対称性
RECURRING 指定時だけ「履歴にあるか」で判定し、ONE_SHOT 指定時は「最新1件のtype」で判定する。同じパラメータの挙動が値によって異なるのは、今後の混乱の原因になる。
EXISTS サブクエリに status フィルタが無い
メインの JOIN サブクエリでは status IN (:statuses) でフィルタしているが、追加された EXISTS サブクエリ(um_hist)には status 条件がない。EXPIRED 等の無効なメンバーシップでもヒットしてしまう。
定期会員一覧に単発会員が混在
画面に表示されるメンバーシップ情報は最新の ONE_SHOT のもの。「定期会員の管理画面」という設計意図に反して、現在は単発会員のユーザーが47名追加表示されることになる。
studioIds の分岐条件のずれ
JOIN パラメータでは studioIds || fallback でフォールバック値を設定するが、EXISTS 側では studioIds && studioIds.length > 0 でガード。2箇所の条件が微妙に異なる。
パフォーマンス
EXISTS サブクエリは user_memberships(user_id, type) で走査する。該当インデックスの有無が未確認。
06 推奨方針

根本原因は「フロントエンドが RECURRING を固定送信している」こと。バックエンドで RECURRING の意味を暗黙的に変えるのではなく、フロントエンド側でフィルタを制御する方が設計として自然。

現PR

B案:バックエンド側で対応

PR #858 のアプローチ。RECURRING 指定時に EXISTS で履歴判定。

  • RECURRING の意味を暗黙的に変更するリスク
  • EXISTS サブクエリの status フィルタ漏れ
  • 定期会員管理画面に単発ユーザーが混在
  • ONE_SHOT との挙動が非対称になる