48 lines
1.1 KiB
PHP
48 lines
1.1 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Exceptions\CouponPoolExhaustedException;
|
|
use App\Models\Coupon;
|
|
use Illuminate\Database\UniqueConstraintViolationException;
|
|
|
|
class CouponService
|
|
{
|
|
public function __construct(
|
|
private CouponCodePool $couponCodePool,
|
|
) {}
|
|
|
|
public function findOrCreateForPhone(string $phone): Coupon
|
|
{
|
|
$existing = Coupon::query()->where('phone', $phone)->first();
|
|
|
|
if ($existing) {
|
|
return $existing;
|
|
}
|
|
|
|
return $this->createWithUniqueCode($phone);
|
|
}
|
|
|
|
private function createWithUniqueCode(string $phone): Coupon
|
|
{
|
|
for ($attempt = 0; $attempt < 10; $attempt++) {
|
|
$code = $this->couponCodePool->pickRandom();
|
|
|
|
if ($code === null) {
|
|
throw new CouponPoolExhaustedException;
|
|
}
|
|
|
|
try {
|
|
return Coupon::query()->create([
|
|
'phone' => $phone,
|
|
'code' => $code,
|
|
]);
|
|
} catch (UniqueConstraintViolationException) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
throw new CouponPoolExhaustedException;
|
|
}
|
|
}
|