@fleetbase/storefront-engine 0.4.0 → 0.4.2
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/components/customer-panel/orders.hbs +2 -2
- package/addon/components/modals/create-gateway.hbs +33 -12
- package/addon/components/network-category-picker.js +1 -1
- package/addon/components/order-panel.hbs +1 -1
- package/addon/components/widget/customers.hbs +5 -2
- package/addon/components/widget/customers.js +14 -6
- package/addon/components/widget/orders.hbs +31 -10
- package/addon/components/widget/orders.js +7 -1
- package/addon/components/widget/storefront-key-metrics.js +2 -2
- package/addon/components/widget/storefront-metrics.hbs +11 -1
- package/addon/components/widget/storefront-metrics.js +103 -1
- package/addon/controllers/networks/index/network/index.js +2 -0
- package/addon/controllers/networks/index/network/stores.js +0 -1
- package/addon/controllers/products/index/category/new.js +13 -2
- package/addon/controllers/settings/gateways.js +6 -1
- package/addon/controllers/settings/index.js +1 -0
- package/addon/controllers/settings/notifications.js +4 -5
- package/addon/models/network.js +1 -0
- package/addon/models/store.js +1 -0
- package/addon/routes/networks/index/network/index.js +5 -0
- package/addon/routes/settings/index.js +5 -0
- package/addon/services/order-actions.js +31 -0
- package/addon/styles/storefront-engine.css +22 -0
- package/addon/templates/home.hbs +2 -2
- package/addon/templates/networks/index/network/index.hbs +21 -8
- package/addon/templates/networks/index/network/stores.hbs +8 -1
- package/addon/templates/products/index/category/new.hbs +149 -134
- package/addon/templates/settings/gateways.hbs +15 -4
- package/addon/templates/settings/index.hbs +13 -0
- package/addon/templates/settings/notifications.hbs +2 -2
- package/addon/utils/commerce-date-ranges.js +263 -0
- package/app/utils/commerce-date-ranges.js +1 -0
- package/composer.json +1 -1
- package/extension.json +1 -1
- package/package.json +4 -4
- package/server/migrations/2025_09_01_041353_add_default_order_config_column.php +110 -0
- package/server/src/Console/Commands/MigrateStripeSandboxCustomers.php +165 -0
- package/server/src/Expansions/OrderExpansion.php +43 -0
- package/server/src/Http/Controllers/NetworkController.php +1 -1
- package/server/src/Http/Controllers/OrderController.php +62 -9
- package/server/src/Http/Controllers/v1/CheckoutController.php +57 -48
- package/server/src/Http/Controllers/v1/ServiceQuoteController.php +19 -3
- package/server/src/Http/Middleware/SetStorefrontSession.php +8 -6
- package/server/src/Http/Resources/Customer.php +41 -17
- package/server/src/Http/Resources/Gateway.php +16 -11
- package/server/src/Http/Resources/Network.php +35 -34
- package/server/src/Http/Resources/NotificationChannel.php +17 -10
- package/server/src/Http/Resources/Product.php +1 -0
- package/server/src/Http/Resources/Store.php +36 -35
- package/server/src/Models/Customer.php +18 -2
- package/server/src/Models/FoodTruck.php +29 -2
- package/server/src/Models/Network.php +63 -1
- package/server/src/Models/Store.php +71 -9
- package/server/src/Notifications/StorefrontOrderAccepted.php +164 -0
- package/server/src/Notifications/StorefrontOrderCanceled.php +11 -1
- package/server/src/Notifications/StorefrontOrderCompleted.php +11 -1
- package/server/src/Notifications/StorefrontOrderDriverAssigned.php +12 -4
- package/server/src/Notifications/StorefrontOrderEnroute.php +12 -4
- package/server/src/Notifications/StorefrontOrderNearby.php +12 -4
- package/server/src/Notifications/StorefrontOrderPreparing.php +12 -4
- package/server/src/Notifications/StorefrontOrderReadyForPickup.php +12 -4
- package/server/src/Observers/OrderObserver.php +6 -4
- package/server/src/Providers/StorefrontServiceProvider.php +1 -0
- package/server/src/Rules/IsValidLocation.php +12 -0
- package/server/src/Support/PushNotification.php +20 -4
- package/server/src/Support/Storefront.php +283 -37
- package/server/src/routes.php +1 -0
- package/translations/{ar-ae.yml → ar-ae.yaml} +313 -253
- package/translations/bg-bg.yaml +734 -0
- package/translations/en-us.yaml +5 -0
- package/translations/es-es.yaml +732 -0
- package/translations/fr-fr.yaml +748 -0
- package/translations/mn-mn.yaml +725 -0
- package/translations/pt-br.yaml +732 -0
- package/translations/ru-ru.yaml +726 -0
- package/translations/vi-vn.yaml +412 -338
- package/translations/zh-cn.yaml +659 -0
|
@@ -20,41 +20,42 @@ class Store extends FleetbaseResource
|
|
|
20
20
|
$currency = $this->currency ?? 'USD';
|
|
21
21
|
|
|
22
22
|
return [
|
|
23
|
-
'id'
|
|
24
|
-
'uuid'
|
|
25
|
-
'public_id'
|
|
26
|
-
'key'
|
|
27
|
-
'company_uuid'
|
|
28
|
-
'created_by_uuid'
|
|
29
|
-
'logo_uuid'
|
|
30
|
-
'backdrop_uuid'
|
|
31
|
-
'
|
|
32
|
-
'
|
|
33
|
-
'
|
|
34
|
-
'
|
|
35
|
-
'
|
|
36
|
-
'
|
|
37
|
-
'
|
|
38
|
-
'
|
|
39
|
-
'
|
|
40
|
-
'
|
|
41
|
-
'
|
|
42
|
-
'
|
|
43
|
-
'
|
|
44
|
-
'
|
|
45
|
-
'
|
|
46
|
-
'
|
|
47
|
-
'
|
|
48
|
-
'
|
|
49
|
-
'
|
|
50
|
-
'
|
|
51
|
-
'
|
|
52
|
-
'
|
|
53
|
-
'
|
|
54
|
-
'
|
|
55
|
-
'
|
|
56
|
-
'
|
|
57
|
-
'
|
|
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
|
+
'key' => $this->when(Http::isInternalRequest(), $this->key),
|
|
27
|
+
'company_uuid' => $this->when(Http::isInternalRequest(), $this->company_uuid),
|
|
28
|
+
'created_by_uuid' => $this->when(Http::isInternalRequest(), $this->created_by_uuid),
|
|
29
|
+
'logo_uuid' => $this->when(Http::isInternalRequest(), $this->logo_uuid),
|
|
30
|
+
'backdrop_uuid' => $this->when(Http::isInternalRequest(), $this->backdrop_uuid),
|
|
31
|
+
'order_config_uuid' => $this->when(Http::isInternalRequest(), $this->order_config_uuid),
|
|
32
|
+
'name' => $this->name,
|
|
33
|
+
'description' => $this->description,
|
|
34
|
+
'translations' => $this->translations ?? [],
|
|
35
|
+
'website' => $this->website,
|
|
36
|
+
'facebook' => $this->facebook,
|
|
37
|
+
'instagram' => $this->instagram,
|
|
38
|
+
'twitter' => $this->twitter,
|
|
39
|
+
'email' => $this->email,
|
|
40
|
+
'phone' => $this->phone,
|
|
41
|
+
'tags' => $this->tags ?? [],
|
|
42
|
+
'currency' => $currency,
|
|
43
|
+
'country' => Utils::getCountryCodeByCurrency($currency, 'US'),
|
|
44
|
+
'options' => $this->formatOptions($this->options),
|
|
45
|
+
'logo_url' => $this->logo_url,
|
|
46
|
+
'backdrop_url' => $this->backdrop_url,
|
|
47
|
+
'rating' => $this->rating,
|
|
48
|
+
'online' => $this->online,
|
|
49
|
+
'alertable' => $this->alertable,
|
|
50
|
+
'is_network' => false,
|
|
51
|
+
'is_store' => true,
|
|
52
|
+
'category' => $this->when($request->filled('network') && ($request->has('with_category') || $request->inArray('with', 'category')), new Category($this->getNetworkCategoryUsingId($request->input('network')))),
|
|
53
|
+
'networks' => $this->when($request->boolean('with_networks') || $request->inArray('with', 'networks'), Network::collection($this->networks)),
|
|
54
|
+
'locations' => $this->when($request->boolean('with_locations') || $request->inArray('with', 'locations'), $this->locations->mapInto(StoreLocation::class)),
|
|
55
|
+
'media' => $this->when($request->boolean('with_media') || $request->inArray('with', 'media'), Media::collection($this->media)),
|
|
56
|
+
'slug' => $this->slug,
|
|
57
|
+
'created_at' => $this->created_at,
|
|
58
|
+
'updated_at' => $this->updated_at,
|
|
58
59
|
];
|
|
59
60
|
}
|
|
60
61
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
namespace Fleetbase\Storefront\Models;
|
|
4
4
|
|
|
5
5
|
use Fleetbase\FleetOps\Models\Contact;
|
|
6
|
+
use Fleetbase\FleetOps\Models\Order;
|
|
6
7
|
use Illuminate\Support\Str;
|
|
7
8
|
|
|
8
9
|
class Customer extends Contact
|
|
@@ -12,6 +13,22 @@ class Customer extends Contact
|
|
|
12
13
|
*/
|
|
13
14
|
protected string $payloadKey = 'customer';
|
|
14
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Boot the model.
|
|
18
|
+
*/
|
|
19
|
+
protected static function boot()
|
|
20
|
+
{
|
|
21
|
+
parent::boot();
|
|
22
|
+
|
|
23
|
+
static::creating(function ($model) {
|
|
24
|
+
$model->type = 'customer';
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
static::addGlobalScope('type', function ($builder) {
|
|
28
|
+
$builder->where('type', 'customer');
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
15
32
|
/**
|
|
16
33
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
|
17
34
|
*/
|
|
@@ -61,10 +78,9 @@ class Customer extends Contact
|
|
|
61
78
|
*/
|
|
62
79
|
public function countStorefrontOrdersFrom($id)
|
|
63
80
|
{
|
|
64
|
-
return
|
|
81
|
+
return Order::where(
|
|
65
82
|
[
|
|
66
83
|
'customer_uuid' => $this->uuid,
|
|
67
|
-
'type' => 'storefront',
|
|
68
84
|
'meta->storefront_id' => $id,
|
|
69
85
|
]
|
|
70
86
|
)->count();
|
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
namespace Fleetbase\Storefront\Models;
|
|
4
4
|
|
|
5
|
+
use Fleetbase\FleetOps\Models\Driver;
|
|
5
6
|
use Fleetbase\FleetOps\Models\ServiceArea;
|
|
6
7
|
use Fleetbase\FleetOps\Models\Vehicle;
|
|
7
8
|
use Fleetbase\FleetOps\Models\Zone;
|
|
9
|
+
use Fleetbase\LaravelMysqlSpatial\Types\Point;
|
|
8
10
|
use Fleetbase\Storefront\Http\Resources\FoodTruck as FoodTruckResource;
|
|
9
11
|
use Fleetbase\Traits\HasApiModelBehavior;
|
|
10
12
|
use Fleetbase\Traits\HasPublicid;
|
|
@@ -61,6 +63,13 @@ class FoodTruck extends StorefrontModel
|
|
|
61
63
|
'status',
|
|
62
64
|
];
|
|
63
65
|
|
|
66
|
+
/**
|
|
67
|
+
* Dynamic attributes that are appended to object.
|
|
68
|
+
*
|
|
69
|
+
* @var array
|
|
70
|
+
*/
|
|
71
|
+
protected $appends = ['location'];
|
|
72
|
+
|
|
64
73
|
/**
|
|
65
74
|
* Get the store that owns this food truck.
|
|
66
75
|
*/
|
|
@@ -171,12 +180,30 @@ class FoodTruck extends StorefrontModel
|
|
|
171
180
|
'subject_type' => get_class($this),
|
|
172
181
|
],
|
|
173
182
|
[
|
|
174
|
-
'company_uuid'
|
|
175
|
-
'created_by_uuid'=> session('user'),
|
|
183
|
+
'company_uuid' => $this->company_uuid,
|
|
184
|
+
'created_by_uuid' => session('user'),
|
|
176
185
|
]
|
|
177
186
|
);
|
|
178
187
|
}
|
|
179
188
|
|
|
180
189
|
return $this;
|
|
181
190
|
}
|
|
191
|
+
|
|
192
|
+
public function getLocationAttribute(): ?Point
|
|
193
|
+
{
|
|
194
|
+
$this->loadMissing('vehicle');
|
|
195
|
+
|
|
196
|
+
return $this->vehicle->location;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Get the driver assigned via the food truck relation.
|
|
201
|
+
*/
|
|
202
|
+
public function getDriverAssigned(): ?Driver
|
|
203
|
+
{
|
|
204
|
+
// Ensure both relations are present without re-querying if already loaded
|
|
205
|
+
$this->loadMissing('vehicle.driver');
|
|
206
|
+
|
|
207
|
+
return $this->vehicle?->driver;
|
|
208
|
+
}
|
|
182
209
|
}
|
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
namespace Fleetbase\Storefront\Models;
|
|
4
4
|
|
|
5
5
|
use Fleetbase\Casts\Json;
|
|
6
|
+
use Fleetbase\FleetOps\Models\OrderConfig;
|
|
6
7
|
use Fleetbase\FleetOps\Support\Utils;
|
|
7
8
|
use Fleetbase\Models\Category;
|
|
8
9
|
use Fleetbase\Models\Company;
|
|
9
10
|
use Fleetbase\Models\File;
|
|
10
11
|
use Fleetbase\Models\Invite;
|
|
11
12
|
use Fleetbase\Models\User;
|
|
13
|
+
use Fleetbase\Storefront\Support\Storefront;
|
|
12
14
|
use Fleetbase\Traits\HasApiModelBehavior;
|
|
13
15
|
use Fleetbase\Traits\HasOptionsAttributes;
|
|
14
16
|
use Fleetbase\Traits\HasPublicid;
|
|
@@ -53,7 +55,7 @@ class Network extends StorefrontModel
|
|
|
53
55
|
*
|
|
54
56
|
* @var array
|
|
55
57
|
*/
|
|
56
|
-
protected $fillable = ['created_by_uuid', 'company_uuid', 'logo_uuid', 'backdrop_uuid', 'key', 'online', 'name', 'description', 'website', 'facebook', 'instagram', 'twitter', 'email', 'phone', 'translations', 'tags', 'currency', 'timezone', 'pod_method', 'options', 'alertable', 'slug'];
|
|
58
|
+
protected $fillable = ['created_by_uuid', 'company_uuid', 'logo_uuid', 'backdrop_uuid', 'order_config_uuid', 'key', 'online', 'name', 'description', 'website', 'facebook', 'instagram', 'twitter', 'email', 'phone', 'translations', 'tags', 'currency', 'timezone', 'pod_method', 'options', 'alertable', 'slug'];
|
|
57
59
|
|
|
58
60
|
/**
|
|
59
61
|
* The attributes that should be cast to native types.
|
|
@@ -133,6 +135,14 @@ class Network extends StorefrontModel
|
|
|
133
135
|
return $this->setConnection(config('fleetbase.connection.db'))->belongsTo(File::class);
|
|
134
136
|
}
|
|
135
137
|
|
|
138
|
+
/**
|
|
139
|
+
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
140
|
+
*/
|
|
141
|
+
public function orderConfig()
|
|
142
|
+
{
|
|
143
|
+
return $this->setConnection(config('fleetbase.connection.db'))->belongsTo(OrderConfig::class);
|
|
144
|
+
}
|
|
145
|
+
|
|
136
146
|
/**
|
|
137
147
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
|
138
148
|
*/
|
|
@@ -287,4 +297,56 @@ class Network extends StorefrontModel
|
|
|
287
297
|
|
|
288
298
|
return $this->createCategory($name, $description, $meta, $translations, $parent, $icon, $iconColor);
|
|
289
299
|
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Get the effective OrderConfig for this model.
|
|
303
|
+
*
|
|
304
|
+
* Loads the related `orderConfig` if missing and returns it.
|
|
305
|
+
* If no specific config is set, it falls back to the global default
|
|
306
|
+
* and memoizes that default into the relation (no DB write; just the relation cache)
|
|
307
|
+
* to avoid repeat lookups in the same request lifecycle.
|
|
308
|
+
*
|
|
309
|
+
* @throws \RuntimeException if no default OrderConfig is available (should not happen in a healthy install)
|
|
310
|
+
*/
|
|
311
|
+
public function getOrderConfig(): OrderConfig
|
|
312
|
+
{
|
|
313
|
+
// Ensure relation is loaded once
|
|
314
|
+
$this->loadMissing('orderConfig');
|
|
315
|
+
|
|
316
|
+
if ($this->orderConfig instanceof OrderConfig) {
|
|
317
|
+
return $this->orderConfig;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// Fallback to default (must exist in your environment)
|
|
321
|
+
$default = Storefront::getDefaultOrderConfig();
|
|
322
|
+
|
|
323
|
+
if (!$default instanceof OrderConfig) {
|
|
324
|
+
// Keep your hard return type contract honest
|
|
325
|
+
throw new \RuntimeException('No default OrderConfig is configured.');
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Memoize the fallback in the in-memory relation to avoid repeated lookups
|
|
329
|
+
$this->setRelation('orderConfig', $default);
|
|
330
|
+
|
|
331
|
+
return $default;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Get the UUID of the effective OrderConfig for this model.
|
|
336
|
+
*
|
|
337
|
+
* Tries to use the local FK if present to avoid loading the relation;
|
|
338
|
+
* otherwise, resolves via getOrderConfig() (which memoizes).
|
|
339
|
+
*
|
|
340
|
+
* @return string non-empty UUID of the effective order config
|
|
341
|
+
*/
|
|
342
|
+
public function getOrderConfigId(): string
|
|
343
|
+
{
|
|
344
|
+
// Fast path: if the FK column is set, use it directly
|
|
345
|
+
if (!empty($this->order_config_uuid)) {
|
|
346
|
+
return (string) $this->order_config_uuid;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Otherwise rely on the resolved config (relation or default)
|
|
350
|
+
return (string) $this->getOrderConfig()->uuid;
|
|
351
|
+
}
|
|
290
352
|
}
|
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
namespace Fleetbase\Storefront\Models;
|
|
4
4
|
|
|
5
5
|
use Fleetbase\Casts\Json;
|
|
6
|
+
use Fleetbase\FleetOps\Models\OrderConfig;
|
|
6
7
|
use Fleetbase\FleetOps\Models\Place;
|
|
7
8
|
use Fleetbase\Models\Category;
|
|
8
9
|
use Fleetbase\Models\Company;
|
|
9
10
|
use Fleetbase\Models\File;
|
|
10
11
|
use Fleetbase\Models\User;
|
|
12
|
+
use Fleetbase\Storefront\Support\Storefront;
|
|
11
13
|
use Fleetbase\Support\Utils as FleetbaseUtils;
|
|
12
14
|
use Fleetbase\Traits\HasApiModelBehavior;
|
|
13
15
|
use Fleetbase\Traits\HasMetaAttributes;
|
|
@@ -56,7 +58,7 @@ class Store extends StorefrontModel
|
|
|
56
58
|
*
|
|
57
59
|
* @var array
|
|
58
60
|
*/
|
|
59
|
-
protected $fillable = ['created_by_uuid', 'company_uuid', 'logo_uuid', 'backdrop_uuid', 'key', 'online', 'name', 'description', 'translations', 'website', 'facebook', 'instagram', 'twitter', 'email', 'phone', 'tags', 'currency', 'meta', 'timezone', 'pod_method', 'options', 'alertable', 'slug'];
|
|
61
|
+
protected $fillable = ['created_by_uuid', 'company_uuid', 'logo_uuid', 'backdrop_uuid', 'order_config_uuid', 'key', 'online', 'name', 'description', 'translations', 'website', 'facebook', 'instagram', 'twitter', 'email', 'phone', 'tags', 'currency', 'meta', 'timezone', 'pod_method', 'options', 'alertable', 'slug'];
|
|
60
62
|
|
|
61
63
|
/**
|
|
62
64
|
* The attributes that should be cast to native types.
|
|
@@ -137,6 +139,22 @@ class Store extends StorefrontModel
|
|
|
137
139
|
return $this->setConnection(config('fleetbase.connection.db'))->belongsTo(File::class);
|
|
138
140
|
}
|
|
139
141
|
|
|
142
|
+
/**
|
|
143
|
+
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
144
|
+
*/
|
|
145
|
+
public function backdrop()
|
|
146
|
+
{
|
|
147
|
+
return $this->setConnection(config('fleetbase.connection.db'))->belongsTo(File::class);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
152
|
+
*/
|
|
153
|
+
public function orderConfig()
|
|
154
|
+
{
|
|
155
|
+
return $this->setConnection(config('fleetbase.connection.db'))->belongsTo(OrderConfig::class);
|
|
156
|
+
}
|
|
157
|
+
|
|
140
158
|
/**
|
|
141
159
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
|
142
160
|
*/
|
|
@@ -167,14 +185,6 @@ class Store extends StorefrontModel
|
|
|
167
185
|
)->where('type', 'storefront_store_media');
|
|
168
186
|
}
|
|
169
187
|
|
|
170
|
-
/**
|
|
171
|
-
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
172
|
-
*/
|
|
173
|
-
public function backdrop()
|
|
174
|
-
{
|
|
175
|
-
return $this->setConnection(config('fleetbase.connection.db'))->belongsTo(File::class);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
188
|
/**
|
|
179
189
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
180
190
|
*/
|
|
@@ -460,4 +470,56 @@ class Store extends StorefrontModel
|
|
|
460
470
|
|
|
461
471
|
return null;
|
|
462
472
|
}
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* Get the effective OrderConfig for this model.
|
|
476
|
+
*
|
|
477
|
+
* Loads the related `orderConfig` if missing and returns it.
|
|
478
|
+
* If no specific config is set, it falls back to the global default
|
|
479
|
+
* and memoizes that default into the relation (no DB write; just the relation cache)
|
|
480
|
+
* to avoid repeat lookups in the same request lifecycle.
|
|
481
|
+
*
|
|
482
|
+
* @throws \RuntimeException if no default OrderConfig is available (should not happen in a healthy install)
|
|
483
|
+
*/
|
|
484
|
+
public function getOrderConfig(): OrderConfig
|
|
485
|
+
{
|
|
486
|
+
// Ensure relation is loaded once
|
|
487
|
+
$this->loadMissing('orderConfig');
|
|
488
|
+
|
|
489
|
+
if ($this->orderConfig instanceof OrderConfig) {
|
|
490
|
+
return $this->orderConfig;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// Fallback to default (must exist in your environment)
|
|
494
|
+
$default = Storefront::getDefaultOrderConfig();
|
|
495
|
+
|
|
496
|
+
if (!$default instanceof OrderConfig) {
|
|
497
|
+
// Keep your hard return type contract honest
|
|
498
|
+
throw new \RuntimeException('No default OrderConfig is configured.');
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// Memoize the fallback in the in-memory relation to avoid repeated lookups
|
|
502
|
+
$this->setRelation('orderConfig', $default);
|
|
503
|
+
|
|
504
|
+
return $default;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Get the UUID of the effective OrderConfig for this model.
|
|
509
|
+
*
|
|
510
|
+
* Tries to use the local FK if present to avoid loading the relation;
|
|
511
|
+
* otherwise, resolves via getOrderConfig() (which memoizes).
|
|
512
|
+
*
|
|
513
|
+
* @return string non-empty UUID of the effective order config
|
|
514
|
+
*/
|
|
515
|
+
public function getOrderConfigId(): string
|
|
516
|
+
{
|
|
517
|
+
// Fast path: if the FK column is set, use it directly
|
|
518
|
+
if (!empty($this->order_config_uuid)) {
|
|
519
|
+
return (string) $this->order_config_uuid;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// Otherwise rely on the resolved config (relation or default)
|
|
523
|
+
return (string) $this->getOrderConfig()->uuid;
|
|
524
|
+
}
|
|
463
525
|
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\Storefront\Notifications;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\FleetOps\Models\Order;
|
|
6
|
+
use Fleetbase\Storefront\Models\Network;
|
|
7
|
+
use Fleetbase\Storefront\Models\Store;
|
|
8
|
+
use Fleetbase\Storefront\Support\PushNotification;
|
|
9
|
+
use Fleetbase\Storefront\Support\Storefront;
|
|
10
|
+
use Illuminate\Bus\Queueable;
|
|
11
|
+
use Illuminate\Notifications\Messages\MailMessage;
|
|
12
|
+
use Illuminate\Notifications\Notification;
|
|
13
|
+
use NotificationChannels\Apn\ApnChannel;
|
|
14
|
+
use NotificationChannels\Fcm\FcmChannel;
|
|
15
|
+
|
|
16
|
+
class StorefrontOrderAccepted extends Notification
|
|
17
|
+
{
|
|
18
|
+
use Queueable;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The order instance this notification is for.
|
|
22
|
+
*/
|
|
23
|
+
public Order $order;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The order instance this notification is for.
|
|
27
|
+
*/
|
|
28
|
+
public Store|Network $storefront;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The time the notification was sent.
|
|
32
|
+
*/
|
|
33
|
+
public string $sentAt;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The ID of the notification.
|
|
37
|
+
*/
|
|
38
|
+
public string $notificationId;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The notification subject.
|
|
42
|
+
*/
|
|
43
|
+
public string $subject;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The notification body.
|
|
47
|
+
*/
|
|
48
|
+
public string $body;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The notification order status.
|
|
52
|
+
*/
|
|
53
|
+
public string $status;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Create a new notification instance.
|
|
57
|
+
*
|
|
58
|
+
* @return void
|
|
59
|
+
*/
|
|
60
|
+
public function __construct(Order $order)
|
|
61
|
+
{
|
|
62
|
+
$this->order = $order;
|
|
63
|
+
$this->storefront = Storefront::findAbout($order->getMeta('storefront_id'));
|
|
64
|
+
$this->sentAt = now()->toDateTimeString();
|
|
65
|
+
$this->notificationId = uniqid('notification_');
|
|
66
|
+
|
|
67
|
+
$this->subject = 'Your order from ' . $this->storefront->name . ' has been accepted.';
|
|
68
|
+
$this->body = 'Your order was accepted.';
|
|
69
|
+
$this->status = 'order_accepted';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Get the notification's delivery channels.
|
|
74
|
+
*
|
|
75
|
+
* @return array
|
|
76
|
+
*/
|
|
77
|
+
public function via($notifiable): array
|
|
78
|
+
{
|
|
79
|
+
$channels = ['mail', 'database'];
|
|
80
|
+
|
|
81
|
+
if (Storefront::hasNotificationChannelConfigured($this->storefront, 'apn')) {
|
|
82
|
+
$channels[] = ApnChannel::class;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (Storefront::hasNotificationChannelConfigured($this->storefront, 'fcm')) {
|
|
86
|
+
$channels[] = FcmChannel::class;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return $channels;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Get the mail representation of the notification.
|
|
94
|
+
*
|
|
95
|
+
* @return MailMessage
|
|
96
|
+
*/
|
|
97
|
+
public function toMail($notifiable)
|
|
98
|
+
{
|
|
99
|
+
$message = (new MailMessage())
|
|
100
|
+
->subject($this->subject)
|
|
101
|
+
->line($this->body);
|
|
102
|
+
|
|
103
|
+
// $message->action('View Details', Utils::consoleUrl('', ['shift' => 'fleet-ops/orders/view/' . $this->order->public_id]));
|
|
104
|
+
|
|
105
|
+
return $message;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Get the firebase cloud message representation of the notification.
|
|
110
|
+
*
|
|
111
|
+
* @return \NotificationChannels\Fcm\FcmMessage
|
|
112
|
+
*/
|
|
113
|
+
public function toFcm($notifiable)
|
|
114
|
+
{
|
|
115
|
+
return PushNotification::createFcmMessage(
|
|
116
|
+
$this->order,
|
|
117
|
+
$this->subject,
|
|
118
|
+
$this->body,
|
|
119
|
+
$this->status,
|
|
120
|
+
$notifiable
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Get the apns message representation of the notification.
|
|
126
|
+
*
|
|
127
|
+
* @return \NotificationChannels\Apn\ApnMessage
|
|
128
|
+
*/
|
|
129
|
+
public function toApn($notifiable)
|
|
130
|
+
{
|
|
131
|
+
return PushNotification::createApnMessage(
|
|
132
|
+
$this->order,
|
|
133
|
+
$this->subject,
|
|
134
|
+
$this->body,
|
|
135
|
+
$this->status,
|
|
136
|
+
$notifiable
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Get the array representation of the notification.
|
|
142
|
+
*/
|
|
143
|
+
public function toArray($notifiable): array
|
|
144
|
+
{
|
|
145
|
+
$this->order->loadMissing(['customer', 'company']);
|
|
146
|
+
$customer = $this->order->customer;
|
|
147
|
+
$company = $this->order->company;
|
|
148
|
+
|
|
149
|
+
return [
|
|
150
|
+
'notifiable' => $notifiable->public_id,
|
|
151
|
+
'notification_id' => $this->notificationId,
|
|
152
|
+
'sent_at' => $this->sentAt,
|
|
153
|
+
'subject' => $this->subject,
|
|
154
|
+
'message' => $this->status,
|
|
155
|
+
'storefront' => $this->storefront->name,
|
|
156
|
+
'storefront_id' => $this->storefront->public_id,
|
|
157
|
+
'id' => $customer->public_id,
|
|
158
|
+
'email' => $customer->email,
|
|
159
|
+
'phone' => $customer->phone,
|
|
160
|
+
'companyId' => $company->public_id,
|
|
161
|
+
'company' => $company->name,
|
|
162
|
+
];
|
|
163
|
+
}
|
|
164
|
+
}
|
|
@@ -74,7 +74,17 @@ class StorefrontOrderCanceled extends Notification
|
|
|
74
74
|
*/
|
|
75
75
|
public function via($notifiable): array
|
|
76
76
|
{
|
|
77
|
-
|
|
77
|
+
$channels = ['mail', 'database'];
|
|
78
|
+
|
|
79
|
+
if (Storefront::hasNotificationChannelConfigured($this->storefront, 'apn')) {
|
|
80
|
+
$channels[] = ApnChannel::class;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (Storefront::hasNotificationChannelConfigured($this->storefront, 'fcm')) {
|
|
84
|
+
$channels[] = FcmChannel::class;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return $channels;
|
|
78
88
|
}
|
|
79
89
|
|
|
80
90
|
/**
|
|
@@ -74,7 +74,17 @@ class StorefrontOrderCompleted extends Notification
|
|
|
74
74
|
*/
|
|
75
75
|
public function via($notifiable): array
|
|
76
76
|
{
|
|
77
|
-
|
|
77
|
+
$channels = ['mail', 'database'];
|
|
78
|
+
|
|
79
|
+
if (Storefront::hasNotificationChannelConfigured($this->storefront, 'apn')) {
|
|
80
|
+
$channels[] = ApnChannel::class;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (Storefront::hasNotificationChannelConfigured($this->storefront, 'fcm')) {
|
|
84
|
+
$channels[] = FcmChannel::class;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return $channels;
|
|
78
88
|
}
|
|
79
89
|
|
|
80
90
|
/**
|
|
@@ -78,12 +78,20 @@ class StorefrontOrderDriverAssigned extends Notification
|
|
|
78
78
|
|
|
79
79
|
/**
|
|
80
80
|
* Get the notification's delivery channels.
|
|
81
|
-
*
|
|
82
|
-
* @return array
|
|
83
81
|
*/
|
|
84
|
-
public function via($notifiable)
|
|
82
|
+
public function via($notifiable): array
|
|
85
83
|
{
|
|
86
|
-
|
|
84
|
+
$channels = ['mail', 'database'];
|
|
85
|
+
|
|
86
|
+
if (Storefront::hasNotificationChannelConfigured($this->storefront, 'apn')) {
|
|
87
|
+
$channels[] = ApnChannel::class;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (Storefront::hasNotificationChannelConfigured($this->storefront, 'fcm')) {
|
|
91
|
+
$channels[] = FcmChannel::class;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return $channels;
|
|
87
95
|
}
|
|
88
96
|
|
|
89
97
|
/**
|
|
@@ -71,12 +71,20 @@ class StorefrontOrderEnroute extends Notification
|
|
|
71
71
|
|
|
72
72
|
/**
|
|
73
73
|
* Get the notification's delivery channels.
|
|
74
|
-
*
|
|
75
|
-
* @return array
|
|
76
74
|
*/
|
|
77
|
-
public function via($notifiable)
|
|
75
|
+
public function via($notifiable): array
|
|
78
76
|
{
|
|
79
|
-
|
|
77
|
+
$channels = ['mail', 'database'];
|
|
78
|
+
|
|
79
|
+
if (Storefront::hasNotificationChannelConfigured($this->storefront, 'apn')) {
|
|
80
|
+
$channels[] = ApnChannel::class;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (Storefront::hasNotificationChannelConfigured($this->storefront, 'fcm')) {
|
|
84
|
+
$channels[] = FcmChannel::class;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return $channels;
|
|
80
88
|
}
|
|
81
89
|
|
|
82
90
|
/**
|
|
@@ -84,12 +84,20 @@ class StorefrontOrderNearby extends Notification
|
|
|
84
84
|
|
|
85
85
|
/**
|
|
86
86
|
* Get the notification's delivery channels.
|
|
87
|
-
*
|
|
88
|
-
* @return array
|
|
89
87
|
*/
|
|
90
|
-
public function via($notifiable)
|
|
88
|
+
public function via($notifiable): array
|
|
91
89
|
{
|
|
92
|
-
|
|
90
|
+
$channels = ['mail', 'database'];
|
|
91
|
+
|
|
92
|
+
if (Storefront::hasNotificationChannelConfigured($this->storefront, 'apn')) {
|
|
93
|
+
$channels[] = ApnChannel::class;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (Storefront::hasNotificationChannelConfigured($this->storefront, 'fcm')) {
|
|
97
|
+
$channels[] = FcmChannel::class;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return $channels;
|
|
93
101
|
}
|
|
94
102
|
|
|
95
103
|
/**
|