150 lines
5.8 KiB
PHP
150 lines
5.8 KiB
PHP
<?php
|
|
|
|
namespace App\Jobs;
|
|
|
|
use App\Models\ClientCase;
|
|
use App\Models\SmsProfile;
|
|
use App\Models\SmsSender;
|
|
use App\Models\SmsTemplate;
|
|
use App\Services\Sms\SmsService;
|
|
use Illuminate\Bus\Queueable;
|
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
use Illuminate\Foundation\Bus\Dispatchable;
|
|
use Illuminate\Queue\InteractsWithQueue;
|
|
use Illuminate\Queue\SerializesModels;
|
|
use Illuminate\Support\Facades\Redis;
|
|
|
|
class SendSmsJob implements ShouldQueue
|
|
{
|
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
|
|
|
/**
|
|
* Create a new job instance.
|
|
*/
|
|
public function __construct(
|
|
public int $profileId,
|
|
public string $to,
|
|
public string $content,
|
|
public ?int $senderId = null,
|
|
public ?string $countryCode = null,
|
|
public bool $deliveryReport = false,
|
|
public ?string $clientReference = null,
|
|
// For optional activity creation (case UI only)
|
|
public ?int $templateId = null,
|
|
public ?int $clientCaseId = null,
|
|
public ?int $userId = null,
|
|
// If provided, update this activity on failure instead of creating a new one
|
|
public ?int $activityId = null,
|
|
) {}
|
|
|
|
/**
|
|
* Execute the job.
|
|
*/
|
|
public function handle(SmsService $sms): void
|
|
{
|
|
// Resolve models
|
|
/** @var SmsProfile|null $profile */
|
|
$profile = SmsProfile::find($this->profileId);
|
|
if (! $profile) {
|
|
return; // nothing to do
|
|
}
|
|
|
|
/** @var SmsSender|null $sender */
|
|
$sender = $this->senderId ? SmsSender::find($this->senderId) : null;
|
|
|
|
// Apply Redis throttle from config to avoid provider rate limits
|
|
$scope = config('services.sms.throttle.scope', 'global');
|
|
$provider = config('services.sms.throttle.provider_key', 'smsapi_si');
|
|
$allow = (int) config('services.sms.throttle.allow', 30);
|
|
$every = (int) config('services.sms.throttle.every', 60);
|
|
$jitter = (int) config('services.sms.throttle.jitter_seconds', 2);
|
|
$key = $scope === 'per_profile' && $profile ? "sms:{$provider}:{$profile->id}" : "sms:{$provider}";
|
|
|
|
$log = null;
|
|
try {
|
|
Redis::throttle($key)->allow($allow)->every($every)->then(function () use (&$log, $sms, $profile, $sender) {
|
|
// Send and get log (handles queued->sent/failed transitions internally)
|
|
$log = $sms->sendRaw(
|
|
profile: $profile,
|
|
to: $this->to,
|
|
content: $this->content,
|
|
sender: $sender,
|
|
countryCode: $this->countryCode,
|
|
deliveryReport: $this->deliveryReport,
|
|
clientReference: $this->clientReference,
|
|
);
|
|
}, function () use ($jitter) {
|
|
return $this->release(max(1, rand(1, $jitter)));
|
|
});
|
|
} catch (\Throwable $e) {
|
|
// Fallback if Redis is unavailable in test or local env
|
|
$log = $sms->sendRaw(
|
|
profile: $profile,
|
|
to: $this->to,
|
|
content: $this->content,
|
|
sender: $sender,
|
|
countryCode: $this->countryCode,
|
|
deliveryReport: $this->deliveryReport,
|
|
clientReference: $this->clientReference,
|
|
);
|
|
}
|
|
// Update an existing pre-created activity ONLY on failure when activityId is provided
|
|
if ($this->activityId && $log && ($log->status === 'failed')) {
|
|
try {
|
|
$activity = \App\Models\Activity::find($this->activityId);
|
|
if ($activity) {
|
|
$note = (string) ($activity->note ?? '');
|
|
$append = sprintf(
|
|
' | Napaka: %s',
|
|
'SMS ni bil poslan!'
|
|
);
|
|
$activity->update(['note' => $note.$append]);
|
|
}
|
|
} catch (\Throwable $e) {
|
|
\Log::warning('SendSmsJob activity update failed', [
|
|
'error' => $e->getMessage(),
|
|
'activity_id' => $this->activityId,
|
|
]);
|
|
}
|
|
}
|
|
|
|
// If no pre-created activity is provided and invoked from the case UI with a selected template, create an Activity
|
|
if (! $this->activityId && $this->templateId && $this->clientCaseId && $log) {
|
|
try {
|
|
/** @var SmsTemplate|null $template */
|
|
$template = SmsTemplate::find($this->templateId);
|
|
/** @var ClientCase|null $case */
|
|
$case = ClientCase::find($this->clientCaseId);
|
|
if ($template && $case) {
|
|
$note = '';
|
|
if ($log->status === 'sent') {
|
|
$note = sprintf('Št: %s | Telo: %s', (string) $this->to, (string) $this->content);
|
|
} elseif ($log->status === 'failed') {
|
|
$note = sprintf(
|
|
'Št: %s | Telo: %s | Napaka: %s',
|
|
(string) $this->to,
|
|
(string) $this->content,
|
|
'SMS ni bil poslan!'
|
|
);
|
|
}
|
|
|
|
$case->activities()->create([
|
|
'note' => $note,
|
|
'action_id' => $template->action_id,
|
|
'decision_id' => $template->decision_id,
|
|
'user_id' => $this->userId,
|
|
]);
|
|
}
|
|
|
|
} catch (\Throwable $e) {
|
|
\Log::warning('SendSmsJob activity creation failed', [
|
|
'error' => $e->getMessage(),
|
|
'client_case_id' => $this->clientCaseId,
|
|
'template_id' => $this->templateId,
|
|
]);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|