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.

173 lines
5.5 KiB

  1. <?php
  2. namespace App\Console\Commands;
  3. use Throwable;
  4. use Carbon\Carbon;
  5. use App\Models\Business;
  6. use Illuminate\Console\Command;
  7. use Morilog\Jalali\CalendarUtils;
  8. use Illuminate\Support\Facades\DB;
  9. use Illuminate\Support\Facades\Cache;
  10. class CostCommand extends Command
  11. {
  12. public const USER_FEE = 400;
  13. public const FILE_FEE = [
  14. 200 => 0,
  15. 400 => 1000,
  16. 800 => 2000,
  17. ];
  18. protected $signature = 'cost:work';
  19. protected $description = 'Run the cost worker';
  20. public function __construct()
  21. {
  22. parent::__construct();
  23. }
  24. public function handle()
  25. {
  26. while (true) {
  27. $business = Business::find(221);
  28. if ($business === null) {
  29. continue;
  30. }
  31. $year = jdate()->getYear();
  32. $month = jdate()->getMonth();
  33. $day = jdate()->getDay();
  34. $hour = jdate()->getHour();
  35. $minute = jdate()->getMinute();
  36. $second = jdate()->getSecond();
  37. if (jdate()->getYear() > jdate($business->calculated_at)->getYear()) {
  38. $year = jdate()->getYear();
  39. $month = 1;
  40. $day = 1;
  41. }
  42. if (
  43. jdate()->getYear() > jdate($business->calculated_at)->getYear()
  44. &&
  45. jdate()->getMonth() > jdate($business->calculated_at)->getMonth()
  46. ) {
  47. $year = jdate()->getYear();
  48. $month = jdate()->getMonth();
  49. $day = 1;
  50. }
  51. $gDate = CalendarUtils::toGregorian($year, $month, $day);
  52. $carbon = Carbon::createFromDate($gDate[0], $gDate[1], $gDate[2]);
  53. $carbon->setTime($hour, $minute, $second);
  54. $now = $carbon;
  55. // if calculated_at less than an hour stop
  56. if ($now->diffInMinutes($business->calculated_at)) {
  57. $this->info('Must be one hour after the last audit.');
  58. continue;
  59. }
  60. try {
  61. DB::beginTransaction();
  62. // Fixed amounts of expenses
  63. $business->load('users', 'cost');
  64. $costs = 0;
  65. $costs += $this->calculateCostOfBusinessUsers($business, $now);
  66. $costs += $this->calculateCostOfBusinessFiles($business, $now);
  67. // increment and decrement of wallet in php
  68. // deduct costs from your business wallet
  69. // make sure save the calculated_at
  70. $business->update([
  71. 'wallet' => $business->wallet - $costs,
  72. 'calculated_at' => Carbon::now(),
  73. ]);
  74. DB::commit();
  75. } catch (Throwable $throwable) {
  76. DB::rollback();
  77. report($throwable);
  78. continue;
  79. }
  80. }
  81. }
  82. public function calculateCostOfBusinessUsers($business, $until_now)
  83. {
  84. $user_fee = enum('business.fee.user');
  85. $calculated_at = $business->calculated_at;
  86. $recorded_month = jdate($business->calculated_at)->format("Y-m-01");
  87. // get business employee
  88. $users_cost = $business->cost
  89. ->where('type', '=', 'users')
  90. ->where('fee', '=', $user_fee)
  91. ->where('month', '=', $recorded_month)
  92. ->where('amount', '=', $business->users->count())
  93. ->first();
  94. if ($users_cost === null) {
  95. $business->cost()->create([
  96. 'type' => 'users',
  97. 'month' => $recorded_month,
  98. 'amount' => $business->users->count(),
  99. 'fee' => $user_fee,
  100. 'duration' => $duration = $until_now->diffInSeconds($calculated_at), // from the created_at time of the newset fifth user
  101. 'additional' => $business->users->pluck('id')->toArray(),
  102. ]);
  103. } else {
  104. $users_cost->update([
  105. 'duration' => $duration = $until_now->diffInMinutes($calculated_at) + $users_cost->duration, // last calc - (current month - now else last calc - end of the past month),
  106. 'additional' => $business->users->pluck('id')->toArray(),
  107. ]);
  108. }
  109. return $user_fee * $duration;
  110. }
  111. public function calculateCostOfBusinessFiles($business, $until_now)
  112. {
  113. $file_fee = enum('business.fee.file');
  114. $calculated_at = $business->calculated_at;
  115. $recorded_month = jdate($business->calculated_at)->format("Y-m-01");
  116. // do the math in php
  117. if (intdiv($business->files_volume, 200) === 0) {
  118. $pads = 0;
  119. } else {
  120. $pads = intdiv($business->files_volume, 200) - 1;
  121. }
  122. $files = $business->cost
  123. ->where('type', '=', 'files')
  124. ->where('fee', '=', $file_fee)
  125. ->where('month', '=', $recorded_month)
  126. ->where('amount', '=', $business->files_volume)
  127. ->first();
  128. if ($files === null) {
  129. $business->cost()->create([
  130. 'type' => 'files',
  131. 'month' => $recorded_month,
  132. 'amount' => $pads,
  133. 'fee' => $file_fee,
  134. 'duration' => $duration = $until_now->diffInMinutes($calculated_at), // how to determine the file?,
  135. ]);
  136. } else {
  137. $files->update([
  138. 'duration' => $duration = $until_now->diffInMinutes($calculated_at) + $files->duration, // last calc - (current month - now else last calc - end of the past month),,
  139. ]);
  140. }
  141. return $file_fee * $duration;
  142. }
  143. }