Files
esun3d/app/code/Esun/CustomerCoupon/Model/RegistrationSubscriptionCouponService.php
2026-09-15 10:35:56 +08:00

116 lines
4.4 KiB
PHP

<?php
declare(strict_types=1);
namespace Esun\CustomerCoupon\Model;
use Esun\CustomerCoupon\Model\ResourceModel\Assignment as AssignmentResource;
use Esun\PromotionPopup\Model\Config as PromotionConfig;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
use Magento\SalesRule\Api\CouponManagementInterface;
use Magento\SalesRule\Api\Data\CouponGenerationSpecInterface;
use Magento\SalesRule\Api\Data\CouponGenerationSpecInterfaceFactory;
use Magento\SalesRule\Model\Rule;
use Magento\SalesRule\Model\RuleFactory;
use Magento\Store\Model\StoreManagerInterface;
class RegistrationSubscriptionCouponService
{
public const ASSIGNMENT_SOURCE = 'registration_newsletter';
public function __construct(
private readonly Config $config,
private readonly RuleFactory $ruleFactory,
private readonly CouponGenerationSpecInterfaceFactory $generationSpecFactory,
private readonly CouponManagementInterface $couponManagement,
private readonly AssignmentService $assignmentService,
private readonly AssignmentResource $assignmentResource,
private readonly TimezoneInterface $timezone,
private readonly StoreManagerInterface $storeManager,
private readonly PromotionConfig $promotionConfig
) {
}
/**
* Generate and assign the one-time registration subscription coupon.
*
* @throws LocalizedException
*/
public function grant(int $customerId, int $websiteId, int $customerGroupId, int $storeId): bool
{
if ($customerId <= 0
|| !$this->promotionConfig->isCampaignActive()
|| !$this->promotionConfig->isRegistrationNewsletterCouponPromotion()
|| $this->hasAlreadyBeenGranted($customerId)
) {
return false;
}
$ruleId = $this->config->getRegistrationSubscriptionRuleId($storeId ?: null);
if ($ruleId <= 0) {
return false;
}
/** @var Rule $rule */
$rule = $this->ruleFactory->create()->load($ruleId);
$scope = $storeId > 0 ? $this->storeManager->getStore($storeId) : $this->storeManager->getStore();
if (!$rule->getId()
|| !$rule->getIsActive()
|| ((int)$rule->getCouponType() !== Rule::COUPON_TYPE_AUTO && !$rule->getUseAutoGeneration())
|| !in_array($websiteId, array_map('intval', $rule->getWebsiteIds()), true)
|| !in_array($customerGroupId, array_map('intval', $rule->getCustomerGroupIds()), true)
|| !$this->timezone->isScopeDateInInterval($scope, $rule->getFromDate(), $rule->getToDate())
) {
throw new LocalizedException(
__('The configured registration subscription coupon rule is not eligible for this customer.')
);
}
/** @var CouponGenerationSpecInterface $specification */
$specification = $this->generationSpecFactory->create();
$specification->setRuleId($ruleId)
->setQuantity(1)
->setLength(12)
->setFormat(CouponGenerationSpecInterface::COUPON_FORMAT_ALPHANUMERIC)
->setPrefix('WELCOME-')
->setDelimiterAtEvery(0);
$codes = $this->couponManagement->generate($specification);
if (count($codes) !== 1) {
if ($codes) {
$this->couponManagement->deleteByCodes($codes);
}
throw new LocalizedException(__('The registration subscription coupon could not be generated.'));
}
try {
$this->assignmentService->assignCodes(
$codes,
[$customerId],
$ruleId,
self::ASSIGNMENT_SOURCE
);
} catch (\Throwable $exception) {
$this->couponManagement->deleteByCodes($codes);
if ($this->hasAlreadyBeenGranted($customerId)) {
return true;
}
throw $exception;
}
return true;
}
private function hasAlreadyBeenGranted(int $customerId): bool
{
$connection = $this->assignmentResource->getConnection();
$select = $connection->select()
->from($this->assignmentResource->getMainTable(), ['entity_id'])
->where('customer_id = ?', $customerId)
->where('source = ?', self::ASSIGNMENT_SOURCE)
->limit(1);
return (bool)$connection->fetchOne($select);
}
}