@ -4,78 +4,60 @@ namespace App\Console\Commands;
use Throwable ;
use Throwable ;
use Carbon\Carbon ;
use Carbon\Carbon ;
use App\Models\Cost ;
use App\Models\Business ;
use App\Models\Business ;
use Illuminate\Console\Command ;
use Illuminate\Console\Command ;
use Morilog\Jalali\CalendarUtils ;
use Morilog\Jalali\CalendarUtils ;
use Illuminate\Support\Facades\DB ;
use Illuminate\Support\Facades\DB ;
use Illuminate\Support\Facades\Cache ;
use Illuminate\Support\Facades\Cache ;
use Illuminate\Support\Facades\Storage ;
class CostCommand extends Command
class CostCommand extends Command
{
{
public const USER_FEE = 400 ;
public const FILE_FEE = [
200 => 0 ,
400 => 1000 ,
800 => 2000 ,
];
protected $signature = 'cost:work' ;
protected $signature = 'cost:work' ;
protected $description = 'Run the cost worker' ;
protected $description = 'Run the cost worker' ;
public function __construct ()
{
parent :: __construct ();
}
public function handle ()
public function handle ()
{
{
while ( true ) {
while ( true ) {
$business = Business :: find ( 221 );
if ( $business === null ) {
$lock = Cache :: get ( 'lock' , false );
if ( $lock ) {
$this -> info ( 'There is no business for auditing.' );
continue ;
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 ;
$business = Business :: orderBy ( 'calculated_at' ) -> first ();
if ( $business === null ) {
continue ;
}
}
if (
jdate () -> getYear () > jdate ( $business -> calculated_at ) -> getYear ()
&&
jdate () -> getMonth () > jdate ( $business -> calculated_at ) -> getMonth ()
) {
$year = jdate () -> getYear ();
$month = jdate () -> getMonth ();
$day = 1 ;
if ( $business -> calculated_at -> isFuture ()) {
continue ;
}
}
$gDate = CalendarUtils :: toGregorian ( $year , $month , $day );
$carbon = Carbon :: createFromDate ( $gDate [ 0 ], $gDate [ 1 ], $gDate [ 2 ]);
$carbon -> setTime ( $hour , $minute , $second );
$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 );
$now = $carbon ;
if ( $now -> isFuture ()) {
$now = Carbon :: now ();
}
// if calculated_at less than an hour stop
// if calculated_at less than an hour stop
if ( $now -> diffInMinutes ( $business -> calculated_at )) {
if ( $now -> diffInMinutes ( $business -> calculated_at ) <= 59 ) {
$this -> info ( 'Must be one hour after the last audit.' );
$this -> info ( 'Must be one hour after the last audit.' );
Cache :: put ( 'lock' , true , $now -> diffInSeconds ( $business -> calculated_at ));
continue ;
continue ;
}
}
try {
try {
DB :: beginTransaction ();
DB :: beginTransaction ();
// Fixed amounts of expenses
// Fixed amounts of expenses
$business -> load ( 'users' , 'cost ' );
$business -> load ( 'users' , 'files ' );
$costs = 0 ;
$costs = 0 ;
$costs += $this -> calculateCostOfBusinessUsers ( $business , $now );
$costs += $this -> calculateCostOfBusinessUsers ( $business , $now );
@ -86,11 +68,13 @@ class CostCommand extends Command
// make sure save the calculated_at
// make sure save the calculated_at
$business -> update ([
$business -> update ([
'wallet' => $business -> wallet - $costs ,
'wallet' => $business -> wallet - $costs ,
'calculated_at' => Carbon :: now () ,
'calculated_at' => $now ,
]);
]);
DB :: commit ();
DB :: commit ();
$this -> info ( " The business # { $business -> id } was audited. " );
} catch ( Throwable $throwable ) {
} catch ( Throwable $throwable ) {
throw $throwable ;
DB :: rollback ();
DB :: rollback ();
report ( $throwable );
report ( $throwable );
continue ;
continue ;
@ -98,16 +82,18 @@ class CostCommand extends Command
}
}
}
}
public function calculateCostOfBusinessUsers ( $business , $until_ now )
public function calculateCostOfBusinessUsers ( $business , $now )
{
{
$user_fee = enum ( 'business.fee.user' );
$user_fee = enum ( 'business.fee.user' );
$calculated_at = $business -> calculated_at ;
$recorded_month = jdate ( $business -> calculated_at ) -> format ( " Y-m-01 " );
$recorded_month = jdate ( $business -> calculated_at ) -> format ( " Y-m-01 " );
if ( $business -> users -> isEmpty ()) {
return 0 ;
}
// get business employee
// get business employee
$users_cost = $business -> cost
$users_cost = $business -> cost
-> where ( 'type' , '=' , 'users' )
-> where ( 'type' , '=' , Cost :: USER_TYPE )
-> where ( 'fee' , '=' , $user_fee )
-> where ( 'fee' , '=' , $user_fee )
-> where ( 'month' , '=' , $recorded_month )
-> where ( 'month' , '=' , $recorded_month )
-> where ( 'amount' , '=' , $business -> users -> count ())
-> where ( 'amount' , '=' , $business -> users -> count ())
@ -115,16 +101,16 @@ class CostCommand extends Command
if ( $users_cost === null ) {
if ( $users_cost === null ) {
$business -> cost () -> create ([
$business -> cost () -> create ([
'type' => 'users' ,
'type' => Cost :: USER_TYPE ,
'month' => $recorded_month ,
'month' => $recorded_month ,
'amount' => $business -> users -> count (),
'amount' => $business -> users -> count (),
'fee' => $user_fee ,
'fee' => $user_fee ,
'duration' => $duration = $until_ now -> diffInSecond s ( $calculated_at ), // from the created_at time of the newset fifth user
'duration' => $duration = $now -> diffInMinute s ( $business -> calculated_at ), // from the created_at time of the newset fifth user
'additional' => $business -> users -> pluck ( 'id' ) -> toArray (),
'additional' => $business -> users -> pluck ( 'id' ) -> toArray (),
]);
]);
} else {
} else {
$users_cost -> update ([
$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),
'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 (),
'additional' => $business -> users -> pluck ( 'id' ) -> toArray (),
]);
]);
}
}
@ -132,7 +118,7 @@ class CostCommand extends Command
return $user_fee * $duration ;
return $user_fee * $duration ;
}
}
public function calculateCostOfBusinessFiles ( $business , $until_ now )
public function calculateCostOfBusinessFiles ( $business , $now )
{
{
$file_fee = enum ( 'business.fee.file' );
$file_fee = enum ( 'business.fee.file' );
$calculated_at = $business -> calculated_at ;
$calculated_at = $business -> calculated_at ;
@ -140,31 +126,33 @@ class CostCommand extends Command
// do the math in php
// do the math in php
if ( intdiv ( $business -> files_volume , 200 ) === 0 ) {
$pads = 0 ;
$packs = intdiv ( $business -> files_volume , 200 );
if ( $packs === 0 ) {
return 0 ;
} else {
} else {
$pads = intdiv ( $business -> files_volume , 200 ) - 1 ;
$packs -- ;
}
}
$files = $business -> cost
$files = $business -> cost
-> where ( 'type' , '=' , 'files' )
-> where ( 'type' , '=' , Cost :: FILE_TYPE )
-> where ( 'fee' , '=' , $file_fee )
-> where ( 'fee' , '=' , $file_fee )
-> where ( 'month' , '=' , $recorded_month )
-> where ( 'month' , '=' , $recorded_month )
-> where ( 'amount' , '=' , $business -> files_volume )
-> where ( 'amount' , '=' , $packs )
-> first ();
-> first ();
if ( $files === null ) {
if ( $files === null ) {
$business -> cost () -> create ([
$business -> cost () -> create ([
'type' => 'files' ,
'type' => Cost :: FILE_TYPE ,
'month' => $recorded_month ,
'month' => $recorded_month ,
'amount' => $pad s ,
'amount' => $pack s ,
'fee' => $file_fee ,
'fee' => $file_fee ,
'duration' => $duration = $until_now -> diffInMinutes ( $calculated_at ), // how to determine the file?,
'duration' => $duration = $now -> diffInMinutes ( $calculated_at ), // how to determine the file?,
'additional' => [ 'volume' => $business -> files_volume ],
]);
]);
} else {
} else {
$files -> update ([
$files -> update ([
'duration' => $duration = $until_now -> diffInMinutes ( $calculated_at ) + $files -> duration , // last calc - (current month - now else last calc - end of the past month),,
'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 ],
]);
]);
}
}