User.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. <?php
  2. namespace App\Module\Fund\Logic;
  3. use App\Module\Fund\Enums\LOG_TYPE;
  4. use App\Module\Fund\Events\FundChangedEvent;
  5. use App\Module\Fund\Models\FundLogModel;
  6. use App\Module\Fund\Models\FundModel;
  7. use Illuminate\Support\Facades\Event;
  8. use UCore\Helper\Logger;
  9. /**
  10. * Class User 用户的资金操作
  11. *
  12. * @package App\Logic\Fund\Service
  13. */
  14. class User
  15. {
  16. /**
  17. * 列表
  18. *
  19. * @param $where
  20. * @param $page
  21. * @param int $rows
  22. */
  23. public static function fund_list($where, $page, $rows = 10)
  24. {
  25. $query = FundModel::query();
  26. // 应用过滤条件
  27. if (isset($where['user_id'])) {
  28. $query->where('user_id', $where['user_id']);
  29. }
  30. if (isset($where['fund_id'])) {
  31. $query->where('fund_id', $where['fund_id']);
  32. }
  33. // 返回分页结果
  34. return $query->paginate($rows, ['*'], 'page', $page);
  35. }
  36. /**
  37. * 用户资金修改日志
  38. *
  39. * @param $user_id 用户uid
  40. * @param $page 当前页数
  41. * @param int $rows 每页行数
  42. */
  43. public static function log_list($user_id, $fund_id, $where, $page, $rows = 10)
  44. {
  45. }
  46. /**
  47. *
  48. * 资金处理
  49. *
  50. * @param $user_id
  51. * @param $fund_id
  52. * @param $amount
  53. * @param $type
  54. * @param $id
  55. * @param $remark
  56. * @return bool|string
  57. */
  58. public static function handle($user_id, int $fund_id, int $amount, LOG_TYPE $type, $id, $remark)
  59. {
  60. # 读取信息
  61. $data_Model = self::get_account($user_id, $fund_id);
  62. if ($data_Model === false) {
  63. return "_don~t have this account";
  64. }
  65. if (!($data_Model instanceof FundModel)) {
  66. return $data_Model;
  67. }
  68. # 记录变更前的余额
  69. $beforeBalance = $data_Model->balance;
  70. # 先写入日志
  71. $re26 = self::log($data_Model, $user_id, $fund_id, $amount, $type, $id, $remark);
  72. if (is_string($re26)) {
  73. return $re26;
  74. }
  75. # 在更新资金信息
  76. $data_Model->update_time = time();
  77. $data_Model->balance = $data_Model->balance + $amount;
  78. if ($data_Model->balance < 0) {
  79. // 可用资金小于0
  80. Logger::error("fund -handle $user_id - $fund_id $amount end < 0");
  81. return "not-sufficient-funds $user_id - $fund_id : $amount ; {$data_Model->balance}";
  82. }
  83. if ($data_Model->save() === false) {
  84. return $data_Model->getMessage();
  85. }
  86. # 触发资金变更事件
  87. Event::dispatch(new FundChangedEvent(
  88. $user_id,
  89. $fund_id,
  90. $amount,
  91. $beforeBalance,
  92. $data_Model->balance,
  93. $type->value(),
  94. $id,
  95. $remark
  96. ));
  97. return true;
  98. }
  99. /**
  100. * 获取账户模型
  101. *
  102. * @param $user_id
  103. * @param $fund_id
  104. * @return fund|string
  105. */
  106. public static function get_account($user_id, $fund_id, $create = false)
  107. {
  108. $Model = FundModel::getAccount($user_id, $fund_id);
  109. if ($Model === null) {
  110. if ($create) {
  111. # 当前账户不存在尝试创建
  112. $Model = self::create_account($user_id, $fund_id);
  113. if (is_string($Model)) {
  114. // 创建失败
  115. return $Model;
  116. }
  117. } else {
  118. throw new \Exception("账户不存在$user_id - $fund_id .");
  119. }
  120. return FundModel::getAccount($user_id, $fund_id);
  121. }
  122. return $Model;
  123. }
  124. /**
  125. * 创建账户 不会进行账户是否存在验证
  126. *
  127. * @param $user_id
  128. * @param $fund_id
  129. * @return \Fund\Model\Fund|string
  130. */
  131. private static function create_account($user_id, $fund_id)
  132. {
  133. $data = [
  134. 'user_id' => $user_id,
  135. 'fund_id' => $fund_id,
  136. 'balance' => 0,
  137. 'create_time' => time(),
  138. 'update_time' => time(),
  139. ];
  140. $fundModel = new FundModel();
  141. $fundModel->setData($data);
  142. if ($fundModel->save() === false) {
  143. return 'sys error';
  144. }
  145. return $fundModel;
  146. }
  147. /**
  148. * 写入更新日志
  149. *
  150. * @param $user_id
  151. * @param $fund_id
  152. * @param $amount
  153. * @param $type
  154. * @param $id
  155. * @param $remark
  156. */
  157. private static function log(
  158. FundModel $data_Model,
  159. $user_id,
  160. $fund_id,
  161. $amount,
  162. LOG_TYPE $type,
  163. $id,
  164. $remark,
  165. $create_ip = ''
  166. ) {
  167. // 读取最新的余额信息
  168. $later_balance = $data_Model->balance + $amount;
  169. $before_balance = $data_Model->balance;
  170. # 读取最后一条记录进行验证
  171. $lastLog = FundLogModel::findLastUserFund($user_id, $fund_id);
  172. // dump($data8);
  173. # 读取最新的余额信息
  174. if ($lastLog === null) {
  175. $data8_arr = [];
  176. # 没有日志判断是否为0
  177. if (bccomp(0, $data_Model->balance, 3) !== 0) {
  178. # 前后效验不通过,
  179. Logger::error('前后效验不通过'." user_id: $user_id , fund_id :$fund_id ");
  180. return '_fund-log-validation-fails-201';
  181. }
  182. } else {
  183. // dump($lastLog);
  184. if (bccomp($lastLog->later_balance, $data_Model->balance, 3) !== 0) {
  185. # 前后效验不通过,
  186. Logger::error('fund-error', [$lastLog->toArray(), $data_Model->toArray()]);
  187. return '_fund-log-validation-fails-210';
  188. }
  189. }
  190. return Log::create_log($user_id, $fund_id, $amount, $remark, $later_balance, $before_balance, $id,
  191. $type->value(), $lastLog);
  192. }
  193. /**
  194. * 获取账户信息
  195. *
  196. * @param $user_id
  197. * @param $fund_id
  198. */
  199. public static function info($user_id, $fund_id)
  200. {
  201. $ModelData = self::get_account($user_id, $fund_id);
  202. return $ModelData->toArray();
  203. }
  204. /**
  205. * @param $userId
  206. * @param $fundIds
  207. * @return mixed[]
  208. * 获取用户全部资金账户
  209. */
  210. public static function getAllAccount($userId,$fundIds)
  211. {
  212. $modelData = FundModel::getAllAccount($userId,$fundIds);
  213. return $modelData->toArray();
  214. }
  215. }