ShopInfoService.php 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. <?php
  2. namespace App\Services;
  3. use App\Enums\ShopStatus;
  4. use App\Enums\TransactionStatus;
  5. use App\Enums\TransactionType;
  6. use App\Models\ShopAuthRecord;
  7. use App\Models\ShopInfo;
  8. use App\Models\WalletTransRecord;
  9. use Illuminate\Support\Facades\Auth;
  10. use Illuminate\Support\Facades\DB;
  11. use Illuminate\Support\Facades\Log;
  12. use Slowlyo\OwlAdmin\Services\AdminService;
  13. /**
  14. * 店铺
  15. *
  16. * @method ShopInfo getModel()
  17. * @method ShopInfo|\Illuminate\Database\Query\Builder query()
  18. */
  19. class ShopInfoService extends AdminService
  20. {
  21. protected string $modelName = ShopInfo::class;
  22. /**
  23. * 审核店铺
  24. *
  25. * @param array $data 包含 shop_id, action 和 reason
  26. */
  27. public function reviewShop(array $data): array
  28. {
  29. try {
  30. DB::beginTransaction();
  31. // 获取店铺信息
  32. $shop = ShopInfo::with('authRecord')->findOrFail($data['shop_id']);
  33. // 验证店铺当前状态
  34. abort_if($shop->state !== ShopStatus::PENDING->value, 422, '店铺状态不允许审核');
  35. // 验证认证记录是否存在
  36. abort_if(! $shop->authRecord, 422, '店铺认证信息不存在');
  37. // 更新店铺状态
  38. $shop->state = $data['action'] === 'approve'
  39. ? ShopStatus::ACTIVE->value
  40. : ShopStatus::REJECTED->value;
  41. $shop->save();
  42. // 更新认证记录状态
  43. $shop->authRecord->state = $data['action'] === 'approve'
  44. ? ShopStatus::ACTIVE->value
  45. : ShopStatus::REJECTED->value;
  46. $shop->authRecord->audit_remark = $data['reason'];
  47. $shop->authRecord->audit_time = now();
  48. $shop->authRecord->auditor = Auth::user()->id;
  49. $shop->authRecord->save();
  50. DB::commit();
  51. return [
  52. 'code' => 200,
  53. 'message' => '审核成功',
  54. 'data' => null,
  55. ];
  56. } catch (\Exception $e) {
  57. DB::rollBack();
  58. Log::error('审核店铺失败', [
  59. 'shop_id' => $data['shop_id'],
  60. 'action' => $data['action'],
  61. 'error' => $e->getMessage(),
  62. 'trace' => $e->getTraceAsString(),
  63. ]);
  64. throw $e;
  65. }
  66. }
  67. /**
  68. * 拉黑店铺
  69. *
  70. * @param array $data 包含 shop_id 和 reason
  71. */
  72. public function blockShop(array $data): array
  73. {
  74. try {
  75. DB::beginTransaction();
  76. // 获取店铺信息
  77. $shop = ShopInfo::findOrFail($data['shop_id']);
  78. // 验证店铺当前状态
  79. abort_if($shop->state === ShopStatus::CLOSED->value, 422, '店铺已经被拉黑');
  80. // 更新店铺状态为拉黑
  81. $shop->state = ShopStatus::CLOSED->value;
  82. $shop->save();
  83. DB::commit();
  84. return [
  85. 'code' => 200,
  86. 'message' => '拉黑成功',
  87. 'data' => null,
  88. ];
  89. } catch (\Exception $e) {
  90. DB::rollBack();
  91. Log::error('拉黑店铺失败', [
  92. 'shop_id' => $data['shop_id'],
  93. 'error' => $e->getMessage(),
  94. 'trace' => $e->getTraceAsString(),
  95. ]);
  96. throw $e;
  97. }
  98. }
  99. /**
  100. * 获取店铺审核记录
  101. *
  102. * @param array $data 包含 shop_id, page 和 perPage
  103. */
  104. public function getShopReviewRecords(array $data): array
  105. {
  106. try {
  107. // 获取店铺认证记录
  108. $query = ShopAuthRecord::where('shop_id', $data['shop_id'])
  109. ->with('auditorUser:id,name')
  110. ->orderBy('created_at', 'desc');
  111. // 分页
  112. $perPage = $data['perPage'] ?? 20;
  113. $records = $query->paginate($perPage, ['*'], 'page', $data['page'] ?? 1);
  114. // 转换数据
  115. $records->through(function ($record) {
  116. // 添加审核人名称
  117. $record->auditor_name = $record->auditorUser?->name ?? '';
  118. unset($record->auditorUser);
  119. // 翻译状态
  120. $record->state_text = ShopStatus::fromValue($record->state)?->label() ?? '未知状态';
  121. return $record;
  122. });
  123. return [
  124. 'code' => 200,
  125. 'message' => 'success',
  126. 'data' => $records,
  127. ];
  128. } catch (\Exception $e) {
  129. Log::error('获取店铺审核记录失败', [
  130. 'shop_id' => $data['shop_id'],
  131. 'error' => $e->getMessage(),
  132. 'trace' => $e->getTraceAsString(),
  133. ]);
  134. throw $e;
  135. }
  136. }
  137. /**
  138. * 冻结店铺余额
  139. *
  140. * @param array $data 包含 shop_id, amount 和 reason
  141. */
  142. public function freezeShopBalance(array $data): array
  143. {
  144. try {
  145. DB::beginTransaction();
  146. // 获取店铺及其钱包信息
  147. $shop = ShopInfo::findOrFail($data['shop_id']);
  148. $wallet = $shop->wallet()->lockForUpdate()->firstOrFail();
  149. // 验证可用余额是否足够
  150. abort_if($wallet->available_amount < $data['amount'], 422, '店铺可用余额不足');
  151. // 更新钱包余额
  152. $wallet->available_amount -= $data['amount'];
  153. $wallet->frozen_amount += $data['amount'];
  154. $wallet->save();
  155. // 记录冻结流水
  156. WalletTransRecord::create([
  157. 'wallet_id' => $wallet->id,
  158. 'owner_id' => $data['shop_id'],
  159. 'owner_type' => ShopInfo::class,
  160. 'trans_type' => TransactionType::FREEZE->value,
  161. 'amount' => $data['amount'],
  162. 'before_amount' => $wallet->available_amount + $data['amount'],
  163. 'after_amount' => $wallet->available_amount,
  164. 'operator_id' => Auth::user()->id,
  165. 'operator_type' => 'admin',
  166. 'remark' => $data['reason'],
  167. 'state' => TransactionStatus::SUCCESS->value,
  168. ]);
  169. DB::commit();
  170. return [
  171. 'code' => 200,
  172. 'message' => '冻结成功',
  173. 'data' => null,
  174. ];
  175. } catch (\Exception $e) {
  176. DB::rollBack();
  177. Log::error('冻结店铺余额失败', [
  178. 'shop_id' => $data['shop_id'],
  179. 'amount' => $data['amount'],
  180. 'error' => $e->getMessage(),
  181. 'trace' => $e->getTraceAsString(),
  182. ]);
  183. throw $e;
  184. }
  185. }
  186. }