diff --git a/app/Console/Commands/CostCommand.php b/app/Console/Commands/CostCommand.php index 99a9db5..9845050 100644 --- a/app/Console/Commands/CostCommand.php +++ b/app/Console/Commands/CostCommand.php @@ -2,9 +2,12 @@ namespace App\Console\Commands; -use DB; +use Throwable; +use Carbon\Carbon; use App\Models\Business; use Illuminate\Console\Command; +use Morilog\Jalali\CalendarUtils; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Cache; class CostCommand extends Command @@ -28,109 +31,143 @@ class CostCommand extends Command 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); + $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 (\Carbon\Carbon::now()->diffInMinutes($until_now) <= 60) { - $this->info('nothing to cost'); + 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'); - // 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; + $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\Carbon::now(), + 'calculated_at' => Carbon::now(), ]); + DB::commit(); - } catch (Throwable $thr) { + } catch (Throwable $throwable) { DB::rollback(); - throw $thr; + 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; + } } diff --git a/config/app.php b/config/app.php index 7f44ebe..d517cdc 100644 --- a/config/app.php +++ b/config/app.php @@ -12,7 +12,7 @@ return [ 'asset_url' => env('ASSET_URL', null), - 'timezone' => 'UTC', + 'timezone' => 'Asia/Tehran', 'locale' => 'fa', diff --git a/database/factories/BusinessFactory.php b/database/factories/BusinessFactory.php index f8dab3d..28f0dae 100644 --- a/database/factories/BusinessFactory.php +++ b/database/factories/BusinessFactory.php @@ -12,6 +12,6 @@ $factory->define(Business::class, function (Faker $faker) { 'slug' => Str::slug($name) . $faker->numberBetween(1, 100), 'wallet' => random_int(111111, 999999), 'color' => $faker->colorName, - 'calculated_at' => \Carbon\Carbon::now()->subMinutes(random_int(1, 1000)), + 'calculated_at' => \Carbon\Carbon::now()->subDays(random_int(1, 31)), ]; }); diff --git a/database/migrations/2020_08_18_085018_create_businesses_table.php b/database/migrations/2020_08_18_085018_create_businesses_table.php index e37d713..b0d168f 100644 --- a/database/migrations/2020_08_18_085018_create_businesses_table.php +++ b/database/migrations/2020_08_18_085018_create_businesses_table.php @@ -23,7 +23,7 @@ class CreateBusinessesTable extends Migration $table->string('description')->nullable(); $table->json('cache')->nullable(); $table->boolean('has_avatar')->default(false); - $table->timestamp('calculated_at')->nullable(); + $table->timestamp('calculated_at')->nullable()->index(); $table->timestamp('created_at')->nullable(); $table->timestamp('updated_at')->nullable(); $table->timestamp('deleted_at')->nullable();