diff --git a/app/Listeners/BusinessUpdateListener.php b/app/Listeners/BusinessUpdateListener.php index 3ef51cb..b9f280f 100644 --- a/app/Listeners/BusinessUpdateListener.php +++ b/app/Listeners/BusinessUpdateListener.php @@ -5,12 +5,13 @@ namespace App\Listeners; use App\Models\User; use App\Models\Business; use Illuminate\Support\Arr; +use App\Channels\FcmChannel; use App\Events\BusinessUpdate; use App\Events\BusinessUserCreate; use App\Notifications\DBNotification; +use App\Notifications\FcmNotification; use App\Notifications\MailNotification; use Illuminate\Queue\InteractsWithQueue; - use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Support\Facades\Notification; @@ -19,14 +20,68 @@ class BusinessUpdateListener public function handle(BusinessUpdate $event) { $payload = $event->message; + $business = Business::findOrFail($payload->business)->load('owners'); + + $this->checkWalletIsRunningLow($business); + $this->checkWalletIsEmptyOrNegative($business); + $this->accountHasBeenSuspended($business); + } + + public function checkWalletIsRunningLow(Business $business): void + { + $moving_average_days = 7; + $predict_ahead_hours = 24; + + $hours = $moving_average_days * 24; + $business->load([ + 'cost' => fn ($query) => $query->where('created_at', '>=', now('Asia/Tehran')->subHours($hours)), + ]); + + // The wallet is running out + // Calculate the average consumption of the N past days + $average_cost = $business->cost->sum('cost') / $hours; + + // Average hourly consumption multiplied by the next 24 hours + // If the account does not charge as much as in the next 24 hours, notified. + $message = ['body' => __('notification.business.wallet_almost_empty')]; + if (($business->wallet / $predict_ahead_hours) < $average_cost) { + Notification::send($business->owners, new MailNotification($message)); + Notification::send($business->owners, new DBNotification($message)); + } + } + + public function checkWalletIsEmptyOrNegative(Business $business): void + { + $message = ['body' => __('notification.business.wallet_empty')]; + if ($business->wallet <= 0) { + Notification::send($business->owners, new MailNotification($message)); + Notification::send($business->owners, new DBNotification($message)); + } + } + + public function accountHasBeenSuspended(Business $business): void + { + if ($business->wallet > 0) { + return; + } + + $recent_payments_number = 10; + $negativity_threshold = 20; + $business->load([ + 'transactions' => fn ($query) => $query->where('succeeded', '=', true) + ->orderBy('created_at') + ->take($recent_payments_number), + ]); - $wallet = $payload?->data?->diff?->wallet; - $owners = Business::findOrFail($payload->business)->owners; - $message = ['body' => 'Test']; + // Your account has been blocked. + // What is the average of the last 10 payments? + $average_payment = $business->transactions->average('amount'); - if ($wallet < 0) { - Notification::send($owners, new MailNotification($message)); - Notification::send($owners, new DBNotification($message)); + $threshold = $average_payment / 100 * $negativity_threshold; + $message = ['body' => __('notification.business.suspended')]; + if ($business->wallet < $threshold) { + Notification::send($business->owners, new MailNotification($message)); + Notification::send($business->owners, new DBNotification($message)); } } } diff --git a/app/Models/Business.php b/app/Models/Business.php index dc03aef..ad38198 100644 --- a/app/Models/Business.php +++ b/app/Models/Business.php @@ -43,6 +43,7 @@ class Business extends Model implements HasMedia protected $casts = [ 'has_avatar' => 'boolean', 'calculated_at' => 'datetime', + 'wallet' => 'integer', ]; public function getValueOf(?string $key) diff --git a/resources/lang/fa/notification.php b/resources/lang/fa/notification.php index 1ef6303..740602e 100644 --- a/resources/lang/fa/notification.php +++ b/resources/lang/fa/notification.php @@ -37,7 +37,9 @@ return [ 'business' => [ 'update' => 'کاربر :user به کسب و کار :business اضافه شد.', - 'update_wallet' => 'پول رو میدی یا پولت کنم', + 'wallet_almost_empty' => 'کیف پول تقریبا خالی است.', + 'wallet_empty' => 'کیف پول خالی است.', + 'suspended' => 'حساب مسدود شد.', ], ];