diff --git a/composer.json b/composer.json index c448a9e..5e5535f 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "fleetbase/storefront-api", - "version": "0.4.6", + "version": "0.4.7", "description": "Headless Commerce & Marketplace Extension for Fleetbase", "keywords": [ "fleetbase-extension", diff --git a/extension.json b/extension.json index 44a2efc..d25b747 100644 --- a/extension.json +++ b/extension.json @@ -1,6 +1,6 @@ { "name": "Storefront", - "version": "0.4.6", + "version": "0.4.7", "description": "Headless Commerce & Marketplace Extension for Fleetbase", "repository": "https://github.com/fleetbase/storefront", "license": "AGPL-3.0-or-later", diff --git a/package.json b/package.json index 4fd0ca3..06608a8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@fleetbase/storefront-engine", - "version": "0.4.6", + "version": "0.4.7", "description": "Headless Commerce & Marketplace Extension for Fleetbase", "fleetbase": { "route": "storefront", diff --git a/server/config/storefront.php b/server/config/storefront.php index 78636b1..9312c57 100644 --- a/server/config/storefront.php +++ b/server/config/storefront.php @@ -43,7 +43,7 @@ |-------------------------------------------------------------------------- */ 'throttle' => [ - 'max_attempts' => env('STOREFRONT_THROTTLE_REQUESTS_PER_MINUTE', 500), + 'max_attempts' => env('STOREFRONT_THROTTLE_REQUESTS_PER_MINUTE', 600), 'decay_minutes' => env('STOREFRONT_THROTTLE_DECAY_MINUTES', 1), ], ]; diff --git a/server/src/Http/Controllers/v1/CheckoutController.php b/server/src/Http/Controllers/v1/CheckoutController.php index ce52d35..0475fd3 100644 --- a/server/src/Http/Controllers/v1/CheckoutController.php +++ b/server/src/Http/Controllers/v1/CheckoutController.php @@ -482,14 +482,14 @@ public static function initializeQPayCheckout(Contact $customer, Gateway $gatewa 'email' => $customer->email ?? null, 'phone' => $customer->phone ?? null, ]); - $lines = []; + $lines = QPay::createQpayInitialLines($cart, $serviceQuote, $checkoutOptions); foreach ($cart->items as $item) { $lines[] = [ 'line_description' => $item->name, 'line_quantity' => number_format($item->quantity ?? 1, 2, '.', ''), 'line_unit_price' => number_format($item->price, 2, '.', ''), 'note' => $checkout->public_id, - 'classification_code' => '0111100', + 'classification_code' => '6511100', 'taxes' => [ [ 'tax_code' => 'VAT', diff --git a/server/src/Http/Controllers/v1/CustomerController.php b/server/src/Http/Controllers/v1/CustomerController.php index 28fe5ff..b976069 100644 --- a/server/src/Http/Controllers/v1/CustomerController.php +++ b/server/src/Http/Controllers/v1/CustomerController.php @@ -139,23 +139,29 @@ public function requestCustomerCreationCode(VerifyCreateCustomerRequest $request $customer = new Contact($attributes); $meta = ['identity' => $identity]; - if ($isEmail) { - VerificationCode::generateEmailVerificationFor($customer, 'storefront_create_customer', [ - 'messageCallback' => function ($verification) use ($about) { - return "Your {$about->name} verification code is {$verification->code}"; - }, - 'meta' => $meta, - ]); - } else { - VerificationCode::generateSmsVerificationFor($customer, 'storefront_create_customer', [ - 'messageCallback' => function ($verification) use ($about) { - return "Your {$about->name} verification code is {$verification->code}"; - }, - 'meta' => $meta, - ]); - } + try { + if ($isEmail) { + VerificationCode::generateEmailVerificationFor($customer, 'storefront_create_customer', [ + 'messageCallback' => function ($verification) use ($about) { + return "Your {$about->name} verification code is {$verification->code}"; + }, + 'meta' => $meta, + ]); + } else { + VerificationCode::generateSmsVerificationFor($customer, 'storefront_create_customer', [ + 'messageCallback' => function ($verification) use ($about) { + return "Your {$about->name} verification code is {$verification->code}"; + }, + 'meta' => $meta, + ]); + } - return response()->json(['status' => 'ok']); + return response()->json(['status' => 'ok']); + } catch (\Exception $e) { + return response()->apiError(app()->hasDebugModeEnabled() ? $e->getMessage() : 'Error sending verification code.'); + } catch (\Twilio\Exceptions\RestException $e) { + return response()->apiError($e->getMessage()); + } } /** diff --git a/server/src/Support/QPay.php b/server/src/Support/QPay.php index 036524b..c7e6a0a 100644 --- a/server/src/Support/QPay.php +++ b/server/src/Support/QPay.php @@ -2,7 +2,10 @@ namespace Fleetbase\Storefront\Support; +use Fleetbase\FleetOps\Models\ServiceQuote; +use Fleetbase\Storefront\Models\Cart; use Fleetbase\Storefront\Models\Checkout; +use Fleetbase\Storefront\Support\Storefront; use Fleetbase\Support\Utils; use GuzzleHttp\Client; use Illuminate\Support\Str; @@ -319,4 +322,77 @@ public static function calculateTax($amount): float return $truncated; } + + public static function createQpayInitialLines(Cart $cart, ?ServiceQuote $serviceQuote, $checkoutOptions): array + { + // Prepare dependencies + $checkoutOptions = (object) $checkoutOptions; + $subtotal = (int) $cart->subtotal; + $total = $subtotal; + $tip = $checkoutOptions->tip ?? false; + $deliveryTip = $checkoutOptions->delivery_tip ?? false; + $isPickup = $checkoutOptions->is_pickup ?? false; + + // Initialize lines + $lines = []; + + if ($tip) { + $tipAmount = Storefront::calculateTipAmount($tip, $subtotal); + $lines[] = [ + 'line_description' => 'Tip', + 'line_quantity' => number_format(1, 2, '.', ''), + 'line_unit_price' => number_format($tipAmount, 2, '.', ''), + 'note' => 'Tip', + 'classification_code' => '6511100', + 'taxes' => [ + [ + 'tax_code' => 'VAT', + 'description' => 'VAT', + 'amount' => QPay::calculateTax($tipAmount), + 'note' => 'Tip', + ], + ], + ]; + } + + if ($deliveryTip && !$isPickup) { + $deliveryTipAmount = Storefront::calculateTipAmount($deliveryTip, $subtotal); + $lines[] = [ + 'line_description' => 'Delivery Tip', + 'line_quantity' => number_format(1, 2, '.', ''), + 'line_unit_price' => number_format($deliveryTipAmount, 2, '.', ''), + 'note' => 'Delivery Tip', + 'classification_code' => '6511100', + 'taxes' => [ + [ + 'tax_code' => 'VAT', + 'description' => 'VAT', + 'amount' => QPay::calculateTax($deliveryTipAmount), + 'note' => 'Delivery Tip', + ], + ], + ]; + } + + if (!$isPickup) { + $serviceQuoteAmount = Utils::numbersOnly($serviceQuote->amount); + $lines[] = [ + 'line_description' => 'Delivery Fee', + 'line_quantity' => number_format(1, 2, '.', ''), + 'line_unit_price' => number_format($serviceQuoteAmount, 2, '.', ''), + 'note' => 'Delivery Fee', + 'classification_code' => '6511100', + 'taxes' => [ + [ + 'tax_code' => 'VAT', + 'description' => 'VAT', + 'amount' => QPay::calculateTax($serviceQuoteAmount), + 'note' => 'Delivery Fee', + ], + ], + ]; + } + + return $lines; + } } diff --git a/server/src/Support/Storefront.php b/server/src/Support/Storefront.php index dcdeb63..2aa577f 100644 --- a/server/src/Support/Storefront.php +++ b/server/src/Support/Storefront.php @@ -21,6 +21,7 @@ use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Notification; use Illuminate\Support\Facades\Redis; +use Illuminate\Support\Facades\Schema; use Illuminate\Support\Str; use Laravel\Sanctum\PersonalAccessToken; @@ -729,4 +730,17 @@ protected static function resolveSubjectToModel(Store|Network|string|null $subje return null; } + + public static function calculateTipAmount($tip, $subtotal) + { + $tipAmount = 0; + + if (is_string($tip) && Str::endsWith($tip, '%')) { + $tipAmount = Utils::calculatePercentage(Utils::numbersOnly($tip), $subtotal); + } else { + $tipAmount = Utils::numbersOnly($tip); + } + + return $tipAmount; + } }