Transfer.php 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. <?php
  2. namespace App\Module\Point\Logic;
  3. use App\Module\Point\Models\PointTransferModel;
  4. /**
  5. * 积分转账逻辑类
  6. *
  7. * 处理不同用户间的积分转账操作
  8. * 专注于整数积分处理,不涉及小数运算
  9. */
  10. class Transfer
  11. {
  12. /**
  13. * 处理用户间积分转账
  14. *
  15. * @param int $fromUserId 转出用户ID
  16. * @param int $pointId 积分类型ID
  17. * @param int $toUserId 转入用户ID
  18. * @param int $amount 转账积分数量
  19. * @param string $remark 备注
  20. * @return int|string 成功返回转账记录ID,失败返回错误信息
  21. */
  22. public static function to_user(int $fromUserId, int $pointId, int $toUserId, int $amount, string $remark)
  23. {
  24. # 参数验证
  25. if ($fromUserId <= 0 || $toUserId <= 0) {
  26. return '用户ID无效';
  27. }
  28. if ($fromUserId === $toUserId) {
  29. return '不能向自己转账';
  30. }
  31. if ($amount <= 0) {
  32. return '转账积分数量必须大于0';
  33. }
  34. # 检查转出方积分余额
  35. $checkResult = User::checkBalance($fromUserId, $pointId, $amount);
  36. if ($checkResult !== true) {
  37. return $checkResult;
  38. }
  39. # 创建转账记录
  40. $transfer = PointTransferModel::createRecord(
  41. $fromUserId,
  42. $toUserId,
  43. $pointId,
  44. $amount,
  45. $remark
  46. );
  47. if (!$transfer) {
  48. return '创建转账记录失败';
  49. }
  50. return $transfer->id;
  51. }
  52. /**
  53. * 批量处理积分转账
  54. *
  55. * @param array $transfers 转账操作数组
  56. * @return array 处理结果数组
  57. */
  58. public static function batchTransfer(array $transfers): array
  59. {
  60. $results = [];
  61. foreach ($transfers as $index => $transfer) {
  62. if (!isset(
  63. $transfer['from_user_id'],
  64. $transfer['to_user_id'],
  65. $transfer['point_id'],
  66. $transfer['amount'],
  67. $transfer['remark']
  68. )) {
  69. $results[$index] = '转账参数不完整';
  70. continue;
  71. }
  72. $result = self::to_user(
  73. $transfer['from_user_id'],
  74. $transfer['point_id'],
  75. $transfer['to_user_id'],
  76. $transfer['amount'],
  77. $transfer['remark']
  78. );
  79. $results[$index] = $result;
  80. }
  81. return $results;
  82. }
  83. /**
  84. * 完成转账操作
  85. *
  86. * @param int $transferId 转账记录ID
  87. * @return bool|string 成功返回true,失败返回错误信息
  88. */
  89. public static function complete(int $transferId)
  90. {
  91. $transfer = PointTransferModel::find($transferId);
  92. if (!$transfer) {
  93. return '转账记录不存在';
  94. }
  95. if ($transfer->isCompleted()) {
  96. return '转账记录已完成';
  97. }
  98. if ($transfer->isFailed()) {
  99. return '转账记录已失败,无法完成';
  100. }
  101. return $transfer->markCompleted();
  102. }
  103. /**
  104. * 标记转账失败
  105. *
  106. * @param int $transferId 转账记录ID
  107. * @return bool|string 成功返回true,失败返回错误信息
  108. */
  109. public static function fail(int $transferId)
  110. {
  111. $transfer = PointTransferModel::find($transferId);
  112. if (!$transfer) {
  113. return '转账记录不存在';
  114. }
  115. if ($transfer->isCompleted()) {
  116. return '转账记录已完成,无法标记为失败';
  117. }
  118. if ($transfer->isFailed()) {
  119. return '转账记录已失败';
  120. }
  121. return $transfer->markFailed();
  122. }
  123. /**
  124. * 获取用户转账记录
  125. *
  126. * @param int $userId 用户ID
  127. * @param int $limit 限制数量
  128. * @return array 转账记录数组
  129. */
  130. public static function getUserRecords(int $userId, int $limit = 50): array
  131. {
  132. $records = PointTransferModel::getUserRecords($userId, $limit);
  133. $result = [];
  134. foreach ($records as $record) {
  135. $result[] = [
  136. 'id' => $record->id,
  137. 'from_user_id' => $record->from_user_id,
  138. 'to_user_id' => $record->to_user_id,
  139. 'point_id' => $record->point_id,
  140. 'amount' => $record->amount,
  141. 'remark' => $record->remark,
  142. 'status' => $record->status,
  143. 'status_name' => $record->getStatusName(),
  144. 'create_time' => $record->create_time,
  145. 'update_time' => $record->update_time,
  146. 'is_transfer_out' => $record->isTransferOut($userId),
  147. 'is_transfer_in' => $record->isTransferIn($userId),
  148. ];
  149. }
  150. return $result;
  151. }
  152. /**
  153. * 获取用户转出记录
  154. *
  155. * @param int $userId 用户ID
  156. * @param int $limit 限制数量
  157. * @return array 转出记录数组
  158. */
  159. public static function getUserTransferOutRecords(int $userId, int $limit = 50): array
  160. {
  161. $records = PointTransferModel::getUserTransferOutRecords($userId, $limit);
  162. $result = [];
  163. foreach ($records as $record) {
  164. $result[] = [
  165. 'id' => $record->id,
  166. 'from_user_id' => $record->from_user_id,
  167. 'to_user_id' => $record->to_user_id,
  168. 'point_id' => $record->point_id,
  169. 'amount' => $record->amount,
  170. 'remark' => $record->remark,
  171. 'status' => $record->status,
  172. 'status_name' => $record->getStatusName(),
  173. 'create_time' => $record->create_time,
  174. 'update_time' => $record->update_time,
  175. ];
  176. }
  177. return $result;
  178. }
  179. /**
  180. * 获取用户转入记录
  181. *
  182. * @param int $userId 用户ID
  183. * @param int $limit 限制数量
  184. * @return array 转入记录数组
  185. */
  186. public static function getUserTransferInRecords(int $userId, int $limit = 50): array
  187. {
  188. $records = PointTransferModel::getUserTransferInRecords($userId, $limit);
  189. $result = [];
  190. foreach ($records as $record) {
  191. $result[] = [
  192. 'id' => $record->id,
  193. 'from_user_id' => $record->from_user_id,
  194. 'to_user_id' => $record->to_user_id,
  195. 'point_id' => $record->point_id,
  196. 'amount' => $record->amount,
  197. 'remark' => $record->remark,
  198. 'status' => $record->status,
  199. 'status_name' => $record->getStatusName(),
  200. 'create_time' => $record->create_time,
  201. 'update_time' => $record->update_time,
  202. ];
  203. }
  204. return $result;
  205. }
  206. /**
  207. * 验证转账操作的有效性
  208. *
  209. * @param int $fromUserId 转出用户ID
  210. * @param int $toUserId 转入用户ID
  211. * @param int $pointId 积分类型ID
  212. * @param int $amount 转账积分数量
  213. * @return bool|string 有效返回true,无效返回错误信息
  214. */
  215. public static function validate(int $fromUserId, int $toUserId, int $pointId, int $amount)
  216. {
  217. # 检查用户ID
  218. if ($fromUserId <= 0 || $toUserId <= 0) {
  219. return '用户ID无效';
  220. }
  221. # 检查是否向自己转账
  222. if ($fromUserId === $toUserId) {
  223. return '不能向自己转账';
  224. }
  225. # 检查积分数量
  226. if ($amount <= 0) {
  227. return '转账积分数量必须大于0';
  228. }
  229. # 检查转出方积分余额
  230. $checkResult = User::checkBalance($fromUserId, $pointId, $amount);
  231. if ($checkResult !== true) {
  232. return $checkResult;
  233. }
  234. return true;
  235. }
  236. /**
  237. * 获取转账统计信息
  238. *
  239. * @param int $userId 用户ID
  240. * @param int|null $pointId 积分类型ID(可选)
  241. * @return array 统计信息数组
  242. */
  243. public static function getTransferStats(int $userId, ?int $pointId = null): array
  244. {
  245. $query = PointTransferModel::where(function($q) use ($userId) {
  246. $q->where('from_user_id', $userId)->orWhere('to_user_id', $userId);
  247. });
  248. if ($pointId !== null) {
  249. $query->where('point_id', $pointId);
  250. }
  251. $records = $query->get();
  252. $stats = [
  253. 'total_count' => $records->count(),
  254. 'transfer_out_count' => 0,
  255. 'transfer_in_count' => 0,
  256. 'transfer_out_amount' => 0,
  257. 'transfer_in_amount' => 0,
  258. ];
  259. foreach ($records as $record) {
  260. if ($record->from_user_id === $userId) {
  261. $stats['transfer_out_count']++;
  262. $stats['transfer_out_amount'] += $record->amount;
  263. } else {
  264. $stats['transfer_in_count']++;
  265. $stats['transfer_in_amount'] += $record->amount;
  266. }
  267. }
  268. return $stats;
  269. }
  270. }