63 lines
4.1 KiB
PHP
63 lines
4.1 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace Esun\Reward\Observer;
|
|
|
|
use Esun\Reward\Model\BalanceManager;
|
|
use Esun\Reward\Model\Config;
|
|
use Magento\Framework\Event\Observer;
|
|
use Magento\Framework\Event\ObserverInterface;
|
|
use Magento\Sales\Model\Order\Creditmemo;
|
|
|
|
class ReverseCreditmemoPoints implements ObserverInterface
|
|
{
|
|
public function __construct(private readonly BalanceManager $balanceManager, private readonly Config $config) {}
|
|
public function execute(Observer $observer): void
|
|
{
|
|
/** @var Creditmemo|null $creditmemo */ $creditmemo = $observer->getEvent()->getCreditmemo();
|
|
$order = $creditmemo?->getOrder(); $customerId = (int)($order?->getCustomerId() ?? 0);
|
|
if (!$creditmemo || !$order || $customerId <= 0 || !$this->config->isEnabled((int)$order->getStoreId())) { return; }
|
|
$rewardShare = (float)$order->getBaseSubtotal() > 0
|
|
? (float)$order->getData('base_reward_discount_amount') * (float)$creditmemo->getBaseSubtotal() / (float)$order->getBaseSubtotal()
|
|
: 0.0;
|
|
$eligible = max(0.0, (float)$creditmemo->getBaseSubtotal() + (float)$creditmemo->getBaseDiscountAmount() - $rewardShare);
|
|
$multiplier = max(1.0, (float)$order->getData('reward_multiplier'));
|
|
$remainingEarned = max(0, (int)$order->getData('reward_points_earned') - (int)$order->getData('reward_points_reversed'));
|
|
$points = min($remainingEarned, (int)floor($eligible * $this->config->orderRate((int)$order->getStoreId()) * $multiplier));
|
|
$websiteId = (int)$order->getStore()->getWebsiteId();
|
|
if ($points > 0) {
|
|
$this->balanceManager->change($customerId, $websiteId, -$points, 'order_refund_reversal', 'creditmemo_reversal:' . (int)$creditmemo->getId(), [
|
|
'reference_type' => 'order', 'reference_id' => (int)$order->getId(), 'reason' => (string)__('Points reversed for refund on order %1', $order->getIncrementId()),
|
|
'metadata' => ['creditmemo_id' => (int)$creditmemo->getId()], 'allow_negative' => true
|
|
]);
|
|
$order->setData('reward_points_reversed', (int)$order->getData('reward_points_reversed') + $points);
|
|
}
|
|
$returnedProductPoints = 0;
|
|
foreach ($creditmemo->getAllItems() as $creditmemoItem) {
|
|
$orderItem = $creditmemoItem->getOrderItem();
|
|
if ($orderItem && (int)$orderItem->getData('reward_redemption')) {
|
|
$returnedProductPoints += (int)round((float)$creditmemoItem->getQty() * (int)$orderItem->getData('reward_points_cost'));
|
|
}
|
|
}
|
|
if ($returnedProductPoints > 0) {
|
|
$this->balanceManager->change($customerId, $websiteId, $returnedProductPoints, 'redemption_refund', 'creditmemo_redemption_refund:' . (int)$creditmemo->getId(), [
|
|
'reference_type' => 'order', 'reference_id' => (int)$order->getId(), 'reason' => (string)__('Product redemption points returned for order %1', $order->getIncrementId()),
|
|
'metadata' => ['creditmemo_id' => (int)$creditmemo->getId()]
|
|
]);
|
|
}
|
|
$remainingCashPoints = max(0, (int)$order->getData('reward_points_used') - (int)$order->getData('reward_points_refunded'));
|
|
$cashPointsToReturn = (float)$order->getBaseSubtotal() > 0
|
|
? min($remainingCashPoints, (int)round((int)$order->getData('reward_points_used') * (float)$creditmemo->getBaseSubtotal() / (float)$order->getBaseSubtotal()))
|
|
: 0;
|
|
if ($cashPointsToReturn > 0) {
|
|
$this->balanceManager->change($customerId, $websiteId, $cashPointsToReturn, 'checkout_refund', 'creditmemo_checkout_refund:' . (int)$creditmemo->getId(), [
|
|
'reference_type' => 'order', 'reference_id' => (int)$order->getId(), 'reason' => (string)__('Checkout points returned for order %1', $order->getIncrementId()),
|
|
'metadata' => ['creditmemo_id' => (int)$creditmemo->getId()]
|
|
]);
|
|
$order->setData('reward_points_refunded', (int)$order->getData('reward_points_refunded') + $cashPointsToReturn);
|
|
}
|
|
$order->save();
|
|
$this->balanceManager->addLifetimeSpend($customerId, $websiteId, -$eligible, (int)$order->getStoreId());
|
|
}
|
|
}
|