Files
kupshop/bundles/KupShop/BonusProgramBundle/Utils/BonusProvider.php
2025-08-02 16:30:27 +02:00

140 lines
3.9 KiB
PHP

<?php
namespace KupShop\BonusProgramBundle\Utils;
use Doctrine\DBAL\Exception;
use KupShop\KupShopBundle\Context\ContextManager;
use KupShop\KupShopBundle\Context\CurrencyContext;
use KupShop\KupShopBundle\Context\UserContext;
use KupShop\KupShopBundle\Util\Contexts;
use KupShop\KupShopBundle\Util\Price\Price;
use KupShop\OrderDiscountBundle\Util\DiscountManager;
use KupShop\OrderingBundle\Util\Purchase\PurchaseUtil;
use Symfony\Contracts\Service\Attribute\Required;
class BonusProvider
{
#[Required]
public DiscountManager $discountManager;
#[Required]
public PurchaseUtil $purchaseUtil;
public function __construct(
protected readonly UserContext $userContext,
protected readonly ContextManager $contextManager,
) {
}
/**
* @throws Exception
*/
public function getActivePointsAmount(int|\User|null $user): int
{
if ($user === null) {
return 0;
}
$contexts = [];
if ($user instanceof \User) {
$contexts[UserContext::class] = $user;
}
return $this->contextManager->activateContexts(
$contexts,
fn () => $this->handleFetchActivePointsAmount(is_int($user) ? $user : $user->id),
);
}
public function getActivePointsValue(\User $user): ?Price
{
if (!($points = $this->getActivePointsAmount($user))) {
return null;
}
if (!($actions = $this->getBonusProgramActions())) {
return null;
}
$currencyContext = Contexts::get(CurrencyContext::class);
$action = reset($actions);
if (!($pointValue = ($action['data']['discount'] ?? null))) {
return null;
}
$pointCurrency = $action['data']['unit'] ?? $currencyContext->getDefaultId();
$pointsValue = toDecimal($pointValue)->mul(toDecimal($points));
return new Price(
$pointsValue,
$currencyContext->getOrDefault($pointCurrency),
0
);
}
/**
* @throws Exception
* @throws \Exception
*/
protected function handleFetchActivePointsAmount(int $userId): int
{
$result = sqlQueryBuilder()
->select('SUM(points)')
->from('bonus_points')
->where(\Query\Operator::equals(['id_user' => $userId, 'status' => 'active']))
->execute()->fetchColumn();
return $result ? (int) $result : 0;
}
public function getPointsHistory($id_user, $spec = null)
{
$qb = sqlQueryBuilder()
->select('bp.*, o.order_no')
->from('bonus_points', 'bp')
->leftJoin('bp', 'orders', 'o', 'bp.id_order = o.id')
->where(\Query\Operator::equals(['bp.id_user' => $id_user]))
->orderBy('bp.date_created', 'DESC');
if ($spec) {
$qb->andWhere($spec);
}
return array_map(
function ($x) {
$x['data'] = json_decode($x['data'] ?: '', true) ?: [];
return $x;
},
$qb->execute()->fetchAllAssociative()
);
}
public function getPointsHistoryCount($id_user)
{
$qb = sqlQueryBuilder()
->select('COUNT(*) count')
->from('bonus_points', 'bp')
->where(\Query\Operator::equals(['bp.id_user' => $id_user]));
return $qb->execute()->fetchOne();
}
private function getBonusProgramActions(): array
{
$purchaseState = $this->purchaseUtil->getEmptyPurchaseState();
$actions = $purchaseState->getActions();
if (is_null($actions)) {
$this->discountManager->setPurchaseState($purchaseState);
$actions = $this->discountManager->getCurrentActions();
$purchaseState->setActions($actions);
$this->purchaseUtil->persistPurchaseState($purchaseState, true);
}
return $actions['bonus_program'] ?? [];
}
}