Cash.php 7.4 KB

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