155 lines
5.1 KiB
PHP
155 lines
5.1 KiB
PHP
<?php
|
|
|
|
namespace Modules\ProjectManagement\Tests\Feature;
|
|
|
|
use App\Models\User;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Modules\ProjectManagement\Models\Project;
|
|
use Modules\ProjectManagement\Models\ProjectMilestone;
|
|
use Modules\ProjectManagement\Models\Task;
|
|
use Modules\ProjectManagement\Enums\ProjectStatus;
|
|
use Modules\MasterData\Models\Material;
|
|
use Modules\Labors\Models\Labor;
|
|
use Modules\Equipments\Models\Equipment;
|
|
use Modules\ApprovalWorkflow\Models\ApprovalChain;
|
|
use Spatie\Permission\Models\Role;
|
|
use Spatie\Permission\Models\Permission;
|
|
use Tests\TestCase;
|
|
|
|
class ProjectEstimationReviewTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
protected User $user;
|
|
protected Project $project;
|
|
protected Material $material;
|
|
protected Labor $labor;
|
|
protected Equipment $equipment;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
// Seed roles & permissions
|
|
$role = Role::firstOrCreate(['name' => 'Super Admin']);
|
|
Permission::firstOrCreate(['name' => 'projects.access']);
|
|
|
|
$this->user = User::factory()->create([
|
|
'status' => 'active',
|
|
'user_type' => 'admin',
|
|
]);
|
|
$this->user->assignRole($role);
|
|
|
|
// Standard Material
|
|
$this->material = Material::create([
|
|
'name' => 'Review Cement Bag',
|
|
'sku' => 'CEM-REV-101',
|
|
'unit' => 'bag',
|
|
'unit_cost' => 350.00,
|
|
'category' => 'cement',
|
|
'type' => 'raw',
|
|
'status' => 'active',
|
|
]);
|
|
|
|
// Standard Labor
|
|
$this->labor = Labor::create([
|
|
'name' => 'Review Foreman',
|
|
'category' => 'skilled',
|
|
'hourly_rate' => 200.00,
|
|
'status' => 'active',
|
|
]);
|
|
|
|
// Standard Equipment
|
|
$this->equipment = Equipment::create([
|
|
'name' => 'Review Excavator',
|
|
'owner_name' => 'Company Owned',
|
|
'hourly_rate' => 1200.00,
|
|
'status' => 'active',
|
|
]);
|
|
|
|
// Create Project
|
|
$this->project = Project::create([
|
|
'name' => 'Review Test Project',
|
|
'code' => 'PRJ-REV-2026',
|
|
'status' => ProjectStatus::Planning,
|
|
'project_type' => 'standard',
|
|
'is_unprofitable' => false,
|
|
'contract_value' => 600000.00,
|
|
'current_wizard_step' => 6,
|
|
]);
|
|
|
|
// Setup materials estimates
|
|
$this->project->materialsEstimates()->create([
|
|
'material_id' => $this->material->id,
|
|
'estimated_qty' => 50,
|
|
'unit_cost' => 350.00, // Total = 17,500
|
|
]);
|
|
|
|
// Setup task, labor & equipment allocations
|
|
$task = $this->project->tasks()->create([
|
|
'name' => 'Main Site Excavation',
|
|
'status' => 'pending',
|
|
'labor_cost' => 0,
|
|
'estimated_hours' => 10,
|
|
'actual_hours' => 0,
|
|
'completion_percentage' => 0,
|
|
'sort_order' => 1,
|
|
]);
|
|
|
|
$task->taskLabors()->create([
|
|
'labor_id' => $this->labor->id,
|
|
'estimated_hours' => 20, // Total = 4,000
|
|
]);
|
|
|
|
$task->taskEquipments()->create([
|
|
'equipment_id' => $this->equipment->id,
|
|
'estimated_hours' => 10, // Total = 12,000
|
|
]);
|
|
|
|
// Grand total estimation cost: 17,500 + 4,000 + 12,000 = 33,500
|
|
}
|
|
|
|
public function test_project_show_returns_estimation_totals(): void
|
|
{
|
|
$response = $this->actingAs($this->user)->get(route('projects.show', $this->project->ulid));
|
|
|
|
$response->assertStatus(200);
|
|
|
|
$page = $response->original->getData()['page'];
|
|
$props = $page['props'];
|
|
|
|
$this->assertEquals('overview', $props['tab']);
|
|
$this->assertArrayHasKey('estimationTotals', $props);
|
|
$this->assertEquals(17500.0, $props['estimationTotals']['materials']);
|
|
$this->assertEquals(4000.0, $props['estimationTotals']['labor']);
|
|
$this->assertEquals(12000.0, $props['estimationTotals']['equipment']);
|
|
$this->assertEquals(33500.0, $props['estimationTotals']['sum']);
|
|
}
|
|
|
|
public function test_approval_chain_breakdown_data_computes_project_totals_correctly(): void
|
|
{
|
|
// Create approval chain for the project
|
|
$chain = ApprovalChain::create([
|
|
'approvable_type' => Project::class,
|
|
'approvable_id' => $this->project->id,
|
|
'status' => 'in_review',
|
|
'initiator_id' => $this->user->id,
|
|
'notes' => 'Review project budget estimations.',
|
|
]);
|
|
|
|
// Seed permission for approvals index/show
|
|
Permission::firstOrCreate(['name' => 'approvals.access']);
|
|
|
|
$response = $this->actingAs($this->user)->get(route('approvals.show', $chain->ulid));
|
|
|
|
$response->assertStatus(200);
|
|
|
|
$page = $response->original->getData()['page'];
|
|
$props = $page['props'];
|
|
|
|
$this->assertArrayHasKey('breakdownData', $props);
|
|
$this->assertEquals('PRJ-REV-2026', $props['breakdownData']['document_number']);
|
|
$this->assertEquals(33500.0, $props['breakdownData']['total_cost']);
|
|
}
|
|
}
|