feat(event): support ticket refund configuration in event endpoints
This commit is contained in:
parent
c0c19c9c01
commit
4bb4f526e4
|
|
@ -33,6 +33,16 @@ class UpdateEventRequest extends FormRequest
|
||||||
'contact.whatsapp_url' => ['nullable', 'url', 'max:2048'],
|
'contact.whatsapp_url' => ['nullable', 'url', 'max:2048'],
|
||||||
'contact.instagram_url' => ['nullable', 'url', 'max:2048'],
|
'contact.instagram_url' => ['nullable', 'url', 'max:2048'],
|
||||||
'contact.facebook_url' => ['nullable', 'url', 'max:2048'],
|
'contact.facebook_url' => ['nullable', 'url', 'max:2048'],
|
||||||
|
'allow_ticket_refund' => ['sometimes', 'boolean'],
|
||||||
|
'allow_ticket_total_refund' => ['sometimes', 'boolean'],
|
||||||
|
'allow_ticket_partial_refund' => ['sometimes', 'boolean'],
|
||||||
|
'ticket_partial_refund_percentage' => [
|
||||||
|
'sometimes',
|
||||||
|
'numeric',
|
||||||
|
'decimal:0,2',
|
||||||
|
'min:0',
|
||||||
|
'max:99.99',
|
||||||
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -49,6 +59,41 @@ class UpdateEventRequest extends FormRequest
|
||||||
'The social media field is required.'
|
'The social media field is required.'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (! array_key_exists('allow_ticket_refund', $input)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ([
|
||||||
|
'allow_ticket_total_refund',
|
||||||
|
'allow_ticket_partial_refund',
|
||||||
|
'ticket_partial_refund_percentage',
|
||||||
|
] as $field) {
|
||||||
|
if (! array_key_exists($field, $input)) {
|
||||||
|
$validator->errors()->add($field, 'El campo es obligatorio.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$totalEnabled = $this->boolean('allow_ticket_total_refund');
|
||||||
|
$partialEnabled = $this->boolean('allow_ticket_partial_refund');
|
||||||
|
|
||||||
|
$refundEnabled = $this->boolean('allow_ticket_refund');
|
||||||
|
|
||||||
|
if ($refundEnabled && ! $totalEnabled && ! $partialEnabled) {
|
||||||
|
$validator->errors()->add(
|
||||||
|
'allow_ticket_refund',
|
||||||
|
'Seleccioná al menos un tipo de reembolso.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($refundEnabled
|
||||||
|
&& $partialEnabled
|
||||||
|
&& (float) ($input['ticket_partial_refund_percentage'] ?? 0) <= 0) {
|
||||||
|
$validator->errors()->add(
|
||||||
|
'ticket_partial_refund_percentage',
|
||||||
|
'Ingresá un porcentaje mayor que cero para el reembolso parcial.'
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,10 @@ class EventResource extends JsonResource
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'title' => $this->event_title,
|
'title' => $this->event_title,
|
||||||
'location' => $this->event_location,
|
'location' => $this->event_location,
|
||||||
|
'allow_ticket_refund' => $this->allow_ticket_refund,
|
||||||
|
'allow_ticket_total_refund' => $this->allow_ticket_total_refund,
|
||||||
|
'allow_ticket_partial_refund' => $this->allow_ticket_partial_refund,
|
||||||
|
'ticket_partial_refund_percentage' => $this->ticket_partial_refund_percentage,
|
||||||
'dates' => EventDateResource::collection($this->eventDates),
|
'dates' => EventDateResource::collection($this->eventDates),
|
||||||
'social_media' => $this->socialMedia->map(fn ($item): array => [
|
'social_media' => $this->socialMedia->map(fn ($item): array => [
|
||||||
'code' => $item->code,
|
'code' => $item->code,
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,12 @@ class EventService
|
||||||
$tenant->update([
|
$tenant->update([
|
||||||
'event_title' => $data['title'],
|
'event_title' => $data['title'],
|
||||||
'event_location' => $data['location'],
|
'event_location' => $data['location'],
|
||||||
|
...array_intersect_key($data, array_flip([
|
||||||
|
'allow_ticket_refund',
|
||||||
|
'allow_ticket_total_refund',
|
||||||
|
'allow_ticket_partial_refund',
|
||||||
|
'ticket_partial_refund_percentage',
|
||||||
|
])),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (array_key_exists('social_media', $data)) {
|
if (array_key_exists('social_media', $data)) {
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,10 @@ class AdminAppEventControllerTest extends TestCase
|
||||||
->assertOk()
|
->assertOk()
|
||||||
->assertJsonPath('data.title', 'Festival Acme')
|
->assertJsonPath('data.title', 'Festival Acme')
|
||||||
->assertJsonPath('data.location', 'Predio Ferial, Rosario')
|
->assertJsonPath('data.location', 'Predio Ferial, Rosario')
|
||||||
|
->assertJsonPath('data.allow_ticket_refund', true)
|
||||||
|
->assertJsonPath('data.allow_ticket_total_refund', true)
|
||||||
|
->assertJsonPath('data.allow_ticket_partial_refund', true)
|
||||||
|
->assertJsonPath('data.ticket_partial_refund_percentage', '25.50')
|
||||||
->assertJsonCount(0, 'data.dates')
|
->assertJsonCount(0, 'data.dates')
|
||||||
->assertJsonPath('data.contact.whatsapp_url', 'https://wa.me/5493415550101')
|
->assertJsonPath('data.contact.whatsapp_url', 'https://wa.me/5493415550101')
|
||||||
->assertJsonPath('data.contact.instagram_url', 'https://instagram.com/acme')
|
->assertJsonPath('data.contact.instagram_url', 'https://instagram.com/acme')
|
||||||
|
|
@ -62,6 +66,10 @@ class AdminAppEventControllerTest extends TestCase
|
||||||
'event_title' => 'Festival Acme',
|
'event_title' => 'Festival Acme',
|
||||||
'event_location' => 'Predio Ferial, Rosario',
|
'event_location' => 'Predio Ferial, Rosario',
|
||||||
'event_date_text' => null,
|
'event_date_text' => null,
|
||||||
|
'allow_ticket_refund' => true,
|
||||||
|
'allow_ticket_total_refund' => true,
|
||||||
|
'allow_ticket_partial_refund' => true,
|
||||||
|
'ticket_partial_refund_percentage' => 25.50,
|
||||||
]);
|
]);
|
||||||
$this->assertDatabaseCount('event_dates', 0);
|
$this->assertDatabaseCount('event_dates', 0);
|
||||||
$this->assertDatabaseHas('tenant_social_media', [
|
$this->assertDatabaseHas('tenant_social_media', [
|
||||||
|
|
@ -71,6 +79,56 @@ class AdminAppEventControllerTest extends TestCase
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_disabling_refunds_preserves_the_configured_types_and_percentage(): void
|
||||||
|
{
|
||||||
|
$tenant = $this->createTenant('acme');
|
||||||
|
$tenant->update([
|
||||||
|
'allow_ticket_refund' => true,
|
||||||
|
'allow_ticket_total_refund' => true,
|
||||||
|
'allow_ticket_partial_refund' => true,
|
||||||
|
'ticket_partial_refund_percentage' => 35.50,
|
||||||
|
]);
|
||||||
|
Sanctum::actingAs($this->createAdminAppUser($tenant));
|
||||||
|
|
||||||
|
$payload = $this->eventPayload();
|
||||||
|
$payload['allow_ticket_refund'] = false;
|
||||||
|
$payload['ticket_partial_refund_percentage'] = 35.50;
|
||||||
|
|
||||||
|
$this->putJson('/api/v1/adminapp/tenant/event', $payload)
|
||||||
|
->assertOk()
|
||||||
|
->assertJsonPath('data.allow_ticket_refund', false)
|
||||||
|
->assertJsonPath('data.allow_ticket_total_refund', true)
|
||||||
|
->assertJsonPath('data.allow_ticket_partial_refund', true)
|
||||||
|
->assertJsonPath('data.ticket_partial_refund_percentage', '35.50');
|
||||||
|
|
||||||
|
$tenant->refresh();
|
||||||
|
$this->assertFalse($tenant->allow_refund());
|
||||||
|
$this->assertTrue($tenant->allow_ticket_total_refund);
|
||||||
|
$this->assertTrue($tenant->allow_ticket_partial_refund);
|
||||||
|
$this->assertSame('35.50', $tenant->ticket_partial_refund_percentage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_enabled_refunds_require_a_type_and_a_valid_partial_percentage(): void
|
||||||
|
{
|
||||||
|
$tenant = $this->createTenant('acme');
|
||||||
|
Sanctum::actingAs($this->createAdminAppUser($tenant));
|
||||||
|
|
||||||
|
$payload = $this->eventPayload();
|
||||||
|
$payload['allow_ticket_total_refund'] = false;
|
||||||
|
$payload['allow_ticket_partial_refund'] = false;
|
||||||
|
|
||||||
|
$this->putJson('/api/v1/adminapp/tenant/event', $payload)
|
||||||
|
->assertUnprocessable()
|
||||||
|
->assertJsonValidationErrors('allow_ticket_refund');
|
||||||
|
|
||||||
|
$payload['allow_ticket_partial_refund'] = true;
|
||||||
|
$payload['ticket_partial_refund_percentage'] = 0;
|
||||||
|
|
||||||
|
$this->putJson('/api/v1/adminapp/tenant/event', $payload)
|
||||||
|
->assertUnprocessable()
|
||||||
|
->assertJsonValidationErrors('ticket_partial_refund_percentage');
|
||||||
|
}
|
||||||
|
|
||||||
public function test_an_adminapp_user_can_read_only_its_tenant_active_event(): void
|
public function test_an_adminapp_user_can_read_only_its_tenant_active_event(): void
|
||||||
{
|
{
|
||||||
$tenant = $this->createTenant('acme');
|
$tenant = $this->createTenant('acme');
|
||||||
|
|
@ -375,6 +433,10 @@ class AdminAppEventControllerTest extends TestCase
|
||||||
return [
|
return [
|
||||||
'title' => 'Festival Acme',
|
'title' => 'Festival Acme',
|
||||||
'location' => 'Predio Ferial, Rosario',
|
'location' => 'Predio Ferial, Rosario',
|
||||||
|
'allow_ticket_refund' => true,
|
||||||
|
'allow_ticket_total_refund' => true,
|
||||||
|
'allow_ticket_partial_refund' => true,
|
||||||
|
'ticket_partial_refund_percentage' => 25.50,
|
||||||
'contact' => [
|
'contact' => [
|
||||||
'whatsapp_url' => 'https://wa.me/5493415550101',
|
'whatsapp_url' => 'https://wa.me/5493415550101',
|
||||||
'instagram_url' => 'https://instagram.com/acme',
|
'instagram_url' => 'https://instagram.com/acme',
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue