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.

81 lines
2.9 KiB

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