0, 400 => 1000, 800 => 2000, ]; protected $signature = 'cost:work'; protected $description = 'Run the cost worker'; public function __construct() { parent::__construct(); } public function handle() { // infinte loop while (true) { // to baghali ha $recorded_month = jdate($business->calculated_at)->format("Y-m-01"); $calculated_at = Cache::get('calculated_at'); if ($calculated_at === null) { $business = Business::orderBy('calculated_at')->first()->load('users', 'cost'); $calculated_at = $business->calculated_at; $until_now = jdate()->getMonth() > jdate($business->calculated_at)->getMonth() ? jdate($business->calculated_at)->toCarbon()->setTime("00", "00", "00") : \Carbon\Carbon::now(); Cache::put('calculated_at', $until_now, 60); } // if calculated_at less than an hour stop if (\Carbon\Carbon::now()->diffInMinutes($until_now) <= 60) { $this->info('nothing to cost'); continue; } try { DB::beginTransaction(); // business order by last_calculated_at take first if (!isset($business)) { $business = Business::orderBy('calculated_at')->first()->load('users', 'cost'); } $user_fee = enum('business.fee.user'); // get business employee $users_cost = $business->cost ->where('type', '=', 'users') ->where('fee', '=', $user_fee) ->where('month', '=', $recorded_month) ->where('amount', '=', $business->users->count()) ->first(); if ($users_cost === null) { $business->cost()->create([ 'type' => 'users', 'month' => $recorded_month, 'amount' => $business->users->count(), 'fee' => $user_fee, 'duration' => $duration = $until_now->diffInSeconds($calculated_at), // from the created_at time of the newset fifth user 'additional' => $business->users->pluck('id')->toArray(), ]); } else { $users_cost->update([ 'duration' => $duration = $until_now->diffInMinutes($calculated_at), // last calc - (current month - now else last calc - end of the past month), 'additional' => $business->users->pluck('id')->toArray(), ]); } $costs = $user_fee * $duration; // do the math in php if (intdiv($business->files_volume, 200) === 0) { $pads = 0; } else { $pads = intdiv($business->files_volume, 200) - 1; } $file_fee = enum('business.fee.file'); $files = $business->cost ->where('type', '=', 'files') ->where('fee', '=', $file_fee) ->where('month', '=', $recorded_month) ->where('amount', '=', $business->files_volume) ->first(); if ($files === null) { $business->cost()->create([ 'type' => 'files', 'month' => $recorded_month, 'amount' => $pads, 'fee' => $file_fee, 'duration' => $duration = $until_now->diffInMinutes($calculated_at), // how to determine the file?, ]); } else { $files->update([ 'duration' => $duration = $until_now->diffInMinutes($calculated_at), // last calc - (current month - now else last calc - end of the past month),, ]); } $costs += $file_fee * $duration; // increment and decrement of wallet in php // deduct costs from your business wallet // make sure save the calculated_at $business->update([ 'wallet' => $business->wallet - $costs, 'calculated_at' => \Carbon\Carbon::now(), ]); DB::commit(); } catch (Throwable $thr) { DB::rollback(); throw $thr; continue; } } } }