Files
Verde-Web/tests/Feature/Api/V1/Store/PartnerStoreSettlementTest.php

145 lines
5.0 KiB
PHP

<?php
namespace Tests\Feature\Api\V1\Store;
use App\Models\PartnerStore;
use App\Models\QrCode;
use App\Models\QrCodeBatch;
use App\Models\StoreSale;
use App\Models\Tenant;
use App\Models\User;
use App\Services\Store\StoreOperations;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class PartnerStoreSettlementTest extends TestCase
{
use RefreshDatabase;
protected User $admin;
protected PartnerStore $store;
protected StoreOperations $ops;
protected function setUp(): void
{
parent::setUp();
// $this->defaultTenant is already created and set in parent::setUp()
$this->admin = User::factory()->create(['tenant_id' => $this->defaultTenant->id, 'role' => 'admin']);
$owner = User::factory()->create(['tenant_id' => $this->defaultTenant->id, 'role' => 'store_partner']);
$this->store = PartnerStore::factory()->create([
'tenant_id' => $this->defaultTenant->id,
'owner_user_id' => $owner->id,
'commission_rate_percent' => 10,
'status' => 'active',
]);
$this->ops = app(StoreOperations::class);
}
public function test_calculate_balance_due_consignment_model()
{
// 1. Issue inventory (already in setup)
// 2. Record sales (Retail Price 100, Commission 10%)
// Total Sold: 2 codes @ 100 each = 200 Gross
// Commission: 10% of 200 = 20
// Net Owed to City: 200 - 20 = 180
StoreSale::factory()->count(2)->create([
'store_id' => $this->store->id,
'retail_price_centavos' => 10000,
'commission_centavos' => 1000
]);
$balance = $this->ops->calculateBalanceDue($this->store);
$this->assertEquals(18000, $balance); // 180.00 in centavos
// 3. Record payment
$response = $this->actingAs($this->admin)
->postJson("/api/v1/admin/partner-stores/{$this->store->uuid}/settle", [
'amount_pesos' => 100,
'payment_method' => 'cash',
'reference_number' => 'REF123'
]);
$response->assertSuccessful();
// 4. Check new balance: 180 - 100 = 80
$newBalance = $this->ops->calculateBalanceDue($this->store);
$this->assertEquals(8000, $newBalance);
}
public function test_report_defective_with_replacement()
{
// Setup: Issue a specific code
$qr = QrCode::factory()->create([
'tenant_id' => $this->defaultTenant->id,
'assigned_to_store_id' => $this->store->id,
'status' => 'allocated'
]);
\App\Models\StoreInventory::create([
'store_id' => $this->store->id,
'current_code_balance' => 1,
'prepaid_balance' => 0
]);
$this->actingAs($this->admin)
->postJson("/api/v1/admin/partner-stores/{$this->store->uuid}/report-issue", [
'serial' => $qr->serial,
'reason' => 'Defective Adhesive'
])
->assertSuccessful();
// Original should be voided
$qr->refresh();
$this->assertEquals('voided', $qr->status);
// A new replacement QR should exist
$replacement = QrCode::where('replacement_for_id', $qr->id)->first();
$this->assertNotNull($replacement);
$this->assertEquals('allocated', $replacement->status);
$this->assertEquals($this->store->id, $replacement->assigned_to_store_id);
// Inventory balance should be 1 (started at 1, -1 for defective, +1 for replacement)
$this->store->refresh()->load('inventory');
$this->assertEquals(1, $this->store->inventory?->current_code_balance ?? 0);
}
public function test_print_replacement_endpoint()
{
$qr = QrCode::factory()->create([
'tenant_id' => $this->defaultTenant->id,
'assigned_to_store_id' => $this->store->id,
'status' => 'voided'
]);
$replacement = QrCode::factory()->create([
'tenant_id' => $this->defaultTenant->id,
'assigned_to_store_id' => $this->store->id,
'status' => 'allocated',
'replacement_for_id' => $qr->id
]);
$this->actingAs($this->admin)
->getJson("/api/v1/admin/partner-stores/{$this->store->uuid}/qr-codes/{$replacement->serial}/print")
->assertSuccessful()
->assertJsonStructure(['data' => ['qr_data', 'serial']]);
}
public function test_analytics_includes_financials()
{
// 1 sale: 100 retail, 10 comm -> 90 owed
StoreSale::factory()->create([
'store_id' => $this->store->id,
'retail_price_centavos' => 10000,
'commission_centavos' => 1000
]);
$this->actingAs($this->admin)
->getJson("/api/v1/admin/partner-stores/{$this->store->uuid}/analytics")
->assertSuccessful()
->assertJsonFragment([
'balance_due_pesos' => '90.00',
'total_settled_pesos' => '0.00'
]);
}
}