company = $this->makeCompany('subs'); } public function test_client_price_computed_from_cost_and_markup(): void { $job = SubcontractJob::create([ 'category' => 'Turbo', 'cost' => 1000, 'markup_pct' => 25, 'status' => 'sent', ]); $this->assertEquals(1250.0, (float) $job->client_price); $this->assertEquals(250.0, $job->margin()); } public function test_manual_client_price_when_no_markup(): void { $job = SubcontractJob::create([ 'category' => 'Vopsitorie', 'cost' => 800, 'markup_pct' => 0, 'client_price' => 1100, 'status' => 'sent', ]); $this->assertEquals(1100.0, (float) $job->client_price); $this->assertEquals(300.0, $job->margin()); } public function test_number_auto_generated(): void { $job = SubcontractJob::create(['cost' => 100, 'markup_pct' => 10, 'status' => 'sent']); $this->assertStringStartsWith('SC-', $job->number); } public function test_wo_total_includes_subcontract_jobs(): void { $wo = $this->makeWorkOrder(); SubcontractJob::create([ 'work_order_id' => $wo->id, 'category' => 'Cutie viteze', 'cost' => 2000, 'markup_pct' => 20, 'status' => 'sent', ]); $wo->refresh(); // client_price = 2000 × 1.20 = 2400 → WO total = 2400 $this->assertEquals(2400.0, (float) $wo->total); } public function test_cancelled_job_excluded_from_total(): void { $wo = $this->makeWorkOrder(); $job = SubcontractJob::create([ 'work_order_id' => $wo->id, 'cost' => 1000, 'markup_pct' => 50, 'status' => 'sent', ]); $wo->refresh(); $this->assertEquals(1500.0, (float) $wo->total); $job->update(['status' => 'cancelled']); $wo->refresh(); $this->assertEquals(0.0, (float) $wo->total); } public function test_deleting_job_recalcs_wo(): void { $wo = $this->makeWorkOrder(); $job = SubcontractJob::create([ 'work_order_id' => $wo->id, 'cost' => 500, 'markup_pct' => 100, 'status' => 'sent', ]); $wo->refresh(); $this->assertEquals(1000.0, (float) $wo->total); $job->delete(); $wo->refresh(); $this->assertEquals(0.0, (float) $wo->total); } public function test_subcontractors_isolated_per_tenant(): void { Subcontractor::create(['name' => 'TurboFix', 'is_active' => true]); $other = $this->makeCompany('othersubs'); app(TenantManager::class)->setCurrent($other); $this->assertEquals(0, Subcontractor::count()); } private function makeCompany(string $slug): Company { $plan = Plan::firstOrCreate(['slug' => 'test'], ['name' => 'T', 'price' => 0, 'features' => []]); $company = Company::create(['plan_id' => $plan->id, 'slug' => $slug, 'name' => ucfirst($slug), 'status' => 'active']); app(TenantManager::class)->setCurrent($company); return $company; } private function makeWorkOrder(): WorkOrder { $client = Client::create(['name' => 'C', 'phone' => '+3736' . random_int(1000000, 9999999), 'type' => 'individual', 'status' => 'active']); $vehicle = Vehicle::create(['client_id' => $client->id, 'make' => 'X', 'model' => 'Y', 'plate' => 'P' . random_int(100, 999)]); return WorkOrder::create([ 'number' => WorkOrder::generateNumber($this->company->id), 'client_id' => $client->id, 'vehicle_id' => $vehicle->id, 'opened_at' => now(), 'status' => 'in_work', ]); } }