diff --git a/app/Domains/FiestaFutbolInfantil/Resources/EntryResource.php b/app/Domains/FiestaFutbolInfantil/Resources/EntryResource.php index 41e414f..eed2e56 100644 --- a/app/Domains/FiestaFutbolInfantil/Resources/EntryResource.php +++ b/app/Domains/FiestaFutbolInfantil/Resources/EntryResource.php @@ -12,7 +12,7 @@ class EntryResource extends JsonResource /** @return array */ public function toArray(Request $request): array { - $variant = $this->variants->sole(); + $variant = $this->variants->whereNull('replaced_by_variant_id')->sole(); return [ 'id' => $this->id, diff --git a/app/Domains/FiestaFutbolInfantil/Services/EntryService.php b/app/Domains/FiestaFutbolInfantil/Services/EntryService.php index 0c44363..eed5231 100644 --- a/app/Domains/FiestaFutbolInfantil/Services/EntryService.php +++ b/app/Domains/FiestaFutbolInfantil/Services/EntryService.php @@ -97,6 +97,7 @@ class EntryService $variants = Variant::query() ->where('catalog_item_id', $catalogItem->id) + ->whereNull('replaced_by_variant_id') ->lockForUpdate() ->get(); diff --git a/tests/Feature/FiestaFutbolInfantil/EntryControllerTest.php b/tests/Feature/FiestaFutbolInfantil/EntryControllerTest.php index 9b084f4..0a1249b 100644 --- a/tests/Feature/FiestaFutbolInfantil/EntryControllerTest.php +++ b/tests/Feature/FiestaFutbolInfantil/EntryControllerTest.php @@ -7,6 +7,7 @@ use App\Domains\Authorization\Enums\RoleCode; use App\Domains\Catalog\Models\Attribute; use App\Domains\Catalog\Models\CatalogItem; use App\Domains\Catalog\Models\Category; +use App\Domains\Catalog\Models\Inventory; use App\Domains\Catalog\Models\Variant; use App\Domains\Menu\Models\Menu; use App\Domains\Shared\Enums\FieldType; @@ -221,6 +222,66 @@ class EntryControllerTest extends TestCase ]); } + public function test_it_reads_and_edits_the_latest_replacement_even_when_sales_are_disabled(): void + { + $tenant = $this->createFiestaTenant(); + $this->createEventDateAttribute($tenant); + $date = $tenant->eventDates()->create([ + 'date' => '2027-10-09', + 'time_start' => '00:00', + 'time_end' => '23:59', + ]); + $otherDate = $tenant->eventDates()->create([ + 'date' => '2027-10-10', + 'time_start' => '00:00', + 'time_end' => '23:59', + ]); + Sanctum::actingAs($this->createAdminAppUser($tenant)); + $entryId = $this->postJson('/api/v1/adminapp/tenant/entries', [ + 'entries' => [[ + 'title' => 'Abono', + 'event_date_ids' => [$date->id], + 'stock' => 10, + 'price' => 100, + ]], + ])->assertOk()->json('data.0.id'); + + $original = Variant::query()->where('catalog_item_id', $entryId)->sole(); + $intermediate = $original->replicate(); + $intermediate->save(); + $replacement = $original->replicate(); + $replacement->inventory_id = Inventory::query()->create(['real_stock' => 20])->id; + $replacement->event_date_id = $otherDate->id; + $replacement->sales_disabled_at = now(); + $replacement->save(); + $replacement->eventDates()->sync([$otherDate->id]); + $original->update(['replaced_by_variant_id' => $intermediate->id, 'sales_disabled_at' => now()]); + $intermediate->update(['replaced_by_variant_id' => $replacement->id, 'sales_disabled_at' => now()]); + + $this->getJson('/api/v1/adminapp/tenant/entries') + ->assertOk() + ->assertJsonPath('data.0.stock', 20) + ->assertJsonPath('data.0.event_date_ids', [$otherDate->id]); + + $this->postJson('/api/v1/adminapp/tenant/entries', [ + 'entries' => [[ + 'id' => $entryId, + 'title' => 'Abono editado', + 'event_date_ids' => [$date->id, $otherDate->id], + 'stock' => 30, + 'price' => 200, + ]], + ])->assertOk() + ->assertJsonPath('data.0.stock', 30) + ->assertJsonPath('data.0.event_date_ids', [$date->id, $otherDate->id]); + + $this->assertSame(10, $original->fresh()->inventory->real_stock); + $this->assertSame([$date->id], $original->fresh()->selectedEventDates()->pluck('id')->all()); + $this->assertSame(30, $replacement->fresh()->inventory->real_stock); + $this->assertNotNull($replacement->fresh()->sales_disabled_at); + $this->assertDatabaseCount('variantes', 3); + } + public function test_it_deletes_an_entry_and_its_inventory(): void { $tenant = $this->createFiestaTenant(); diff --git a/tests/Unit/FiestaFutbolInfantil/EntryResourceTest.php b/tests/Unit/FiestaFutbolInfantil/EntryResourceTest.php new file mode 100644 index 0000000..6f71b8a --- /dev/null +++ b/tests/Unit/FiestaFutbolInfantil/EntryResourceTest.php @@ -0,0 +1,45 @@ + 2]); + $intermediate = new Variant(['replaced_by_variant_id' => 3]); + $current = new Variant(['sales_disabled_at' => now()]); + $date = new EventDate; + $date->id = 13; + $current->setRelation('eventDates', collect([$date])); + $current->setRelation('inventory', new Inventory(['real_stock' => 20])); + $entry = new CatalogItem(['nombre' => 'Abono', 'precio' => 100]); + $entry->setRelation('variants', collect([$original, $intermediate, $current])); + + $data = (new EntryResource($entry))->resolve(Request::create('/')); + + $this->assertSame([13], $data['event_date_ids']->all()); + $this->assertSame(20, $data['stock']); + $this->assertSame('Abono', $data['title']); + $this->assertNotNull($current->sales_disabled_at); + } + + public function test_it_does_not_choose_arbitrarily_between_current_variants(): void + { + $entry = new CatalogItem; + $entry->setRelation('variants', collect([new Variant, new Variant])); + + $this->expectException(MultipleItemsFoundException::class); + + (new EntryResource($entry))->resolve(Request::create('/')); + } +}