0, 400 => 1000, 800 => 2000, ]; protected $signature = 'cost:work'; protected $description = 'Run the cost worker'; public function __construct() { parent::__construct(); } public function handle() { while (true) { $business = Business::find(221); if ($business === null) { continue; } $year = jdate()->getYear(); $month = jdate()->getMonth(); $day = jdate()->getDay(); $hour = jdate()->getHour(); $minute = jdate()->getMinute(); $second = jdate()->getSecond(); if (jdate()->getYear() > jdate($business->calculated_at)->getYear()) { $year = jdate()->getYear(); $month = 1; $day = 1; } if ( jdate()->getYear() > jdate($business->calculated_at)->getYear() && jdate()->getMonth() > jdate($business->calculated_at)->getMonth() ) { $year = jdate()->getYear(); $month = jdate()->getMonth(); $day = 1; } $gDate = CalendarUtils::toGregorian($year, $month, $day); $carbon = Carbon::createFromDate($gDate[0], $gDate[1], $gDate[2]); $carbon->setTime($hour, $minute, $second); $now = $carbon; // if calculated_at less than an hour stop if ($now->diffInMinutes($business->calculated_at)) { $this->info('Must be one hour after the last audit.'); continue; } try { DB::beginTransaction(); // Fixed amounts of expenses $business->load('users', 'cost'); $costs = 0; $costs += $this->calculateCostOfBusinessUsers($business, $now); $costs += $this->calculateCostOfBusinessFiles($business, $now); // 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::now(), ]); DB::commit(); } catch (Throwable $throwable) { DB::rollback(); report($throwable); continue; } } } public function calculateCostOfBusinessUsers($business, $until_now) { $user_fee = enum('business.fee.user'); $calculated_at = $business->calculated_at; $recorded_month = jdate($business->calculated_at)->format("Y-m-01"); // 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) + $users_cost->duration, // last calc - (current month - now else last calc - end of the past month), 'additional' => $business->users->pluck('id')->toArray(), ]); } return $user_fee * $duration; } public function calculateCostOfBusinessFiles($business, $until_now) { $file_fee = enum('business.fee.file'); $calculated_at = $business->calculated_at; $recorded_month = jdate($business->calculated_at)->format("Y-m-01"); // do the math in php if (intdiv($business->files_volume, 200) === 0) { $pads = 0; } else { $pads = intdiv($business->files_volume, 200) - 1; } $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) + $files->duration, // last calc - (current month - now else last calc - end of the past month),, ]); } return $file_fee * $duration; } }