@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.
Files changed (77) hide show
  1. package/addon/components/customer-panel/orders.hbs +2 -2
  2. package/addon/components/modals/create-gateway.hbs +33 -12
  3. package/addon/components/network-category-picker.js +1 -1
  4. package/addon/components/order-panel.hbs +1 -1
  5. package/addon/components/widget/customers.hbs +5 -2
  6. package/addon/components/widget/customers.js +14 -6
  7. package/addon/components/widget/orders.hbs +31 -10
  8. package/addon/components/widget/orders.js +7 -1
  9. package/addon/components/widget/storefront-key-metrics.js +2 -2
  10. package/addon/components/widget/storefront-metrics.hbs +11 -1
  11. package/addon/components/widget/storefront-metrics.js +103 -1
  12. package/addon/controllers/networks/index/network/index.js +2 -0
  13. package/addon/controllers/networks/index/network/stores.js +0 -1
  14. package/addon/controllers/products/index/category/new.js +13 -2
  15. package/addon/controllers/settings/gateways.js +6 -1
  16. package/addon/controllers/settings/index.js +1 -0
  17. package/addon/controllers/settings/notifications.js +4 -5
  18. package/addon/models/network.js +1 -0
  19. package/addon/models/store.js +1 -0
  20. package/addon/routes/networks/index/network/index.js +5 -0
  21. package/addon/routes/settings/index.js +5 -0
  22. package/addon/services/order-actions.js +31 -0
  23. package/addon/styles/storefront-engine.css +22 -0
  24. package/addon/templates/home.hbs +2 -2
  25. package/addon/templates/networks/index/network/index.hbs +21 -8
  26. package/addon/templates/networks/index/network/stores.hbs +8 -1
  27. package/addon/templates/products/index/category/new.hbs +149 -134
  28. package/addon/templates/settings/gateways.hbs +15 -4
  29. package/addon/templates/settings/index.hbs +13 -0
  30. package/addon/templates/settings/notifications.hbs +2 -2
  31. package/addon/utils/commerce-date-ranges.js +263 -0
  32. package/app/utils/commerce-date-ranges.js +1 -0
  33. package/composer.json +1 -1
  34. package/extension.json +1 -1
  35. package/package.json +4 -4
  36. package/server/migrations/2025_09_01_041353_add_default_order_config_column.php +110 -0
  37. package/server/src/Console/Commands/MigrateStripeSandboxCustomers.php +165 -0
  38. package/server/src/Expansions/OrderExpansion.php +43 -0
  39. package/server/src/Http/Controllers/NetworkController.php +1 -1
  40. package/server/src/Http/Controllers/OrderController.php +62 -9
  41. package/server/src/Http/Controllers/v1/CheckoutController.php +57 -48
  42. package/server/src/Http/Controllers/v1/ServiceQuoteController.php +19 -3
  43. package/server/src/Http/Middleware/SetStorefrontSession.php +8 -6
  44. package/server/src/Http/Resources/Customer.php +41 -17
  45. package/server/src/Http/Resources/Gateway.php +16 -11
  46. package/server/src/Http/Resources/Network.php +35 -34
  47. package/server/src/Http/Resources/NotificationChannel.php +17 -10
  48. package/server/src/Http/Resources/Product.php +1 -0
  49. package/server/src/Http/Resources/Store.php +36 -35
  50. package/server/src/Models/Customer.php +18 -2
  51. package/server/src/Models/FoodTruck.php +29 -2
  52. package/server/src/Models/Network.php +63 -1
  53. package/server/src/Models/Store.php +71 -9
  54. package/server/src/Notifications/StorefrontOrderAccepted.php +164 -0
  55. package/server/src/Notifications/StorefrontOrderCanceled.php +11 -1
  56. package/server/src/Notifications/StorefrontOrderCompleted.php +11 -1
  57. package/server/src/Notifications/StorefrontOrderDriverAssigned.php +12 -4
  58. package/server/src/Notifications/StorefrontOrderEnroute.php +12 -4
  59. package/server/src/Notifications/StorefrontOrderNearby.php +12 -4
  60. package/server/src/Notifications/StorefrontOrderPreparing.php +12 -4
  61. package/server/src/Notifications/StorefrontOrderReadyForPickup.php +12 -4
  62. package/server/src/Observers/OrderObserver.php +6 -4
  63. package/server/src/Providers/StorefrontServiceProvider.php +1 -0
  64. package/server/src/Rules/IsValidLocation.php +12 -0
  65. package/server/src/Support/PushNotification.php +20 -4
  66. package/server/src/Support/Storefront.php +283 -37
  67. package/server/src/routes.php +1 -0
  68. package/translations/{ar-ae.yml → ar-ae.yaml} +313 -253
  69. package/translations/bg-bg.yaml +734 -0
  70. package/translations/en-us.yaml +5 -0
  71. package/translations/es-es.yaml +732 -0
  72. package/translations/fr-fr.yaml +748 -0
  73. package/translations/mn-mn.yaml +725 -0
  74. package/translations/pt-br.yaml +732 -0
  75. package/translations/ru-ru.yaml +726 -0
  76. package/translations/vi-vn.yaml +412 -338
  77. 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' => $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
- 'name' => $this->name,
32
- 'description' => $this->description,
33
- 'translations' => $this->translations ?? [],
34
- 'website' => $this->website,
35
- 'facebook' => $this->facebook,
36
- 'instagram' => $this->instagram,
37
- 'twitter' => $this->twitter,
38
- 'email' => $this->email,
39
- 'phone' => $this->phone,
40
- 'tags' => $this->tags ?? [],
41
- 'currency' => $currency,
42
- 'country' => Utils::getCountryCodeByCurrency($currency, 'US'),
43
- 'options' => $this->formatOptions($this->options),
44
- 'logo_url' => $this->logo_url,
45
- 'backdrop_url' => $this->backdrop_url,
46
- 'rating' => $this->rating,
47
- 'online' => $this->online,
48
- 'alertable' => $this->alertable,
49
- 'is_network' => false,
50
- 'is_store' => true,
51
- 'category' => $this->when($request->filled('network') && ($request->has('with_category') || $request->inArray('with', 'category')), new Category($this->getNetworkCategoryUsingId($request->input('network')))),
52
- 'networks' => $this->when($request->boolean('with_networks') || $request->inArray('with', 'networks'), Network::collection($this->networks)),
53
- 'locations' => $this->when($request->boolean('with_locations') || $request->inArray('with', 'locations'), $this->locations->mapInto(StoreLocation::class)),
54
- 'media' => $this->when($request->boolean('with_media') || $request->inArray('with', 'media'), Media::collection($this->media)),
55
- 'slug' => $this->slug,
56
- 'created_at' => $this->created_at,
57
- 'updated_at' => $this->updated_at,
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 \Fleetbase\FleetOps\Models\Order::where(
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' => $this->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
- return ['mail', 'database', FcmChannel::class, ApnChannel::class];
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
- return ['mail', 'database', FcmChannel::class, ApnChannel::class];
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
- return ['mail', 'database', FcmChannel::class, ApnChannel::class];
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
- return ['mail', 'database', FcmChannel::class, ApnChannel::class];
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
- return ['mail', 'database', FcmChannel::class, ApnChannel::class];
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
  /**