@fleetbase/storefront-engine 0.3.23 → 0.3.25
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/addon/adapters/catalog.js +1 -0
- package/addon/adapters/food-truck.js +1 -0
- package/addon/components/customer-panel/orders.hbs +7 -1
- package/addon/components/modals/assign-food-truck-catalogs.hbs +14 -0
- package/addon/components/modals/create-catalog.hbs +96 -0
- package/addon/components/modals/create-first-store.hbs +6 -1
- package/addon/components/modals/create-food-truck.hbs +69 -0
- package/addon/components/modals/manage-addons.js +1 -15
- package/addon/components/order-panel.hbs +2 -2
- package/addon/components/widget/customers.hbs +5 -5
- package/addon/components/widget/orders.hbs +7 -4
- package/addon/components/widget/orders.js +11 -1
- package/addon/controllers/catalogs/index.js +121 -0
- package/addon/controllers/food-trucks/index.js +100 -0
- package/addon/models/catalog-category.js +6 -0
- package/addon/models/catalog-hour.js +72 -0
- package/addon/models/catalog.js +45 -0
- package/addon/models/food-truck.js +47 -0
- package/addon/models/product.js +1 -0
- package/addon/routes/catalogs/index.js +22 -0
- package/addon/routes/catalogs.js +3 -0
- package/addon/routes/food-trucks/index.js +22 -0
- package/addon/routes/food-trucks.js +3 -0
- package/addon/routes.js +6 -0
- package/addon/serializers/catalog-category.js +15 -0
- package/addon/serializers/catalog.js +16 -0
- package/addon/serializers/food-truck.js +18 -0
- package/addon/serializers/product-variant.js +0 -1
- package/addon/services/storefront.js +1 -1
- package/addon/styles/storefront-engine.css +15 -5
- package/addon/templates/application.hbs +14 -0
- package/addon/templates/catalogs/index.hbs +46 -0
- package/addon/templates/catalogs.hbs +1 -0
- package/addon/templates/customers/index.hbs +1 -1
- package/addon/templates/food-trucks/index.hbs +52 -0
- package/addon/templates/food-trucks.hbs +1 -0
- package/addon/templates/networks/index.hbs +14 -2
- package/addon/templates/products/index/category/new.hbs +10 -3
- package/addon/templates/products/index/index.hbs +1 -2
- package/addon/templates/products/index.hbs +16 -2
- package/app/adapters/catalog.js +1 -0
- package/app/adapters/food-truck.js +1 -0
- package/app/components/modals/assign-food-truck-catalogs.js +1 -0
- package/app/components/modals/create-catalog.js +1 -0
- package/app/components/modals/create-food-truck.js +1 -0
- package/app/controllers/catalogs/index.js +1 -0
- package/app/controllers/food-trucks/index.js +1 -0
- package/app/models/catalog-category.js +1 -0
- package/app/models/catalog-hour.js +1 -0
- package/app/models/catalog.js +1 -0
- package/app/models/food-truck.js +1 -0
- package/app/routes/catalogs/index.js +1 -0
- package/app/routes/catalogs.js +1 -0
- package/app/routes/food-trucks/index.js +1 -0
- package/app/routes/food-trucks.js +1 -0
- package/app/serializers/catalog-category.js +1 -0
- package/app/serializers/catalog.js +1 -0
- package/app/serializers/food-truck.js +1 -0
- package/app/templates/catalogs/index.js +1 -0
- package/app/templates/catalogs.js +1 -0
- package/app/templates/food-trucks/index.js +1 -0
- package/app/templates/food-trucks.js +1 -0
- package/composer.json +1 -1
- package/extension.json +1 -1
- package/package.json +1 -1
- package/server/migrations/2025_01_30_042853_create_catalogs_table.php +41 -0
- package/server/migrations/2025_01_30_044728_create_catalog_category_products_table.php +35 -0
- package/server/migrations/2025_01_30_050611_create_food_trucks_table.php +72 -0
- package/server/migrations/2025_01_30_052157_create_catalog_subjects_table.php +54 -0
- package/server/migrations/2025_01_30_052402_create_catalog_hours_table.php +39 -0
- package/server/src/Auth/Schemas/Storefront.php +16 -0
- package/server/src/Console/Commands/PurgeExpiredCarts.php +49 -0
- package/server/src/Http/Controllers/CatalogCategoryController.php +13 -0
- package/server/src/Http/Controllers/CatalogController.php +13 -0
- package/server/src/Http/Controllers/CatalogHourController.php +13 -0
- package/server/src/Http/Controllers/FoodTruckController.php +13 -0
- package/server/src/Http/Controllers/v1/CatalogController.php +38 -0
- package/server/src/Http/Controllers/v1/CategoryController.php +1 -1
- package/server/src/Http/Controllers/v1/FoodTruckController.php +39 -0
- package/server/src/Http/Controllers/v1/OrderController.php +43 -0
- package/server/src/Http/Controllers/v1/ProductController.php +1 -1
- package/server/src/Http/Controllers/v1/ReviewController.php +8 -6
- package/server/src/Http/Filter/FoodTruckFilter.php +37 -0
- package/server/src/Http/Resources/Catalog.php +34 -0
- package/server/src/Http/Resources/CatalogCategory.php +38 -0
- package/server/src/Http/Resources/CatalogProduct.php +55 -0
- package/server/src/Http/Resources/FoodTruck.php +42 -0
- package/server/src/Http/Resources/Product.php +2 -1
- package/server/src/Models/AddonCategory.php +12 -0
- package/server/src/Models/Cart.php +6 -0
- package/server/src/Models/Catalog.php +213 -0
- package/server/src/Models/CatalogCategory.php +118 -0
- package/server/src/Models/CatalogHour.php +46 -0
- package/server/src/Models/CatalogProduct.php +25 -0
- package/server/src/Models/CatalogSubject.php +70 -0
- package/server/src/Models/FoodTruck.php +182 -0
- package/server/src/Models/Product.php +16 -1
- package/server/src/Notifications/StorefrontOrderCanceled.php +80 -121
- package/server/src/Notifications/StorefrontOrderCompleted.php +86 -131
- package/server/src/Notifications/StorefrontOrderCreated.php +29 -15
- package/server/src/Notifications/StorefrontOrderDriverAssigned.php +96 -130
- package/server/src/Notifications/StorefrontOrderEnroute.php +89 -129
- package/server/src/Notifications/StorefrontOrderNearby.php +103 -132
- package/server/src/Notifications/StorefrontOrderPreparing.php +89 -134
- package/server/src/Notifications/StorefrontOrderReadyForPickup.php +89 -134
- package/server/src/Observers/CatalogObserver.php +40 -0
- package/server/src/Observers/FoodTruckObserver.php +24 -0
- package/server/src/Observers/ProductObserver.php +3 -27
- package/server/src/Providers/StorefrontServiceProvider.php +7 -3
- package/server/src/Support/PushNotification.php +127 -0
- package/server/src/routes.php +15 -0
- package/translations/en-us.yaml +5 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\Storefront\Http\Resources;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\Support\Http;
|
|
6
|
+
|
|
7
|
+
class CatalogProduct extends Product
|
|
8
|
+
{
|
|
9
|
+
/**
|
|
10
|
+
* Transform the resource into an array.
|
|
11
|
+
*
|
|
12
|
+
* @param \Illuminate\Http\Request $request
|
|
13
|
+
*
|
|
14
|
+
* @return array
|
|
15
|
+
*/
|
|
16
|
+
public function toArray($request)
|
|
17
|
+
{
|
|
18
|
+
return [
|
|
19
|
+
'id' => $this->when(Http::isInternalRequest(), $this->id, $this->public_id),
|
|
20
|
+
'uuid' => $this->when(Http::isInternalRequest(), $this->uuid),
|
|
21
|
+
'public_id' => $this->when(Http::isInternalRequest(), $this->public_id),
|
|
22
|
+
'company_uuid' => $this->when(Http::isInternalRequest(), $this->company_uuid),
|
|
23
|
+
'store_uuid' => $this->when(Http::isInternalRequest(), $this->store_uuid),
|
|
24
|
+
'category_uuid' => $this->when(Http::isInternalRequest(), $this->category_uuid),
|
|
25
|
+
'created_by_uuid' => $this->when(Http::isInternalRequest(), $this->created_by_uuid),
|
|
26
|
+
'primary_image_uuid' => $this->when(Http::isInternalRequest(), $this->primary_image_uuid),
|
|
27
|
+
'name' => $this->name,
|
|
28
|
+
'description' => $this->description,
|
|
29
|
+
'sku' => $this->sku,
|
|
30
|
+
'primary_image_url' => $this->primary_image_url,
|
|
31
|
+
'price' => $this->price,
|
|
32
|
+
'sale_price' => $this->sale_price,
|
|
33
|
+
'currency' => $this->currency,
|
|
34
|
+
'is_on_sale' => $this->is_on_sale,
|
|
35
|
+
'is_recommended' => $this->is_recommended,
|
|
36
|
+
'is_service' => $this->is_service,
|
|
37
|
+
'is_bookable' => $this->is_bookable,
|
|
38
|
+
'is_available' => $this->is_available,
|
|
39
|
+
'tags' => $this->tags ?? [],
|
|
40
|
+
'status' => $this->status,
|
|
41
|
+
'slug' => $this->slug,
|
|
42
|
+
'translations' => $this->translations ?? [],
|
|
43
|
+
'addon_categories' => $this->mapAddonCategories($this->addonCategories),
|
|
44
|
+
'variants' => $this->mapVariants($this->variants),
|
|
45
|
+
'files' => $this->when(Http::isInternalRequest(), $this->files),
|
|
46
|
+
'images' => $this->when(!Http::isInternalRequest(), $this->mapFiles($this->files)),
|
|
47
|
+
'videos' => $this->when(!Http::isInternalRequest(), $this->mapFiles($this->files, 'video')),
|
|
48
|
+
'hours' => $this->mapHours($this->hours),
|
|
49
|
+
'youtube_urls' => $this->youtube_urls ?? [],
|
|
50
|
+
'created_at' => $this->created_at,
|
|
51
|
+
'updated_at' => $this->updated_at,
|
|
52
|
+
'type' => $this->when(Http::isInternalRequest(), 'product'),
|
|
53
|
+
];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\Storefront\Http\Resources;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\FleetOps\Http\Resources\v1\ServiceArea as ServiceAreaResource;
|
|
6
|
+
use Fleetbase\FleetOps\Http\Resources\v1\Vehicle as VehicleResource;
|
|
7
|
+
use Fleetbase\FleetOps\Http\Resources\v1\Zone as ZoneResource;
|
|
8
|
+
use Fleetbase\Http\Resources\FleetbaseResource;
|
|
9
|
+
use Fleetbase\Support\Http;
|
|
10
|
+
|
|
11
|
+
class FoodTruck extends FleetbaseResource
|
|
12
|
+
{
|
|
13
|
+
/**
|
|
14
|
+
* Transform the resource into an array.
|
|
15
|
+
*
|
|
16
|
+
* @param \Illuminate\Http\Request $request
|
|
17
|
+
*
|
|
18
|
+
* @return array
|
|
19
|
+
*/
|
|
20
|
+
public function toArray($request)
|
|
21
|
+
{
|
|
22
|
+
return [
|
|
23
|
+
'id' => $this->when(Http::isInternalRequest(), $this->id, $this->public_id),
|
|
24
|
+
'uuid' => $this->when(Http::isInternalRequest(), $this->uuid),
|
|
25
|
+
'public_id' => $this->when(Http::isInternalRequest(), $this->public_id),
|
|
26
|
+
'company_uuid' => $this->when(Http::isInternalRequest(), $this->company_uuid),
|
|
27
|
+
'created_by_uuid' => $this->when(Http::isInternalRequest(), $this->created_by_uuid),
|
|
28
|
+
'store_uuid' => $this->when(Http::isInternalRequest(), $this->store_uuid),
|
|
29
|
+
'service_area_uuid' => $this->when(Http::isInternalRequest(), $this->service_area_uuid),
|
|
30
|
+
'zone_uuid' => $this->when(Http::isInternalRequest(), $this->zone_uuid),
|
|
31
|
+
'vehicle_uuid' => $this->when(Http::isInternalRequest(), $this->vehicle_uuid),
|
|
32
|
+
'vehicle' => $this->vehicle ? new VehicleResource($this->vehicle) : null,
|
|
33
|
+
'service_area' => $this->serviceArea ? new ServiceAreaResource($this->serviceArea) : null,
|
|
34
|
+
'zone' => $this->zone ? new ZoneResource($this->zone) : null,
|
|
35
|
+
'catalogs' => Catalog::collection($this->catalogs ?? []),
|
|
36
|
+
'online' => $this->vehicle ? $this->vehicle->online : false,
|
|
37
|
+
'status' => $this->status,
|
|
38
|
+
'created_at' => $this->created_at,
|
|
39
|
+
'updated_at' => $this->updated_at,
|
|
40
|
+
];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -5,8 +5,8 @@ namespace Fleetbase\Storefront\Http\Resources;
|
|
|
5
5
|
use Fleetbase\Http\Resources\FleetbaseResource;
|
|
6
6
|
use Fleetbase\Support\Http;
|
|
7
7
|
use Illuminate\Support\Arr;
|
|
8
|
-
use Illuminate\Support\Str;
|
|
9
8
|
use Illuminate\Support\Collection;
|
|
9
|
+
use Illuminate\Support\Str;
|
|
10
10
|
|
|
11
11
|
class Product extends FleetbaseResource
|
|
12
12
|
{
|
|
@@ -53,6 +53,7 @@ class Product extends FleetbaseResource
|
|
|
53
53
|
'youtube_urls' => $this->youtube_urls ?? [],
|
|
54
54
|
'created_at' => $this->created_at,
|
|
55
55
|
'updated_at' => $this->updated_at,
|
|
56
|
+
'type' => $this->when(Http::isInternalRequest(), 'product'),
|
|
56
57
|
];
|
|
57
58
|
}
|
|
58
59
|
|
|
@@ -20,6 +20,18 @@ class AddonCategory extends Category
|
|
|
20
20
|
*/
|
|
21
21
|
protected string $payloadKey = 'addon_category';
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Override the boot method to set "for" automatically.
|
|
25
|
+
*/
|
|
26
|
+
protected static function boot()
|
|
27
|
+
{
|
|
28
|
+
parent::boot();
|
|
29
|
+
|
|
30
|
+
static::creating(function (Category $model) {
|
|
31
|
+
$model->for = 'storefront_product_addon';
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
23
35
|
/**
|
|
24
36
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
|
25
37
|
*/
|
|
@@ -334,6 +334,12 @@ class Cart extends StorefrontModel
|
|
|
334
334
|
'addons' => $addons,
|
|
335
335
|
];
|
|
336
336
|
|
|
337
|
+
// If item was added from a food truck
|
|
338
|
+
if ($storeLocationId && Str::startsWith($storeLocationId, 'food_truck_')) {
|
|
339
|
+
$properties['food_truck_id'] = $storeLocationId;
|
|
340
|
+
$properties['store_location_id'] = Utils::get($product, 'store.locations.0.public_id');
|
|
341
|
+
}
|
|
342
|
+
|
|
337
343
|
$this->updateCurrency($product->currency, false);
|
|
338
344
|
|
|
339
345
|
foreach ($properties as $prop => $value) {
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\Storefront\Models;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\Casts\Json;
|
|
6
|
+
use Fleetbase\Models\Company;
|
|
7
|
+
use Fleetbase\Models\User;
|
|
8
|
+
use Fleetbase\Traits\HasApiModelBehavior;
|
|
9
|
+
use Fleetbase\Traits\HasPublicid;
|
|
10
|
+
use Fleetbase\Traits\HasUuid;
|
|
11
|
+
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
12
|
+
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
13
|
+
use Illuminate\Database\Eloquent\Relations\MorphToMany;
|
|
14
|
+
|
|
15
|
+
class Catalog extends StorefrontModel
|
|
16
|
+
{
|
|
17
|
+
use HasUuid;
|
|
18
|
+
use HasPublicid;
|
|
19
|
+
use HasApiModelBehavior;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The type of public ID to generate.
|
|
23
|
+
*
|
|
24
|
+
* @var string
|
|
25
|
+
*/
|
|
26
|
+
protected $publicIdType = 'catalog';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The database table used by the model.
|
|
30
|
+
*
|
|
31
|
+
* @var string
|
|
32
|
+
*/
|
|
33
|
+
protected $table = 'catalogs';
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Searchable columns.
|
|
37
|
+
*
|
|
38
|
+
* @var array
|
|
39
|
+
*/
|
|
40
|
+
protected $searchableColumns = ['name'];
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* The attributes that are mass assignable.
|
|
44
|
+
*
|
|
45
|
+
* @var array
|
|
46
|
+
*/
|
|
47
|
+
protected $fillable = [
|
|
48
|
+
'uuid',
|
|
49
|
+
'store_uuid',
|
|
50
|
+
'company_uuid',
|
|
51
|
+
'created_by_uuid',
|
|
52
|
+
'name',
|
|
53
|
+
'description',
|
|
54
|
+
'status',
|
|
55
|
+
'meta',
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The attributes that should be cast to native types.
|
|
60
|
+
*
|
|
61
|
+
* @var array
|
|
62
|
+
*/
|
|
63
|
+
protected $casts = [
|
|
64
|
+
'meta' => Json::class,
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Dynamic attributes that are appended to object.
|
|
69
|
+
*
|
|
70
|
+
* @var array
|
|
71
|
+
*/
|
|
72
|
+
protected $appends = [];
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* The attributes excluded from the model's JSON form.
|
|
76
|
+
*
|
|
77
|
+
* @var array
|
|
78
|
+
*/
|
|
79
|
+
protected $hidden = [];
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Get the user who created the catalog.
|
|
83
|
+
*/
|
|
84
|
+
public function createdBy(): BelongsTo
|
|
85
|
+
{
|
|
86
|
+
return $this
|
|
87
|
+
->setConnection(config('fleetbase.connection.db'))
|
|
88
|
+
->belongsTo(User::class, 'created_by_uuid', 'uuid');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Get the company this catalog belongs to.
|
|
93
|
+
*/
|
|
94
|
+
public function company(): BelongsTo
|
|
95
|
+
{
|
|
96
|
+
return $this
|
|
97
|
+
->setConnection(config('fleetbase.connection.db'))
|
|
98
|
+
->belongsTo(Company::class, 'company_uuid', 'uuid');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Get the store that owns this food truck.
|
|
103
|
+
*/
|
|
104
|
+
public function store(): BelongsTo
|
|
105
|
+
{
|
|
106
|
+
return $this->belongsTo(Store::class, 'store_uuid', 'uuid');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Hours the catalog is available to customers.
|
|
111
|
+
*/
|
|
112
|
+
public function hours(): HasMany
|
|
113
|
+
{
|
|
114
|
+
return $this->hasMany(CatalogHour::class, 'catalog_uuid', 'uuid');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Categories the catalog contains.
|
|
119
|
+
*/
|
|
120
|
+
public function categories(): HasMany
|
|
121
|
+
{
|
|
122
|
+
return $this->setConnection(config('fleetbase.connection.db'))->hasMany(CatalogCategory::class, 'owner_uuid', 'uuid');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Assignments of subjects the catalog has.
|
|
127
|
+
*/
|
|
128
|
+
public function assignments(): HasMany
|
|
129
|
+
{
|
|
130
|
+
return $this->hasMany(CatalogSubject::class, 'catalog_uuid', 'uuid');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Subjects the catalog has been assigned too.
|
|
135
|
+
*/
|
|
136
|
+
public function subjects(): MorphToMany
|
|
137
|
+
{
|
|
138
|
+
return $this->morphedByMany(
|
|
139
|
+
StorefrontModel::class,
|
|
140
|
+
'subject',
|
|
141
|
+
'catalog_subjects',
|
|
142
|
+
'catalog_uuid',
|
|
143
|
+
'subject_uuid'
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Update or create categories for this catalog based on the provided array.
|
|
149
|
+
*
|
|
150
|
+
* This method:
|
|
151
|
+
* 1) Deletes categories that are no longer in the `$categories` list.
|
|
152
|
+
* 2) Updates existing categories if their UUID is found in `$categories`.
|
|
153
|
+
* 3) Creates new categories for entries without a UUID.
|
|
154
|
+
* 4) Delegates product assignment to `setProducts()` on each category.
|
|
155
|
+
*
|
|
156
|
+
* @param array $categories An array of category data, each containing:
|
|
157
|
+
* - 'uuid' (optional): if provided, indicates an existing category to update
|
|
158
|
+
* - 'name': the category name
|
|
159
|
+
* - 'products' (optional): an array of product UUIDs or objects to link
|
|
160
|
+
*
|
|
161
|
+
* @return $this
|
|
162
|
+
*/
|
|
163
|
+
public function setCategories(array $categories = []): Catalog
|
|
164
|
+
{
|
|
165
|
+
// Ensure categories relation is loaded.
|
|
166
|
+
$this->loadMissing('categories');
|
|
167
|
+
|
|
168
|
+
// Grab all existing categories for this catalog.
|
|
169
|
+
$existingCategories = $this->categories;
|
|
170
|
+
|
|
171
|
+
// Extract incoming category UUIDs (if any).
|
|
172
|
+
$incomingUuids = collect($categories)->pluck('uuid')->filter()->unique();
|
|
173
|
+
|
|
174
|
+
// 1) Delete categories that are no longer present.
|
|
175
|
+
// (i.e., they exist in DB but their UUID is not in $incomingUuids)
|
|
176
|
+
$existingCategories
|
|
177
|
+
->whereNotIn('uuid', $incomingUuids)
|
|
178
|
+
->each(function (CatalogCategory $cat) {
|
|
179
|
+
$cat->delete(); // or $cat->forceDelete() if you don't want soft deletes
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// 2) Loop through incoming categories array
|
|
183
|
+
foreach ($categories as $categoryData) {
|
|
184
|
+
$categoryUuid = data_get($categoryData, 'uuid');
|
|
185
|
+
$products = data_get($categoryData, 'products', []);
|
|
186
|
+
$name = data_get($categoryData, 'name');
|
|
187
|
+
|
|
188
|
+
// Try to find an existing category
|
|
189
|
+
$categoryRecord = null;
|
|
190
|
+
if ($categoryUuid) {
|
|
191
|
+
$categoryRecord = $existingCategories->firstWhere('uuid', $categoryUuid);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if ($categoryRecord) {
|
|
195
|
+
// 2a) Update existing category
|
|
196
|
+
$categoryRecord->update(['name' => $name]);
|
|
197
|
+
} else {
|
|
198
|
+
// 2b) Create a new category
|
|
199
|
+
$categoryRecord = CatalogCategory::create([
|
|
200
|
+
'name' => $name,
|
|
201
|
+
'company_uuid' => $this->company_uuid,
|
|
202
|
+
'owner_uuid' => $this->uuid,
|
|
203
|
+
'owner_type' => get_class($this),
|
|
204
|
+
]);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// 3) Update products for this category
|
|
208
|
+
$categoryRecord->setProducts($products);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return $this;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\Storefront\Models;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\Models\Category;
|
|
6
|
+
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
7
|
+
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
|
8
|
+
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
|
9
|
+
use Illuminate\Support\Str;
|
|
10
|
+
|
|
11
|
+
class CatalogCategory extends Category
|
|
12
|
+
{
|
|
13
|
+
/**
|
|
14
|
+
* The key to use in the payload responses (optional).
|
|
15
|
+
*/
|
|
16
|
+
protected string $payloadKey = 'catalog_category';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Override the boot method to set "for" automatically.
|
|
20
|
+
*/
|
|
21
|
+
protected static function boot()
|
|
22
|
+
{
|
|
23
|
+
parent::boot();
|
|
24
|
+
|
|
25
|
+
static::creating(function (Category $model) {
|
|
26
|
+
$model->for = 'storefront_catalog';
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The catalog the category belongs to.
|
|
32
|
+
*/
|
|
33
|
+
public function owner(): MorphTo
|
|
34
|
+
{
|
|
35
|
+
return $this->setConnection(config('storefront.connection.db'))->morphTo(__FUNCTION__, 'owner_type', 'owner_uuid');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The catalog the category belongs to.
|
|
40
|
+
*/
|
|
41
|
+
public function catalog(): BelongsTo
|
|
42
|
+
{
|
|
43
|
+
return $this->setConnection(config('storefront.connection.db'))->belongsTo(Catalog::class, 'owner_uuid', 'uuid');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Many-to-many relationship with Product via the pivot table.
|
|
48
|
+
*/
|
|
49
|
+
public function products(): BelongsToMany
|
|
50
|
+
{
|
|
51
|
+
return $this->setConnection(config('storefront.connection.db'))
|
|
52
|
+
->belongsToMany(
|
|
53
|
+
Product::class,
|
|
54
|
+
'catalog_category_products',
|
|
55
|
+
'catalog_category_uuid',
|
|
56
|
+
'product_uuid'
|
|
57
|
+
)
|
|
58
|
+
->using(CatalogProduct::class)
|
|
59
|
+
->withTimestamps()
|
|
60
|
+
->wherePivotNull('deleted_at');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Update or create product relationships for this catalog category.
|
|
65
|
+
*
|
|
66
|
+
* This method:
|
|
67
|
+
* 1) Removes pivot entries (CatalogProduct) for products no longer in `$products`.
|
|
68
|
+
* 2) Creates pivot entries for new product IDs/UUIDs in `$products`.
|
|
69
|
+
*
|
|
70
|
+
* @param array $products an array of product identifiers (UUIDs) or objects containing a 'uuid' key
|
|
71
|
+
*
|
|
72
|
+
* @return $this
|
|
73
|
+
*/
|
|
74
|
+
public function setProducts(array $products = []): CatalogCategory
|
|
75
|
+
{
|
|
76
|
+
// Ensure products relation is loaded if needed (optional).
|
|
77
|
+
$this->loadMissing('products');
|
|
78
|
+
|
|
79
|
+
// Fetch existing pivot records for this category
|
|
80
|
+
$existingPivotRecords = CatalogProduct::where('catalog_category_uuid', $this->uuid)->get();
|
|
81
|
+
$existingProductUuids = $existingPivotRecords->pluck('product_uuid')->toArray();
|
|
82
|
+
|
|
83
|
+
// Normalize incoming product UUIDs
|
|
84
|
+
$incomingProductUuids = collect($products)
|
|
85
|
+
->map(function ($item) {
|
|
86
|
+
// If $item is simply a UUID string, use it
|
|
87
|
+
if (is_string($item) && Str::isUuid($item)) {
|
|
88
|
+
return $item;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// If $item is an array/object, try to extract 'uuid'
|
|
92
|
+
return data_get($item, 'uuid');
|
|
93
|
+
})
|
|
94
|
+
->filter(fn ($uuid) => Str::isUuid($uuid)) // only valid UUIDs
|
|
95
|
+
->unique()
|
|
96
|
+
->values()
|
|
97
|
+
->toArray();
|
|
98
|
+
|
|
99
|
+
// 1) Remove pivot rows for products not in incoming list
|
|
100
|
+
$toRemove = array_diff($existingProductUuids, $incomingProductUuids);
|
|
101
|
+
if (!empty($toRemove)) {
|
|
102
|
+
CatalogProduct::where('catalog_category_uuid', $this->uuid)
|
|
103
|
+
->whereIn('product_uuid', $toRemove)
|
|
104
|
+
->delete();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// 2) Create pivot rows for new products
|
|
108
|
+
$toAdd = array_diff($incomingProductUuids, $existingProductUuids);
|
|
109
|
+
foreach ($toAdd as $productUuid) {
|
|
110
|
+
CatalogProduct::create([
|
|
111
|
+
'catalog_category_uuid' => $this->uuid,
|
|
112
|
+
'product_uuid' => $productUuid,
|
|
113
|
+
]);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return $this;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\Storefront\Models;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\Traits\HasApiModelBehavior;
|
|
6
|
+
use Fleetbase\Traits\HasUuid;
|
|
7
|
+
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
8
|
+
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
9
|
+
|
|
10
|
+
class CatalogHour extends StorefrontModel
|
|
11
|
+
{
|
|
12
|
+
use HasUuid;
|
|
13
|
+
use HasApiModelBehavior;
|
|
14
|
+
use SoftDeletes;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The database table used by the model.
|
|
18
|
+
*
|
|
19
|
+
* @var string
|
|
20
|
+
*/
|
|
21
|
+
protected $table = 'catalog_hours';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The attributes that are mass assignable.
|
|
25
|
+
*
|
|
26
|
+
* @var array
|
|
27
|
+
*/
|
|
28
|
+
protected $fillable = [
|
|
29
|
+
'catalog_uuid',
|
|
30
|
+
'day_of_week',
|
|
31
|
+
'start',
|
|
32
|
+
'end',
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The relationships that should always be loaded.
|
|
37
|
+
*
|
|
38
|
+
* @var array
|
|
39
|
+
*/
|
|
40
|
+
protected $with = [];
|
|
41
|
+
|
|
42
|
+
public function catalog(): BelongsTo
|
|
43
|
+
{
|
|
44
|
+
return $this->belongsTo(Catalog::class, 'catalog_uuid', 'uuid');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\Storefront\Models;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\Traits\HasUuid;
|
|
6
|
+
use Illuminate\Database\Eloquent\Relations\Pivot;
|
|
7
|
+
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
8
|
+
|
|
9
|
+
class CatalogProduct extends Pivot
|
|
10
|
+
{
|
|
11
|
+
use SoftDeletes;
|
|
12
|
+
use HasUuid;
|
|
13
|
+
|
|
14
|
+
protected $connection = 'storefront';
|
|
15
|
+
protected $table = 'catalog_category_products';
|
|
16
|
+
protected $primaryKey = 'uuid';
|
|
17
|
+
public $incrementing = false;
|
|
18
|
+
protected $fillable = ['catalog_category_uuid', 'product_uuid'];
|
|
19
|
+
|
|
20
|
+
public function __construct(array $attributes = [])
|
|
21
|
+
{
|
|
22
|
+
$this->setConnection(config('storefront.connection.db'));
|
|
23
|
+
parent::__construct($attributes);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\Storefront\Models;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\Traits\HasApiModelBehavior;
|
|
6
|
+
use Fleetbase\Traits\HasUuid;
|
|
7
|
+
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
8
|
+
use Illuminate\Database\Eloquent\Relations\MorphPivot;
|
|
9
|
+
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
|
10
|
+
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
11
|
+
|
|
12
|
+
class CatalogSubject extends MorphPivot
|
|
13
|
+
{
|
|
14
|
+
use HasUuid;
|
|
15
|
+
use HasApiModelBehavior;
|
|
16
|
+
use SoftDeletes;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The default database connection to use.
|
|
20
|
+
*
|
|
21
|
+
* @var string
|
|
22
|
+
*/
|
|
23
|
+
protected $connection = 'storefront';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The table associated with the model.
|
|
27
|
+
*
|
|
28
|
+
* @var string
|
|
29
|
+
*/
|
|
30
|
+
protected $table = 'catalog_subjects';
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The attributes that are mass assignable.
|
|
34
|
+
*
|
|
35
|
+
* @var array
|
|
36
|
+
*/
|
|
37
|
+
protected $fillable = [
|
|
38
|
+
'uuid',
|
|
39
|
+
'catalog_uuid',
|
|
40
|
+
'subject_type',
|
|
41
|
+
'subject_uuid',
|
|
42
|
+
'company_uuid',
|
|
43
|
+
'created_by_uuid',
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Set the configured connection.
|
|
48
|
+
*/
|
|
49
|
+
public function __construct(array $attributes = [])
|
|
50
|
+
{
|
|
51
|
+
$this->setConnection(config('storefront.connection.db'));
|
|
52
|
+
parent::__construct($attributes);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The "subject" of this pivot - can be a Store, FoodTruck, etc.
|
|
57
|
+
*/
|
|
58
|
+
public function subject(): MorphTo
|
|
59
|
+
{
|
|
60
|
+
return $this->morphTo(__FUNCTION__, 'subject_type', 'subject_uuid');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Get the associated catalog.
|
|
65
|
+
*/
|
|
66
|
+
public function catalog(): BelongsTo
|
|
67
|
+
{
|
|
68
|
+
return $this->belongsTo(Catalog::class, 'catalog_uuid', 'uuid');
|
|
69
|
+
}
|
|
70
|
+
}
|