@fleetbase/storefront-engine 0.1.7 → 0.1.9
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/composer.json +88 -0
- package/extension.json +10 -0
- package/package.json +6 -6
- 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,60 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\Storefront\Jobs;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\Storefront\Models\Product;
|
|
6
|
+
use Fleetbase\Models\File;
|
|
7
|
+
use Fleetbase\FleetOps\Support\Utils;
|
|
8
|
+
use Illuminate\Bus\Queueable;
|
|
9
|
+
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
10
|
+
use Illuminate\Foundation\Bus\Dispatchable;
|
|
11
|
+
use Illuminate\Queue\InteractsWithQueue;
|
|
12
|
+
use Illuminate\Queue\SerializesModels;
|
|
13
|
+
|
|
14
|
+
class DownloadProductImageUrl implements ShouldQueue
|
|
15
|
+
{
|
|
16
|
+
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The uuid of the product.
|
|
20
|
+
*
|
|
21
|
+
* @var string
|
|
22
|
+
*/
|
|
23
|
+
public $product;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The url of the image to download.
|
|
27
|
+
*
|
|
28
|
+
* @var string
|
|
29
|
+
*/
|
|
30
|
+
public $url;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Create a new job instance.
|
|
34
|
+
*
|
|
35
|
+
* @return void
|
|
36
|
+
*/
|
|
37
|
+
public function __construct(Product $product, string $url)
|
|
38
|
+
{
|
|
39
|
+
$this->product = $product->uuid;
|
|
40
|
+
$this->url = $url;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Execute the job.
|
|
45
|
+
*
|
|
46
|
+
* @return void
|
|
47
|
+
*/
|
|
48
|
+
public function handle()
|
|
49
|
+
{
|
|
50
|
+
// get product record
|
|
51
|
+
$product = Product::find($this->product);
|
|
52
|
+
// download and save to product as image
|
|
53
|
+
$image = Utils::urlToStorefrontFile($this->url, 'storefront_product', $product);
|
|
54
|
+
|
|
55
|
+
// if image is \Fleetbase\Models\File then set as primary image
|
|
56
|
+
if ($image instanceof File) {
|
|
57
|
+
$product->update(['primary_image_uuid' => $image->uuid]);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\Storefront\Listeners;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\FleetOps\Events\OrderCompleted;
|
|
6
|
+
use Fleetbase\Storefront\Notifications\StorefrontOrderCompleted;
|
|
7
|
+
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
8
|
+
use Illuminate\Queue\InteractsWithQueue;
|
|
9
|
+
|
|
10
|
+
class HandleOrderCompleted implements ShouldQueue
|
|
11
|
+
{
|
|
12
|
+
use InteractsWithQueue;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Handle the event.
|
|
16
|
+
*
|
|
17
|
+
* @param object $event
|
|
18
|
+
* @return void
|
|
19
|
+
*/
|
|
20
|
+
public function handle(OrderCompleted $event)
|
|
21
|
+
{
|
|
22
|
+
/** @var \Fleetbase\FleetOps\Models\Order $order */
|
|
23
|
+
$order = $event->getModelRecord();
|
|
24
|
+
|
|
25
|
+
// if storefront order notify customer driver has been addigned
|
|
26
|
+
if ($order->hasMeta('storefront_id')) {
|
|
27
|
+
$order->load(['customer']);
|
|
28
|
+
$order->customer->notify(new StorefrontOrderCompleted($order));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\Storefront\Listeners;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\FleetOps\Events\OrderDispatched;
|
|
6
|
+
use Fleetbase\Storefront\Notifications\StorefrontOrderReadyForPickup;
|
|
7
|
+
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
8
|
+
use Illuminate\Queue\InteractsWithQueue;
|
|
9
|
+
|
|
10
|
+
class HandleOrderDispatched implements ShouldQueue
|
|
11
|
+
{
|
|
12
|
+
use InteractsWithQueue;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Handle the event.
|
|
16
|
+
*
|
|
17
|
+
* @param object $event
|
|
18
|
+
* @return void
|
|
19
|
+
*/
|
|
20
|
+
public function handle(OrderDispatched $event)
|
|
21
|
+
{
|
|
22
|
+
/** @var \Fleetbase\FleetOps\Models\Order $order */
|
|
23
|
+
$order = $event->getModelRecord();
|
|
24
|
+
|
|
25
|
+
// notufy customer order is ready for pickup
|
|
26
|
+
if ($order->isMeta('is_pickup')) {
|
|
27
|
+
$order->load(['customer']);
|
|
28
|
+
|
|
29
|
+
if ($order->customer) {
|
|
30
|
+
$order->customer->notify(new StorefrontOrderReadyForPickup($order));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\Storefront\Listeners;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\FleetOps\Events\OrderDriverAssigned;
|
|
6
|
+
use Fleetbase\FleetOps\Models\Order;
|
|
7
|
+
use Fleetbase\Storefront\Notifications\StorefrontOrderDriverAssigned;
|
|
8
|
+
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
9
|
+
use Illuminate\Queue\InteractsWithQueue;
|
|
10
|
+
|
|
11
|
+
class HandleOrderDriverAssigned implements ShouldQueue
|
|
12
|
+
{
|
|
13
|
+
use InteractsWithQueue;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Handle the event.
|
|
17
|
+
*
|
|
18
|
+
* @param object $event
|
|
19
|
+
* @return void
|
|
20
|
+
*/
|
|
21
|
+
public function handle(OrderDriverAssigned $event)
|
|
22
|
+
{
|
|
23
|
+
/** @var \Fleetbase\FleetOps\Models\Order $order */
|
|
24
|
+
$order = $event->getModelRecord();
|
|
25
|
+
|
|
26
|
+
// halt if unable to resolve order record from event
|
|
27
|
+
if (!$order instanceof Order) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// if storefront order notify customer driver has been addigned
|
|
32
|
+
if ($order->hasMeta('storefront_id')) {
|
|
33
|
+
$order->load(['customer']);
|
|
34
|
+
$order->customer->notify(new StorefrontOrderDriverAssigned($order));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\Storefront\Listeners;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\FleetOps\Events\OrderStarted;
|
|
6
|
+
use Fleetbase\Storefront\Notifications\StorefrontOrderEnroute;
|
|
7
|
+
|
|
8
|
+
class HandleOrderStarted
|
|
9
|
+
{
|
|
10
|
+
/**
|
|
11
|
+
* Handle the event.
|
|
12
|
+
*
|
|
13
|
+
* @param object $event
|
|
14
|
+
* @return void
|
|
15
|
+
*/
|
|
16
|
+
public function handle(OrderStarted $event)
|
|
17
|
+
{
|
|
18
|
+
/** @var \Fleetbase\FleetOps\Models\Order $order */
|
|
19
|
+
$order = $event->getModelRecord();
|
|
20
|
+
|
|
21
|
+
// if storefront order / notify customer driver has started and is en-route
|
|
22
|
+
if ($order->hasMeta('storefront_id')) {
|
|
23
|
+
$order->load(['customer']);
|
|
24
|
+
$order->customer->notify(new StorefrontOrderEnroute($order));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\Storefront\Mail;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\Storefront\Models\Network;
|
|
6
|
+
use Fleetbase\Models\Invite;
|
|
7
|
+
use Fleetbase\Models\User;
|
|
8
|
+
use Fleetbase\FleetOps\Support\Utils;
|
|
9
|
+
use Illuminate\Bus\Queueable;
|
|
10
|
+
use Illuminate\Mail\Mailable;
|
|
11
|
+
use Illuminate\Queue\SerializesModels;
|
|
12
|
+
|
|
13
|
+
class StorefrontNetworkInvite extends Mailable
|
|
14
|
+
{
|
|
15
|
+
use Queueable, SerializesModels;
|
|
16
|
+
|
|
17
|
+
public Invite $invite;
|
|
18
|
+
public Network $network;
|
|
19
|
+
public User $sender;
|
|
20
|
+
public string $url;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Create a new message instance.
|
|
24
|
+
*
|
|
25
|
+
* @return void
|
|
26
|
+
*/
|
|
27
|
+
public function __construct(Invite $invite)
|
|
28
|
+
{
|
|
29
|
+
$this->invite = $invite;
|
|
30
|
+
$this->network = $this->invite->subject;
|
|
31
|
+
$this->sender = $this->invite->createdBy;
|
|
32
|
+
$this->url = Utils::consoleUrl('join/network/' . $this->invite->uri);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Build the message.
|
|
37
|
+
*
|
|
38
|
+
* @return $this
|
|
39
|
+
*/
|
|
40
|
+
public function build()
|
|
41
|
+
{
|
|
42
|
+
return $this
|
|
43
|
+
->subject('You have been invited to join ' . $this->invite->subject->name . '!')
|
|
44
|
+
->from('hello@fleetbase.io', $this->invite->subject->name)
|
|
45
|
+
->to($this->invite->recipients ?? [])
|
|
46
|
+
->markdown('emails.storefront-network-invite');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\Storefront\Models;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\Models\Category;
|
|
6
|
+
|
|
7
|
+
class AddonCategory extends Category
|
|
8
|
+
{
|
|
9
|
+
/**
|
|
10
|
+
* Relationships to auto load with driver
|
|
11
|
+
*
|
|
12
|
+
* @var array
|
|
13
|
+
*/
|
|
14
|
+
protected $with = ['addons'];
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The key to use in the payload responses
|
|
18
|
+
*
|
|
19
|
+
* @var string
|
|
20
|
+
*/
|
|
21
|
+
protected string $payloadKey = 'addon_category';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
|
25
|
+
*/
|
|
26
|
+
public function addons()
|
|
27
|
+
{
|
|
28
|
+
return $this->setConnection(config('storefront.connection.db'))->hasMany(ProductAddon::class, 'category_uuid');
|
|
29
|
+
}
|
|
30
|
+
}
|