| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- <?php
- namespace common\models;
- use common\helpers\Date;
- use common\helpers\LoggerTool;
- use common\helpers\Tool;
- use common\libs\lock\RedisLock;
- use Yii;
- use common\libs\logging\operate\valueType\Config as ValueTypeConfig;
- use yii\base\Exception;
- use yii\db\Expression;
- /**
- * This is the model class for table "{{%USER_PERFORMANCE}}".
- *
- * @property string $ID
- * @property string $USER_ID
- * @property string $CASH
- * @property integer $UPDATED_AT
- * @property integer $CLEAR_BY_CLOSED_AT
- * @property User $user
- */
- class UserPerformance extends \common\components\ActiveRecord
- {
- const NEWS = 10;
- const USING = 20;
- const FINISHED = 30;
- const NULLIFY = 40;
- const EXPIRED = 50;
- const USER_PERFORMANCE_BALANCE_LOCK_KEY = 'userPerformanceLock';
- public static function getEffective(): array
- {
- return [self::NEWS, self::USING];
- }
- public static function getInvalid(): array
- {
- return [self::FINISHED, self::NULLIFY, self::EXPIRED];
- }
- /**
- * {@inheritdoc}
- */
- public static function tableName()
- {
- return '{{%USER_PERFORMANCE}}';
- }
- /**
- * @inheritdoc
- */
- public function rules()
- {
- return [
- [['USER_ID'], 'required'],
- [['AMOUNTS', 'ORIGINAL'], 'number'],
- [['UPDATED_AT', 'STATUS_ID'], 'integer'],
- [['ID','USER_ID'], 'string', 'max' => 32],
- [['USER_ID'], 'unique'],
- ];
- }
- /**
- * @inheritdoc
- */
- public function attributeLabels()
- {
- return [
- 'ID' => 'ID',
- 'USER_ID' => '用户id',
- 'AMOUNTS' => '当前余额',
- 'ORIGINAL' => '原始金额',
- 'UPDATED_AT' => '修改时间',
- ];
- }
- /**
- * 获取一名会员的余额
- * @param $userId
- * @return array|null
- */
- public static function getAmountByUserId($userId)
- {
- $data = UserPerformance::find()->select('SUM(AMOUNTS) AS AMOUNTS')->where('USER_ID=:USER_ID AND STATUS_ID<(:STATUS_ID)', [':USER_ID' => $userId, ':STATUS_ID' => self::FINISHED])->asArray()->one();
- if(!$data){
- $data = [
- 'USER_ID' => $userId,
- 'AMOUNTS' => 0,
- ];
- }
- return $data;
- }
- public static function getAmounts($userId)
- {
- $data = UserPerformance::find()->select('SUM(AMOUNTS) AS AMOUNTS')->where('USER_ID=:USER_ID AND STATUS_ID<(:STATUS_ID)', [':USER_ID' => $userId, ':STATUS_ID' => self::FINISHED])->asArray()->one();
- return $data['AMOUNTS'] ?? 0;
- }
- /**
- * @param $userId
- * @param $amount
- * @param string $orderId
- * @return true
- * @throws Exception
- * @throws \yii\db\Exception
- */
- public static function changeUserPerformance($userId, $amount, string $orderId = ''): bool
- {
- if ($amount == 0) {
- return true;
- }
- // 会员总绩效奖金
- $userPerformanceAmount = self::getAmountByUserId($userId);
- if ($amount > $userPerformanceAmount) {
- throw new Exception(Yii::t('app', 'applicantPrpShort'));
- }
- $period = Period::instance();
- $periodNum = $period->getNowPeriodNum();
- $calcYearMonth = $period->getYearMonth($periodNum);
- // redis加锁(防止并发余额数值不准确出错)
- $lockKey = self::USER_PERFORMANCE_BALANCE_LOCK_KEY . $userId;
- if (RedisLock::instance()->lock($lockKey)) {
- // 根据规则获取绩效奖金:过期时间(升序) -> 发放时间(升序)
- $records = self::find()
- ->where('USER_ID=:USER_ID AND AMOUNTS>0 AND STATUS_ID<:STATUS_ID', [':USER_ID' => $userId, ':STATUS_ID' => self::FINISHED])
- ->orderBy('EXPIRED_AT ASC, CREATED_AT ASC')
- ->asArray()
- ->all();
- $db = \Yii::$app->db;
- $transaction = $db->beginTransaction();
- try {
- // 循环扣除绩效奖金
- $surplus = $amount;
- foreach ($records as $record) {
- $balance = 0;
- if ($record['AMOUNTS'] > $surplus) {
- $balance = $record['AMOUNTS'] - $surplus;
- // 扣除奖金
- UserPerformance::updateAll(['AMOUNTS' => $balance, 'STATUS_ID' => self::USING], 'ID=:ID', [':ID' => $record['ID']]);
- // 写日志
- UserPerformanceLogs::changeAmountLogs($record['ID'], $surplus, $periodNum, $orderId);
- break;
- }
- if ($record['AMOUNTS'] == $surplus) {
- $balance = $record['AMOUNTS'] - $surplus;
- // 扣除奖金
- UserPerformance::updateAll(['AMOUNTS' => $balance, 'STATUS_ID' => self::FINISHED], 'ID=:ID', [':ID' => $record['ID']]);
- // 写日志
- UserPerformanceLogs::changeAmountLogs($record['ID'], $surplus, $periodNum, $orderId);
- break;
- }
- if ($record['AMOUNTS'] < $surplus) {
- $balance = $surplus - $record['AMOUNTS'];
- $surplus = $balance;
- // 扣除奖金
- UserPerformance::updateAll(['AMOUNTS' => 0, 'STATUS_ID' => self::FINISHED], 'ID=:ID', [':ID' => $record['ID']]);
- // 写日志
- UserPerformanceLogs::changeAmountLogs($record['ID'], $surplus, $periodNum, $orderId);
- }
- }
- $transaction->commit();
- } catch (\Exception $e) {
- $transaction->rollBack();
- throw new Exception($e->getMessage());
- }
- // 解除锁
- RedisLock::instance()->unlock($lockKey);
- } else {
- throw new Exception(Yii::t('app', 'flowCreateError'));
- }
- return true;
- }
- /**
- * 绩效奖金发放
- * @param $userId
- * @param $amount
- * @param $bountyPeriodNum
- * @return bool
- * @throws Exception
- */
- public static function sentUserPerformance($userId, $amount, $bountyPeriodNum): bool
- {
- if ($amount == 0) {
- return true;
- }
- // 会员国家
- $countryCode = Countries::getById(User::getEnCodeInfo($userId)['COUNTRY_ID'])['CODE'];
- $period = Period::instance();
- $periodNum = $period->getNowPeriodNum();
- $db = \Yii::$app->db;
- $transaction = $db->beginTransaction();
- try {
- // 奖金发放
- $id = 'EP' . Tool::generateUserPerformanceNo($countryCode);
- self::insertOne([
- 'ID' => $id,
- 'USER_ID' => $userId,
- 'AMOUNTS' => $amount,
- 'ORIGINAL' => $amount,
- 'STATUS_ID' => self::NEWS,
- 'EXPIRED_AT' => date('Y-m-d H:i:s', strtotime('+1 year', time())),
- 'CREATED_AT' => date('Y-m-d H:i:s', time()),
- 'UPDATED_AT' => date('Y-m-d H:i:s', time()),
- 'REMARK' => DealType::getDealTypeTagById(DealType::USER_PERFORMANCE_SEND),
- 'BOUNTY_PERIOD_NUM' => $bountyPeriodNum,
- 'PAID_PERIOD_NUM' => $periodNum,
- ]);
- // 写日志
- UserPerformanceLogs::changeAmountLogs($id, $amount, $periodNum, '', DealType::getDealTypeTagById(DealType::USER_PERFORMANCE_SEND));
- $transaction->commit();
- } catch (\Exception $e) {
- $transaction->rollBack();
- throw new Exception(sprintf('PB奖金挂网异常:File: %s, Line: {%s}, message: %s', $e->getFile(), $e->getLine(), $e->getMessage()));
- }
- return true;
- }
- /**
- * 绩效奖金发放
- * @param $userId
- * @param $amount
- * @param $bountyPeriodNum
- * @return bool
- * @throws Exception
- */
- public static function sentUserPerformanceApi($userId, $amount, $bountyPeriodNum): bool
- {
- if ($amount == 0) {
- return true;
- }
- // 会员国家
- $countryCode = Countries::getById(User::getEnCodeInfo($userId)['COUNTRY_ID'])['CODE'];
- $db = \Yii::$app->db;
- $transaction = $db->beginTransaction();
- try {
- // 奖金发放
- $id = 'EP' . Tool::generateUserPerformanceNo($countryCode);
- self::insertOne([
- 'ID' => $id,
- 'USER_ID' => $userId,
- 'AMOUNTS' => $amount,
- 'ORIGINAL' => $amount,
- 'STATUS_ID' => self::NEWS,
- 'EXPIRED_AT' => date('Y-m-d H:i:s', strtotime('+1 year', time())),
- 'CREATED_AT' => date('Y-m-d H:i:s', time()),
- 'UPDATED_AT' => date('Y-m-d H:i:s', time()),
- 'REMARK' => DealType::getDealTypeTagById(DealType::USER_PERFORMANCE_SEND),
- 'BOUNTY_PERIOD_NUM' => $bountyPeriodNum,
- 'PAID_PERIOD_NUM' => $bountyPeriodNum+1,
- ]);
- // 写日志
- UserPerformanceLogs::changeAmountLogs($id, $amount, $bountyPeriodNum+1, '', DealType::getDealTypeTagById(DealType::USER_PERFORMANCE_SEND));
- $transaction->commit();
- } catch (\Exception $e) {
- $transaction->rollBack();
- throw new Exception(sprintf('PB奖金挂网异常:File: %s, Line: {%s}, message: %s', $e->getFile(), $e->getLine(), $e->getMessage()));
- }
- return true;
- }
- }
|