Package system sms
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
use App\Jobs\PackageItemSmsJob;
|
||||
use App\Models\Package;
|
||||
use App\Models\SmsLog;
|
||||
use App\Models\SmsProfile;
|
||||
use App\Services\Sms\SmsService;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
it('processes a queued package item and updates counters', function () {
|
||||
$package = Package::create([
|
||||
'uuid' => (string) Str::uuid(),
|
||||
'type' => Package::TYPE_SMS,
|
||||
'status' => Package::STATUS_DRAFT,
|
||||
'name' => 'Test SMS Package',
|
||||
'total_items' => 1,
|
||||
]);
|
||||
|
||||
$profile = SmsProfile::factory()->create();
|
||||
|
||||
$item = $package->items()->create([
|
||||
'status' => 'queued',
|
||||
'target_json' => ['number' => '+38640123456'],
|
||||
'payload_json' => ['profile_id' => $profile->id, 'body' => 'Hello world'],
|
||||
]);
|
||||
|
||||
// Mock SmsService to return a successful log
|
||||
$log = new SmsLog([
|
||||
'status' => 'sent',
|
||||
'provider_message_id' => 'abc123',
|
||||
'cost' => 0.0100,
|
||||
'currency' => 'EUR',
|
||||
'meta' => ['parts' => 1],
|
||||
]);
|
||||
|
||||
$this->mock(SmsService::class)
|
||||
->shouldReceive('sendFromTemplate')->zeroOrMoreTimes()
|
||||
->andReturn($log);
|
||||
$this->mock(SmsService::class)
|
||||
->shouldReceive('sendRaw')->zeroOrMoreTimes()
|
||||
->andReturn($log);
|
||||
|
||||
$job = new PackageItemSmsJob($item->id);
|
||||
$job->handle(app(SmsService::class));
|
||||
|
||||
$item->refresh();
|
||||
$package->refresh();
|
||||
|
||||
expect($item->status)->toBe('sent');
|
||||
expect($package->sent_count)->toBe(1);
|
||||
expect($package->failed_count)->toBe(0);
|
||||
});
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Person\Person;
|
||||
use App\Models\Person\PersonPhone;
|
||||
use App\Services\Contact\PhoneSelector;
|
||||
|
||||
it('selects validated mobile first', function () {
|
||||
$person = Person::factory()->create();
|
||||
// Non-mobile validated
|
||||
PersonPhone::factory()->for($person, 'person')->landline()->validated()->create();
|
||||
// Mobile not validated
|
||||
PersonPhone::factory()->for($person, 'person')->mobile()->notValidated()->create();
|
||||
// Mobile validated (should win)
|
||||
$best = PersonPhone::factory()->for($person, 'person')->mobile()->validated()->create();
|
||||
|
||||
$selector = new PhoneSelector;
|
||||
$result = $selector->selectForPerson($person->fresh('phones'));
|
||||
|
||||
expect($result['phone'])->not->toBeNull();
|
||||
expect($result['phone']->id)->toBe($best->id);
|
||||
expect($result['reason'])->toBeNull();
|
||||
});
|
||||
|
||||
it('falls back to validated any type then mobile', function () {
|
||||
$person = Person::factory()->create();
|
||||
$validatedAny = PersonPhone::factory()->for($person, 'person')->landline()->validated()->create();
|
||||
$mobile = PersonPhone::factory()->for($person, 'person')->mobile()->notValidated()->create();
|
||||
|
||||
$selector = new PhoneSelector;
|
||||
$result = $selector->selectForPerson($person->fresh('phones'));
|
||||
|
||||
expect($result['phone']->id)->toBe($validatedAny->id);
|
||||
});
|
||||
|
||||
it('returns first active when no better option', function () {
|
||||
$person = Person::factory()->create();
|
||||
$first = PersonPhone::factory()->for($person, 'person')->landline()->notValidated()->create();
|
||||
PersonPhone::factory()->for($person, 'person')->landline()->notValidated()->create();
|
||||
|
||||
$selector = new PhoneSelector;
|
||||
$result = $selector->selectForPerson($person->fresh('phones'));
|
||||
|
||||
expect($result['phone']->id)->toBe($first->id);
|
||||
});
|
||||
|
||||
it('returns reason when no phones', function () {
|
||||
$person = Person::factory()->create();
|
||||
$selector = new PhoneSelector;
|
||||
$result = $selector->selectForPerson($person->fresh('phones'));
|
||||
|
||||
expect($result['phone'])->toBeNull();
|
||||
expect($result['reason'])->toBe('no_active_phones');
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
use App\Models\SmsProfile;
|
||||
use App\Services\Sms\SmsClient;
|
||||
use App\Services\Sms\SmsMessage;
|
||||
use App\Services\Sms\SmsResult;
|
||||
use App\Services\Sms\SmsService;
|
||||
|
||||
it('formats amounts to EU style', function () {
|
||||
$client = new class implements SmsClient
|
||||
{
|
||||
public function send(SmsProfile $profile, SmsMessage $message): SmsResult
|
||||
{
|
||||
throw new RuntimeException('not used');
|
||||
}
|
||||
|
||||
public function getCreditBalance(SmsProfile $profile): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPriceQuotes(SmsProfile $profile): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
$sms = new SmsService($client);
|
||||
|
||||
expect($sms->formatAmountEu(0))->toBe('0,00');
|
||||
expect($sms->formatAmountEu('1'))->toBe('1,00');
|
||||
expect($sms->formatAmountEu('12.3'))->toBe('12,30');
|
||||
expect($sms->formatAmountEu('1234.56'))->toBe('1.234,56');
|
||||
expect($sms->formatAmountEu('9876543.21'))->toBe('9.876.543,21');
|
||||
expect($sms->formatAmountEu('-42.5'))->toBe('-42,50');
|
||||
// Accept EU input too
|
||||
expect($sms->formatAmountEu('1.234,56'))->toBe('1.234,56');
|
||||
});
|
||||
Reference in New Issue
Block a user