361 lines
12 KiB
PHP
361 lines
12 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature\Api\V1\Admin;
|
|
|
|
use App\Models\Barangay;
|
|
use App\Models\Household;
|
|
use App\Models\HouseholdMember;
|
|
use App\Models\User;
|
|
use Database\Seeders\RoleSeeder;
|
|
use Database\Seeders\SamplePsgcSeeder;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Laravel\Sanctum\Sanctum;
|
|
use MatanYadaev\EloquentSpatial\Objects\LineString;
|
|
use MatanYadaev\EloquentSpatial\Objects\Point;
|
|
use MatanYadaev\EloquentSpatial\Objects\Polygon;
|
|
use Tests\TestCase;
|
|
|
|
class AdminHouseholdMemberTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
private User $admin;
|
|
|
|
private Barangay $barangay;
|
|
|
|
private Household $household;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
$this->seed([RoleSeeder::class, SamplePsgcSeeder::class]);
|
|
|
|
$this->admin = User::factory()->create([
|
|
'role' => User::ROLE_ADMIN,
|
|
'status' => User::STATUS_ACTIVE,
|
|
]);
|
|
$this->admin->assignRole(User::ROLE_ADMIN);
|
|
|
|
// Fetch or create a Barangay with boundary polygon for spatial tests
|
|
$this->barangay = Barangay::first();
|
|
$boundary = new Polygon([
|
|
new LineString([
|
|
new Point(14.0, 120.0, 4326),
|
|
new Point(15.0, 120.0, 4326),
|
|
new Point(15.0, 121.0, 4326),
|
|
new Point(14.0, 121.0, 4326),
|
|
new Point(14.0, 120.0, 4326),
|
|
]),
|
|
], 4326);
|
|
$this->barangay->update([
|
|
'boundary' => $boundary,
|
|
'centroid' => new Point(14.5, 120.5, 4326),
|
|
]);
|
|
|
|
$resident = User::factory()->create([
|
|
'role' => User::ROLE_RESIDENT,
|
|
'status' => User::STATUS_ACTIVE,
|
|
]);
|
|
|
|
$this->household = Household::create([
|
|
'tenant_id' => $this->defaultTenant->id,
|
|
'head_user_id' => $resident->id,
|
|
'barangay_id' => $this->barangay->id,
|
|
'address_line' => '123 Test St',
|
|
'coordinates' => new Point(14.5, 120.5, 4326),
|
|
'household_size' => 2,
|
|
'verification_status' => Household::VERIFICATION_APPROVED,
|
|
]);
|
|
|
|
HouseholdMember::create([
|
|
'household_id' => $this->household->id,
|
|
'user_id' => $resident->id,
|
|
'relationship' => HouseholdMember::RELATIONSHIP_HEAD,
|
|
'full_name' => $resident->full_name,
|
|
]);
|
|
}
|
|
|
|
public function test_admin_can_update_household_details_inside_barangay(): void
|
|
{
|
|
Sanctum::actingAs($this->admin);
|
|
|
|
$payload = [
|
|
'address_line' => 'Updated Address St',
|
|
'lat' => 14.6,
|
|
'lng' => 120.6,
|
|
'barangay_id' => $this->barangay->id,
|
|
'household_size' => 4,
|
|
];
|
|
|
|
$response = $this->patchJson("/api/v1/admin/households/{$this->household->uuid}", $payload);
|
|
|
|
$response->assertStatus(200)
|
|
->assertJsonPath('data.address_line', 'Updated Address St')
|
|
->assertJsonPath('data.household_size', 4);
|
|
|
|
$this->assertDatabaseHas('households', [
|
|
'id' => $this->household->id,
|
|
'address_line' => 'Updated Address St',
|
|
'household_size' => 4,
|
|
]);
|
|
}
|
|
|
|
public function test_admin_cannot_update_household_outside_barangay_boundary(): void
|
|
{
|
|
Sanctum::actingAs($this->admin);
|
|
|
|
$payload = [
|
|
'address_line' => 'Outside Barangay St',
|
|
'lat' => 16.0, // outside boundary
|
|
'lng' => 122.0,
|
|
'barangay_id' => $this->barangay->id,
|
|
'household_size' => 4,
|
|
];
|
|
|
|
$response = $this->patchJson("/api/v1/admin/households/{$this->household->uuid}", $payload);
|
|
|
|
$response->assertStatus(422)
|
|
->assertJsonValidationErrors(['barangay_id']);
|
|
}
|
|
|
|
public function test_admin_can_add_member_profile_guest(): void
|
|
{
|
|
Sanctum::actingAs($this->admin);
|
|
|
|
$payload = [
|
|
'relationship' => 'child',
|
|
'full_name' => 'Billy Kid',
|
|
'date_of_birth' => '2015-05-10',
|
|
];
|
|
|
|
$response = $this->postJson("/api/v1/admin/households/{$this->household->uuid}/members", $payload);
|
|
|
|
$response->assertStatus(201)
|
|
->assertJsonFragment([
|
|
'full_name' => 'Billy Kid',
|
|
'relationship' => 'child',
|
|
]);
|
|
|
|
$this->assertDatabaseHas('household_members', [
|
|
'household_id' => $this->household->id,
|
|
'full_name' => 'Billy Kid',
|
|
'relationship' => 'child',
|
|
]);
|
|
}
|
|
|
|
public function test_admin_can_add_member_registered_user(): void
|
|
{
|
|
Sanctum::actingAs($this->admin);
|
|
|
|
$newResident = User::factory()->create([
|
|
'role' => User::ROLE_RESIDENT,
|
|
'status' => User::STATUS_ACTIVE,
|
|
]);
|
|
|
|
$payload = [
|
|
'relationship' => 'spouse',
|
|
'user_id' => $newResident->id,
|
|
];
|
|
|
|
$response = $this->postJson("/api/v1/admin/households/{$this->household->uuid}/members", $payload);
|
|
|
|
$response->assertStatus(201);
|
|
|
|
$this->assertDatabaseHas('household_members', [
|
|
'household_id' => $this->household->id,
|
|
'user_id' => $newResident->id,
|
|
'relationship' => 'spouse',
|
|
]);
|
|
}
|
|
|
|
public function test_admin_cannot_add_resident_already_in_household(): void
|
|
{
|
|
Sanctum::actingAs($this->admin);
|
|
|
|
// The head user is already in a household.
|
|
$headUserId = $this->household->head_user_id;
|
|
|
|
$payload = [
|
|
'relationship' => 'sibling',
|
|
'user_id' => $headUserId,
|
|
];
|
|
|
|
$response = $this->postJson("/api/v1/admin/households/{$this->household->uuid}/members", $payload);
|
|
|
|
$response->assertStatus(422)
|
|
->assertJsonValidationErrors(['user_id']);
|
|
}
|
|
|
|
public function test_admin_can_edit_household_member(): void
|
|
{
|
|
Sanctum::actingAs($this->admin);
|
|
|
|
$member = HouseholdMember::create([
|
|
'household_id' => $this->household->id,
|
|
'relationship' => 'other',
|
|
'full_name' => 'Uncle Ben',
|
|
]);
|
|
|
|
$payload = [
|
|
'relationship' => 'parent',
|
|
'full_name' => 'Uncle Benjamin',
|
|
];
|
|
|
|
$response = $this->patchJson("/api/v1/admin/households/{$this->household->uuid}/members/{$member->id}", $payload);
|
|
|
|
$response->assertStatus(200);
|
|
|
|
$this->assertDatabaseHas('household_members', [
|
|
'id' => $member->id,
|
|
'relationship' => 'parent',
|
|
'full_name' => 'Uncle Benjamin',
|
|
]);
|
|
}
|
|
|
|
public function test_admin_can_delete_member(): void
|
|
{
|
|
Sanctum::actingAs($this->admin);
|
|
|
|
$member = HouseholdMember::create([
|
|
'household_id' => $this->household->id,
|
|
'relationship' => 'other',
|
|
'full_name' => 'To Delete',
|
|
]);
|
|
|
|
$response = $this->deleteJson("/api/v1/admin/households/{$this->household->uuid}/members/{$member->id}");
|
|
|
|
$response->assertStatus(200);
|
|
|
|
$this->assertSoftDeleted('household_members', [
|
|
'id' => $member->id,
|
|
]);
|
|
}
|
|
|
|
public function test_admin_cannot_delete_head(): void
|
|
{
|
|
Sanctum::actingAs($this->admin);
|
|
|
|
$headMember = $this->household->members()->where('relationship', HouseholdMember::RELATIONSHIP_HEAD)->first();
|
|
|
|
$response = $this->deleteJson("/api/v1/admin/households/{$this->household->uuid}/members/{$headMember->id}");
|
|
|
|
$response->assertStatus(422);
|
|
}
|
|
|
|
public function test_admin_can_transfer_resident_from_another_household_and_clean_it_up(): void
|
|
{
|
|
Sanctum::actingAs($this->admin);
|
|
|
|
// 1. Create a resident user who heads their own household (default signup scenario)
|
|
$resident = User::factory()->create([
|
|
'role' => User::ROLE_RESIDENT,
|
|
'status' => User::STATUS_ACTIVE,
|
|
]);
|
|
|
|
$oldHousehold = Household::create([
|
|
'tenant_id' => $this->defaultTenant->id,
|
|
'head_user_id' => $resident->id,
|
|
'barangay_id' => $this->barangay->id,
|
|
'address_line' => '456 Previous St',
|
|
'coordinates' => new Point(14.5, 120.5, 4326),
|
|
'household_size' => 1,
|
|
'verification_status' => Household::VERIFICATION_APPROVED,
|
|
]);
|
|
|
|
$oldMember = HouseholdMember::create([
|
|
'household_id' => $oldHousehold->id,
|
|
'user_id' => $resident->id,
|
|
'relationship' => HouseholdMember::RELATIONSHIP_HEAD,
|
|
'full_name' => $resident->full_name,
|
|
]);
|
|
|
|
// 2. Transfer them as a child to the new household
|
|
$payload = [
|
|
'relationship' => 'child',
|
|
'user_id' => $resident->id,
|
|
];
|
|
|
|
$response = $this->postJson("/api/v1/admin/households/{$this->household->uuid}/members", $payload);
|
|
|
|
$response->assertStatus(201);
|
|
|
|
// 3. Assert they are now a member of the target household
|
|
$this->assertDatabaseHas('household_members', [
|
|
'household_id' => $this->household->id,
|
|
'user_id' => $resident->id,
|
|
'relationship' => 'child',
|
|
]);
|
|
|
|
// 4. Assert old membership record is deleted
|
|
$this->assertSoftDeleted('household_members', [
|
|
'id' => $oldMember->id,
|
|
]);
|
|
|
|
// 5. Assert old empty household is deleted
|
|
$this->assertSoftDeleted('households', [
|
|
'id' => $oldHousehold->id,
|
|
]);
|
|
}
|
|
|
|
public function test_admin_can_transfer_resident_leaving_others_active(): void
|
|
{
|
|
Sanctum::actingAs($this->admin);
|
|
|
|
// 1. Create old household with head and spouse
|
|
$head = User::factory()->create(['role' => User::ROLE_RESIDENT]);
|
|
$spouse = User::factory()->create(['role' => User::ROLE_RESIDENT]);
|
|
|
|
$oldHousehold = Household::create([
|
|
'tenant_id' => $this->defaultTenant->id,
|
|
'head_user_id' => $head->id,
|
|
'barangay_id' => $this->barangay->id,
|
|
'address_line' => '789 Shared St',
|
|
'coordinates' => new Point(14.5, 120.5, 4326),
|
|
'household_size' => 2,
|
|
'verification_status' => Household::VERIFICATION_APPROVED,
|
|
]);
|
|
|
|
$headMember = HouseholdMember::create([
|
|
'household_id' => $oldHousehold->id,
|
|
'user_id' => $head->id,
|
|
'relationship' => HouseholdMember::RELATIONSHIP_HEAD,
|
|
'full_name' => $head->full_name,
|
|
]);
|
|
|
|
$spouseMember = HouseholdMember::create([
|
|
'household_id' => $oldHousehold->id,
|
|
'user_id' => $spouse->id,
|
|
'relationship' => HouseholdMember::RELATIONSHIP_SPOUSE,
|
|
'full_name' => $spouse->full_name,
|
|
]);
|
|
|
|
// 2. Transfer spouse to target household
|
|
$payload = [
|
|
'relationship' => 'sibling',
|
|
'user_id' => $spouse->id,
|
|
];
|
|
|
|
$response = $this->postJson("/api/v1/admin/households/{$this->household->uuid}/members", $payload);
|
|
|
|
$response->assertStatus(201);
|
|
|
|
// 3. Assert spouse is added to target household
|
|
$this->assertDatabaseHas('household_members', [
|
|
'household_id' => $this->household->id,
|
|
'user_id' => $spouse->id,
|
|
'relationship' => 'sibling',
|
|
]);
|
|
|
|
// 4. Assert old household is NOT deleted (since head is still there)
|
|
$this->assertDatabaseHas('households', [
|
|
'id' => $oldHousehold->id,
|
|
'deleted_at' => null,
|
|
]);
|
|
|
|
// 5. Assert old spouse member is soft deleted
|
|
$this->assertSoftDeleted('household_members', [
|
|
'id' => $spouseMember->id,
|
|
]);
|
|
}
|
|
}
|