Files
esun3d/app/code/Esun/Reward/Controller/Cart/Apply.php
T
2026-09-15 10:35:56 +08:00

47 lines
3.1 KiB
PHP

<?php
declare(strict_types=1);
namespace Esun\Reward\Controller\Cart;
use Esun\Reward\Model\BalanceManager;
use Esun\Reward\Model\Config;
use Esun\Reward\Model\ReservationManager;
use Magento\Checkout\Model\Session;
use Magento\Checkout\Helper\Data as CheckoutHelper;
use Magento\Customer\Model\Session as CustomerSession;
use Magento\Framework\App\Action\HttpPostActionInterface;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\Controller\Result\JsonFactory;
use Magento\Framework\Data\Form\FormKey\Validator;
use Magento\Quote\Api\CartRepositoryInterface;
class Apply implements HttpPostActionInterface
{
public function __construct(private readonly RequestInterface $request, private readonly Validator $formKey, private readonly JsonFactory $jsonFactory, private readonly Session $checkoutSession, private readonly CustomerSession $customerSession, private readonly CartRepositoryInterface $quotes, private readonly BalanceManager $balances, private readonly ReservationManager $reservations, private readonly Config $config, private readonly CheckoutHelper $checkoutHelper) {}
public function execute()
{
$result = $this->jsonFactory->create();
try {
if (!$this->formKey->validate($this->request) || !$this->customerSession->isLoggedIn()) { throw new \Magento\Framework\Exception\LocalizedException(__('Please sign in to use reward points.')); }
$quote = $this->checkoutSession->getQuote(); $requested = max(0, (int)$this->request->getParam('points'));
$maximum = $this->config->maxCheckoutPoints((int)$quote->getStoreId()); $customerId = (int)$this->customerSession->getCustomerId(); $websiteId = (int)$quote->getStore()->getWebsiteId();
$balance = (int)$this->balances->getAccount($customerId, $websiteId)['balance'];
$quote->setData('reward_points_used', 0)->setTotalsCollectedFlag(false)->collectTotals();
$valueLimit = (int)floor(max(0.0, (float)$quote->getBaseGrandTotal()) * $this->config->redemptionRate((int)$quote->getStoreId()));
$points = min($requested, $maximum, $balance, $valueLimit);
$this->reservations->reserve($customerId, $websiteId, (int)$quote->getId(), $points + (int)$quote->getData('reward_product_points'));
$quote->setData('reward_points_used', $points)->setTotalsCollectedFlag(false)->collectTotals(); $this->quotes->save($quote);
return $result->setData([
'success' => true,
'points' => $points,
'balance' => $balance,
'reward_discount' => (float)$quote->getData('reward_discount_amount') > 0
? '-' . $this->checkoutHelper->formatPrice((float)$quote->getData('reward_discount_amount'))
: '',
'grand_total' => $this->checkoutHelper->formatPrice((float)$quote->getGrandTotal()),
'message' => $points > 0 ? (string)__('Reward points were applied.') : (string)__('Reward points were removed.'),
]);
} catch (\Throwable $e) { return $result->setHttpResponseCode(400)->setData(['success' => false, 'message' => $e->getMessage()]); }
}
}