fix: QrCode relation bug and Endroid create() error
This commit is contained in:
@@ -95,6 +95,7 @@ class StorePortalController extends ApiController
|
||||
]);
|
||||
|
||||
if (!$request->household_id && !$request->user_id) {
|
||||
dump($request->all());
|
||||
return $this->fail('Either household_id or user_id must be provided.', null, 422);
|
||||
}
|
||||
|
||||
@@ -121,14 +122,15 @@ class StorePortalController extends ApiController
|
||||
->get();
|
||||
|
||||
$qrData = $codes->map(function ($code) {
|
||||
$qr = \Endroid\QrCode\QrCode::create($code->serial)
|
||||
->setSize(300)
|
||||
->setMargin(10);
|
||||
$writer = new PngWriter;
|
||||
$qr = \Endroid\QrCode\Builder\Builder::create()
|
||||
->data($code->serial)
|
||||
->size(300)
|
||||
->margin(10)
|
||||
->build();
|
||||
|
||||
return [
|
||||
'serial' => $code->serial,
|
||||
'qr_base64' => base64_encode($writer->write($qr)->getString()),
|
||||
'qr_base64' => base64_encode($qr->getString()),
|
||||
];
|
||||
});
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ class QrCode extends Model
|
||||
'status',
|
||||
'replacement_for_id',
|
||||
'assigned_to_household_id',
|
||||
'assigned_to_user_id',
|
||||
'assigned_to_store_id',
|
||||
'allocated_at',
|
||||
'activated_at',
|
||||
@@ -54,7 +55,7 @@ class QrCode extends Model
|
||||
public function getActivitylogOptions(): LogOptions
|
||||
{
|
||||
return LogOptions::defaults()
|
||||
->logOnly(['status', 'assigned_to_household_id', 'assigned_to_store_id', 'used_at_drop_off_id'])
|
||||
->logOnly(['status', 'assigned_to_household_id', 'assigned_to_user_id', 'assigned_to_store_id', 'used_at_drop_off_id'])
|
||||
->logOnlyDirty()
|
||||
->dontSubmitEmptyLogs()
|
||||
->useLogName('qr_code');
|
||||
@@ -70,6 +71,11 @@ class QrCode extends Model
|
||||
return $this->belongsTo(Household::class, 'assigned_to_household_id');
|
||||
}
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'assigned_to_user_id');
|
||||
}
|
||||
|
||||
public function usedAtDropOff(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(DropOffPoint::class, 'used_at_drop_off_id');
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('qr_codes', function (Blueprint $table) {
|
||||
$table->foreignId('assigned_to_user_id')->nullable()->after('assigned_to_household_id')->constrained('users')->nullOnDelete();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('qr_codes', function (Blueprint $table) {
|
||||
$table->dropForeign(['assigned_to_user_id']);
|
||||
$table->dropColumn('assigned_to_user_id');
|
||||
});
|
||||
}
|
||||
};
|
||||
95
tests/Feature/Api/V1/Store/ResidentSaleScanTest.php
Normal file
95
tests/Feature/Api/V1/Store/ResidentSaleScanTest.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\V1\Store;
|
||||
|
||||
use App\Models\DropOffPoint;
|
||||
use App\Models\PartnerStore;
|
||||
use App\Models\QrCode;
|
||||
use App\Models\User;
|
||||
use App\Services\Store\StoreOperations;
|
||||
use Database\Seeders\RoleSeeder;
|
||||
use Database\Seeders\SampleDropOffPointsSeeder;
|
||||
use Database\Seeders\SamplePsgcSeeder;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Laravel\Sanctum\Sanctum;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ResidentSaleScanTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_end_to_end_resident_sale_and_scan(): void
|
||||
{
|
||||
// 1. Setup Environment
|
||||
$this->seed([RoleSeeder::class, SamplePsgcSeeder::class, SampleDropOffPointsSeeder::class]);
|
||||
|
||||
$admin = User::factory()->create(['role' => User::ROLE_ADMIN, 'status' => 'active']);
|
||||
$storeOwner = User::factory()->create(['role' => User::ROLE_STORE_PARTNER, 'status' => 'active']);
|
||||
$resident = User::factory()->create(['role' => User::ROLE_RESIDENT, 'status' => 'active']);
|
||||
$scannerUser = User::factory()->create(['role' => User::ROLE_SCANNER, 'status' => 'active']);
|
||||
|
||||
$dop = DropOffPoint::first();
|
||||
|
||||
// 2. Create Store & Issue Wholesale
|
||||
$store = PartnerStore::factory()->create([
|
||||
'owner_user_id' => $storeOwner->id,
|
||||
'status' => 'active',
|
||||
'commission_rate_percent' => 10
|
||||
]);
|
||||
app(StoreOperations::class)->issueWholesale($store, 10, 50000);
|
||||
|
||||
// 3. Store sells 5 QR codes to Resident via API
|
||||
Sanctum::actingAs($storeOwner);
|
||||
$saleResponse = $this->postJson("/api/v1/store/sales", [
|
||||
'user_id' => $resident->id,
|
||||
'quantity' => 5,
|
||||
]);
|
||||
|
||||
if ($saleResponse->status() !== 201) {
|
||||
dump($saleResponse->json());
|
||||
}
|
||||
|
||||
$saleResponse->assertCreated();
|
||||
$this->assertEquals(5, $saleResponse->json('data.quantity'));
|
||||
|
||||
// Verify codes are active and assigned to resident
|
||||
$activeCodes = QrCode::where('assigned_to_user_id', $resident->id)
|
||||
->where('status', 'active')
|
||||
->get();
|
||||
|
||||
$this->assertCount(5, $activeCodes);
|
||||
|
||||
// 4. Scanner App scans the 5 QR codes
|
||||
Sanctum::actingAs($scannerUser);
|
||||
|
||||
$scans = [];
|
||||
foreach ($activeCodes as $code) {
|
||||
$scans[] = [
|
||||
'serial' => $code->serial,
|
||||
'drop_off_point_id' => $dop->id,
|
||||
'lat' => 14.6539,
|
||||
'lng' => 121.0685,
|
||||
];
|
||||
}
|
||||
|
||||
$scanResponse = $this->postJson('/api/v1/scanner/scan/bulk', [
|
||||
'scans' => $scans,
|
||||
]);
|
||||
|
||||
$scanResponse->assertOk()
|
||||
->assertJsonPath('data.accepted_count', 5)
|
||||
->assertJsonPath('data.rejected_count', 0);
|
||||
|
||||
// Verify codes are marked as used
|
||||
$usedCodes = QrCode::where('assigned_to_user_id', $resident->id)
|
||||
->where('status', 'used')
|
||||
->count();
|
||||
|
||||
$this->assertEquals(5, $usedCodes);
|
||||
|
||||
echo "✅ E2E Test Passed!\n";
|
||||
echo "1. Issued wholesale to store.\n";
|
||||
echo "2. Store sold 5 codes to resident (user_id: {$resident->id}).\n";
|
||||
echo "3. Scanner app successfully scanned all 5 codes.\n";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user