Browse Source

feat:后端-店铺管理

刘学玺 4 months ago
parent
commit
3784770429

+ 92 - 0
app/Admin/Controllers/ShopInfoController.php

@@ -84,4 +84,96 @@ class ShopInfoController extends AdminController
 
         return $this->service->reviewShop($validated);
     }
+
+    /**
+     * [店铺管理]拉黑店铺
+     *
+     * @description 将店铺加入黑名单
+     *
+     * @header x-xsrf-token required CSRF令牌 Example: your_csrf_token
+     *
+     * @bodyParam shop_id integer required 店铺ID Example: 1
+     * @bodyParam reason string required 拉黑原因 Example: 违规经营
+     *
+     * @response {
+     *   "code": 200,
+     *   "message": "拉黑成功",
+     *   "data": null
+     * }
+     */
+    public function blockShop(Request $request)
+    {
+        $validated = $request->validate([
+            'shop_id' => 'required|integer|exists:shop_infos,id',
+            'reason' => 'required|string|max:255',
+        ]);
+
+        return $this->service->blockShop($validated);
+    }
+
+    /**
+     * [店铺管理]审核记录
+     *
+     * @description 获取店铺审核记录列表
+     *
+     * @queryParam shop_id integer required 店铺ID Example: 1
+     * @queryParam page int 页码 Example: 1
+     * @queryParam perPage int 每页数量 Example: 20
+     *
+     * @response {
+     *   "code": 200,
+     *   "message": "success",
+     *   "data": {
+     *     "current_page": 1,
+     *     "data": [{
+     *       "id": 1,
+     *       "shop_id": 1,
+     *       "state": "ENABLE",
+     *       "audit_remark": "资料齐全,符合要求",
+     *       "audit_time": "2024-03-20 10:00:00",
+     *       "auditor": 1,
+     *       "created_at": "2024-03-20 10:00:00"
+     *     }],
+     *     "total": 10
+     *   }
+     * }
+     */
+    public function reviewRecords(Request $request)
+    {
+        $validated = $request->validate([
+            'shop_id' => 'required|integer|exists:shop_infos,id',
+            'page' => 'nullable|integer|min:1',
+            'perPage' => 'nullable|integer|min:1',
+        ]);
+
+        return $this->service->getShopReviewRecords($validated);
+    }
+
+    /**
+     * [店铺管理]冻结店铺余额
+     *
+     * @description 冻结店铺钱包余额
+     *
+     * @header x-xsrf-token required CSRF令牌 Example: your_csrf_token
+     *
+     * @bodyParam shop_id integer required 店铺ID Example: 1
+     * @bodyParam amount numeric required 冻结金额 Example: 100.00
+     * @bodyParam reason string required 冻结原因 Example: 涉嫌违规操作
+     *
+     * @response {
+     *   "code": 200,
+     *   "message": "冻结成功",
+     *   "data": null
+     * }
+     */
+    public function freezeBalance(Request $request)
+    {
+        $validated = $request->validate([
+            'shop_id' => 'required|integer|exists:shop_infos,id',
+            'amount' => 'required|numeric|min:0.01',
+            'reason' => 'required|string|max:255',
+        ]);
+
+        return $this->service->freezeShopBalance($validated);
+    }
 }

+ 12 - 3
app/Models/ShopAuthRecord.php

@@ -10,16 +10,25 @@ use Slowlyo\OwlAdmin\Models\BaseModel as Model;
  */
 class ShopAuthRecord extends Model
 {
-	use SoftDeletes;
+    use SoftDeletes;
 
-	protected $table = 'shop_auth_records';
+    protected $table = 'shop_auth_records';
 
     /**
      * @Author FelixYin
+     *
      * @description 认证记录所属店铺
      */
     public function shop()
     {
         return $this->belongsTo('App\Models\ShopInfo', 'shop_id');
     }
-}
+
+    /**
+     * 获取审核人信息
+     */
+    public function auditorUser()
+    {
+        return $this->belongsTo(AdminUser::class, 'auditor', 'id');
+    }
+}

+ 149 - 1
app/Services/ShopInfoService.php

@@ -3,7 +3,11 @@
 namespace App\Services;
 
 use App\Enums\ShopStatus;
+use App\Enums\TransactionStatus;
+use App\Enums\TransactionType;
+use App\Models\ShopAuthRecord;
 use App\Models\ShopInfo;
+use App\Models\WalletTransRecord;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Log;
@@ -50,7 +54,7 @@ class ShopInfoService extends AdminService
                 : ShopStatus::REJECTED->value;
             $shop->authRecord->audit_remark = $data['reason'];
             $shop->authRecord->audit_time = now();
-            $shop->authRecord->auditor = Auth::id();
+            $shop->authRecord->auditor = Auth::user()->id;
             $shop->authRecord->save();
 
             DB::commit();
@@ -73,4 +77,148 @@ class ShopInfoService extends AdminService
             throw $e;
         }
     }
+
+    /**
+     * 拉黑店铺
+     *
+     * @param  array  $data  包含 shop_id 和 reason
+     */
+    public function blockShop(array $data): array
+    {
+        try {
+            DB::beginTransaction();
+
+            // 获取店铺信息
+            $shop = ShopInfo::findOrFail($data['shop_id']);
+
+            // 验证店铺当前状态
+            abort_if($shop->state === ShopStatus::CLOSED->value, 422, '店铺已经被拉黑');
+
+            // 更新店铺状态为拉黑
+            $shop->state = ShopStatus::CLOSED->value;
+            $shop->save();
+
+            DB::commit();
+
+            return [
+                'code' => 200,
+                'message' => '拉黑成功',
+                'data' => null,
+            ];
+
+        } catch (\Exception $e) {
+            DB::rollBack();
+            Log::error('拉黑店铺失败', [
+                'shop_id' => $data['shop_id'],
+                'error' => $e->getMessage(),
+                'trace' => $e->getTraceAsString(),
+            ]);
+
+            throw $e;
+        }
+    }
+
+    /**
+     * 获取店铺审核记录
+     *
+     * @param  array  $data  包含 shop_id, page 和 perPage
+     */
+    public function getShopReviewRecords(array $data): array
+    {
+        try {
+            // 获取店铺认证记录
+            $query = ShopAuthRecord::where('shop_id', $data['shop_id'])
+                ->with('auditorUser:id,name')
+                ->orderBy('created_at', 'desc');
+
+            // 分页
+            $perPage = $data['perPage'] ?? 20;
+            $records = $query->paginate($perPage, ['*'], 'page', $data['page'] ?? 1);
+
+            // 转换数据
+            $records->through(function ($record) {
+                // 添加审核人名称
+                $record->auditor_name = $record->auditorUser?->name ?? '';
+                unset($record->auditorUser);
+
+                // 翻译状态
+                $record->state_text = ShopStatus::fromValue($record->state)?->label() ?? '未知状态';
+
+                return $record;
+            });
+
+            return [
+                'code' => 200,
+                'message' => 'success',
+                'data' => $records,
+            ];
+
+        } catch (\Exception $e) {
+            Log::error('获取店铺审核记录失败', [
+                'shop_id' => $data['shop_id'],
+                'error' => $e->getMessage(),
+                'trace' => $e->getTraceAsString(),
+            ]);
+
+            throw $e;
+        }
+    }
+
+    /**
+     * 冻结店铺余额
+     *
+     * @param  array  $data  包含 shop_id, amount 和 reason
+     */
+    public function freezeShopBalance(array $data): array
+    {
+        try {
+            DB::beginTransaction();
+
+            // 获取店铺及其钱包信息
+            $shop = ShopInfo::findOrFail($data['shop_id']);
+            $wallet = $shop->wallet()->lockForUpdate()->firstOrFail();
+
+            // 验证可用余额是否足够
+            abort_if($wallet->available_amount < $data['amount'], 422, '店铺可用余额不足');
+
+            // 更新钱包余额
+            $wallet->available_amount -= $data['amount'];
+            $wallet->frozen_amount += $data['amount'];
+            $wallet->save();
+
+            // 记录冻结流水
+            WalletTransRecord::create([
+                'wallet_id' => $wallet->id,
+                'owner_id' => $data['shop_id'],
+                'owner_type' => ShopInfo::class,
+                'trans_type' => TransactionType::FREEZE->value,
+                'amount' => $data['amount'],
+                'before_amount' => $wallet->available_amount + $data['amount'],
+                'after_amount' => $wallet->available_amount,
+                'operator_id' => Auth::user()->id,
+                'operator_type' => 'admin',
+                'remark' => $data['reason'],
+                'state' => TransactionStatus::SUCCESS->value,
+            ]);
+
+            DB::commit();
+
+            return [
+                'code' => 200,
+                'message' => '冻结成功',
+                'data' => null,
+            ];
+
+        } catch (\Exception $e) {
+            DB::rollBack();
+            Log::error('冻结店铺余额失败', [
+                'shop_id' => $data['shop_id'],
+                'amount' => $data['amount'],
+                'error' => $e->getMessage(),
+                'trace' => $e->getTraceAsString(),
+            ]);
+
+            throw $e;
+        }
+    }
 }

+ 5 - 0
routes/web.php

@@ -1,7 +1,9 @@
 <?php
 
+use App\Admin\Controllers\CoachUserController;
 use App\Admin\Controllers\MemberUserController;
 use App\Admin\Controllers\OrderController;
+use App\Admin\Controllers\ShopInfoController;
 use App\Http\Controllers\EnumController;
 use Illuminate\Routing\Router;
 use Illuminate\Support\Facades\Route;
@@ -173,5 +175,8 @@ Route::group([
         Route::post('coach/block', [CoachUserController::class, 'blockCoach']);
         Route::post('coach/freeze-balance', [CoachUserController::class, 'freezeBalance']);
         Route::post('shop/review', [ShopInfoController::class, 'review']);
+        Route::post('shop/block', [ShopInfoController::class, 'blockShop']);
+        Route::get('shop/{shop_id}/review-records', [ShopInfoController::class, 'reviewRecords']);
+        Route::post('shop/freeze-balance', [ShopInfoController::class, 'freezeBalance']);
     });
 });