AccountService.php 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. <?php
  2. namespace App\Module\Point\Services;
  3. use App\Module\Point\Dto\PointAccountDto;
  4. use App\Module\Point\Models\PointModel;
  5. use App\Module\Point\Models\PointConfigModel;
  6. use App\Module\Point\Enums\POINT_TYPE;
  7. /**
  8. * 积分账户服务类
  9. *
  10. * 提供积分账户相关的业务功能
  11. */
  12. class AccountService
  13. {
  14. /**
  15. * 获取用户积分账户信息
  16. *
  17. * @param int $userId 用户ID
  18. * @param int|null $pointId 积分类型ID(可选)
  19. * @return PointAccountDto|array 单个账户返回DTO,多个账户返回数组
  20. */
  21. public static function getAccountInfo(int $userId, ?int $pointId = null)
  22. {
  23. if ($pointId !== null) {
  24. $account = PointModel::getAccount($userId, $pointId);
  25. return new PointAccountDto([
  26. 'user_id' => $userId,
  27. 'point_id' => $pointId,
  28. 'balance' => $account ? $account->balance : 0,
  29. 'create_time' => $account ? $account->create_time : 0,
  30. 'update_time' => $account ? $account->update_time : 0,
  31. ]);
  32. }
  33. $accounts = PointModel::userAccount($userId);
  34. $result = [];
  35. foreach ($accounts as $account) {
  36. $result[] = new PointAccountDto([
  37. 'user_id' => $account->user_id,
  38. 'point_id' => $account->point_id,
  39. 'balance' => $account->balance,
  40. 'create_time' => $account->create_time,
  41. 'update_time' => $account->update_time,
  42. ]);
  43. }
  44. return $result;
  45. }
  46. /**
  47. * 获取用户所有积分账户余额
  48. *
  49. * @param int $userId 用户ID
  50. * @return array 积分余额数组,key为积分类型ID,value为余额
  51. */
  52. public static function getAllBalances(int $userId): array
  53. {
  54. $accounts = PointModel::userAccount($userId);
  55. $balances = [];
  56. foreach ($accounts as $account) {
  57. $balances[$account->point_id] = $account->balance;
  58. }
  59. return $balances;
  60. }
  61. /**
  62. * 获取用户指定积分类型的余额
  63. *
  64. * @param int $userId 用户ID
  65. * @param int $pointId 积分类型ID
  66. * @return int 积分余额
  67. */
  68. public static function getBalance(int $userId, int $pointId): int
  69. {
  70. return PointModel::getBalance($userId, $pointId);
  71. }
  72. /**
  73. * 检查用户积分余额是否足够
  74. *
  75. * @param int $userId 用户ID
  76. * @param int $pointId 积分类型ID
  77. * @param int $amount 需要的积分数量
  78. * @return bool 是否足够
  79. */
  80. public static function checkBalance(int $userId, int $pointId, int $amount): bool
  81. {
  82. return PointModel::checkBalance($userId, $pointId, $amount);
  83. }
  84. /**
  85. * 创建或获取用户积分账户
  86. *
  87. * @param int $userId 用户ID
  88. * @param int $pointId 积分类型ID
  89. * @return PointModel 积分账户模型
  90. */
  91. public static function createOrGetAccount(int $userId, int $pointId): PointModel
  92. {
  93. return PointModel::createOrGet($userId, $pointId);
  94. }
  95. /**
  96. * 获取用户积分账户统计信息
  97. *
  98. * @param int $userId 用户ID
  99. * @return array 统计信息
  100. */
  101. public static function getAccountStats(int $userId): array
  102. {
  103. $accounts = PointModel::userAccount($userId);
  104. $stats = [
  105. 'total_accounts' => $accounts->count(),
  106. 'total_balance' => 0,
  107. 'account_details' => [],
  108. ];
  109. foreach ($accounts as $account) {
  110. $stats['total_balance'] += $account->balance;
  111. $stats['account_details'][] = [
  112. 'point_id' => $account->point_id,
  113. 'point_type_name' => $account->getPointTypeName(),
  114. 'balance' => $account->balance,
  115. 'create_time' => $account->create_time,
  116. 'update_time' => $account->update_time,
  117. ];
  118. }
  119. return $stats;
  120. }
  121. /**
  122. * 批量获取用户积分余额
  123. *
  124. * @param array $userIds 用户ID数组
  125. * @param int $pointId 积分类型ID
  126. * @return array 用户积分余额数组,key为用户ID,value为余额
  127. */
  128. public static function batchGetBalances(array $userIds, int $pointId): array
  129. {
  130. $accounts = PointModel::whereIn('user_id', $userIds)
  131. ->where('point_id', $pointId)
  132. ->get();
  133. $balances = [];
  134. foreach ($userIds as $userId) {
  135. $balances[$userId] = 0; // 默认余额为0
  136. }
  137. foreach ($accounts as $account) {
  138. $balances[$account->user_id] = $account->balance;
  139. }
  140. return $balances;
  141. }
  142. /**
  143. * 获取积分类型配置信息
  144. *
  145. * @param int|null $pointType 积分类型(可选)
  146. * @return array 配置信息数组
  147. */
  148. public static function getPointTypeConfigs(?int $pointType = null): array
  149. {
  150. if ($pointType !== null) {
  151. $config = PointConfigModel::getByType($pointType);
  152. return $config ? [
  153. 'id' => $config->id,
  154. 'name' => $config->name,
  155. 'type' => $config->type,
  156. 'type_name' => $config->getTypeName(),
  157. 'currency_id' => $config->currency_id,
  158. 'display_attributes' => $config->display_attributes,
  159. ] : [];
  160. }
  161. $configs = PointConfigModel::getAllConfigs();
  162. $result = [];
  163. foreach ($configs as $config) {
  164. $result[] = [
  165. 'id' => $config->id,
  166. 'name' => $config->name,
  167. 'type' => $config->type,
  168. 'type_name' => $config->getTypeName(),
  169. 'currency_id' => $config->currency_id,
  170. 'display_attributes' => $config->display_attributes,
  171. ];
  172. }
  173. return $result;
  174. }
  175. /**
  176. * 验证积分类型是否有效
  177. *
  178. * @param int $pointType 积分类型
  179. * @return bool 是否有效
  180. */
  181. public static function validatePointType(int $pointType): bool
  182. {
  183. return POINT_TYPE::isValid($pointType) && PointConfigModel::typeExists($pointType);
  184. }
  185. /**
  186. * 获取用户积分排行榜
  187. *
  188. * @param int $pointId 积分类型ID
  189. * @param int $limit 限制数量
  190. * @return array 排行榜数组
  191. */
  192. public static function getPointRanking(int $pointId, int $limit = 100): array
  193. {
  194. $accounts = PointModel::where('point_id', $pointId)
  195. ->where('balance', '>', 0)
  196. ->orderBy('balance', 'desc')
  197. ->limit($limit)
  198. ->get();
  199. $ranking = [];
  200. $rank = 1;
  201. foreach ($accounts as $account) {
  202. $ranking[] = [
  203. 'rank' => $rank++,
  204. 'user_id' => $account->user_id,
  205. 'balance' => $account->balance,
  206. 'point_id' => $account->point_id,
  207. 'point_type_name' => $account->getPointTypeName(),
  208. ];
  209. }
  210. return $ranking;
  211. }
  212. /**
  213. * 获取用户在指定积分类型中的排名
  214. *
  215. * @param int $userId 用户ID
  216. * @param int $pointId 积分类型ID
  217. * @return array 排名信息
  218. */
  219. public static function getUserRanking(int $userId, int $pointId): array
  220. {
  221. $userAccount = PointModel::getAccount($userId, $pointId);
  222. if (!$userAccount) {
  223. return [
  224. 'rank' => 0,
  225. 'balance' => 0,
  226. 'total_users' => 0,
  227. ];
  228. }
  229. $higherCount = PointModel::where('point_id', $pointId)
  230. ->where('balance', '>', $userAccount->balance)
  231. ->count();
  232. $totalUsers = PointModel::where('point_id', $pointId)
  233. ->where('balance', '>', 0)
  234. ->count();
  235. return [
  236. 'rank' => $higherCount + 1,
  237. 'balance' => $userAccount->balance,
  238. 'total_users' => $totalUsers,
  239. ];
  240. }
  241. }