From c59a7d54028dde0cebdb43b3320a650c30361f3f Mon Sep 17 00:00:00 2001 From: iamnothardcoded Date: Mon, 3 Aug 2026 01:21:44 +0200 Subject: [PATCH] fix(checkout): still require a delivery address when the area restriction is disabled Since a252f72d the delivery address check is skipped entirely when the "Reject Orders Outside Delivery Area" setting (location_order) is disabled. That setting ships disabled by default, so out of the box a delivery order can be placed with no address at all: address_id ends up NULL and the order is accepted, leaving the restaurant with an undeliverable order. The address fields are not part of the checkout form config, so nothing else validates them - the skipped after() callback was the only guard. Keep the intent of a252f72d (no geocoding or delivery-area enforcement when the restriction is off, so legitimate customers are not blocked by geocoder failures), but still require the address to be present. --- src/Livewire/Checkout.php | 23 +++++++++++++++-------- tests/Livewire/CheckoutTest.php | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/Livewire/Checkout.php b/src/Livewire/Checkout.php index 4362457..23be3a2 100644 --- a/src/Livewire/Checkout.php +++ b/src/Livewire/Checkout.php @@ -376,14 +376,21 @@ protected function validateCheckout(Order $order) $this->withValidator(function($validator) use ($order): void { $validator->after(function($validator) use ($order): void { - if ($order->isDeliveryType() && Location::requiresUserPosition()) { - rescue(function(): void { - $this->orderManager->validateDeliveryAddress(array_only($this->fields, [ - 'address_1', 'city', 'state', 'postcode', 'country', - ])); - }, function(Throwable $ex) use ($validator): void { - $validator->errors()->add('delivery_address', $ex->getMessage()); - }); + if ($order->isDeliveryType()) { + if (Location::requiresUserPosition()) { + rescue(function(): void { + $this->orderManager->validateDeliveryAddress(array_only($this->fields, [ + 'address_1', 'city', 'state', 'postcode', 'country', + ])); + }, function(Throwable $ex) use ($validator): void { + $validator->errors()->add('delivery_address', $ex->getMessage()); + }); + } elseif (blank(array_get($this->fields, 'address_1'))) { + // The delivery area restriction is disabled, so the address is + // deliberately not geocoded or area-checked. It must still exist: + // a delivery order without a street address cannot be delivered. + $validator->errors()->add('delivery_address', lang('igniter.local::default.alert_missing_street_address')); + } } if ($this->fields['payment'] && !$this->orderManager->getPayment($this->fields['payment'])) { diff --git a/tests/Livewire/CheckoutTest.php b/tests/Livewire/CheckoutTest.php index 720aaca..9d0fc79 100644 --- a/tests/Livewire/CheckoutTest.php +++ b/tests/Livewire/CheckoutTest.php @@ -277,6 +277,39 @@ function setupCheckout() ->assertHasErrors(['delivery_address' => [lang('igniter.local::default.alert_missing_street_address')]]); }); +it('onValidate requires a delivery address when the delivery area restriction is disabled', function(): void { + setting()->set(['location_order' => '0']); + setupCheckout(); + + // No usable position, so no address is prepared onto the order + LocationFacade::updateUserPosition(new GeoliteLocation('test')); + + $order = resolve(OrderManager::class)->getOrder(); + $order->order_type = Location::DELIVERY; + $order->save(); + LocationFacade::updateOrderType(Location::DELIVERY); + + Livewire::test(Checkout::class) + ->dispatch('checkout::validate') + ->assertHasErrors(['delivery_address' => [lang('igniter.local::default.alert_missing_street_address')]]); +}); + +it('onValidate does not geocode the delivery address when the delivery area restriction is disabled', function(): void { + setting()->set(['location_order' => '0']); + setupCheckout(); + + $order = resolve(OrderManager::class)->getOrder(); + $order->order_type = Location::DELIVERY; + $order->save(); + LocationFacade::updateOrderType(Location::DELIVERY); + + Geocoder::shouldReceive('geocode')->never(); + + Livewire::test(Checkout::class) + ->dispatch('checkout::validate') + ->assertHasNoErrors('delivery_address'); +}); + it('onValidate dispatches an event on success', function(): void { Event::fake(['igniter.orange.validateCheckout']); setupCheckout();