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

95 lines
3.0 KiB
PHP

<?php
declare(strict_types=1);
namespace KupShop\BonusProgramBundle\Utils\Exchange;
use KupShop\BonusProgramBundle\Utils\BonusProvider;
use KupShop\KupShopBundle\Context\UserContext;
use KupShop\KupShopBundle\Util\Contexts;
use KupShop\OrderingBundle\Util\Discount\DiscountGenerator;
use Query\Operator;
class BonusExchangeUtil
{
private BonusProvider $bonusProvider;
private DiscountGenerator $discountGenerator;
public function __construct(BonusProvider $bonusProvider, DiscountGenerator $discountGenerator)
{
$this->bonusProvider = $bonusProvider;
$this->discountGenerator = $discountGenerator;
}
public function exchange(int $id, ?int $userId = null): bool
{
if (!$userId) {
if (!($userId = Contexts::get(UserContext::class)->getActiveId())) {
throw new \InvalidArgumentException('There is no active user neither userId argument was not specified');
}
}
return sqlGetConnection()->transactional(function () use ($id, $userId) {
if (!($item = $this->getExchangeItem($id))) {
throw new \RuntimeException('Bonus program exchange item not found');
}
$userPoints = $this->bonusProvider->getActivePointsAmount($userId);
if ($userPoints < $item['points']) {
return false;
}
// generate new coupon for specified user
$generated = $this->generateUserCoupon($item, (int) $item['id_discount'], (int) $userId);
if (($generated['count'] ?? 0) > 0) {
// subtract points from user
sqlQueryBuilder()
->insert('bonus_points')
->directValues(
[
'id_user' => $userId,
'points' => toDecimal($item['points'])->mul(\DecimalConstants::negativeOne()),
'date_created' => date('Y-m-d H:i:s'),
'note' => sprintf(translate_shop('exchangeLogMessage', 'bonus_program'), $item['points'], $item['name']),
'status' => 'active',
]
)->execute();
return true;
}
return false;
});
}
public function getExchangeItem(int $id): ?array
{
$item = sqlQueryBuilder()
->select('*')
->from('bonus_points_exchange')
->where(
Operator::equals(
[
'id' => $id,
'active' => 1,
]
)
)
->orderBy('id', 'DESC')
->forUpdate()
->execute()->fetchAssociative();
if (!$item) {
return null;
}
return $item;
}
protected function generateUserCoupon(array $item, int $discountId, int $userId): array
{
return $this->discountGenerator->generateNewCoupons(id_discount: $discountId, userId: $userId);
}
}