Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

ArsenMK's avatar

laravel artisan command workin uncorrect

this is my Commands.CalculateMonthlyPayments.php

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use App\Models\Project;
use App\Models\Finance;
use Carbon\Carbon;

class CalculateMonthlyPayments extends Command
{
    protected $signature = 'calculate:monthly-payments';
    protected $description = 'Calculate monthly payments for projects and save them in the finances table';

    public function __construct()
    {
        parent::__construct();
    }

    public function handle()
    {
        $projects = Project::with('price')->whereNotNull('paymanagir_start')->get();

        foreach ($projects as $project) {
            $paymanagirStart = Carbon::parse($project->paymanagir_start);
            $paymanagirEnd = $project->paymanagir_end ? Carbon::parse($project->paymanagir_end) : null;

            $this->calculateMonthlyPayments($project, $paymanagirStart, $paymanagirEnd);
        }
    }

    protected function calculateMonthlyPayments($project, $start, $end)
    {
        $currentDate = Carbon::now();
        $endDate = $end ? $end->copy()->endOfMonth() : $currentDate->copy()->subMonth()->endOfMonth();

        // Loop through each month from start to end date or one month before the current date
        for ($date = $start->copy()->startOfMonth(); $date->lessThanOrEqualTo($endDate); $date->addMonth()) {
            $startOfMonth = $date->copy()->startOfMonth();
            $endOfMonth = $date->copy()->endOfMonth();

            if ($date->month == $start->month && $date->year == $start->year) {
                $startOfMonth = $start;
            }

            if ($end && $date->month == $end->month && $date->year == $end->year) {
                $endOfMonth = $end;
            }

            // Only process complete months
            if ($endOfMonth->greaterThan($currentDate->subMonth()->endOfMonth())) {
                continue;
            }

            $daysInPeriod = $startOfMonth->diffInDays($endOfMonth) + 1;
            $pricePerDay = $project->price->amount / $date->daysInMonth;
            $payment = $pricePerDay * $daysInPeriod;

            Finance::create([
                'project_id' => $project->id,
                'mouth' => $date->format('F'),
                'payment' => round($payment, 2),
            ]);
        }
    }
}


and this is my routes.console.php

<?php

use Illuminate\Foundation\Inspiring;
use Illuminate\Support\Facades\Artisan;

use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use Illuminate\Support\Facades\Schedule;
Artisan::command('inspire', function () {
    $this->comment(Inspiring::quote());
})->purpose('Display an inspiring quote')->hourly();

Schedule::command('calculate:monthly-payments')->monthlyOn(1, '00:00');

i have project which id =2 which price_id=2 whose price = 7000

I manually change the date(for testing) from the computer (currently June 22) manually set October 1

and after in command line write this php artisan calculate:monthly-payments after my finance table updating and it was designed to work like this

Pseudocode for Calculations


July:
paymanagir_start: July 22.
Days in July: 31.
Days from July 22 to July 31: 10 days.
Daily amount: 7000 / 31 ≈ 225.81.
Total amount for 10 days: 225.81 * 10 ≈ 2258.06.

August:
Full month (31 days).
Daily amount: 7000 / 31 ≈ 225.81.
Total amount for August: 225.81 * 31 = 7000.

September:
Full month (30 days).
Daily amount: 7000 / 30 ≈ 233.33.
Total amount for September: 233.33 * 30 = 7000.
October (up to October 1):

Since October 1 is the current date, we do not include October in the calculation as it is not yet completed.

and table

| **id** | **project_id** | **mouth** | **payment** | **created_at**      | **updated_at**      |
| ------ | -------------- | --------- | ----------- | ------------------- | ------------------- |
| 1      | 3              | July      | 2258.06     | 2024-07-31 00:00:00 | 2024-07-31 00:00:00 |
| 2      | 3              | August    | 7000        | 2024-08-31 00:00:00 | 2024-08-31 00:00:00 |
| 3      | 3              | September | 7000        | 2024-09-30 00:00:00 | 2024-09-30 00:00:00 |

BUT when i set date manually october 1 adn write in command line php artisan calculate:monthly-payments my finances table is like this

| id | project_id | mouth |  payment | created_at   | updated_at |
|----|--------------|-----------|--------------|-----------------|---------------------|
| 37 | 3 | July      | 3387.1  | 2024-10-01 00:45:09 | 2024-10-01 00:45:09 |
| 38 | 3 | August    | 7225.81 | 2024-10-01 00:45:09 | 2024-10-01 00:45:09 |
| 39 | 3 | September | 7233.33 | 2024-10-01 00:45:09 | 2024-10-01 00:45:09 |
| 40 | 3 | October   | 232.89  | 2024-10-01 00:45:09 | 2024-10-01 00:45:09 |

why my base save this not what i need to be saved and sorry for english

0 likes
9 replies
Tray2's avatar

What does your data look like and what is the expected result?

It looks to me that you should be able to let the database do all the calculations for you, instead of using php to process it.

1 like
ArsenMK's avatar

@Tray2 the calculation should be done on its own every month on the first day without my intervention

Tray2's avatar

@ArsenMK So?

You create a command that runs a query in the database to generate the data needed.

Basically

INSERT INTO monthly calculation
SELECT MONTH(CURRENT_DATE), company_id , SUM(payment) 
WHERE MONTH(created_at) =   MONTH(CURRENT_DATE - INTERVAL 1 MONTH )
GROUP BY 1, company_id;

Might need some tweaking.

ArsenMK's avatar

@Tray2 i need this

| **id** | **project_id** | **mouth** | **payment** | **created_at**      | **updated_at**      |
| ------ | -------------- | --------- | ----------- | ------------------- | ------------------- |
| 1      | 3              | July      | 2258.06     | 2024-07-31 00:00:00 | 2024-07-31 00:00:00 |
| 2      | 3              | August    | 7000        | 2024-08-31 00:00:00 | 2024-08-31 00:00:00 |
| 3      | 3              | September | 7000        | 2024-09-30 00:00:00 | 2024-09-30 00:00:00 |

but i have this

| id | project_id | mouth |  payment | created_at   | updated_at |
|----|--------------|-----------|--------------|-----------------|---------------------|
| 37 | 3 | July      | 3387.1  | 2024-10-01 00:45:09 | 2024-10-01 00:45:09 |
| 38 | 3 | August    | 7225.81 | 2024-10-01 00:45:09 | 2024-10-01 00:45:09 |
| 39 | 3 | September | 7233.33 | 2024-10-01 00:45:09 | 2024-10-01 00:45:09 |
| 40 | 3 | October   | 232.89  | 2024-10-01 00:45:09 | 2024-10-01 00:45:09 |

in paper my code need to do the first variant but it does the second i want to know why

Snapey's avatar

You have not explained what the problem is?

ArsenMK's avatar

@Snapey i need this

| **id** | **project_id** | **mouth** | **payment** | **created_at**      | **updated_at**      |
| ------ | -------------- | --------- | ----------- | ------------------- | ------------------- |
| 1      | 3              | July      | 2258.06     | 2024-07-31 00:00:00 | 2024-07-31 00:00:00 |
| 2      | 3              | August    | 7000        | 2024-08-31 00:00:00 | 2024-08-31 00:00:00 |
| 3      | 3              | September | 7000        | 2024-09-30 00:00:00 | 2024-09-30 00:00:00 |

but i have this

| id | project_id | mouth |  payment | created_at   | updated_at |
|----|--------------|-----------|--------------|-----------------|---------------------|
| 37 | 3 | July      | 3387.1  | 2024-10-01 00:45:09 | 2024-10-01 00:45:09 |
| 38 | 3 | August    | 7225.81 | 2024-10-01 00:45:09 | 2024-10-01 00:45:09 |
| 39 | 3 | September | 7233.33 | 2024-10-01 00:45:09 | 2024-10-01 00:45:09 |
| 40 | 3 | October   | 232.89  | 2024-10-01 00:45:09 | 2024-10-01 00:45:09 |
Snapey's avatar

by the way, "mouth" is the hole in your face, not part of a year

ArsenMK's avatar

I found the problem, $daysInPeriod = $startOfMonth->diffInDays($endOfMonth) +1; I changed it to this $daysInPeriod = $startOfMonth->diffInDays($endOfMonth); and in my database paymanagir_start was set to July 18 not 22)) and thanks to wew for the help

Please or to participate in this conversation.