You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

87 lines
3.1 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. <?php
  2. namespace App\Listeners;
  3. use App\Models\User;
  4. use App\Models\Business;
  5. use Illuminate\Support\Arr;
  6. use App\Channels\FcmChannel;
  7. use App\Events\BusinessUpdate;
  8. use App\Events\BusinessUserCreate;
  9. use App\Notifications\DBNotification;
  10. use App\Notifications\FcmNotification;
  11. use App\Notifications\MailNotification;
  12. use Illuminate\Queue\InteractsWithQueue;
  13. use Illuminate\Contracts\Queue\ShouldQueue;
  14. use Illuminate\Support\Facades\Notification;
  15. class BusinessUpdateListener
  16. {
  17. public function handle(BusinessUpdate $event)
  18. {
  19. $payload = $event->message;
  20. $business = Business::findOrFail($payload->business)->load('owners');
  21. $this->checkWalletIsRunningLow($business);
  22. $this->checkWalletIsEmptyOrNegative($business);
  23. $this->accountHasBeenSuspended($business);
  24. }
  25. public function checkWalletIsRunningLow(Business $business): void
  26. {
  27. $moving_average_days = 7;
  28. $predict_ahead_hours = 24;
  29. $hours = $moving_average_days * 24;
  30. $business->load([
  31. 'cost' => fn ($query) => $query->where('created_at', '>=', now('Asia/Tehran')->subHours($hours)),
  32. ]);
  33. // The wallet is running out
  34. // Calculate the average consumption of the N past days
  35. $average_cost = $business->cost->sum('cost') / $hours;
  36. // Average hourly consumption multiplied by the next 24 hours
  37. // If the account does not charge as much as in the next 24 hours, notified.
  38. $message = ['body' => __('notification.business.wallet_almost_empty')];
  39. if (($business->wallet / $predict_ahead_hours) < $average_cost) {
  40. Notification::send($business->owners, new MailNotification($message));
  41. Notification::send($business->owners, new DBNotification($message));
  42. }
  43. }
  44. public function checkWalletIsEmptyOrNegative(Business $business): void
  45. {
  46. $message = ['body' => __('notification.business.wallet_empty')];
  47. if ($business->wallet <= 0) {
  48. Notification::send($business->owners, new MailNotification($message));
  49. Notification::send($business->owners, new DBNotification($message));
  50. }
  51. }
  52. public function accountHasBeenSuspended(Business $business): void
  53. {
  54. if ($business->wallet > 0) {
  55. return;
  56. }
  57. $recent_payments_number = 10;
  58. $negativity_threshold = 20;
  59. $business->load([
  60. 'transactions' => fn ($query) => $query->where('succeeded', '=', true)
  61. ->orderBy('created_at')
  62. ->take($recent_payments_number),
  63. ]);
  64. // Your account has been blocked.
  65. // What is the average of the last 10 payments?
  66. $average_payment = $business->transactions->average('amount');
  67. $threshold = $average_payment / 100 * $negativity_threshold;
  68. $message = ['body' => __('notification.business.suspended')];
  69. if ($business->wallet < $threshold) {
  70. Notification::send($business->owners, new MailNotification($message));
  71. Notification::send($business->owners, new DBNotification($message));
  72. }
  73. }
  74. }