Update
This commit is contained in:
212
app/Helpers/FirstParty/Credits/CreditsHelper.php
Normal file
212
app/Helpers/FirstParty/Credits/CreditsHelper.php
Normal file
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers\FirstParty\Credits;
|
||||
|
||||
use App\Helpers\FirstParty\Purchase\PurchaseHelper;
|
||||
use App\Models\UserCredit;
|
||||
use App\Models\UserCreditTransaction;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class CreditsHelper
|
||||
{
|
||||
public static function getCreditPackByStripePriceId($stripe_price_id)
|
||||
{
|
||||
$credit_packs = self::getCreditPacks(null, true);
|
||||
|
||||
foreach ($credit_packs as $credit_pack) {
|
||||
|
||||
$stripe_price_ids = PurchaseHelper::getPlanSystemProperty($credit_pack, 'stripe.stripe_price_ids');
|
||||
|
||||
if (in_array($stripe_price_id, $stripe_price_ids)) {
|
||||
return $credit_pack;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function getCreditsPackById($id, $enabled = true, $system = false)
|
||||
{
|
||||
$credits_packs = self::getCreditPacks($enabled, $system);
|
||||
foreach ($credits_packs as $credits_pack) {
|
||||
if ($credits_pack['id'] == $id) {
|
||||
return $credits_pack;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function getCreditPacks($enabled = null, $system = true)
|
||||
{
|
||||
|
||||
$credit_packs = [];
|
||||
|
||||
$one_times = PurchaseHelper::getOneTimePurchases($enabled, $system);
|
||||
|
||||
foreach ($one_times as $one_time) {
|
||||
|
||||
if ($one_time['type'] == 'alacarte_credits') {
|
||||
$credit_packs[] = $one_time;
|
||||
}
|
||||
}
|
||||
|
||||
return $credit_packs;
|
||||
}
|
||||
|
||||
// ////
|
||||
|
||||
public static function getUserCredits(int $user_id): UserCredit
|
||||
{
|
||||
$user_credit = UserCredit::where('user_id', $user_id)->first();
|
||||
|
||||
if (! $user_credit) {
|
||||
$user_credit = UserCredit::create([
|
||||
'user_id' => $user_id,
|
||||
'subscription_credits' => 0,
|
||||
'alacarte_credits' => 0,
|
||||
'spend_subscription_first' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
return $user_credit;
|
||||
}
|
||||
|
||||
// when user purchase annual subscription, need to 12x the deposit amount
|
||||
public static function deposit(int $user_id, int $amount, string $type, ?string $description = null): bool
|
||||
{
|
||||
if ($amount <= 0) {
|
||||
throw new \InvalidArgumentException('Amount must be positive');
|
||||
}
|
||||
|
||||
if (! in_array($type, [UserCredit::TYPE_SUBSCRIPTION, UserCredit::TYPE_ALACARTE])) {
|
||||
throw new \InvalidArgumentException('Type must be subscription or alacarte');
|
||||
}
|
||||
|
||||
return DB::transaction(function () use ($user_id, $amount, $type, $description) {
|
||||
$user_credit = self::getUserCredits($user_id);
|
||||
|
||||
if ($type === UserCredit::TYPE_SUBSCRIPTION) {
|
||||
$user_credit->subscription_credits += $amount;
|
||||
} else {
|
||||
$user_credit->alacarte_credits += $amount;
|
||||
}
|
||||
|
||||
$user_credit->save();
|
||||
self::logTransaction($user_id, $type, 'deposit', $amount, $user_credit, $description);
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public static function spend(int $user_id, int $amount, ?string $description = null, ?bool $use_subscription_first = null): bool
|
||||
{
|
||||
if ($amount <= 0) {
|
||||
throw new \InvalidArgumentException('Amount must be positive');
|
||||
}
|
||||
|
||||
if (! self::canSpend($user_id, $amount)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return DB::transaction(function () use ($user_id, $amount, $description, $use_subscription_first) {
|
||||
$user_credit = self::getUserCredits($user_id);
|
||||
$remaining = $amount;
|
||||
$subscription_first = $use_subscription_first ?? $user_credit->spend_subscription_first;
|
||||
|
||||
$spend_order = $subscription_first
|
||||
? [UserCredit::TYPE_SUBSCRIPTION, UserCredit::TYPE_ALACARTE]
|
||||
: [UserCredit::TYPE_ALACARTE, UserCredit::TYPE_SUBSCRIPTION];
|
||||
|
||||
foreach ($spend_order as $type) {
|
||||
if ($remaining <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
$available = $type === UserCredit::TYPE_SUBSCRIPTION
|
||||
? $user_credit->subscription_credits
|
||||
: $user_credit->alacarte_credits;
|
||||
|
||||
if ($available > 0) {
|
||||
$to_spend = min($remaining, $available);
|
||||
|
||||
if ($type === UserCredit::TYPE_SUBSCRIPTION) {
|
||||
$user_credit->subscription_credits -= $to_spend;
|
||||
} else {
|
||||
$user_credit->alacarte_credits -= $to_spend;
|
||||
}
|
||||
|
||||
self::logTransaction($user_id, $type, 'spend', -$to_spend, $user_credit, $description);
|
||||
$remaining -= $to_spend;
|
||||
}
|
||||
}
|
||||
|
||||
$user_credit->save();
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public static function canSpend(int $user_id, int $amount): bool
|
||||
{
|
||||
$user_credit = self::getUserCredits($user_id);
|
||||
|
||||
return self::_getTotalBalance($user_credit) >= $amount;
|
||||
}
|
||||
|
||||
public static function summary(int $user_id): array
|
||||
{
|
||||
$user_credit = self::getUserCredits($user_id);
|
||||
|
||||
return [
|
||||
'subscription' => $user_credit->subscription_credits,
|
||||
'alacarte' => $user_credit->alacarte_credits,
|
||||
'total' => self::_getTotalBalance($user_credit),
|
||||
'preference' => $user_credit->spend_subscription_first ? 'subscription_first' : 'alacarte_first',
|
||||
];
|
||||
}
|
||||
|
||||
public static function balance(int $user_id, ?string $type = null): int
|
||||
{
|
||||
$user_credit = self::getUserCredits($user_id);
|
||||
|
||||
return match ($type) {
|
||||
UserCredit::TYPE_SUBSCRIPTION => $user_credit->subscription_credits,
|
||||
UserCredit::TYPE_ALACARTE => $user_credit->alacarte_credits,
|
||||
default => self::_getTotalBalance($user_credit),
|
||||
};
|
||||
}
|
||||
|
||||
private static function _getTotalBalance(UserCredit $user_credit): int
|
||||
{
|
||||
return $user_credit->subscription_credits + $user_credit->alacarte_credits;
|
||||
}
|
||||
|
||||
public static function setSpendSubscriptionFirst(int $user_id, bool $spendSubscriptionFirst): bool
|
||||
{
|
||||
$user_credit = self::getUserCredits($user_id);
|
||||
$user_credit->spend_subscription_first = $spendSubscriptionFirst;
|
||||
|
||||
return $user_credit->save();
|
||||
}
|
||||
|
||||
public static function transactionHistory(int $user_id, int $limit = 20): \Illuminate\Database\Eloquent\Collection
|
||||
{
|
||||
$user_credit = self::getUserCredits($user_id);
|
||||
|
||||
return $user_credit->transactions()->limit($limit)->get();
|
||||
}
|
||||
|
||||
private static function logTransaction(int $user_id, string $type, string $operation, int $amount, UserCredit $user_credit, ?string $description = null): void
|
||||
{
|
||||
UserCreditTransaction::create([
|
||||
'user_id' => $user_id,
|
||||
'credit_type' => $type,
|
||||
'operation' => $operation,
|
||||
'amount' => $amount,
|
||||
'subscription_balance_after' => $user_credit->subscription_credits,
|
||||
'alacarte_balance_after' => $user_credit->alacarte_credits,
|
||||
'description' => $description,
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user