Cash.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: leo
  5. * Date: 2018/10/30
  6. * Time: 下午3:19
  7. */
  8. namespace common\helpers\user;
  9. use common\helpers\Date;
  10. use common\helpers\Form;
  11. use common\libs\lock\RedisLock;
  12. use common\models\FlowWallet;
  13. use common\models\Period;
  14. use common\models\UserWallet;
  15. use yii\base\Exception;
  16. use yii\db\Expression;
  17. class Cash {
  18. const INCR_REDUCE = 0; // 减少
  19. const INCR_ADD = 1; // 增加
  20. const INCR_FREEZE = 2; // 冻结
  21. const INCR_UNFREEZE = 3; // 解冻
  22. const CASH_BALANCE_LOCK_KEY = 'Cash';
  23. /**
  24. * 获取当前可用余额
  25. * @param $userId
  26. * @return int|mixed
  27. */
  28. public static function getAvailableBalance($userId) {
  29. $oneData = UserWallet::find()->where('USER_ID=:USER_ID', [':USER_ID' => $userId])->asArray()->one();
  30. if ($oneData) {
  31. return $oneData['CASH'];
  32. } else {
  33. return 0;
  34. }
  35. }
  36. /**
  37. * 改变会员的现金余额
  38. * @param $userId
  39. * @param $type
  40. * @param $amount
  41. * @param array $params
  42. * @param bool $allowMinus
  43. * @return bool
  44. * @throws Exception
  45. * @throws \yii\db\Exception
  46. */
  47. public static function changeUserCash($userId, $type='CASH', $amount, $params = [], $allowMinus = false) {
  48. if ($amount == 0) return true;
  49. $period = Period::instance();
  50. if (!isset($params['PERIOD_NUM'])) {
  51. $periodNum = $period->getNowPeriodNum();
  52. } else {
  53. $periodNum = $params['PERIOD_NUM'];
  54. }
  55. $calcYearMonth = $period->getYearMonth($periodNum);
  56. // redis加锁(防止并发余额数值不准确出错)
  57. switch ($type) {
  58. case 'CASH':
  59. $lockKey = self::CASH_BALANCE_LOCK_KEY . $userId;
  60. break;
  61. default:
  62. throw new Exception('流水类型错误');
  63. }
  64. if (RedisLock::instance()->lock($lockKey)) {
  65. // 改变发奖
  66. $paramData = [];
  67. $oneUserBonusModel = UserWallet::findOne(['USER_ID' => $userId]);
  68. if ($oneUserBonusModel) {
  69. $paramData[$type] = new Expression($type.' + '.$amount);
  70. $oneUserBonusModel->$type += $amount;
  71. if ($oneUserBonusModel->$type < 0) {
  72. RedisLock::instance()->unlock($lockKey);
  73. throw new Exception('金额不足');
  74. }
  75. UserWallet::updateAll($paramData, 'USER_ID=:USER_ID', [':USER_ID' => $userId]);
  76. } else {
  77. $paramData = [
  78. 'USER_ID'=>$userId,
  79. $type=>$amount,
  80. 'UPDATED_AT'=>Date::nowTime()
  81. ];
  82. UserWallet::insertOne($paramData);
  83. // $oneUserBonusModel = new UserWallet();
  84. // $oneUserBonusModel->USER_ID = $userId;
  85. // $oneUserBonusModel->$type = $amount;
  86. // $oneUserBonusModel->UPDATED_AT = Date::nowTime();
  87. // if (!$oneUserBonusModel->save()) {
  88. // throw new \yii\db\Exception(Form::formatErrorsForApi($oneUserBonusModel->getErrors()));
  89. // }
  90. }
  91. unset($oneUserBonusModel,$paramData);
  92. // 获取发放完成的奖金信息
  93. $oneUserBonus = UserWallet::find()->where('USER_ID=:USER_ID', [':USER_ID' => $userId])->asArray()->one();
  94. // 记录流水
  95. $flowInsertData = [
  96. 'USER_ID' => $userId,
  97. 'CALC_ID' => $params['CALC_ID'] ?? null,
  98. 'AMOUNT' => $amount,
  99. 'TOTAL' => $oneUserBonus[$type],
  100. 'IS_INCR' => $amount > 0 ? FlowWallet::INCR_ADD : FlowWallet::INCR_REDUCE,
  101. 'REMARK' => $params['REMARK'] ?? null,
  102. 'PERIOD_NUM' => $params['PERIOD_NUM'] ?? $periodNum,
  103. 'CALC_MONTH' => $calcYearMonth,
  104. 'P_MONTH' => Date::ociToDate(),
  105. 'CREATED_AT' => $params['TIME'] ?? Date::nowTime(),
  106. 'ADMIN_NAME' => $params['ADMIN_NAME'] ?? 'system',
  107. 'SORT' => $params['SORT'] ?? 0,
  108. 'TRANSFER_SN' => $params['TRANSFER_SN'] ?? '',
  109. ];
  110. if (strtolower($type) == 'cash') FlowWallet::insertOne($flowInsertData);
  111. unset($flowInsertData);
  112. RedisLock::instance()->unlock($lockKey);
  113. } else {
  114. throw new Exception('流水产生错误');
  115. }
  116. return true;
  117. }
  118. /**
  119. * 清空会员现金所有流水
  120. * @param $userId
  121. * @param array $params
  122. * @throws Exception
  123. * @throws \yii\db\Exception
  124. */
  125. public static function clearAllCash($userId, $params = []) {
  126. // 先查找会员的全部余额
  127. $userWallet = UserWallet::findOne(['USER_ID' => $userId]);
  128. // 如果没有会员余额数据,新建余额数据
  129. if (!$userWallet) {
  130. UserWallet::insertOne(['USER_ID' => $userId, 'CREATED_AT' => Date::nowTime()]);
  131. } else {
  132. $period = Period::instance();
  133. $field = 'CASH';
  134. if ($userWallet[$field]<=0) return;
  135. $flowInsertData = [
  136. 'USER_ID' => $userId,
  137. 'CALC_ID' => $params['CALC_ID'] ?? null,
  138. 'AMOUNT' => -$userWallet[$field],
  139. 'TOTAL' => 0,
  140. 'IS_INCR' => FlowWallet::INCR_REDUCE,
  141. 'REMARK' => $params['REMARK'] ?? null,
  142. 'PERIOD_NUM' => $params['PERIOD_NUM'] ?? $period->getNowPeriodNum(),
  143. 'CALC_MONTH' => $period->getNowYearMonth(),
  144. 'P_MONTH' => Date::ociToDate(),
  145. 'CREATED_AT' => $params['TIME'] ?? Date::nowTime(),
  146. 'ADMIN_NAME' => $params['ADMIN_NAME'] ?? 'system',
  147. 'SORT' => $params['SORT'] ?? 0,
  148. 'TRANSFER_SN' => $params['TRANSFER_SN'] ?? '',
  149. ];
  150. // 流水
  151. if (strtolower($field) == 'cash') FlowWallet::insertOne($flowInsertData);
  152. // 清空
  153. $userWallet->CASH = 0;
  154. if (!$userWallet->save()) {
  155. throw new Exception(Form::formatErrorsForApi($userWallet->getErrors()));
  156. }
  157. }
  158. FlowWallet::updateAll(['DELETED' => 1, 'DELETED_AT' => Date::nowTime()], 'USER_ID=:USER_ID', [':USER_ID' => $userId]);
  159. }
  160. /**
  161. * 是否存在现金余额
  162. * @param $userId
  163. * @return bool
  164. */
  165. public static function hasCash($userId) {
  166. $userWallet = UserWallet::findOne(['USER_ID' => $userId]);
  167. if (!$userWallet) {
  168. return false;
  169. }
  170. if (isset($userWallet['CASH']) && $userWallet['CASH'] > 0) {
  171. return true;
  172. }
  173. }
  174. /**
  175. * 获取金额用于日志
  176. * @param $userId
  177. * @return array
  178. */
  179. public static function getLogData($userId){
  180. $userWallet = UserWallet::findOne(['USER_ID' => $userId]);
  181. $userName = Info::getUserNameByUserId($userId);
  182. $data = [];
  183. $data[$userId]['label'] = $userName.'余额';
  184. $data[$userId]['value'] = '奖金'.self::getAvailableBalance($userId).',现金'.$userWallet['CASH'];
  185. return $data;
  186. }
  187. }