You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

161 lines
5.4 KiB

<?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.');
Cache::put('lock', true, $now->diffInSeconds($business->calculated_at));
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;
}
}