inspiren-sem-tool/tests/Feature/UpdateCurrentClientInvoicePaymentItemSpendingTest.php

113 lines
4.0 KiB
PHP

<?php
use App\Models\BillingItemType;
use App\Models\Client;
use App\Models\ClientInvoice;
use App\Models\ClientInvoicePayment;
use App\Models\ClientInvoicePaymentItem;
use App\Services\GoogleAdsService;
use Illuminate\Support\Carbon;
function createCurrentSpendingInvoiceItem(
Client $client,
int $billingItemTypeId,
?string $startDate,
?string $endDate,
float $spending = 0,
): ClientInvoicePaymentItem {
$invoice = ClientInvoice::query()->forceCreate([
'client_id' => $client->id,
'invoice_no' => fake()->unique()->numerify('INV-####'),
]);
$payment = ClientInvoicePayment::query()->create([
'client_invoice_id' => $invoice->id,
]);
return ClientInvoicePaymentItem::query()->create([
'client_invoice_payment_id' => $payment->id,
'billing_item_types_id' => $billingItemTypeId,
'start_date' => $startDate,
'end_date' => $endDate,
'spending' => $spending,
]);
}
test('it updates eligible invoice payment items ending today or later through today', function () {
Carbon::setTestNow('2026-06-25 10:00:00');
BillingItemType::query()->insert([
['id' => 1, 'name' => 'Media'],
['id' => 2, 'name' => 'Management'],
]);
$client = Client::factory()->create([
'customer_id' => '1111111111',
'status' => 'ENABLED',
'time_zone' => 'Asia/Kuala_Lumpur',
]);
$expiredItem = createCurrentSpendingInvoiceItem($client, 1, '2026-06-01', '2026-06-24', 10);
$todayItem = createCurrentSpendingInvoiceItem($client, 1, '2026-06-01', '2026-06-25');
$futureEndItem = createCurrentSpendingInvoiceItem($client, 1, '2026-06-10', '2026-06-30');
$futureStartItem = createCurrentSpendingInvoiceItem($client, 1, '2026-06-26', '2026-06-30', 30);
$openEndedItem = createCurrentSpendingInvoiceItem($client, 1, '2026-06-01', null, 40);
$otherTypeItem = createCurrentSpendingInvoiceItem($client, 2, '2026-06-01', '2026-06-30', 50);
$adsService = Mockery::mock(GoogleAdsService::class);
$adsService->shouldReceive('listCampaigns')
->twice()
->with('1111111111')
->andReturn([['id' => 101]]);
$adsService->shouldReceive('listCampaignsMetricsById')
->once()
->with('1111111111', '101', '2026-06-01', '2026-06-25')
->andReturn([['actual_spend' => 12.25]]);
$adsService->shouldReceive('listCampaignsMetricsById')
->once()
->with('1111111111', '101', '2026-06-10', '2026-06-25')
->andReturn([['actual_spend' => 7.75]]);
app()->instance(GoogleAdsService::class, $adsService);
$this->artisan('customer:update-current-invoice-item-spending')
->expectsOutputToContain('Done. 2 calculated, 1 skipped, 0 failed.')
->assertSuccessful();
expect((float) $expiredItem->fresh()->spending)->toBe(10.0)
->and((float) $todayItem->fresh()->spending)->toBe(12.25)
->and((float) $futureEndItem->fresh()->spending)->toBe(7.75)
->and((float) $futureStartItem->fresh()->spending)->toBe(30.0)
->and((float) $openEndedItem->fresh()->spending)->toBe(40.0)
->and((float) $otherTypeItem->fresh()->spending)->toBe(50.0);
});
test('dry run calculates current spending without updating the item', function () {
Carbon::setTestNow('2026-06-25 10:00:00');
BillingItemType::query()->insert([
'id' => 1,
'name' => 'Media',
]);
$client = Client::factory()->create([
'customer_id' => '3333333333',
'status' => 'ENABLED',
'time_zone' => 'Asia/Kuala_Lumpur',
]);
$item = createCurrentSpendingInvoiceItem($client, 1, '2026-06-01', '2026-06-30', 8);
$adsService = Mockery::mock(GoogleAdsService::class);
$adsService->shouldReceive('listCampaigns')
->once()
->with('3333333333')
->andReturn([]);
app()->instance(GoogleAdsService::class, $adsService);
$this->artisan('customer:update-current-invoice-item-spending', ['--dry-run' => true])
->assertSuccessful();
expect((float) $item->fresh()->spending)->toBe(8.0);
});