|
|
<?php
namespace App\Console\Commands;
use Throwable; use Carbon\Carbon; use App\Models\Cost; use App\Models\Business; use Illuminate\Console\Command; use Morilog\Jalali\CalendarUtils; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Storage;
class CostCommand extends Command { protected $signature = 'cost:work';
protected $description = 'Run the cost worker';
public function handle() { while (true) { $lock = Cache::get('lock', false); if ($lock) { $this->info('There is no business for auditing.'); continue; }
$business = Business::orderBy('calculated_at')->first(); if ($business === null) { continue; }
if ($business->calculated_at->isFuture()) { continue; }
$next_month = jdate($business->calculated_at)->addMonths(); [$year, $month, $day] = CalendarUtils::toGregorian( $next_month->getYear(), $next_month->getMonth(), 1 ); $now = Carbon::createFromDate($year, $month, $day); $now->setTime(0, 0, 0);
if ($now->isFuture()) { $now = Carbon::now(); }
// if calculated_at less than an hour stop
if ($now->diffInMinutes($business->calculated_at) <= 59) { $this->info('Must be one hour after the last audit.'); $this->ensureLockIsWritten(); continue; }
try { DB::beginTransaction(); // Fixed amounts of expenses
$business->load('users', 'files');
$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' => $now, ]);
DB::commit(); $this->info("The business #{$business->id} was audited."); } catch (Throwable $throwable) { throw $throwable; DB::rollback(); report($throwable); continue; } } }
public function calculateCostOfBusinessUsers($business, $now) { $user_fee = enum('business.fee.user'); $recorded_month = jdate($business->calculated_at)->format("Y-m-01");
if ($business->users->isEmpty()) { return 0; }
// get business employee
$users_cost = $business->cost ->where('type', '=', Cost::USER_TYPE) ->where('fee', '=', $user_fee) ->where('month', '=', $recorded_month) ->where('amount', '=', $business->users->count()) ->first();
if ($users_cost === null) { $business->cost()->create([ 'type' => Cost::USER_TYPE, 'month' => $recorded_month, 'amount' => $business->users->count(), 'fee' => $user_fee, 'duration' => $duration = $now->diffInMinutes($business->calculated_at), // from the created_at time of the newset fifth user
'additional' => $business->users->pluck('id')->toArray(), ]); } else { $users_cost->update([ 'duration' => $duration = $now->diffInMinutes($business->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, $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
$packs = intdiv($business->files_volume, 200); if ($packs === 0) { return 0; } else { $packs--; }
$files = $business->cost ->where('type', '=', Cost::FILE_TYPE) ->where('fee', '=', $file_fee) ->where('month', '=', $recorded_month) ->where('amount', '=', $packs) ->first();
if ($files === null) { $business->cost()->create([ 'type' => Cost::FILE_TYPE, 'month' => $recorded_month, 'amount' => $packs, 'fee' => $file_fee, 'duration' => $duration = $now->diffInMinutes($calculated_at), // how to determine the file?,
'additional' => ['volume' => $business->files_volume], ]); } else { $files->update([ 'duration' => $duration = $now->diffInMinutes($calculated_at) + $files->duration, // last calc - (current month - now else last calc - end of the past month),,
'additional' => ['volume' => $business->files_volume], ]); }
return $file_fee * $duration; }
public function ensureLockIsWritten(): void { Cache::put('lock', true, 3600); while (Cache::get('lock', false) === false) { // prevent
} } }
|