diff --git a/app/Domains/Sale/Requests/AdminAppSaleIndexRequest.php b/app/Domains/Sale/Requests/AdminAppSaleIndexRequest.php index d4a2d32..0462296 100644 --- a/app/Domains/Sale/Requests/AdminAppSaleIndexRequest.php +++ b/app/Domains/Sale/Requests/AdminAppSaleIndexRequest.php @@ -20,7 +20,7 @@ class AdminAppSaleIndexRequest extends FormRequest 'q' => ['sometimes', 'nullable', 'string', 'max:255'], 'id' => ['sometimes', 'nullable', 'integer', 'min:1'], 'sale_date' => ['sometimes', 'nullable', 'date_format:Y-m-d'], - 'status' => ['sometimes', 'nullable', 'string', Rule::in(Purchase::statuses())], + 'status' => ['sometimes', 'nullable', 'string', Rule::in(Purchase::adminStatusCodes())], 'sort_by' => ['sometimes', 'string', 'in:id,date,customer_name,quantity,status,total'], 'sort_direction' => ['sometimes', 'string', 'in:asc,desc'], 'page' => ['sometimes', 'integer', 'min:1'], diff --git a/app/Domains/Sale/Resources/AdminApp/SaleModificationResource.php b/app/Domains/Sale/Resources/AdminApp/SaleModificationResource.php index 8a9a651..5554dd1 100644 --- a/app/Domains/Sale/Resources/AdminApp/SaleModificationResource.php +++ b/app/Domains/Sale/Resources/AdminApp/SaleModificationResource.php @@ -23,6 +23,12 @@ class SaleModificationResource extends JsonResource 'attribute' => $this->attribute, 'old_value' => $this->old_value, 'new_value' => $this->new_value, + 'admin_status' => is_string($this->new_value) + ? Purchase::adminStatusFor($this->new_value) + : null, + 'status_label' => is_string($this->new_value) + ? Purchase::adminStatusNameFor($this->new_value) + : null, 'changed_at' => $this->changed_at->utc()->toIso8601String(), 'date' => $this->changed_at->format('Y-m-d'), 'time' => $this->changed_at->format('H:i:s'), @@ -31,6 +37,8 @@ class SaleModificationResource extends JsonResource 'id' => $sale->id, 'customer_name' => $sale->nombre_apellido, 'status' => $sale->status, + 'admin_status' => Purchase::adminStatusFor($sale->status), + 'status_label' => Purchase::adminStatusNameFor($sale->status), ] : null, 'modified_by' => $user ? [ 'id' => $user->id, diff --git a/app/Domains/Sale/Resources/AdminApp/SaleResource.php b/app/Domains/Sale/Resources/AdminApp/SaleResource.php index 3a11ced..3e23620 100644 --- a/app/Domains/Sale/Resources/AdminApp/SaleResource.php +++ b/app/Domains/Sale/Resources/AdminApp/SaleResource.php @@ -20,6 +20,8 @@ class SaleResource extends JsonResource 'customer_name' => $this->nombre_apellido, 'quantity' => (int) ($this->quantity ?? 0), 'status' => $this->status, + 'admin_status' => Purchase::adminStatusFor($this->status), + 'status_label' => Purchase::adminStatusNameFor($this->status), 'total' => number_format((float) $this->total, 2, '.', ''), 'tickets_count' => $ticketsCount, 'has_generated_tickets' => $ticketsCount > 0, diff --git a/app/Domains/Sale/Services/AdminAppSaleService.php b/app/Domains/Sale/Services/AdminAppSaleService.php index e4e073d..061c83e 100644 --- a/app/Domains/Sale/Services/AdminAppSaleService.php +++ b/app/Domains/Sale/Services/AdminAppSaleService.php @@ -126,7 +126,6 @@ class AdminAppSaleService return Purchase::query() ->where('tenant_codigo', $tenant->codigo) - ->where('status', '!=', Purchase::STATUS_SUPERSEDED) ->when($filters['q'] ?? null, function (Builder $query, string $search): void { $term = trim($search); @@ -144,12 +143,10 @@ class AdminAppSaleService ) ->when( $filters['status'] ?? null, - fn (Builder $query, string $status): Builder => $status === Purchase::STATUS_PENDING_PAYMENT - ? $query->whereIn('status', [ - Purchase::STATUS_PENDING_PAYMENT, - Purchase::STATUS_IN_REVIEW, - ]) - : $query->where('status', $status) + fn (Builder $query, string $status): Builder => $query->whereIn( + 'status', + Purchase::realStatusesForAdminStatus($status), + ) ) ->select('compras.*') ->selectRaw( diff --git a/tests/Feature/Sale/AdminAppSaleControllerTest.php b/tests/Feature/Sale/AdminAppSaleControllerTest.php index 76eaad9..5c118c5 100644 --- a/tests/Feature/Sale/AdminAppSaleControllerTest.php +++ b/tests/Feature/Sale/AdminAppSaleControllerTest.php @@ -2,6 +2,8 @@ namespace Tests\Feature\Sale; +use App\Domains\Attachable\Enums\AttachmentType; +use App\Domains\Attachable\Models\Attachment; use App\Domains\Auth\Models\User; use App\Domains\Authorization\Enums\RoleCode; use App\Domains\Cart\Models\Cart; @@ -64,6 +66,7 @@ class AdminAppSaleControllerTest extends TestCase PurchaseItem::query()->create([ 'compra_id' => $createdPurchase->id, 'source_catalog_item_id' => $catalogItem->id, + 'nombre' => $catalogItem->nombre, 'item_nombre' => $catalogItem->nombre, 'cantidad' => 3, 'precio_unitario' => '10000.00', @@ -88,6 +91,7 @@ class AdminAppSaleControllerTest extends TestCase PurchaseItem::query()->create([ 'compra_id' => $pendingPurchase->id, 'source_catalog_item_id' => $catalogItem->id, + 'nombre' => $catalogItem->nombre, 'item_nombre' => $catalogItem->nombre, 'cantidad' => 4, 'precio_unitario' => '10000.00', @@ -102,6 +106,7 @@ class AdminAppSaleControllerTest extends TestCase PurchaseItem::query()->create([ 'compra_id' => $paidPurchase->id, 'source_catalog_item_id' => $catalogItem->id, + 'nombre' => $catalogItem->nombre, 'item_nombre' => $catalogItem->nombre, 'cantidad' => 2, 'precio_unitario' => '10000.00', @@ -116,6 +121,7 @@ class AdminAppSaleControllerTest extends TestCase PurchaseItem::query()->create([ 'compra_id' => $supersededPurchase->id, 'source_catalog_item_id' => $catalogItem->id, + 'nombre' => $catalogItem->nombre, 'item_nombre' => $catalogItem->nombre, 'cantidad' => 5, 'precio_unitario' => '10000.00', @@ -124,17 +130,25 @@ class AdminAppSaleControllerTest extends TestCase $this->getJson('/api/v1/adminapp/tenant/sales?sort_by=id&sort_direction=asc') ->assertOk() - ->assertJsonCount(3, 'data') + ->assertJsonCount(4, 'data') ->assertJsonPath('data.0.id', $createdPurchase->id) ->assertJsonPath('data.0.quantity', 3) + ->assertJsonPath('data.0.admin_status', Purchase::ADMIN_STATUS_INCOMPLETE) + ->assertJsonPath('data.0.status_label', 'Por completar datos') ->assertJsonPath('data.1.id', $pendingPurchase->id) ->assertJsonPath('data.1.quantity', 4) + ->assertJsonPath('data.1.admin_status', Purchase::ADMIN_STATUS_AWAITING_PAYMENT) + ->assertJsonPath('data.1.status_label', 'Esperando pago') ->assertJsonPath('data.2.id', $paidPurchase->id) - ->assertJsonPath('data.2.quantity', 2); + ->assertJsonPath('data.2.quantity', 2) + ->assertJsonPath('data.2.admin_status', Purchase::ADMIN_STATUS_CONFIRMED) + ->assertJsonPath('data.2.status_label', 'Confirmado') + ->assertJsonPath('data.3.id', $supersededPurchase->id) + ->assertJsonPath('data.3.admin_status', Purchase::ADMIN_STATUS_CANCELLED) + ->assertJsonPath('data.3.status_label', 'Anulado'); $this->getJson('/api/v1/adminapp/tenant/sales?status='.Purchase::STATUS_SUPERSEDED) - ->assertOk() - ->assertJsonCount(0, 'data'); + ->assertUnprocessable(); } public function test_authentication_is_required_to_read_a_sale_detail(): void @@ -142,7 +156,7 @@ class AdminAppSaleControllerTest extends TestCase $this->getJson('/api/v1/adminapp/tenant/sales/1')->assertUnauthorized(); } - public function test_pending_payment_filter_also_returns_purchases_in_review(): void + public function test_awaiting_payment_filter_returns_every_mapped_real_status(): void { $tenant = $this->createTenant('acme'); Sanctum::actingAs($this->createAdminAppUser($tenant)); @@ -160,13 +174,41 @@ class AdminAppSaleControllerTest extends TestCase 'status' => Purchase::STATUS_PAID, ]); - $this->getJson('/api/v1/adminapp/tenant/sales?status=pending_payment&sort_by=id&sort_direction=asc') + $this->getJson('/api/v1/adminapp/tenant/sales?status=awaiting_payment&sort_by=id&sort_direction=asc') ->assertOk() ->assertJsonCount(2, 'data') ->assertJsonPath('data.0.id', $pendingPurchase->id) ->assertJsonPath('data.1.id', $reviewPurchase->id); } + public function test_cancelled_filter_returns_every_visible_mapped_real_status(): void + { + $tenant = $this->createTenant('acme'); + Sanctum::actingAs($this->createAdminAppUser($tenant)); + + foreach ([ + Purchase::STATUS_CANCELLED, + Purchase::STATUS_REJECTED, + Purchase::STATUS_EXPIRED, + Purchase::STATUS_SUPERSEDED, + ] as $status) { + Purchase::query()->create([ + 'tenant_codigo' => $tenant->codigo, + 'status' => $status, + ]); + } + Purchase::query()->create([ + 'tenant_codigo' => $tenant->codigo, + 'status' => Purchase::STATUS_PAID, + ]); + + $this->getJson('/api/v1/adminapp/tenant/sales?status=cancelled') + ->assertOk() + ->assertJsonCount(4, 'data') + ->assertJsonPath('data.0.admin_status', Purchase::ADMIN_STATUS_CANCELLED) + ->assertJsonPath('data.0.status_label', 'Anulado'); + } + public function test_an_adminapp_user_can_read_a_sale_detail_from_its_tenant(): void { $tenant = $this->createTenant('acme'); @@ -233,6 +275,7 @@ class AdminAppSaleControllerTest extends TestCase $purchaseItem = PurchaseItem::query()->create([ 'compra_id' => $purchase->id, 'source_catalog_item_id' => $catalogItem->id, + 'nombre' => $catalogItem->nombre, 'item_nombre' => $catalogItem->nombre, 'cantidad' => 2, 'precio_unitario' => '12500.00', @@ -479,6 +522,7 @@ class AdminAppSaleControllerTest extends TestCase PurchaseItem::query()->create([ 'compra_id' => $purchase->id, 'source_catalog_item_id' => $catalogItem->id, + 'nombre' => $catalogItem->nombre, 'item_nombre' => $catalogItem->nombre, 'cantidad' => 2, 'precio_unitario' => '10000.00', @@ -574,14 +618,34 @@ class AdminAppSaleControllerTest extends TestCase private function createTenant(string $code): Tenant { + $headerLogo = $this->createAttachment("{$code}-header"); + $footerLogo = $this->createAttachment("{$code}-footer"); + return Tenant::query()->create([ 'codigo' => $code, 'nombre' => ucfirst($code), 'dominio' => "{$code}.test", + 'primary_color' => '#000000', + 'secondary_color' => '#ffffff', + 'danger_color' => '#dc3545', + 'header_bg_color' => '#ffffff', + 'footer_bg_color' => '#000000', + 'header_logo_id' => $headerLogo->id, + 'footer_logo_id' => $footerLogo->id, 'website_type_code' => 'onticket', ]); } + private function createAttachment(string $name): Attachment + { + return Attachment::query()->create([ + 'path' => "test/{$name}.png", + 'filename' => "{$name}.png", + 'type' => AttachmentType::Image, + 'mime_type' => 'image/png', + ]); + } + private function createAdminAppUser(Tenant $tenant): User { return User::factory()->create([ diff --git a/tests/Unit/Sale/SaleModificationResourceTest.php b/tests/Unit/Sale/SaleModificationResourceTest.php index 1fe1386..3f2e3a4 100644 --- a/tests/Unit/Sale/SaleModificationResourceTest.php +++ b/tests/Unit/Sale/SaleModificationResourceTest.php @@ -3,6 +3,7 @@ namespace Tests\Unit\Sale; use App\Domains\Logging\Models\ValueChange; +use App\Domains\Purchase\Models\Purchase; use App\Domains\Sale\Resources\AdminApp\SaleModificationResource; use Carbon\CarbonImmutable; use Illuminate\Http\Request; @@ -29,5 +30,7 @@ class SaleModificationResourceTest extends TestCase $this->assertSame('2026-08-24T17:53:00+00:00', $data['changed_at']); $this->assertSame('2026-08-24', $data['date']); $this->assertSame('17:53:00', $data['time']); + $this->assertSame(Purchase::ADMIN_STATUS_CANCELLED, $data['admin_status']); + $this->assertSame('Anulado', $data['status_label']); } }