2021-06-21 02:01:26 +08:00
|
|
|
<?php
|
|
|
|
|
namespace App\Repositories;
|
|
|
|
|
|
2023-01-05 18:29:31 +08:00
|
|
|
use App\Exceptions\NexusException;
|
2021-06-21 02:01:26 +08:00
|
|
|
use App\Models\BonusLogs;
|
|
|
|
|
use App\Models\HitAndRun;
|
2023-01-05 18:29:31 +08:00
|
|
|
use App\Models\Invite;
|
2022-01-19 23:54:55 +08:00
|
|
|
use App\Models\Medal;
|
2021-06-21 02:01:26 +08:00
|
|
|
use App\Models\Setting;
|
|
|
|
|
use App\Models\User;
|
2022-03-19 14:55:43 +08:00
|
|
|
use App\Models\UserMedal;
|
2023-01-05 18:29:31 +08:00
|
|
|
use App\Models\UserMeta;
|
2021-06-21 02:01:26 +08:00
|
|
|
use Carbon\Carbon;
|
2021-12-14 16:22:03 +08:00
|
|
|
use Illuminate\Database\Eloquent\Builder;
|
2021-06-21 02:01:26 +08:00
|
|
|
use Nexus\Database\NexusDB;
|
|
|
|
|
|
|
|
|
|
class BonusRepository extends BaseRepository
|
|
|
|
|
{
|
2022-01-19 23:54:55 +08:00
|
|
|
public function consumeToCancelHitAndRun($uid, $hitAndRunId): bool
|
2021-06-21 02:01:26 +08:00
|
|
|
{
|
2021-06-22 14:34:45 +08:00
|
|
|
if (!HitAndRun::getIsEnabled()) {
|
2021-06-21 02:01:26 +08:00
|
|
|
throw new \LogicException("H&R not enabled.");
|
|
|
|
|
}
|
|
|
|
|
$user = User::query()->findOrFail($uid);
|
|
|
|
|
$hitAndRun = HitAndRun::query()->findOrFail($hitAndRunId);
|
|
|
|
|
if ($hitAndRun->uid != $uid) {
|
|
|
|
|
throw new \LogicException("H&R: $hitAndRunId not belongs to user: $uid.");
|
|
|
|
|
}
|
2022-06-08 14:15:59 +08:00
|
|
|
if ($hitAndRun->status == HitAndRun::STATUS_PARDONED) {
|
|
|
|
|
throw new \LogicException("H&R: $hitAndRunId already pardoned.");
|
|
|
|
|
}
|
2021-06-21 02:01:26 +08:00
|
|
|
$requireBonus = BonusLogs::getBonusForCancelHitAndRun();
|
2022-01-19 23:54:55 +08:00
|
|
|
NexusDB::transaction(function () use ($user, $hitAndRun, $requireBonus) {
|
2021-06-21 02:01:26 +08:00
|
|
|
$comment = nexus_trans('hr.bonus_cancel_comment', [
|
|
|
|
|
'bonus' => $requireBonus,
|
|
|
|
|
], $user->locale);
|
|
|
|
|
do_log("comment: $comment");
|
2022-01-19 23:54:55 +08:00
|
|
|
|
|
|
|
|
$this->consumeUserBonus($user, $requireBonus, BonusLogs::BUSINESS_TYPE_CANCEL_HIT_AND_RUN, "$comment(H&R ID: {$hitAndRun->id})");
|
|
|
|
|
|
2021-06-21 02:01:26 +08:00
|
|
|
$hitAndRun->update([
|
|
|
|
|
'status' => HitAndRun::STATUS_PARDONED,
|
2022-08-02 01:58:08 +08:00
|
|
|
'comment' => NexusDB::raw("if(comment = '', '$comment', concat_ws('\n', '$comment', comment))"),
|
2021-06-21 02:01:26 +08:00
|
|
|
]);
|
|
|
|
|
});
|
|
|
|
|
|
2022-01-19 23:54:55 +08:00
|
|
|
return true;
|
2021-06-21 02:01:26 +08:00
|
|
|
|
|
|
|
|
}
|
2021-12-14 16:22:03 +08:00
|
|
|
|
|
|
|
|
|
2022-01-19 23:54:55 +08:00
|
|
|
public function consumeToBuyMedal($uid, $medalId): bool
|
|
|
|
|
{
|
|
|
|
|
$user = User::query()->findOrFail($uid);
|
|
|
|
|
$medal = Medal::query()->findOrFail($medalId);
|
|
|
|
|
$exists = $user->valid_medals()->where('medal_id', $medalId)->exists();
|
|
|
|
|
do_log(last_query());
|
|
|
|
|
if ($exists) {
|
|
|
|
|
throw new \LogicException("user: $uid already own this medal: $medalId.");
|
|
|
|
|
}
|
2022-12-19 19:01:22 +08:00
|
|
|
if ($medal->get_type != Medal::GET_TYPE_EXCHANGE) {
|
|
|
|
|
throw new \LogicException("This medal can not be buy.");
|
|
|
|
|
}
|
2023-01-25 20:22:32 +08:00
|
|
|
if ($medal->inventory !== null && $medal->inventory <= 0) {
|
|
|
|
|
throw new \LogicException("Inventory empty.");
|
|
|
|
|
}
|
|
|
|
|
$now = now();
|
|
|
|
|
if ($medal->sale_begin_time && $medal->sale_begin_time->gt($now)) {
|
|
|
|
|
throw new \LogicException("Before sale begin time.");
|
|
|
|
|
}
|
|
|
|
|
if ($medal->sale_end_time && $medal->sale_end_time->lt($now)) {
|
|
|
|
|
throw new \LogicException("After sale end time.");
|
|
|
|
|
}
|
2022-01-19 23:54:55 +08:00
|
|
|
$requireBonus = $medal->price;
|
|
|
|
|
NexusDB::transaction(function () use ($user, $medal, $requireBonus) {
|
|
|
|
|
$comment = nexus_trans('bonus.comment_buy_medal', [
|
|
|
|
|
'bonus' => $requireBonus,
|
|
|
|
|
'medal_name' => $medal->name,
|
|
|
|
|
], $user->locale);
|
|
|
|
|
do_log("comment: $comment");
|
|
|
|
|
$this->consumeUserBonus($user, $requireBonus, BonusLogs::BUSINESS_TYPE_BUY_MEDAL, "$comment(medal ID: {$medal->id})");
|
|
|
|
|
$expireAt = null;
|
|
|
|
|
if ($medal->duration > 0) {
|
|
|
|
|
$expireAt = Carbon::now()->addDays($medal->duration)->toDateTimeString();
|
|
|
|
|
}
|
2022-03-19 14:55:43 +08:00
|
|
|
$user->medals()->attach([$medal->id => ['expire_at' => $expireAt, 'status' => UserMedal::STATUS_NOT_WEARING]]);
|
2023-01-25 20:22:32 +08:00
|
|
|
if ($medal->inventory !== null) {
|
|
|
|
|
$affectedRows = NexusDB::table('medals')
|
|
|
|
|
->where('id', $medal->id)
|
|
|
|
|
->where('inventory', $medal->inventory)
|
|
|
|
|
->decrement('inventory')
|
|
|
|
|
;
|
|
|
|
|
if ($affectedRows != 1) {
|
|
|
|
|
throw new \RuntimeException("Decrement medal({$medal->id}) inventory affected rows != 1($affectedRows)");
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-01-19 23:54:55 +08:00
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-04 17:26:26 +08:00
|
|
|
public function consumeToBuyAttendanceCard($uid): bool
|
|
|
|
|
{
|
|
|
|
|
$user = User::query()->findOrFail($uid);
|
|
|
|
|
$requireBonus = BonusLogs::getBonusForBuyAttendanceCard();
|
|
|
|
|
NexusDB::transaction(function () use ($user, $requireBonus) {
|
|
|
|
|
$comment = nexus_trans('bonus.comment_buy_attendance_card', [
|
|
|
|
|
'bonus' => $requireBonus,
|
|
|
|
|
], $user->locale);
|
|
|
|
|
do_log("comment: $comment");
|
2022-05-29 18:22:56 +08:00
|
|
|
$this->consumeUserBonus($user, $requireBonus, BonusLogs::BUSINESS_TYPE_BUY_ATTENDANCE_CARD, $comment);
|
2022-04-04 17:26:26 +08:00
|
|
|
User::query()->where('id', $user->id)->increment('attendance_card');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-05 18:29:31 +08:00
|
|
|
|
|
|
|
|
public function consumeToBuyTemporaryInvite($uid, $count = 1): bool
|
|
|
|
|
{
|
|
|
|
|
$requireBonus = BonusLogs::getBonusForBuyTemporaryInvite();
|
2023-01-07 16:27:27 +08:00
|
|
|
if ($requireBonus <= 0) {
|
|
|
|
|
throw new \RuntimeException("Temporary invite require bonus <= 0 !");
|
|
|
|
|
}
|
|
|
|
|
$user = User::query()->findOrFail($uid);
|
2023-01-05 18:29:31 +08:00
|
|
|
$toolRep = new ToolRepository();
|
|
|
|
|
$hashArr = $toolRep->generateUniqueInviteHash([], $count, $count);
|
|
|
|
|
NexusDB::transaction(function () use ($user, $requireBonus, $hashArr) {
|
|
|
|
|
$comment = nexus_trans('bonus.comment_buy_temporary_invite', [
|
|
|
|
|
'bonus' => $requireBonus,
|
|
|
|
|
'count' => count($hashArr)
|
|
|
|
|
], $user->locale);
|
|
|
|
|
do_log("comment: $comment");
|
|
|
|
|
$this->consumeUserBonus($user, $requireBonus, BonusLogs::BUSINESS_TYPE_BUY_TEMPORARY_INVITE, $comment);
|
|
|
|
|
$invites = [];
|
|
|
|
|
foreach ($hashArr as $hash) {
|
|
|
|
|
$invites[] = [
|
|
|
|
|
'inviter' => $user->id,
|
|
|
|
|
'invitee' => '',
|
|
|
|
|
'hash' => $hash,
|
|
|
|
|
'valid' => 0,
|
|
|
|
|
'expired_at' => Carbon::now()->addDays(Invite::TEMPORARY_INVITE_VALID_DAYS),
|
|
|
|
|
'created_at' => Carbon::now(),
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
Invite::query()->insert($invites);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function consumeToBuyRainbowId($uid, $duration = 30): bool
|
|
|
|
|
{
|
|
|
|
|
$user = User::query()->findOrFail($uid);
|
|
|
|
|
$requireBonus = BonusLogs::getBonusForBuyRainbowId();
|
|
|
|
|
NexusDB::transaction(function () use ($user, $requireBonus, $duration) {
|
|
|
|
|
$comment = nexus_trans('bonus.comment_buy_rainbow_id', [
|
|
|
|
|
'bonus' => $requireBonus,
|
|
|
|
|
'duration' => $duration,
|
|
|
|
|
], $user->locale);
|
|
|
|
|
do_log("comment: $comment");
|
|
|
|
|
$this->consumeUserBonus($user, $requireBonus, BonusLogs::BUSINESS_TYPE_BUY_RAINBOW_ID, $comment);
|
|
|
|
|
$metaData = [
|
|
|
|
|
'meta_key' => UserMeta::META_KEY_PERSONALIZED_USERNAME,
|
|
|
|
|
'duration' => $duration,
|
|
|
|
|
];
|
|
|
|
|
$userRep = new UserRepository();
|
|
|
|
|
$userRep->addMeta($user, $metaData, $metaData, false);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function consumeToBuyChangeUsernameCard($uid): bool
|
|
|
|
|
{
|
|
|
|
|
$user = User::query()->findOrFail($uid);
|
|
|
|
|
$requireBonus = BonusLogs::getBonusForBuyChangeUsernameCard();
|
|
|
|
|
if (UserMeta::query()->where('uid', $uid)->where('meta_key', UserMeta::META_KEY_CHANGE_USERNAME)->exists()) {
|
|
|
|
|
throw new NexusException("user already has change username card");
|
|
|
|
|
}
|
|
|
|
|
NexusDB::transaction(function () use ($user, $requireBonus) {
|
|
|
|
|
$comment = nexus_trans('bonus.comment_buy_change_username_card', [
|
|
|
|
|
'bonus' => $requireBonus,
|
|
|
|
|
], $user->locale);
|
|
|
|
|
do_log("comment: $comment");
|
|
|
|
|
$this->consumeUserBonus($user, $requireBonus, BonusLogs::BUSINESS_TYPE_BUY_CHANGE_USERNAME_CARD, $comment);
|
|
|
|
|
$metaData = [
|
|
|
|
|
'meta_key' => UserMeta::META_KEY_CHANGE_USERNAME,
|
|
|
|
|
];
|
|
|
|
|
$userRep = new UserRepository();
|
|
|
|
|
$userRep->addMeta($user, $metaData, $metaData, false);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-25 03:31:19 +08:00
|
|
|
public function consumeUserBonus($user, $requireBonus, $logBusinessType, $logComment = '', array $userUpdates = [])
|
2022-01-19 23:54:55 +08:00
|
|
|
{
|
2022-07-25 03:31:19 +08:00
|
|
|
if (!isset(BonusLogs::$businessTypes[$logBusinessType])) {
|
|
|
|
|
throw new \InvalidArgumentException("Invalid logBusinessType: $logBusinessType");
|
|
|
|
|
}
|
|
|
|
|
if (isset($userUpdates['seedbonus']) || isset($userUpdates['bonuscomment'])) {
|
|
|
|
|
throw new \InvalidArgumentException("Not support update seedbonus or bonuscomment");
|
|
|
|
|
}
|
2022-06-08 14:15:59 +08:00
|
|
|
if ($requireBonus <= 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-07-25 03:31:19 +08:00
|
|
|
$user = $this->getUser($user);
|
2022-01-19 23:54:55 +08:00
|
|
|
if ($user->seedbonus < $requireBonus) {
|
|
|
|
|
do_log("user: {$user->id}, bonus: {$user->seedbonus} < requireBonus: $requireBonus", 'error');
|
2022-08-02 01:58:08 +08:00
|
|
|
throw new \LogicException("User bonus not enough.");
|
2022-01-19 23:54:55 +08:00
|
|
|
}
|
2022-07-25 03:31:19 +08:00
|
|
|
NexusDB::transaction(function () use ($user, $requireBonus, $logBusinessType, $logComment, $userUpdates) {
|
|
|
|
|
$logComment = addslashes($logComment);
|
2022-05-29 18:22:56 +08:00
|
|
|
$bonusComment = date('Y-m-d') . " - $logComment";
|
2022-01-19 23:54:55 +08:00
|
|
|
$oldUserBonus = $user->seedbonus;
|
|
|
|
|
$newUserBonus = bcsub($oldUserBonus, $requireBonus);
|
|
|
|
|
$log = "user: {$user->id}, requireBonus: $requireBonus, oldUserBonus: $oldUserBonus, newUserBonus: $newUserBonus, logBusinessType: $logBusinessType, logComment: $logComment";
|
|
|
|
|
do_log($log);
|
2022-07-25 03:31:19 +08:00
|
|
|
$userUpdates['seedbonus'] = $newUserBonus;
|
|
|
|
|
$userUpdates['bonuscomment'] = NexusDB::raw("if(bonuscomment = '', '$bonusComment', concat_ws('\n', '$bonusComment', bonuscomment))");
|
2022-01-19 23:54:55 +08:00
|
|
|
$affectedRows = NexusDB::table($user->getTable())
|
|
|
|
|
->where('id', $user->id)
|
|
|
|
|
->where('seedbonus', $oldUserBonus)
|
2022-07-25 03:31:19 +08:00
|
|
|
->update($userUpdates);
|
2022-01-19 23:54:55 +08:00
|
|
|
if ($affectedRows != 1) {
|
|
|
|
|
do_log("update user seedbonus affected rows != 1, query: " . last_query(), 'error');
|
|
|
|
|
throw new \RuntimeException("Update user seedbonus fail.");
|
|
|
|
|
}
|
|
|
|
|
$bonusLog = [
|
|
|
|
|
'business_type' => $logBusinessType,
|
|
|
|
|
'uid' => $user->id,
|
|
|
|
|
'old_total_value' => $oldUserBonus,
|
|
|
|
|
'value' => $requireBonus,
|
|
|
|
|
'new_total_value' => $newUserBonus,
|
2022-07-25 03:31:19 +08:00
|
|
|
'comment' => sprintf('[%s] %s', BonusLogs::$businessTypes[$logBusinessType]['text'], $logComment),
|
2022-01-19 23:54:55 +08:00
|
|
|
];
|
|
|
|
|
BonusLogs::query()->insert($bonusLog);
|
|
|
|
|
do_log("bonusLog: " . nexus_json_encode($bonusLog));
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-06-21 02:01:26 +08:00
|
|
|
}
|