Files
2026-09-15 10:35:56 +08:00

41 lines
2.5 KiB
PHP

<?php
declare(strict_types=1);
namespace Esun\Reward\Observer;
use Esun\Reward\Model\BalanceManager;
use Esun\Reward\Model\Config;
use Esun\Reward\Model\TierResolver;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Sales\Model\Order\Invoice;
class AwardInvoicePoints implements ObserverInterface
{
public function __construct(private readonly BalanceManager $balanceManager, private readonly Config $config, private readonly TierResolver $tierResolver) {}
public function execute(Observer $observer): void
{
/** @var Invoice|null $invoice */ $invoice = $observer->getEvent()->getInvoice();
$order = $invoice?->getOrder(); $customerId = (int)($order?->getCustomerId() ?? 0);
if (!$invoice || !$order || !$this->config->isEnabled((int)$order->getStoreId()) || $customerId <= 0) { return; }
$websiteId = (int)$order->getStore()->getWebsiteId();
$account = $this->balanceManager->getAccount($customerId, $websiteId);
$tier = $this->tierResolver->resolveEffective((string)$account['tier_code'], (float)$account['lifetime_spend_base'], (int)$order->getStoreId());
$rewardShare = (float)$order->getBaseSubtotal() > 0
? (float)$order->getData('base_reward_discount_amount') * (float)$invoice->getBaseSubtotal() / (float)$order->getBaseSubtotal()
: 0.0;
$eligible = max(0.0, (float)$invoice->getBaseSubtotal() + (float)$invoice->getBaseDiscountAmount() - $rewardShare);
$rule = $this->config->earningRule('order_earned', (int)$order->getStoreId());
$points = (int)floor($eligible * (float)$rule['points'] * (float)$tier['multiplier']);
if ($points > 0 && $this->balanceManager->change($customerId, $websiteId, $points, 'order_earned', 'invoice_earned:' . (int)$invoice->getId(), [
'reference_type' => 'order', 'reference_id' => (int)$order->getId(), 'reason' => (string)__($rule['reason'], $order->getIncrementId()),
'metadata' => ['invoice_id' => (int)$invoice->getId(), 'eligible_amount' => $eligible, 'tier' => $tier['code'], 'multiplier' => $tier['multiplier']]
])) {
$order->setData('reward_points_earned', (int)$order->getData('reward_points_earned') + $points);
$order->setData('reward_tier_code', $tier['code']); $order->setData('reward_multiplier', $tier['multiplier']); $order->save();
$this->balanceManager->addLifetimeSpend($customerId, $websiteId, $eligible, (int)$order->getStoreId());
}
}
}