PointService.php 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. <?php
  2. namespace App\Module\Point\Services;
  3. use App\Module\Point\Dto\CirculationDto;
  4. use App\Module\Point\Dto\PointAccountDto;
  5. use App\Module\Point\Dto\PointAdminDto;
  6. use App\Module\Point\Dto\TradeResultDto;
  7. use App\Module\Point\Dto\TransferResultDto;
  8. use App\Module\Point\Enums\POINT_TYPE;
  9. use App\Module\Point\Enums\LOG_TYPE;
  10. use App\Module\Point\Models\PointAdminModel;
  11. use App\Module\Point\Models\PointModel;
  12. use App\Module\Point\Logic\Circulation;
  13. use App\Module\Point\Logic\Transfer;
  14. use App\Module\Point\Logic\User;
  15. use Illuminate\Support\Facades\DB;
  16. use UCore\Db\Helper;
  17. /**
  18. * 积分服务类
  19. *
  20. * 提供积分相关的核心业务功能,专注于整数积分处理
  21. * 包括积分增减、流转、转账等操作
  22. */
  23. class PointService
  24. {
  25. /**
  26. * 用户ID
  27. */
  28. private int $userId;
  29. /**
  30. * 积分类型ID
  31. */
  32. private int $pointId;
  33. /**
  34. * 构造函数
  35. *
  36. * @param int $userId 用户ID
  37. * @param int $pointId 积分类型ID
  38. */
  39. public function __construct(int $userId, int $pointId)
  40. {
  41. $this->userId = $userId;
  42. $this->pointId = $pointId;
  43. }
  44. /**
  45. * 积分流转
  46. * (同用户,不同积分账户)
  47. *
  48. * @param POINT_TYPE $toPointId 目标积分类型
  49. * @param int $amount 积分数量
  50. * @param int $reId 关联ID
  51. * @param string $reType 关联类型
  52. * @param string $remark 备注
  53. * @return CirculationDto|string 成功返回DTO,失败返回错误信息
  54. */
  55. public function circulation(POINT_TYPE $toPointId, int $amount, int $reId, string $reType, string $remark)
  56. {
  57. # 检查积分类型是否相同
  58. if ($this->pointId === $toPointId->valueInt()) {
  59. return '源积分类型和目标积分类型不能相同';
  60. }
  61. # 检查积分数量
  62. if ($amount <= 0) {
  63. return '积分数量必须大于0';
  64. }
  65. Helper::check_tr();
  66. # 先进行流转记录
  67. $circulation_id = Circulation::handle($this->userId, $this->pointId, $toPointId->valueInt(), $amount, $reId, $reType, $remark);
  68. if (is_string($circulation_id)) {
  69. return $circulation_id;
  70. }
  71. # 进行双方的积分修改
  72. # 先减少源积分
  73. $result1 = User::handle($this->userId, $this->pointId, -$amount, LOG_TYPE::CIRCULATION, $circulation_id, $remark);
  74. if (is_string($result1)) {
  75. return $result1;
  76. }
  77. # 再增加目标积分
  78. $result2 = User::handle($this->userId, $toPointId->valueInt(), $amount, LOG_TYPE::CIRCULATION, $circulation_id, $remark);
  79. if (is_string($result2)) {
  80. return $result2;
  81. }
  82. # 返回流转结果
  83. return new CirculationDto([
  84. 'circulation_id' => $circulation_id,
  85. 'from_point_id' => $this->pointId,
  86. 'to_point_id' => $toPointId->valueInt(),
  87. 'amount' => $amount,
  88. 'user_id' => $this->userId,
  89. 'remark' => $remark
  90. ]);
  91. }
  92. /**
  93. * 转账
  94. * (不同人,同积分类型)
  95. *
  96. * @param int $toUserId 接收用户ID
  97. * @param int $amount 积分数量
  98. * @param string $remark 备注
  99. * @return TransferResultDto|string 成功返回DTO,失败返回错误信息
  100. */
  101. public function transfer(int $toUserId, int $amount, string $remark)
  102. {
  103. # 检查参数
  104. if ($this->userId === $toUserId) {
  105. return '不能向自己转账';
  106. }
  107. if ($amount <= 0) {
  108. return '积分数量必须大于0';
  109. }
  110. # 开启事务
  111. DB::beginTransaction();
  112. # 先进行转账记录
  113. $transfer_id = Transfer::to_user($this->userId, $this->pointId, $toUserId, $amount, $remark);
  114. if (is_string($transfer_id)) {
  115. DB::rollBack();
  116. return $transfer_id;
  117. }
  118. # 进行双方的积分修改
  119. # 先减少转出方积分
  120. $result1 = User::handle($this->userId, $this->pointId, -$amount, LOG_TYPE::TRANSFER, $transfer_id, $remark);
  121. if (is_string($result1)) {
  122. DB::rollBack();
  123. return $result1;
  124. }
  125. # 再增加转入方积分
  126. $result2 = User::handle($toUserId, $this->pointId, $amount, LOG_TYPE::TRANSFER, $transfer_id, $remark);
  127. if (is_string($result2)) {
  128. DB::rollBack();
  129. return $result2;
  130. }
  131. DB::commit();
  132. # 返回转账结果
  133. return new TransferResultDto([
  134. 'transfer_id' => $transfer_id,
  135. 'from_user_id' => $this->userId,
  136. 'to_user_id' => $toUserId,
  137. 'point_id' => $this->pointId,
  138. 'amount' => $amount,
  139. 'remark' => $remark
  140. ]);
  141. }
  142. /**
  143. * 增加积分
  144. *
  145. * @param int $amount 积分数量
  146. * @param LOG_TYPE $logType 日志类型
  147. * @param string $operateId 操作ID
  148. * @param string $remark 备注
  149. * @return TradeResultDto|string 成功返回DTO,失败返回错误信息
  150. */
  151. public function increase(int $amount, LOG_TYPE $logType, string $operateId, string $remark)
  152. {
  153. if ($amount <= 0) {
  154. return '积分数量必须大于0';
  155. }
  156. $result = User::handle($this->userId, $this->pointId, $amount, $logType, $operateId, $remark);
  157. if (is_string($result)) {
  158. return $result;
  159. }
  160. return new TradeResultDto([
  161. 'user_id' => $this->userId,
  162. 'point_id' => $this->pointId,
  163. 'amount' => $amount,
  164. 'log_type' => $logType,
  165. 'operate_id' => $operateId,
  166. 'remark' => $remark,
  167. 'success' => true
  168. ]);
  169. }
  170. /**
  171. * 减少积分
  172. *
  173. * @param int $amount 积分数量
  174. * @param LOG_TYPE $logType 日志类型
  175. * @param string $operateId 操作ID
  176. * @param string $remark 备注
  177. * @return TradeResultDto|string 成功返回DTO,失败返回错误信息
  178. */
  179. public function decrease(int $amount, LOG_TYPE $logType, string $operateId, string $remark)
  180. {
  181. if ($amount <= 0) {
  182. return '积分数量必须大于0';
  183. }
  184. $result = User::handle($this->userId, $this->pointId, -$amount, $logType, $operateId, $remark);
  185. if (is_string($result)) {
  186. return $result;
  187. }
  188. return new TradeResultDto([
  189. 'user_id' => $this->userId,
  190. 'point_id' => $this->pointId,
  191. 'amount' => -$amount,
  192. 'log_type' => $logType,
  193. 'operate_id' => $operateId,
  194. 'remark' => $remark,
  195. 'success' => true
  196. ]);
  197. }
  198. /**
  199. * 获取积分余额
  200. *
  201. * @return int 积分余额
  202. */
  203. public function getBalance(): int
  204. {
  205. return PointModel::getBalance($this->userId, $this->pointId);
  206. }
  207. /**
  208. * 检查积分余额是否足够
  209. *
  210. * @param int $amount 需要的积分数量
  211. * @return bool 是否足够
  212. */
  213. public function checkBalance(int $amount): bool
  214. {
  215. return PointModel::checkBalance($this->userId, $this->pointId, $amount);
  216. }
  217. /**
  218. * 获取用户积分账户信息
  219. *
  220. * @return PointAccountDto 积分账户DTO
  221. */
  222. public function getAccountInfo(): PointAccountDto
  223. {
  224. $account = PointModel::getAccount($this->userId, $this->pointId);
  225. return new PointAccountDto([
  226. 'user_id' => $this->userId,
  227. 'point_id' => $this->pointId,
  228. 'balance' => $account ? $account->balance : 0,
  229. 'create_time' => $account ? $account->create_time : 0,
  230. 'update_time' => $account ? $account->update_time : 0,
  231. ]);
  232. }
  233. /**
  234. * Admin 积分操作
  235. *
  236. * @param int $admin_id 管理员ID
  237. * @param POINT_TYPE $point_id 积分类型
  238. * @param int $point_amount 积分数量
  239. * @param string $remark 备注
  240. * @return PointAdminDto|string 成功返回DTO,失败返回错误信息
  241. */
  242. public function admin_operate(int $admin_id, POINT_TYPE $point_id, int $point_amount, string $remark)
  243. {
  244. $data = [
  245. 'total_points' => $point_amount,
  246. 'status' => 1,
  247. 'user_id' => $this->userId,
  248. 'point_id' => $point_id->valueInt(),
  249. 'admin_id' => $admin_id,
  250. 'create_time' => time(),
  251. 'remark' => $remark
  252. ];
  253. # 启动事务
  254. DB::beginTransaction();
  255. # 写日志
  256. $point_admin = new PointAdminModel();
  257. $point_admin->setData($data);
  258. if ($point_admin->save() === false) {
  259. DB::rollBack();
  260. return '_Model-error';
  261. }
  262. # 进行积分操作
  263. $result = User::handle($this->userId, $point_id->valueInt(), $point_amount, LOG_TYPE::ADMIN_OPERATE, $point_admin->id, $remark);
  264. if (is_string($result)) {
  265. DB::rollBack();
  266. return $result;
  267. }
  268. DB::commit();
  269. return new PointAdminDto([
  270. 'id' => $point_admin->id,
  271. 'user_id' => $this->userId,
  272. 'point_id' => $point_id->valueInt(),
  273. 'admin_id' => $admin_id,
  274. 'total_points' => $point_amount,
  275. 'remark' => $remark,
  276. 'create_time' => time()
  277. ]);
  278. }
  279. }