@fleetbase/storefront-engine 0.4.1 → 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 (32) hide show
  1. package/addon/components/widget/orders.hbs +1 -1
  2. package/addon/controllers/products/index/category/new.js +13 -2
  3. package/addon/controllers/settings/notifications.js +1 -0
  4. package/addon/templates/home.hbs +2 -2
  5. package/addon/templates/networks/index/network/index.hbs +8 -8
  6. package/addon/templates/products/index/category/new.hbs +149 -134
  7. package/composer.json +1 -1
  8. package/extension.json +1 -1
  9. package/package.json +4 -4
  10. package/server/src/Console/Commands/MigrateStripeSandboxCustomers.php +15 -0
  11. package/server/src/Http/Controllers/v1/CheckoutController.php +12 -0
  12. package/server/src/Http/Resources/Product.php +1 -0
  13. package/server/src/Models/FoodTruck.php +14 -2
  14. package/server/src/Notifications/StorefrontOrderAccepted.php +12 -2
  15. package/server/src/Notifications/StorefrontOrderCanceled.php +11 -1
  16. package/server/src/Notifications/StorefrontOrderCompleted.php +11 -1
  17. package/server/src/Notifications/StorefrontOrderDriverAssigned.php +12 -4
  18. package/server/src/Notifications/StorefrontOrderEnroute.php +12 -4
  19. package/server/src/Notifications/StorefrontOrderNearby.php +12 -4
  20. package/server/src/Notifications/StorefrontOrderPreparing.php +12 -4
  21. package/server/src/Notifications/StorefrontOrderReadyForPickup.php +12 -4
  22. package/server/src/Support/PushNotification.php +9 -2
  23. package/server/src/Support/Storefront.php +85 -1
  24. package/translations/{ar-ae.yml → ar-ae.yaml} +313 -253
  25. package/translations/bg-bg.yaml +734 -0
  26. package/translations/es-es.yaml +732 -0
  27. package/translations/fr-fr.yaml +748 -0
  28. package/translations/mn-mn.yaml +725 -0
  29. package/translations/pt-br.yaml +732 -0
  30. package/translations/ru-ru.yaml +726 -0
  31. package/translations/vi-vn.yaml +412 -338
  32. package/translations/zh-cn.yaml +659 -0
@@ -74,9 +74,19 @@ class StorefrontOrderAccepted extends Notification
74
74
  *
75
75
  * @return array
76
76
  */
77
- public function via($notifiable)
77
+ public function via($notifiable): array
78
78
  {
79
- return ['mail', 'database', FcmChannel::class, ApnChannel::class];
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;
80
90
  }
81
91
 
82
92
  /**
@@ -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
  /**
@@ -71,12 +71,20 @@ class StorefrontOrderPreparing 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
  /**
@@ -71,12 +71,20 @@ class StorefrontOrderReadyForPickup 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
  /**
@@ -22,7 +22,8 @@ class PushNotification
22
22
  $storefront = static::getStorefrontFromOrder($order);
23
23
  $client = static::getApnClient($storefront, $order);
24
24
  if (!$client) {
25
- return null;
25
+ // create apn message anyway
26
+ return new ApnMessage($title, $body);
26
27
  }
27
28
 
28
29
  return ApnMessage::create()
@@ -41,7 +42,13 @@ class PushNotification
41
42
  $storefront = static::getStorefrontFromOrder($order);
42
43
  $notificationChannel = static::getNotificationChannel('apn', $storefront, $order);
43
44
  if (!$notificationChannel) {
44
- return null;
45
+ // create fcm message anyway
46
+ return new FcmMessage(
47
+ notification: new FcmNotification(
48
+ title: $title,
49
+ body: $body
50
+ )
51
+ );
45
52
  }
46
53
 
47
54
  // Configure FCM
@@ -10,6 +10,7 @@ use Fleetbase\Models\Company;
10
10
  use Fleetbase\Models\User;
11
11
  use Fleetbase\Storefront\Models\Gateway;
12
12
  use Fleetbase\Storefront\Models\Network;
13
+ use Fleetbase\Storefront\Models\NotificationChannel;
13
14
  use Fleetbase\Storefront\Models\Product;
14
15
  use Fleetbase\Storefront\Models\Store;
15
16
  use Fleetbase\Storefront\Notifications\StorefrontOrderAccepted;
@@ -602,7 +603,7 @@ class Storefront
602
603
  $order->setStatus($activity->code);
603
604
  $order->insertActivity($activity, $order->getLastLocation());
604
605
  } catch (\Exception $e) {
605
- Log::debug('[Storefront] was able to accept an order.', ['order' => $order, 'activity' => $activity]);
606
+ Log::debug('[Storefront] was unable to accept an order.', ['order' => $order, 'activity' => $activity]);
606
607
 
607
608
  return response()->error('Unable to accept order.');
608
609
  }
@@ -645,4 +646,87 @@ class Storefront
645
646
 
646
647
  return $order;
647
648
  }
649
+
650
+ /**
651
+ * Determine whether the given Store or Network has a configured notification channel.
652
+ *
653
+ * Accepts either a model instance (Store|Network) or an identifier string.
654
+ * When a string is provided, this method attempts to resolve it in the following order:
655
+ * 1) UUID → `where('uuid', $id)`
656
+ * 2) public_id → `where('public_id', $id)` (if your models use a public_id column)
657
+ *
658
+ * If resolution fails, the method returns false.
659
+ *
660
+ * @param Store|\Fleetbase\FleetOps\Models\Network|string|null $subject
661
+ * Store/Network model instance or identifier (uuid/public_id)
662
+ * @param string $channel Channel scheme/key (e.g., "email", "sms", "fcm").
663
+ *
664
+ * @return bool true if a NotificationChannel exists for the subject and scheme; otherwise false
665
+ *
666
+ * @example
667
+ * YourClass::hasNotificationChannelConfigures($store, 'email');
668
+ * YourClass::hasNotificationChannelConfigures($networkUuid, 'fcm');
669
+ * YourClass::hasNotificationChannelConfigures('STO-12345', 'sms'); // public_id example
670
+ *
671
+ * @note The method name appears to have a typo; consider renaming to:
672
+ * hasNotificationChannelConfigured() and keeping this as a BC alias.
673
+ */
674
+ public static function hasNotificationChannelConfigured(Store|Network|string|null $subject, string $channel): bool
675
+ {
676
+ $model = self::resolveSubjectToModel($subject);
677
+
678
+ if (!$model) {
679
+ return false;
680
+ }
681
+
682
+ return NotificationChannel::query()
683
+ ->where('owner_uuid', $model->uuid)
684
+ ->where('scheme', $channel)
685
+ ->exists();
686
+ }
687
+
688
+ /**
689
+ * Resolve the provided subject into a Store or Network model.
690
+ *
691
+ * Attempts resolution by uuid first, then by public_id (if present).
692
+ * Returns null if no matching model can be found.
693
+ *
694
+ * @param Store|\Fleetbase\FleetOps\Models\Network|string|null $subject
695
+ *
696
+ * @return Store|\Fleetbase\FleetOps\Models\Network|null
697
+ */
698
+ protected static function resolveSubjectToModel(Store|Network|string|null $subject): Store|Network|null
699
+ {
700
+ if ($subject instanceof Store || $subject instanceof Network) {
701
+ return $subject;
702
+ }
703
+
704
+ if (!is_string($subject) || $subject === '') {
705
+ return null;
706
+ }
707
+
708
+ // Try UUID
709
+ if (Str::isUuid($subject)) {
710
+ if ($found = Store::query()->where('uuid', $subject)->first()) {
711
+ return $found;
712
+ }
713
+ if ($found = Network::query()->where('uuid', $subject)->first()) {
714
+ return $found;
715
+ }
716
+ }
717
+
718
+ // Try public_id (optional; remove if you don't use it)
719
+ if (property_exists(Store::class, 'public_id') || Schema::hasColumn((new Store())->getTable(), 'public_id')) {
720
+ if ($found = Store::query()->where('public_id', $subject)->first()) {
721
+ return $found;
722
+ }
723
+ }
724
+ if (property_exists(Network::class, 'public_id') || Schema::hasColumn((new Network())->getTable(), 'public_id')) {
725
+ if ($found = Network::query()->where('public_id', $subject)->first()) {
726
+ return $found;
727
+ }
728
+ }
729
+
730
+ return null;
731
+ }
648
732
  }