diff --git a/app/Http/Controllers/Portal/Invoices.php b/app/Http/Controllers/Portal/Invoices.php index 71fd97208..401eeaaab 100644 --- a/app/Http/Controllers/Portal/Invoices.php +++ b/app/Http/Controllers/Portal/Invoices.php @@ -44,8 +44,19 @@ class Invoices extends Controller */ public function show(Document $invoice, Request $request) { - // Use DocumentService to optimally load all relationships needed for template rendering - app(\App\Services\DocumentService::class)->loadForShow($invoice); + $invoice->load([ + 'items.taxes.tax', + 'items.item', + 'totals', + 'contact', + 'currency', + 'category', + 'histories', + 'media', + 'transactions', + 'recurring', + 'children', + ]); $payment_methods = Modules::getPaymentMethods(); diff --git a/app/Http/Controllers/Purchases/Bills.php b/app/Http/Controllers/Purchases/Bills.php index 23513a82c..a1f82b564 100644 --- a/app/Http/Controllers/Purchases/Bills.php +++ b/app/Http/Controllers/Purchases/Bills.php @@ -45,8 +45,19 @@ class Bills extends Controller */ public function show(Document $bill) { - // Use DocumentService to optimally load all relationships needed for template rendering - app(\App\Services\DocumentService::class)->loadForShow($bill); + $bill->load([ + 'items.taxes.tax', + 'items.item', + 'totals', + 'contact', + 'currency', + 'category', + 'histories', + 'media', + 'transactions', + 'recurring', + 'children', + ]); return view('purchases.bills.show', compact('bill')); } diff --git a/app/Http/Controllers/Sales/Invoices.php b/app/Http/Controllers/Sales/Invoices.php index 89bb4da3b..e003919d5 100644 --- a/app/Http/Controllers/Sales/Invoices.php +++ b/app/Http/Controllers/Sales/Invoices.php @@ -47,8 +47,19 @@ class Invoices extends Controller */ public function show(Document $invoice) { - // Use DocumentService to optimally load all relationships needed for template rendering - app(\App\Services\DocumentService::class)->loadForShow($invoice); + $invoice->load([ + 'items.taxes.tax', + 'items.item', + 'totals', + 'contact', + 'currency', + 'category', + 'histories', + 'media', + 'transactions', + 'recurring', + 'children', + ]); return view('sales.invoices.show', compact('invoice')); } diff --git a/app/Services/DocumentService.php b/app/Services/DocumentService.php deleted file mode 100644 index e70869732..000000000 --- a/app/Services/DocumentService.php +++ /dev/null @@ -1,117 +0,0 @@ -load($relationships); - } - - /** - * Load document with all relationships needed for show pages - * Includes template relationships plus show-specific ones - * - * @param Document $document - * @param array $additionalRelationships - * @return Document - */ - public function loadForShow(Document $document, array $additionalRelationships = []): Document - { - $relationships = array_merge( - self::TEMPLATE_RELATIONSHIPS, - self::SHOW_RELATIONSHIPS, - $additionalRelationships - ); - - return $document->load($relationships); - } - - /** - * Load minimal relationships for document listing - * Optimized for index pages with many documents - * - * @param Document $document - * @return Document - */ - public function loadForIndex(Document $document): Document - { - return $document->load([ - 'contact', - 'category', - 'currency', - 'last_history' - ]); - } - - /** - * Check if document has all necessary relationships loaded - * Useful for debugging and ensuring optimal performance - * - * @param Document $document - * @return bool - */ - public function hasTemplateRelationshipsLoaded(Document $document): bool - { - foreach (self::TEMPLATE_RELATIONSHIPS as $relationship) { - if (!$document->relationLoaded($this->getBaseRelationship($relationship))) { - return false; - } - } - - return true; - } - - /** - * Get the base relationship name from a nested relationship string - * e.g., "items.taxes.tax" returns "items" - * - * @param string $relationship - * @return string - */ - private function getBaseRelationship(string $relationship): string - { - return explode('.', $relationship)[0]; - } -} \ No newline at end of file diff --git a/tests/Feature/Performance/N1QueryOptimizationTest.php b/tests/Feature/Performance/N1QueryOptimizationTest.php index 09984a552..859f72ceb 100644 --- a/tests/Feature/Performance/N1QueryOptimizationTest.php +++ b/tests/Feature/Performance/N1QueryOptimizationTest.php @@ -6,7 +6,6 @@ use App\Models\Common\Dashboard; use App\Models\Common\Item; use App\Models\Document\Document; use App\Models\Setting\Tax; -use App\Services\DocumentService; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Support\Facades\DB; use Tests\Feature\FeatureTestCase; @@ -102,65 +101,6 @@ class N1QueryOptimizationTest extends FeatureTestCase $this->assertLessThan(10, $queryCount, 'Autocomplete should not use excessive queries'); } - /** - * Test DocumentService optimization - * This validates our DocumentService implementation - */ - public function testDocumentServiceOptimization() - { - $this->loginAs(); - - // Create a realistic document scenario - $document = Document::factory()->invoice()->create([ - 'company_id' => $this->company->id - ]); - - $item = Item::factory()->create(['company_id' => $this->company->id]); - $tax = Tax::factory()->create(['company_id' => $this->company->id]); - - $documentItem = $document->items()->create([ - 'company_id' => $this->company->id, - 'type' => $document->type, - 'item_id' => $item->id, - 'name' => $item->name, - 'quantity' => 1, - 'price' => 100, - 'total' => 100 - ]); - - $documentItem->taxes()->create([ - 'company_id' => $this->company->id, - 'type' => $document->type, - 'document_id' => $document->id, - 'tax_id' => $tax->id, - 'name' => $tax->name, - 'amount' => 10 - ]); - - // Test our DocumentService - $documentService = app(DocumentService::class); - - // Test loadForShow method - $freshDocument = Document::find($document->id); - $optimizedDocument = $documentService->loadForShow($freshDocument); - - // Verify all critical relationships are loaded - $this->assertTrue($optimizedDocument->relationLoaded('items'), 'Items should be loaded'); - $this->assertTrue($optimizedDocument->relationLoaded('contact'), 'Contact should be loaded'); - $this->assertTrue($optimizedDocument->relationLoaded('currency'), 'Currency should be loaded'); - $this->assertTrue($optimizedDocument->relationLoaded('totals'), 'Totals should be loaded'); - - // Test nested relationships - if ($optimizedDocument->items->count() > 0) { - $firstItem = $optimizedDocument->items->first(); - $this->assertTrue($firstItem->relationLoaded('taxes'), 'Item taxes should be loaded'); - $this->assertTrue($firstItem->relationLoaded('item'), 'Item details should be loaded'); - } - - // Test service methods - $this->assertTrue($documentService->hasTemplateRelationshipsLoaded($optimizedDocument)); - } - /** * Test that our optimizations prevent the classic N+1 scenario * This validates that eager loading works correctly