@fleetbase/storefront-engine 0.1.6 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.php-cs-fixer.php +29 -0
- package/LICENSE.md +16 -4
- package/README.md +106 -13
- package/addon/components/modals/add-store-to-category.hbs +5 -0
- package/addon/components/modals/create-network-category.hbs +28 -28
- package/addon/components/modals/share-network.hbs +3 -3
- package/addon/components/modals/store-details.hbs +22 -0
- package/addon/components/modals/store-form.hbs +22 -0
- package/addon/components/modals/store-form.js +21 -0
- package/addon/components/network-category-picker.hbs +40 -0
- package/addon/components/network-category-picker.js +83 -0
- package/addon/components/store-selector.hbs +4 -2
- package/addon/components/widget/orders.js +22 -17
- package/addon/controllers/networks/index/network/index.js +133 -9
- package/addon/controllers/networks/index/network/stores.js +422 -153
- package/addon/controllers/networks/index.js +66 -4
- package/addon/controllers/products/index/category.js +1 -1
- package/addon/controllers/settings/index.js +14 -7
- package/addon/controllers/settings/notifications.js +1 -1
- package/addon/models/store.js +44 -7
- package/addon/routes/networks/index/network/customers.js +4 -1
- package/addon/routes/networks/index/network/orders.js +4 -1
- package/addon/routes/networks/index/network/stores.js +19 -15
- package/addon/serializers/store.js +1 -0
- package/addon/templates/customers/index.hbs +0 -11
- package/addon/templates/networks/index/network/index.hbs +1 -1
- package/addon/templates/networks/index/network/stores.hbs +8 -163
- package/addon/templates/networks/index/network.hbs +2 -3
- package/addon/utils/create-shareable-link.js +21 -0
- package/app/adapters/addon-category.js +1 -1
- package/app/adapters/gateway.js +1 -1
- package/app/adapters/network.js +1 -1
- package/app/adapters/notification-channel.js +1 -1
- package/app/adapters/product-addon-category.js +1 -1
- package/app/adapters/product-addon.js +1 -1
- package/app/adapters/product-hour.js +1 -1
- package/app/adapters/product-store-location.js +1 -1
- package/app/adapters/product-variant-option.js +1 -1
- package/app/adapters/product-variant.js +1 -1
- package/app/adapters/product.js +1 -1
- package/app/adapters/store-hour.js +1 -1
- package/app/adapters/store-location.js +1 -1
- package/app/adapters/store.js +1 -1
- package/app/adapters/storefront.js +1 -1
- package/app/components/file-record.js +1 -1
- package/app/components/modals/add-store-hours.js +1 -1
- package/app/components/modals/add-store-to-category.js +1 -0
- package/app/components/modals/add-stores-to-network.js +1 -1
- package/app/components/modals/assign-driver.js +1 -1
- package/app/components/modals/create-first-store.js +1 -1
- package/app/components/modals/create-gateway.js +1 -1
- package/app/components/modals/create-network-category.js +1 -1
- package/app/components/modals/create-network.js +1 -1
- package/app/components/modals/create-new-variant.js +1 -1
- package/app/components/modals/create-notification-channel.js +1 -1
- package/app/components/modals/create-product-category.js +1 -1
- package/app/components/modals/create-store.js +1 -1
- package/app/components/modals/edit-network.js +1 -1
- package/app/components/modals/import-products.js +1 -1
- package/app/components/modals/incoming-order.js +1 -1
- package/app/components/modals/manage-addons.js +1 -1
- package/app/components/modals/order-ready-assign-driver.js +1 -1
- package/app/components/modals/select-addon-category.js +1 -1
- package/app/components/modals/share-network.js +1 -1
- package/app/components/modals/store-details.js +1 -0
- package/app/components/modals/store-form.js +1 -0
- package/app/components/modals/store-location-form.js +1 -1
- package/app/components/network-category-picker.js +1 -0
- package/app/components/order-card.js +1 -1
- package/app/components/schedule-manager.js +1 -1
- package/app/components/settings-container.js +1 -1
- package/app/components/store-selector.js +1 -1
- package/app/components/widget/customers.js +1 -1
- package/app/components/widget/orders.js +1 -1
- package/app/components/widget/storefront-metrics.js +1 -1
- package/app/controllers/application.js +1 -1
- package/app/controllers/customers/index.js +1 -1
- package/app/controllers/home.js +1 -1
- package/app/controllers/networks/index/network/customers.js +1 -1
- package/app/controllers/networks/index/network/index.js +1 -1
- package/app/controllers/networks/index/network/orders.js +1 -1
- package/app/controllers/networks/index/network/stores.js +1 -1
- package/app/controllers/networks/index/network.js +1 -1
- package/app/controllers/networks/index.js +1 -1
- package/app/controllers/orders/index.js +1 -1
- package/app/controllers/products/index/category/edit.js +1 -1
- package/app/controllers/products/index/category/new.js +1 -1
- package/app/controllers/products/index/category.js +1 -1
- package/app/controllers/products/index/index/edit.js +1 -1
- package/app/controllers/products/index/index.js +1 -1
- package/app/controllers/products/index.js +1 -1
- package/app/controllers/settings/api.js +1 -1
- package/app/controllers/settings/gateways.js +1 -1
- package/app/controllers/settings/index.js +1 -1
- package/app/controllers/settings/locations.js +1 -1
- package/app/controllers/settings/notifications.js +1 -1
- package/app/helpers/get-tip-amount.js +1 -1
- package/app/models/addon-category.js +1 -1
- package/app/models/gateway.js +1 -1
- package/app/models/network.js +1 -1
- package/app/models/notification-channel.js +1 -1
- package/app/models/product-addon-category.js +1 -1
- package/app/models/product-addon.js +1 -1
- package/app/models/product-hour.js +1 -1
- package/app/models/product-store-location.js +1 -1
- package/app/models/product-variant-option.js +1 -1
- package/app/models/product-variant.js +1 -1
- package/app/models/product.js +1 -1
- package/app/models/store-hour.js +1 -1
- package/app/models/store-location.js +1 -1
- package/app/models/store.js +1 -1
- package/app/routes/application.js +1 -1
- package/app/routes/customers/index/edit.js +1 -1
- package/app/routes/customers/index.js +1 -1
- package/app/routes/home.js +1 -1
- package/app/routes/networks/index/network/customers.js +1 -1
- package/app/routes/networks/index/network/index.js +1 -1
- package/app/routes/networks/index/network/orders.js +1 -1
- package/app/routes/networks/index/network/stores.js +1 -1
- package/app/routes/networks/index/network.js +1 -1
- package/app/routes/networks/index.js +1 -1
- package/app/routes/orders/index/edit.js +1 -1
- package/app/routes/orders/index/new.js +1 -1
- package/app/routes/orders/index/view.js +1 -1
- package/app/routes/orders/index.js +1 -1
- package/app/routes/products/index/category/edit.js +1 -1
- package/app/routes/products/index/category/new.js +1 -1
- package/app/routes/products/index/category.js +1 -1
- package/app/routes/products/index/index/edit.js +1 -1
- package/app/routes/products/index/index.js +1 -1
- package/app/routes/products/index.js +1 -1
- package/app/routes/settings/api.js +1 -1
- package/app/routes/settings/gateways.js +1 -1
- package/app/routes/settings/index.js +1 -1
- package/app/routes/settings/locations.js +1 -1
- package/app/routes/settings/notifications.js +1 -1
- package/app/serializers/addon-category.js +1 -1
- package/app/serializers/network.js +1 -1
- package/app/serializers/notification-channel.js +1 -1
- package/app/serializers/product-addon-category.js +1 -1
- package/app/serializers/product-variant.js +1 -1
- package/app/serializers/product.js +1 -1
- package/app/serializers/store-location.js +1 -1
- package/app/serializers/store.js +1 -1
- package/app/services/storefront.js +1 -1
- package/app/templates/customers/index/edit.js +1 -1
- package/app/templates/customers/index.js +1 -1
- package/app/templates/home.js +1 -1
- package/app/templates/networks/index/network/customers.js +1 -1
- package/app/templates/networks/index/network/index.js +1 -1
- package/app/templates/networks/index/network/orders.js +1 -1
- package/app/templates/networks/index/network/stores.js +1 -1
- package/app/templates/networks/index/network.js +1 -1
- package/app/templates/networks/index.js +1 -1
- package/app/templates/orders/index/edit.js +1 -1
- package/app/templates/orders/index/new.js +1 -1
- package/app/templates/orders/index/view.js +1 -1
- package/app/templates/orders/index.js +1 -1
- package/app/templates/products/index/category/edit.js +1 -1
- package/app/templates/products/index/category/new.js +1 -1
- package/app/templates/products/index/category.js +1 -1
- package/app/templates/products/index/index/edit.js +1 -1
- package/app/templates/products/index/index.js +1 -1
- package/app/templates/products/index.js +1 -1
- package/app/templates/settings/api.js +1 -1
- package/app/templates/settings/gateways.js +1 -1
- package/app/templates/settings/index.js +1 -1
- package/app/templates/settings/locations.js +1 -1
- package/app/templates/settings/notifications.js +1 -1
- package/app/templates/settings.js +1 -1
- package/app/utils/create-shareable-link.js +1 -0
- package/app/utils/get-gateway-schemas.js +1 -1
- package/app/utils/get-notification-schemas.js +1 -1
- package/composer.json +88 -0
- package/extension.json +10 -0
- package/package.json +6 -7
- package/phpstan.neon.dist +8 -0
- package/phpunit.xml.dist +16 -0
- package/server/.gitattributes +14 -0
- package/server/README.md +40 -0
- package/server/config/api.php +101 -0
- package/server/config/database.connections.php +57 -0
- package/server/config/storefront.php +19 -0
- package/server/config/twilio-notification-channel.php +36 -0
- package/server/migrations/2023_05_03_025307_create_carts_table.php +44 -0
- package/server/migrations/2023_05_03_025307_create_checkouts_table.php +51 -0
- package/server/migrations/2023_05_03_025307_create_gateways_table.php +48 -0
- package/server/migrations/2023_05_03_025307_create_network_stores_table.php +36 -0
- package/server/migrations/2023_05_03_025307_create_networks_table.php +56 -0
- package/server/migrations/2023_05_03_025307_create_notification_channels_table.php +43 -0
- package/server/migrations/2023_05_03_025307_create_payment_methods_table.php +44 -0
- package/server/migrations/2023_05_03_025307_create_product_addon_categories_table.php +38 -0
- package/server/migrations/2023_05_03_025307_create_product_addons_table.php +43 -0
- package/server/migrations/2023_05_03_025307_create_product_hours_table.php +37 -0
- package/server/migrations/2023_05_03_025307_create_product_store_locations_table.php +34 -0
- package/server/migrations/2023_05_03_025307_create_product_variant_options_table.php +40 -0
- package/server/migrations/2023_05_03_025307_create_product_variants_table.php +44 -0
- package/server/migrations/2023_05_03_025307_create_products_table.php +59 -0
- package/server/migrations/2023_05_03_025307_create_reviews_table.php +41 -0
- package/server/migrations/2023_05_03_025307_create_store_hours_table.php +37 -0
- package/server/migrations/2023_05_03_025307_create_store_locations_table.php +38 -0
- package/server/migrations/2023_05_03_025307_create_stores_table.php +57 -0
- package/server/migrations/2023_05_03_025307_create_votes_table.php +39 -0
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_carts_table.php +40 -0
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_checkouts_table.php +48 -0
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_gateways_table.php +40 -0
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_network_stores_table.php +40 -0
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_networks_table.php +42 -0
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_notification_channels_table.php +40 -0
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_payment_methods_table.php +40 -0
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_product_addon_categories_table.php +38 -0
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_product_addons_table.php +38 -0
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_product_hours_table.php +32 -0
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_product_store_locations_table.php +34 -0
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_product_variant_options_table.php +32 -0
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_product_variants_table.php +32 -0
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_products_table.php +44 -0
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_reviews_table.php +38 -0
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_store_hours_table.php +32 -0
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_store_locations_table.php +40 -0
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_stores_table.php +42 -0
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_votes_table.php +38 -0
- package/server/src/Auth/Schemas/Storefront.php +95 -0
- package/server/src/Console/Commands/NotifyStorefrontOrderNearby.php +86 -0
- package/server/src/Expansions/EntityExpansion.php +44 -0
- package/server/src/Http/Controllers/ActionController.php +119 -0
- package/server/src/Http/Controllers/AddonCategoryController.php +13 -0
- package/server/src/Http/Controllers/CustomerController.php +13 -0
- package/server/src/Http/Controllers/GatewayController.php +13 -0
- package/server/src/Http/Controllers/MetricsController.php +71 -0
- package/server/src/Http/Controllers/NetworkController.php +170 -0
- package/server/src/Http/Controllers/NotificationChannelController.php +13 -0
- package/server/src/Http/Controllers/OrderController.php +154 -0
- package/server/src/Http/Controllers/ProductAddonCategoryController.php +14 -0
- package/server/src/Http/Controllers/ProductAddonController.php +14 -0
- package/server/src/Http/Controllers/ProductController.php +123 -0
- package/server/src/Http/Controllers/ProductHourController.php +13 -0
- package/server/src/Http/Controllers/ProductVariantController.php +13 -0
- package/server/src/Http/Controllers/ProductVariantOptionController.php +13 -0
- package/server/src/Http/Controllers/ReviewController.php +13 -0
- package/server/src/Http/Controllers/StoreController.php +26 -0
- package/server/src/Http/Controllers/StoreHourController.php +13 -0
- package/server/src/Http/Controllers/StoreLocationController.php +13 -0
- package/server/src/Http/Controllers/StorefrontController.php +15 -0
- package/server/src/Http/Controllers/VoteController.php +13 -0
- package/server/src/Http/Controllers/v1/CartController.php +161 -0
- package/server/src/Http/Controllers/v1/CategoryController.php +138 -0
- package/server/src/Http/Controllers/v1/CheckoutController.php +957 -0
- package/server/src/Http/Controllers/v1/CustomerController.php +482 -0
- package/server/src/Http/Controllers/v1/GatewayControllerController.php +11 -0
- package/server/src/Http/Controllers/v1/NetworkController.php +281 -0
- package/server/src/Http/Controllers/v1/PaymentMethodController.php +11 -0
- package/server/src/Http/Controllers/v1/ProductController.php +94 -0
- package/server/src/Http/Controllers/v1/ReviewController.php +270 -0
- package/server/src/Http/Controllers/v1/ServiceQuoteController.php +402 -0
- package/server/src/Http/Controllers/v1/StoreController.php +176 -0
- package/server/src/Http/Filter/AddonCategoryFilter.php +19 -0
- package/server/src/Http/Filter/CustomerFilter.php +18 -0
- package/server/src/Http/Filter/GatewayFilter.php +13 -0
- package/server/src/Http/Filter/NetworkFilter.php +18 -0
- package/server/src/Http/Filter/NotificationChannelFilter.php +13 -0
- package/server/src/Http/Filter/OrderFilter.php +46 -0
- package/server/src/Http/Filter/ProductFilter.php +28 -0
- package/server/src/Http/Filter/StoreFilter.php +42 -0
- package/server/src/Http/Filter/StoreLocationFilter.php +23 -0
- package/server/src/Http/Middleware/SetStorefrontSession.php +130 -0
- package/server/src/Http/Requests/AddStoreToNetworkCategory.php +45 -0
- package/server/src/Http/Requests/CaptureOrderRequest.php +30 -0
- package/server/src/Http/Requests/CreateCustomerRequest.php +44 -0
- package/server/src/Http/Requests/CreateReviewRequest.php +34 -0
- package/server/src/Http/Requests/GetServiceQuoteFromCart.php +40 -0
- package/server/src/Http/Requests/InitializeCheckoutRequest.php +38 -0
- package/server/src/Http/Requests/NetworkActionRequest.php +43 -0
- package/server/src/Http/Requests/VerifyCreateCustomerRequest.php +31 -0
- package/server/src/Http/Resources/Cart.php +31 -0
- package/server/src/Http/Resources/Category.php +48 -0
- package/server/src/Http/Resources/Customer.php +36 -0
- package/server/src/Http/Resources/Gateway.php +32 -0
- package/server/src/Http/Resources/Media.php +29 -0
- package/server/src/Http/Resources/Network.php +48 -0
- package/server/src/Http/Resources/Product.php +209 -0
- package/server/src/Http/Resources/Review.php +45 -0
- package/server/src/Http/Resources/ReviewCustomer.php +60 -0
- package/server/src/Http/Resources/Store.php +76 -0
- package/server/src/Http/Resources/StoreHour.php +29 -0
- package/server/src/Http/Resources/StoreLocation.php +33 -0
- package/server/src/Imports/ProductsImport.php +20 -0
- package/server/src/Jobs/DownloadProductImageUrl.php +60 -0
- package/server/src/Listeners/HandleOrderCompleted.php +31 -0
- package/server/src/Listeners/HandleOrderDispatched.php +34 -0
- package/server/src/Listeners/HandleOrderDriverAssigned.php +37 -0
- package/server/src/Listeners/HandleOrderStarted.php +27 -0
- package/server/src/Mail/StorefrontNetworkInvite.php +48 -0
- package/server/src/Models/AddonCategory.php +30 -0
- package/server/src/Models/Cart.php +691 -0
- package/server/src/Models/Checkout.php +166 -0
- package/server/src/Models/Customer.php +88 -0
- package/server/src/Models/Gateway.php +165 -0
- package/server/src/Models/Network.php +300 -0
- package/server/src/Models/NetworkStore.php +86 -0
- package/server/src/Models/NotificationChannel.php +147 -0
- package/server/src/Models/PaymentMethod.php +99 -0
- package/server/src/Models/Product.php +315 -0
- package/server/src/Models/ProductAddon.php +128 -0
- package/server/src/Models/ProductAddonCategory.php +90 -0
- package/server/src/Models/ProductHour.php +59 -0
- package/server/src/Models/ProductStoreLocation.php +77 -0
- package/server/src/Models/ProductVariant.php +125 -0
- package/server/src/Models/ProductVariantOption.php +86 -0
- package/server/src/Models/Review.php +127 -0
- package/server/src/Models/Store.php +478 -0
- package/server/src/Models/StoreHour.php +59 -0
- package/server/src/Models/StoreLocation.php +126 -0
- package/server/src/Models/StorefrontModel.php +22 -0
- package/server/src/Models/Vote.php +84 -0
- package/server/src/Notifications/StorefrontOrderCanceled.php +196 -0
- package/server/src/Notifications/StorefrontOrderCompleted.php +201 -0
- package/server/src/Notifications/StorefrontOrderCreated.php +157 -0
- package/server/src/Notifications/StorefrontOrderDriverAssigned.php +200 -0
- package/server/src/Notifications/StorefrontOrderEnroute.php +199 -0
- package/server/src/Notifications/StorefrontOrderNearby.php +201 -0
- package/server/src/Notifications/StorefrontOrderPreparing.php +202 -0
- package/server/src/Notifications/StorefrontOrderReadyForPickup.php +202 -0
- package/server/src/Observers/NetworkObserver.php +40 -0
- package/server/src/Observers/ProductObserver.php +118 -0
- package/server/src/Providers/EventServiceProvider.php +23 -0
- package/server/src/Providers/StorefrontServiceProvider.php +103 -0
- package/server/src/Support/Metrics.php +193 -0
- package/server/src/Support/OrderConfig.php +13 -0
- package/server/src/Support/QPay.php +208 -0
- package/server/src/Support/Storefront.php +201 -0
- package/server/src/routes.php +180 -0
- package/server/tests/Feature.php +5 -0
|
@@ -0,0 +1,691 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\Storefront\Models;
|
|
4
|
+
|
|
5
|
+
use Exception;
|
|
6
|
+
use Fleetbase\Casts\Json;
|
|
7
|
+
use Fleetbase\Models\Company;
|
|
8
|
+
use Fleetbase\FleetOps\Models\Contact;
|
|
9
|
+
use Fleetbase\FleetOps\Support\Utils;
|
|
10
|
+
use Fleetbase\Traits\Expirable;
|
|
11
|
+
use Fleetbase\Traits\HasUuid;
|
|
12
|
+
Use Fleetbase\Traits\HasApiModelBehavior;
|
|
13
|
+
use Fleetbase\Traits\HasPublicId;
|
|
14
|
+
use Illuminate\Support\Arr;
|
|
15
|
+
use Illuminate\Support\Carbon;
|
|
16
|
+
use Illuminate\Support\Str;
|
|
17
|
+
use stdClass;
|
|
18
|
+
|
|
19
|
+
class Cart extends StorefrontModel
|
|
20
|
+
{
|
|
21
|
+
use HasUuid, HasPublicId, HasApiModelBehavior, Expirable;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The type of public Id to generate
|
|
25
|
+
*
|
|
26
|
+
* @var string
|
|
27
|
+
*/
|
|
28
|
+
protected $publicIdType = 'cart';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The database table used by the model.
|
|
32
|
+
*
|
|
33
|
+
* @var string
|
|
34
|
+
*/
|
|
35
|
+
protected $table = 'carts';
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* These attributes that can be queried
|
|
39
|
+
*
|
|
40
|
+
* @var array
|
|
41
|
+
*/
|
|
42
|
+
protected $searchableColumns = [];
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The attributes that are mass assignable.
|
|
46
|
+
*
|
|
47
|
+
* @var array
|
|
48
|
+
*/
|
|
49
|
+
protected $fillable = ['company_uuid', 'user_uuid', 'checkout_uuid', 'customer_id', 'unique_identifier', 'currency', 'discount_code', 'items', 'events', 'expires_at'];
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The attributes that should be cast to native types.
|
|
53
|
+
*
|
|
54
|
+
* @var array
|
|
55
|
+
*/
|
|
56
|
+
protected $casts = [
|
|
57
|
+
'expires_at' => 'datetime'
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Dynamic attributes that are appended to object
|
|
62
|
+
*
|
|
63
|
+
* @var array
|
|
64
|
+
*/
|
|
65
|
+
protected $appends = ['total_items', 'total_unique_items', 'subtotal'];
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
69
|
+
*/
|
|
70
|
+
public function company()
|
|
71
|
+
{
|
|
72
|
+
return $this->setConnection(config('fleetbase.connection.db'))->belongsTo(Company::class);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
*
|
|
77
|
+
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
78
|
+
*/
|
|
79
|
+
public function user()
|
|
80
|
+
{
|
|
81
|
+
return $this->setConnection(config('fleetbase.connection.db'))->belongsTo(User::class);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
86
|
+
*/
|
|
87
|
+
public function customer()
|
|
88
|
+
{
|
|
89
|
+
return $this->setConnection(config('fleetbase.connection.db'))->belongsTo(Contact::class, 'public_id');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
94
|
+
*/
|
|
95
|
+
public function checkout()
|
|
96
|
+
{
|
|
97
|
+
return $this->belongsTo(Checkout::class);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Set cart items.
|
|
102
|
+
*
|
|
103
|
+
* @return void
|
|
104
|
+
*/
|
|
105
|
+
public function setItemsAttribute($items)
|
|
106
|
+
{
|
|
107
|
+
$this->attributes['items'] = json_encode($items);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Set cart events.
|
|
112
|
+
*
|
|
113
|
+
* @return void
|
|
114
|
+
*/
|
|
115
|
+
public function setEventsAttribute($events)
|
|
116
|
+
{
|
|
117
|
+
$this->attributes['items'] = json_encode($events);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Get cart items.
|
|
122
|
+
*
|
|
123
|
+
* @return array
|
|
124
|
+
*/
|
|
125
|
+
public function getItemsAttribute($items)
|
|
126
|
+
{
|
|
127
|
+
if (is_array($items)) {
|
|
128
|
+
return $items;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return (array) json_decode($items, false);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Get cart events.
|
|
136
|
+
*
|
|
137
|
+
* @return array
|
|
138
|
+
*/
|
|
139
|
+
public function getEventsAttribute($events)
|
|
140
|
+
{
|
|
141
|
+
if (is_array($events)) {
|
|
142
|
+
return $events;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return (array) json_decode($events, false);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Computes subtotal of cart.
|
|
150
|
+
*
|
|
151
|
+
* @return int
|
|
152
|
+
*/
|
|
153
|
+
public function getSubtotalAttribute()
|
|
154
|
+
{
|
|
155
|
+
$items = $this->getAttribute('items') ?? [];
|
|
156
|
+
$subtotal = 0;
|
|
157
|
+
|
|
158
|
+
foreach ($items as $item) {
|
|
159
|
+
$subtotal += Utils::numbersOnly($item->subtotal);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return $subtotal;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Computes total items in cart.
|
|
167
|
+
*
|
|
168
|
+
* @return int
|
|
169
|
+
*/
|
|
170
|
+
public function getTotalItemsAttribute()
|
|
171
|
+
{
|
|
172
|
+
$items = $this->getAttribute('items') ?? [];
|
|
173
|
+
$total = 0;
|
|
174
|
+
|
|
175
|
+
foreach ($items as $item) {
|
|
176
|
+
$total += Utils::numbersOnly($item->quantity);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return $total;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Computes total unique items in cart.
|
|
184
|
+
*
|
|
185
|
+
* @return int
|
|
186
|
+
*/
|
|
187
|
+
public function getTotalUniqueItemsAttribute()
|
|
188
|
+
{
|
|
189
|
+
return count($this->getAttribute('items'));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* The last cart event.
|
|
194
|
+
*
|
|
195
|
+
* @return stdClass|null
|
|
196
|
+
*/
|
|
197
|
+
public function getLastEventAttribute()
|
|
198
|
+
{
|
|
199
|
+
$events = $this->getAttribute('events') ?? [];
|
|
200
|
+
|
|
201
|
+
return Arr::last($events);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* If the cart is a multi cart
|
|
206
|
+
*
|
|
207
|
+
* @return boolean
|
|
208
|
+
*/
|
|
209
|
+
public function getIsMultiCartAttribute()
|
|
210
|
+
{
|
|
211
|
+
return collect($this->items)->pluck('store_id')->unique()->count() > 1;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Returns the checkout store id
|
|
216
|
+
*
|
|
217
|
+
* @return string
|
|
218
|
+
*/
|
|
219
|
+
public function getCheckoutStoreIdAttribute()
|
|
220
|
+
{
|
|
221
|
+
return collect($this->items)->pluck('store_id')->unique()->first();
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Returns the checkout store ids for all stores being checked out from
|
|
226
|
+
*
|
|
227
|
+
* @return array
|
|
228
|
+
*/
|
|
229
|
+
public function getCheckoutStoreIdsAttribute()
|
|
230
|
+
{
|
|
231
|
+
return collect($this->items)->pluck('store_id')->unique()->toArray();
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Returns cart items for a specific store only
|
|
236
|
+
*
|
|
237
|
+
* @return array
|
|
238
|
+
*/
|
|
239
|
+
public function getItemsForStore($id)
|
|
240
|
+
{
|
|
241
|
+
if ($id instanceof Store) {
|
|
242
|
+
$id = $id->public_id;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return collect($this->items)->filter(function ($cartItem) use ($id) {
|
|
246
|
+
return $cartItem->store_id === $id;
|
|
247
|
+
})->toArray();
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Computes subtotal of specific cart items of a store.
|
|
252
|
+
*
|
|
253
|
+
* @return int
|
|
254
|
+
*/
|
|
255
|
+
public function getSubtotalForStore($id)
|
|
256
|
+
{
|
|
257
|
+
$items = $this->getItemsForStore($id);
|
|
258
|
+
$subtotal = 0;
|
|
259
|
+
|
|
260
|
+
foreach ($items as $item) {
|
|
261
|
+
$subtotal += Utils::numbersOnly($item->subtotal);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return $subtotal;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Adds item to cart.
|
|
269
|
+
*
|
|
270
|
+
* @param Product|string $product
|
|
271
|
+
* @param integer $quantity
|
|
272
|
+
* @param array $variants
|
|
273
|
+
* @param array $addons
|
|
274
|
+
* @param string|null $createdAt
|
|
275
|
+
* @return stdClass
|
|
276
|
+
* @throws Exception
|
|
277
|
+
*/
|
|
278
|
+
public function add($product, $quantity = 1, $variants = [], $addons = [], $storeLocationId = null, $scheduledAt = null, $createdAt = null)
|
|
279
|
+
{
|
|
280
|
+
if ($product instanceof Product) {
|
|
281
|
+
return $this->addItem($product, $quantity, $variants, $addons, $storeLocationId, $scheduledAt, $createdAt);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (is_string($product)) {
|
|
285
|
+
$product = static::findProduct($product);
|
|
286
|
+
|
|
287
|
+
return $this->add($product, $quantity, $variants, $addons, $storeLocationId, $scheduledAt, $createdAt);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
throw new Exception('Invalid product provided to cart!');
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Adds an item to cart.
|
|
295
|
+
*
|
|
296
|
+
* @param \Fleetbase\Models\Storefront\Product $product
|
|
297
|
+
* @param integer $quantity
|
|
298
|
+
* @param array $variants
|
|
299
|
+
* @param array $addons
|
|
300
|
+
* @param string $createdAt
|
|
301
|
+
*/
|
|
302
|
+
public function addItem(Product $product, $quantity = 1, $variants = [], $addons = [], $storeLocationId = null, $scheduledAt = null, $createdAt = null)
|
|
303
|
+
{
|
|
304
|
+
$id = Utils::generatePublicId('cart_item');
|
|
305
|
+
$cartItem = new stdClass();
|
|
306
|
+
|
|
307
|
+
// set base price
|
|
308
|
+
$price = Utils::numbersOnly($product->is_on_sale ? $product->sale_price : $product->price);
|
|
309
|
+
|
|
310
|
+
// calculate subtotal
|
|
311
|
+
$subtotal = static::calculateProductSubtotal($product, $quantity, $variants, $addons);
|
|
312
|
+
|
|
313
|
+
// if no store location id, default to first store location
|
|
314
|
+
if (empty($storeLocationId)) {
|
|
315
|
+
$storeLocationId = Utils::get($product, 'store.locations.0.public_id');
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
$properties = [
|
|
319
|
+
'id' => $id,
|
|
320
|
+
'store_id' => $product->store_id,
|
|
321
|
+
'store_location_id' => $storeLocationId,
|
|
322
|
+
'product_id' => $product->public_id,
|
|
323
|
+
'product_image_url' => $product->primary_image_url,
|
|
324
|
+
'name' => $product->name,
|
|
325
|
+
'description' => $product->description,
|
|
326
|
+
'scheduled_at' => $scheduledAt,
|
|
327
|
+
'created_at' => $createdAt ?? time(),
|
|
328
|
+
'updated_at' => time(),
|
|
329
|
+
'quantity' => $quantity,
|
|
330
|
+
'price' => $price,
|
|
331
|
+
'subtotal' => $subtotal,
|
|
332
|
+
'variants' => $variants,
|
|
333
|
+
'addons' => $addons
|
|
334
|
+
];
|
|
335
|
+
|
|
336
|
+
foreach ($properties as $prop => $value) {
|
|
337
|
+
$cartItem->{$prop} = $value;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
$items = $this->getAttribute('items');
|
|
341
|
+
|
|
342
|
+
$items[] = $cartItem;
|
|
343
|
+
|
|
344
|
+
$this->createEvent('cart.item_added', $cartItem->id, false);
|
|
345
|
+
$this->attributes['items'] = $items;
|
|
346
|
+
$this->save();
|
|
347
|
+
|
|
348
|
+
return $cartItem;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Adds item to cart.
|
|
353
|
+
*
|
|
354
|
+
* @param stdClass|string $cartItem
|
|
355
|
+
* @param integer $quantity
|
|
356
|
+
* @param array $variants
|
|
357
|
+
* @param array $addons
|
|
358
|
+
* @param string|null $createdAt
|
|
359
|
+
* @return stdClass
|
|
360
|
+
* @throws Exception
|
|
361
|
+
*/
|
|
362
|
+
public function updateItem($cartItem, $quantity = 1, $variants = [], $addons = [], $scheduledAt = null)
|
|
363
|
+
{
|
|
364
|
+
if ($cartItem instanceof stdClass) {
|
|
365
|
+
return $this->updateCartItem($cartItem, $quantity, $variants, $addons, $scheduledAt);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (is_string($cartItem)) {
|
|
369
|
+
$cartItem = $this->findCartItem($cartItem);
|
|
370
|
+
|
|
371
|
+
return $this->updateItem($cartItem, $quantity, $variants, $addons, $scheduledAt);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
throw new Exception('Invalid cart item provided to cart!');
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Updates an item in cart.
|
|
379
|
+
*
|
|
380
|
+
* @param [type] $cartItem
|
|
381
|
+
* @param integer $quantity
|
|
382
|
+
* @param array $variants
|
|
383
|
+
* @param array $addons
|
|
384
|
+
* @return stdClass
|
|
385
|
+
*/
|
|
386
|
+
public function updateCartItem($cartItem, $quantity = 1, $variants = [], $addons = [], $scheduledAt = null)
|
|
387
|
+
{
|
|
388
|
+
// get the line item product
|
|
389
|
+
$productId = $cartItem->product_id;
|
|
390
|
+
$product = static::findProduct($productId);
|
|
391
|
+
|
|
392
|
+
// set base price
|
|
393
|
+
$price = Utils::numbersOnly($product->is_on_sale ? $product->sale_price : $product->price);
|
|
394
|
+
|
|
395
|
+
// calculate subtotal
|
|
396
|
+
$subtotal = static::calculateProductSubtotal($product, $quantity, $variants, $addons);
|
|
397
|
+
|
|
398
|
+
// get cart items
|
|
399
|
+
$items = $this->getAttribute('items');
|
|
400
|
+
|
|
401
|
+
// find the item from cart
|
|
402
|
+
$index = $this->findCartItemIndex($cartItem->id);
|
|
403
|
+
|
|
404
|
+
$existingCartItem = $items[$index] ?? new stdClass();
|
|
405
|
+
|
|
406
|
+
$properties = [
|
|
407
|
+
'id' => $cartItem->id,
|
|
408
|
+
'store_id' => $product->store_id,
|
|
409
|
+
'product_id' => $product->public_id,
|
|
410
|
+
'product_image_url' => $product->primary_image_url,
|
|
411
|
+
'name' => $product->name,
|
|
412
|
+
'description' => $product->description,
|
|
413
|
+
'scheduled_at' => $scheduledAt,
|
|
414
|
+
'created_at' => $cartItem->created_at,
|
|
415
|
+
'updated_at' => time(),
|
|
416
|
+
'quantity' => $quantity ?? $cartItem->quantity,
|
|
417
|
+
'price' => $price,
|
|
418
|
+
'subtotal' => $subtotal,
|
|
419
|
+
'variants' => $variants ?? $cartItem->variants,
|
|
420
|
+
'addons' => $addons ?? $cartItem->addons
|
|
421
|
+
];
|
|
422
|
+
|
|
423
|
+
foreach ($properties as $prop => $value) {
|
|
424
|
+
$existingCartItem->{$prop} = $value;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
$items[$index] = $existingCartItem;
|
|
428
|
+
|
|
429
|
+
$this->createEvent('cart.item_updated', $cartItem->id, false);
|
|
430
|
+
$this->attributes['items'] = $items;
|
|
431
|
+
$this->save();
|
|
432
|
+
|
|
433
|
+
return $existingCartItem;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Updates a cart item by id.
|
|
438
|
+
*
|
|
439
|
+
* @param string $id
|
|
440
|
+
* @param integer $quantity
|
|
441
|
+
* @param array $variants
|
|
442
|
+
* @param array $addons
|
|
443
|
+
* @return stdClass
|
|
444
|
+
*/
|
|
445
|
+
public function updateCartItemById(string $id, $quantity = 1, $variants = [], $addons = [], $scheduledAt = null)
|
|
446
|
+
{
|
|
447
|
+
$cartItem = $this->findCartItem($id);
|
|
448
|
+
|
|
449
|
+
return $this->updateCartItem($cartItem, $quantity, $variants, $addons, $scheduledAt);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Remove item from cart.
|
|
454
|
+
*
|
|
455
|
+
* @param stdClass|string $cartItem
|
|
456
|
+
* @return stdClass
|
|
457
|
+
* @throws Exception
|
|
458
|
+
*/
|
|
459
|
+
public function remove($cartItem)
|
|
460
|
+
{
|
|
461
|
+
if ($cartItem instanceof stdClass) {
|
|
462
|
+
return $this->removeItem($cartItem);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
if (is_string($cartItem)) {
|
|
466
|
+
$cartItem = $this->findCartItem($cartItem);
|
|
467
|
+
|
|
468
|
+
return $this->remove($cartItem);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
throw new Exception('Invalid cart item provided to cart!');
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* Removes an item from cart.
|
|
476
|
+
*
|
|
477
|
+
* @param stdClass $cartItem
|
|
478
|
+
* @return \Fleetbase\Models\Storefront\Cart
|
|
479
|
+
*/
|
|
480
|
+
public function removeItem($cartItem)
|
|
481
|
+
{
|
|
482
|
+
$items = $this->getAttribute('items');
|
|
483
|
+
$index = $this->findCartItemIndex($cartItem->id);
|
|
484
|
+
|
|
485
|
+
unset($items[$index]);
|
|
486
|
+
|
|
487
|
+
$this->createEvent('cart.item_removed', $cartItem->id, false);
|
|
488
|
+
$this->attributes['items'] = $items;
|
|
489
|
+
$this->save();
|
|
490
|
+
|
|
491
|
+
return $this;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Removes a cart item by id.
|
|
496
|
+
*
|
|
497
|
+
* @param string $id
|
|
498
|
+
* @return \Fleetbase\Models\Storefront\Cart
|
|
499
|
+
*/
|
|
500
|
+
public function removeItemById(string $id)
|
|
501
|
+
{
|
|
502
|
+
$cartItem = $this->findCartItem($id);
|
|
503
|
+
|
|
504
|
+
return $this->removeItem($cartItem);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Empties the cart.
|
|
509
|
+
*
|
|
510
|
+
* @return \Fleetbase\Models\Storefront\Cart
|
|
511
|
+
*/
|
|
512
|
+
public function empty()
|
|
513
|
+
{
|
|
514
|
+
$this->createEvent('cart.emptied', null, false);
|
|
515
|
+
$this->attributes['items'] = [];
|
|
516
|
+
$this->updateCurrency(null, false);
|
|
517
|
+
$this->save();
|
|
518
|
+
|
|
519
|
+
return $this;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* Finds an item in cart by id.
|
|
524
|
+
*
|
|
525
|
+
* @param string $id
|
|
526
|
+
* @return stdClass|null
|
|
527
|
+
*/
|
|
528
|
+
public function findCartItem(string $id): ?stdClass
|
|
529
|
+
{
|
|
530
|
+
$items = $this->getAttribute('items');
|
|
531
|
+
|
|
532
|
+
$foundCartItem = collect($items)->first(function ($item) use ($id) {
|
|
533
|
+
return $item->id === $id;
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
return $foundCartItem;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* Finds index of a cart item.
|
|
541
|
+
*
|
|
542
|
+
* @param string $id
|
|
543
|
+
* @return integer|null
|
|
544
|
+
*/
|
|
545
|
+
public function findCartItemIndex(string $id): ?int
|
|
546
|
+
{
|
|
547
|
+
$items = $this->getAttribute('items');
|
|
548
|
+
|
|
549
|
+
foreach ($items as $index => $item) {
|
|
550
|
+
if ($item->id === $id) {
|
|
551
|
+
return $index;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
return -1;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* Create a new cart event.
|
|
560
|
+
*
|
|
561
|
+
* @param string $eventName
|
|
562
|
+
* @param string|null $cartItemId
|
|
563
|
+
* @return \Fleetbase\Models\Storefront\Cart
|
|
564
|
+
*/
|
|
565
|
+
public function createEvent(string $eventName, $cartItemId = null, $save = true)
|
|
566
|
+
{
|
|
567
|
+
$events = $this->getAttribute('events') ?? [];
|
|
568
|
+
|
|
569
|
+
$events[] = Utils::createObject([
|
|
570
|
+
'event' => $eventName,
|
|
571
|
+
'cart_item_id' => $cartItemId,
|
|
572
|
+
'time' => time()
|
|
573
|
+
]);
|
|
574
|
+
|
|
575
|
+
$this->attributes['events'] = $events;
|
|
576
|
+
|
|
577
|
+
if ($save) {
|
|
578
|
+
$this->save();
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
return $this;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Update the cart session currency code.
|
|
586
|
+
*
|
|
587
|
+
* @param string $currencyCode
|
|
588
|
+
* @param boolean $save
|
|
589
|
+
* @return \Fleetbase\Models\Storefront\Cart
|
|
590
|
+
*/
|
|
591
|
+
public function updateCurrency(?string $currencyCode = null, $save = false)
|
|
592
|
+
{
|
|
593
|
+
$this->attributes['currency'] = $currencyCode ?? session('storefront_currency');
|
|
594
|
+
|
|
595
|
+
if ($save) {
|
|
596
|
+
$this->save();
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
return $this;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* Reset the cart currency code to the current session.
|
|
604
|
+
*
|
|
605
|
+
* @return \Fleetbase\Models\Storefront\Cart
|
|
606
|
+
*/
|
|
607
|
+
public function resetCurrency()
|
|
608
|
+
{
|
|
609
|
+
return $this->updateCurrency(null, true);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* Creates a new cart.
|
|
614
|
+
*
|
|
615
|
+
* @param string|null $uniqueId
|
|
616
|
+
* @return \Fleetbase\Models\Storefront\Cart
|
|
617
|
+
*/
|
|
618
|
+
public static function newCart($uniqueId = null): Cart
|
|
619
|
+
{
|
|
620
|
+
return Cart::create([
|
|
621
|
+
'unique_identifier' => $uniqueId,
|
|
622
|
+
'company_uuid' => session('company'),
|
|
623
|
+
'expires_at' => Carbon::now()->addDays(7),
|
|
624
|
+
'currency' => session('storefront_currency'),
|
|
625
|
+
'customer_id' => session('customer_id'),
|
|
626
|
+
'items' => [],
|
|
627
|
+
'events' => []
|
|
628
|
+
]);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
/**
|
|
632
|
+
* Retrieve a cart by id or unique id.
|
|
633
|
+
*
|
|
634
|
+
* @param string $id
|
|
635
|
+
* @return Cart
|
|
636
|
+
*/
|
|
637
|
+
public static function retrieve(string $id, bool $excludeCheckedout = true): Cart
|
|
638
|
+
{
|
|
639
|
+
$query = static::where(function ($q) use ($id) {
|
|
640
|
+
$q->where('public_id', $id);
|
|
641
|
+
$q->orWhere('unique_identifier', $id);
|
|
642
|
+
});
|
|
643
|
+
|
|
644
|
+
if ($excludeCheckedout) {
|
|
645
|
+
$query->whereNull('checkout_uuid');
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
$cart = $query->first();
|
|
649
|
+
|
|
650
|
+
if (!$cart) {
|
|
651
|
+
return static::newCart(!Str::startsWith($id, 'cart_') ? $id : null);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
return $cart;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* Calculates the subtotal for a product using quantity vairants and addons.
|
|
659
|
+
*
|
|
660
|
+
* @param \Fleetbase\Models\Storefront\Product $product
|
|
661
|
+
* @param integer $quantity
|
|
662
|
+
* @param array $variants
|
|
663
|
+
* @param array $addons
|
|
664
|
+
* @return integer
|
|
665
|
+
*/
|
|
666
|
+
public static function calculateProductSubtotal(Product $product, $quantity = 1, $variants = [], $addons = []): int
|
|
667
|
+
{
|
|
668
|
+
$subtotal = $product->is_on_sale ? $product->sale_price : $product->price;
|
|
669
|
+
|
|
670
|
+
foreach ($variants as $variant) {
|
|
671
|
+
$subtotal += Utils::get($variant, 'additional_cost');
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
foreach ($addons as $addon) {
|
|
675
|
+
$subtotal += Utils::get($addon, 'is_on_sale') ? Utils::get($addon, 'sale_price') : Utils::get($addon, 'price');
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
return $subtotal * $quantity;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
/**
|
|
682
|
+
* Finds a product via id.
|
|
683
|
+
*
|
|
684
|
+
* @param string $id
|
|
685
|
+
* @return Product|null
|
|
686
|
+
*/
|
|
687
|
+
public static function findProduct(string $id): ?Product
|
|
688
|
+
{
|
|
689
|
+
return Product::select(['uuid', 'store_uuid', 'public_id', 'name', 'description', 'price', 'sale_price', 'is_on_sale'])->where(['public_id' => $id])->with([])->first();
|
|
690
|
+
}
|
|
691
|
+
}
|