Files
baodev0andClaude Opus 5.5 46aa138eec feat(admin): IP pool allocation, billing exports, service attachments
- IP pool: sheet import (xlsx/csv) matched by address, bulk allocate/revoke
  with notification email (ip_allocated/ip_revoked), ip_pool_logs history.
- Orders/invoices: Excel export on branded template (BrandedReportWriter),
  shared billing filters, order item service info in list responses.
- Web design quote Excel export; activity log export.
- Service attachments with copy-to-invoice; deployment invoice attachments.
- Customer email attachments stored on disk and attached by path.
- Admin password change endpoint; user.fullname backfill migration;
  orders.user_id backfill from logs.
- Disable deploy workflow until CI/CD is set up.
- Ignore stored customer email and service attachment uploads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 19:58:36 +07:00

58 lines
2.5 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Feature\Api\Admin\IpPool;
use App\Models\Customer;
use App\Models\IpPool;
use App\Models\ModuleIpAddress;
use App\Models\ModuleNetwork;
use App\Models\ModuleVmware;
use App\Models\Service;
use App\Models\User;
use App\Models\VirtualMachines;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;
use Spatie\Permission\Models\Role;
use Tests\TestCase;
class IpPoolUsageTest extends TestCase
{
use RefreshDatabase;
public function test_list_links_ips_to_their_vm_service_customer_and_vcenter_vm(): void
{
Role::firstOrCreate(['name' => 'Full Administrator', 'guard_name' => 'admin']);
$admin = User::factory()->create();
$admin->assignRole('Full Administrator');
$network = ModuleNetwork::create(['name' => 'VM Network 56']);
$customer = Customer::factory()->create(['fullname' => 'Công ty A']);
foreach (['10.0.0.5', '10.0.0.6', '10.0.0.7'] as $ip) {
IpPool::create(['ip_address' => $ip, 'module_network_id' => $network->id, 'cidr' => 24, 'status' => 'assigned']);
ModuleIpAddress::create(['ip' => $ip, 'module_network_id' => $network->id, 'status' => 1, 'vm_name' => "{$ip}_vm"]);
}
$vmware = ModuleVmware::create(['name' => '10.0.0.5_customer-vm', 'ip' => '10.0.0.5', 'customer_id' => $customer->id]);
$service = Service::create(['customer_id' => $customer->id, 'status' => 'active', 'server_name' => 'vps-a', 'vm_id' => $vmware->id]);
Schema::disableForeignKeyConstraints();
$vcenterVm = VirtualMachines::create(['uuid' => (string) Str::uuid(), 'vm_id' => 'vm-1', 'name' => '10.0.0.6_test-vm', 'datacenter_id' => 1, 'host_id' => 1]);
$items = collect($this->actingAs($admin, 'admin')
->getJson('/api/v1/administrator/ip-pool?all=1')
->assertOk()
->json('data.items'))
->keyBy('ip_address');
$this->assertSame($service->id, $items['10.0.0.5']['usage']['service_id']);
$this->assertSame('vps-a', $items['10.0.0.5']['usage']['service_name']);
$this->assertSame($customer->uuid, $items['10.0.0.5']['usage']['customer_uuid']);
$this->assertSame($vcenterVm->id, $items['10.0.0.6']['usage']['vcenter_vm_id']);
$this->assertNull($items['10.0.0.6']['usage']['service_id']);
$this->assertSame('10.0.0.7_vm', $items['10.0.0.7']['usage']['vm_name']);
$this->assertNull($items['10.0.0.7']['usage']['vcenter_vm_id']);
}
}