Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions app/Http/Controllers/ResellerPaymentImportController.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ public function store(Request $request)
$count = 0;

DB::transaction(function () use ($previewData, &$count) {
// Optimally fetch all involved resellers
$resellerIds = collect($previewData)->pluck('reseller_id')->unique()->filter();
$resellers = Reseller::whereIn('id', $resellerIds)->get()->keyBy('id');
$updatedResellers = collect();

foreach ($previewData as $row) {
if (!empty($row['errors'])) continue;

Expand All @@ -124,14 +129,23 @@ public function store(Request $request)
]);

// Update Reseller Due
$reseller = Reseller::find($row['reseller_id']);
if ($reseller) {
if (isset($resellers[$row['reseller_id']])) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Normalize reseller IDs before keyed lookup

The new condition isset($resellers[$row['reseller_id']]) depends on an exact array key match, which can fail for string-formatted IDs (for example '001' or '1 ') even when preview accepted the row via Reseller::find(...) and SQL numeric coercion. In that case, ResellerPayment is still created but the reseller’s due_amount is not decremented, creating inconsistent financial data. Normalize/cast reseller_id before whereIn and lookup to preserve previous behavior.

Useful? React with πŸ‘Β / πŸ‘Ž.

$reseller = $resellers[$row['reseller_id']];
$reseller->due_amount -= $row['amount'];
$reseller->save();

// Track unique resellers to save later
if (!$updatedResellers->has($reseller->id)) {
$updatedResellers->put($reseller->id, $reseller);
}
}

$count++;
}

// Save all updated resellers in one go (well, N queries but N = unique resellers, not N = total rows)
foreach ($updatedResellers as $reseller) {
$reseller->save();
}
});

session()->forget('import_preview_data');
Expand Down
72 changes: 72 additions & 0 deletions tests/Feature/ResellerPaymentImportOptimizationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
use App\Models\User;
use App\Models\Reseller;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Session;

class ResellerPaymentImportOptimizationTest extends TestCase
{
use RefreshDatabase;

public function test_import_store_performance()
{
// Setup
$user = User::factory()->create();
$this->actingAs($user);

// Seed 50 Resellers
$resellers = collect();
for ($i = 0; $i < 50; $i++) {
$resellers->push(Reseller::create([
'business_name' => 'Reseller ' . $i,
'name' => 'Owner ' . $i,
'mobile' => '077123456' . $i,
'due_amount' => 10000,
]));
}

// Create 1000 simulated payment records
$previewData = [];
$resellerIds = $resellers->pluck('id');
for ($i = 0; $i < 1000; $i++) {
$previewData[] = [
'reseller_id' => $resellerIds->random(),
'amount' => 100,
'method' => 'cash',
'reference' => 'REF' . $i,
'date' => now()->format('Y-m-d'),
'errors' => []
];
}

// Set session data
session(['import_preview_data' => $previewData]);

// Enable query logging
DB::enableQueryLog();
$startTime = microtime(true);

// Call the store method via route
$response = $this->post(route('reseller-payments.import.store'));

$endTime = microtime(true);
$queries = DB::getQueryLog();
$queryCount = count($queries);
$executionTime = $endTime - $startTime;

// Output results
echo "\n\nBenchmark Results:\n";
echo "Execution Time: " . round($executionTime, 4) . " seconds\n";
echo "Total Queries: " . $queryCount . "\n\n";

// Assertions
$response->assertRedirect(route('reseller-payments.index'));
$this->assertDatabaseCount('reseller_payments', 1000);
}
}