70 lines
2.5 KiB
PHP
70 lines
2.5 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace Esun\CustomerCoupon\Model;
|
|
|
|
use Esun\CustomerCoupon\Api\CouponNotifierInterface;
|
|
use Esun\CustomerCoupon\Model\ResourceModel\Assignment as AssignmentResource;
|
|
use Magento\Framework\Exception\LocalizedException;
|
|
use Magento\SalesRule\Model\CouponFactory;
|
|
|
|
class AssignmentService
|
|
{
|
|
public function __construct(
|
|
private readonly AssignmentFactory $assignmentFactory,
|
|
private readonly AssignmentResource $assignmentResource,
|
|
private readonly CouponFactory $couponFactory,
|
|
private readonly CouponNotifierInterface $couponNotifier
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* Assign generated coupon codes to customers.
|
|
*
|
|
* @param string[] $codes
|
|
* @param int[] $customerIds
|
|
* @param int $ruleId
|
|
* @param string|null $source Stable source key used to make automatic grants idempotent
|
|
*/
|
|
public function assignCodes(array $codes, array $customerIds, int $ruleId, ?string $source = null): void
|
|
{
|
|
if (count($codes) !== count($customerIds)) {
|
|
throw new LocalizedException(__('The generated coupon count does not match the selected customer count.'));
|
|
}
|
|
|
|
$connection = $this->assignmentResource->getConnection();
|
|
$assignmentIds = [];
|
|
$connection->beginTransaction();
|
|
try {
|
|
foreach (array_values($codes) as $index => $code) {
|
|
$coupon = $this->couponFactory->create()->load($code, 'code');
|
|
if (!$coupon->getId()) {
|
|
throw new LocalizedException(__('The generated coupon "%1" could not be loaded.', $code));
|
|
}
|
|
|
|
$assignment = $this->assignmentFactory->create();
|
|
$assignment->setData([
|
|
'coupon_id' => (int)$coupon->getId(),
|
|
'rule_id' => $ruleId,
|
|
'customer_id' => (int)$customerIds[$index],
|
|
'source' => $source,
|
|
]);
|
|
$this->assignmentResource->save($assignment);
|
|
$assignmentIds[] = (int)$assignment->getId();
|
|
}
|
|
$connection->commit();
|
|
} catch (\Throwable $exception) {
|
|
$connection->rollBack();
|
|
throw $exception;
|
|
}
|
|
|
|
foreach ($assignmentIds as $assignmentId) {
|
|
try {
|
|
$this->couponNotifier->notify($assignmentId);
|
|
} catch (\Throwable) {
|
|
// Notification delivery is best-effort and must not invalidate an assigned coupon.
|
|
}
|
|
}
|
|
}
|
|
}
|