@ -2,9 +2,12 @@
namespace App\Console\Commands ;
namespace App\Console\Commands ;
use DB ;
use Throwable ;
use Carbon\Carbon ;
use App\Models\Business ;
use App\Models\Business ;
use Illuminate\Console\Command ;
use Illuminate\Console\Command ;
use Morilog\Jalali\CalendarUtils ;
use Illuminate\Support\Facades\DB ;
use Illuminate\Support\Facades\Cache ;
use Illuminate\Support\Facades\Cache ;
class CostCommand extends Command
class CostCommand extends Command
@ -28,109 +31,143 @@ class CostCommand extends Command
public function handle ()
public function handle ()
{
{
// infinte loop
while ( true ) {
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 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 ;
continue ;
}
}
try {
try {
DB :: beginTransaction ();
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
// increment and decrement of wallet in php
// deduct costs from your business wallet
// deduct costs from your business wallet
// 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\ Carbon:: now (),
'calculated_at' => Carbon :: now (),
]);
]);
DB :: commit ();
DB :: commit ();
} catch ( Throwable $thr ) {
} catch ( Throwable $throwable ) {
DB :: rollback ();
DB :: rollback ();
throw $thr ;
report ( $throwable );
continue ;
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 ;
}
}
}