管理者が顧客を検索・新規作成・編集し、お届け先やパスワードを管理する機能の仕様を、開発者向けにまとめます。
本書は
specs/34_管理者向け顧客管理機能 実装手順書.md(Ver.3.0) を土台に、現行コード(mg_customers/accounts)と照合して再構成したものです。挙動は実装を正とし、差分は本文中で明示します。
関連: design/データベース設計(User/Destination) / アカウント・認証
| 機能 | ファイル |
|---|---|
| 顧客一覧・詳細・新規作成 | mg_customers/views.py(customer_list_view / customer_detail_view / customer_create_view) |
| お届け先 CRUD・顧客情報更新・パスワード再設定 API | mg_customers/api.py |
すべて /management/customers/ 配下(dashboard:mg_customers:*)。ビューは @login_required + @user_passes_test(is_staff_user)、API は staff_member_required(更新系は csrf_protect)でスタッフ限定。管理操作は Django 管理サイトではなく専用 UI+API の非同期通信で完結する。
customer_list_view)URL: dashboard:mg_customers:customer_list(画面 SCR-AD-070)。スタッフ以外の User(is_staff=False)を対象に表示。
q): ログイン ID(username)・お届け先の宛名(destination__name)・住所(destination__address)の部分一致(distinct)。sort): username / last_order_date / total_order_amount(各昇降順、既定 -last_order_date)。last_order_date … 最終注文日時(Max('order__created_at'))。total_order_amount … 累計注文金額。キャンセル注文を除外して算出する。集計ロジックの注意: 累計注文金額は、商品合計(
price_at_order × quantityの総和)と送料合計を別々に計算してから合算する。送料合計は注文ごとに「確定送料があればそれ、無ければ参考送料」(Coalesce(final_shipping_fee, provisional_shipping_fee))をSubqueryで集計する。商品明細数に応じて送料が多重カウントされる不具合を避けるための実装。
customer_detail_view)URL: dashboard:mg_customers:customer_detail(画面 SCR-AD-071)。顧客の基本情報・お届け先一覧・繰越残高を表示し、以下の編集をすべて API との非同期通信で画面遷移なく行う。お届け先の選択肢(配送方法・送料区分)は JSON でテンプレートへ渡し、JS フォームで利用する。
入金済み注文のキャンセルで「次回支払いへ繰越」を選んだ金額は、CustomerCreditTransaction の履歴合計として顧客別に管理される。顧客詳細画面では現在残高と履歴一覧を表示する。
| 表示項目 | 内容 |
|---|---|
| 繰越残高 | CustomerCreditTransaction.balance_for(customer) |
| 発生日 | 履歴の created_at |
| 種別 | 繰越加算 / 注文への充当 / 充当先キャンセルによる戻し |
| 金額 | 残高加算は正、注文への充当は負 |
| 元注文 | キャンセルで繰越が発生した注文(source_order) |
| 充当先注文 | 繰越を充当した注文(target_order) |
| メモ | 管理者メモ |
返金・寄付扱いの PaymentAdjustment は繰越残高台帳に入れないため、顧客残高には混ざらない。
編集操作と対応 API は次節のとおり。
customer_create_view)URL: dashboard:mg_customers:customer_create(GET で作成フォーム表示/POST で作成)。
username)、メール(email、任意)、パスワード(password)。errors)でフォーム再表示。User.objects.create_user() で作成し、顧客詳細画面へリダイレクト。| API | URL 名 | メソッド | 内容 |
|---|---|---|---|
| お届け先一覧取得 | dashboard:mg_customers:api_destinations_list |
GET | 当該顧客のお届け先を、有効な destinations と削除済みの deleted_destinations に分けて返す(配送方法・送料区分は値+表示名) |
| お届け先 作成/更新 | dashboard:mg_customers:api_destinations_upsert |
POST | id 指定で更新、無指定で新規。宛名・郵便番号・住所・電話番号は必須。配送方法/送料区分の既定は YAMATO/NORMAL |
| お届け先 削除 | dashboard:mg_customers:api_destinations_delete |
POST | ソフトデリート(is_deleted=True)。注文状態・販売年度にかかわらず一覧と今後の選択候補から除外し、既存の注文・荷物からの参照は保持する |
| お届け先 復元 | dashboard:mg_customers:api_destinations_restore |
POST | 削除済みのお届け先を is_deleted=False に戻し、通常一覧と今後のお届け先選択候補へ復帰させる |
| 顧客情報更新 | dashboard:mg_customers:api_info_update |
POST | ログイン ID(自分以外との重複不可)・メールを更新 |
| パスワード再設定 | dashboard:mg_customers:api_password_set |
POST | 8 文字以上で set_password()。要件どおり管理者による手動再設定(顧客自身のオンライン再設定機能は無い) |
いずれも成功時は {"ok": true, ...} 形式の JSON を返す。バリデーションエラー(必須項目不足・重複・パスワード長など)は _bad_request() で {"ok": false, "error": {"message": ...}} + 400。一方、対象ユーザー/お届け先が存在しない場合は get_object_or_404() による通常の 404 になる。
現行実装上の注意: 顧客一覧・顧客詳細画面は
is_staff=Falseのユーザーのみを対象にする(customer_list_view/customer_detail_view)。一方で、顧客管理 API(DestinationListView/DestinationUpsertView/CustomerInfoUpdateView/CustomerPasswordSetView)のuser_id指定はget_object_or_404(User, id=...)のみで、is_staff=Falseを明示的には検証していない。現状は管理者(実質 1 名)のみが利用する前提のため実害は限定的だが、将来スタッフ権限を複数人に付与する場合は、API 側でも非スタッフ顧客に限定する制御を追加すること。
Destination は Order.destination(SET_NULL)や Package.destination(PROTECT)から参照されるため、物理削除せず is_deleted=True で論理削除する。これにより過去・進行中の注文や荷物の参照を壊さずに、通常一覧と今後の注文で使う選択候補から非表示にする。削除済みのお届け先は顧客詳細画面の別枠に表示し、管理者が「復元」すると通常一覧・選択候補へ戻る。履歴自体は保持されるため、注文状態・入金状態・販売年度を削除可否の条件にはしない。
元資料: specs/34_管理者向け顧客管理機能 実装手順書.md (Ver.3.0) を現行コード(mg_customers/views.py, mg_customers/api.py, accounts/models.py)と照合して再構成
関連: README, specs棚卸し表, Issue #1