mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-11-04 02:47:34 -05:00 
			
		
		
		
	Merge pull request #8428 from turbo124/v5-develop
Add updated calculated fields cron
This commit is contained in:
		
						commit
						fb48fbf69e
					
				@ -15,6 +15,7 @@ use App\Jobs\Cron\AutoBillCron;
 | 
				
			|||||||
use App\Jobs\Cron\RecurringExpensesCron;
 | 
					use App\Jobs\Cron\RecurringExpensesCron;
 | 
				
			||||||
use App\Jobs\Cron\RecurringInvoicesCron;
 | 
					use App\Jobs\Cron\RecurringInvoicesCron;
 | 
				
			||||||
use App\Jobs\Cron\SubscriptionCron;
 | 
					use App\Jobs\Cron\SubscriptionCron;
 | 
				
			||||||
 | 
					use App\Jobs\Cron\UpdateCalculatedFields;
 | 
				
			||||||
use App\Jobs\Invoice\InvoiceCheckLateWebhook;
 | 
					use App\Jobs\Invoice\InvoiceCheckLateWebhook;
 | 
				
			||||||
use App\Jobs\Ninja\AdjustEmailQuota;
 | 
					use App\Jobs\Ninja\AdjustEmailQuota;
 | 
				
			||||||
use App\Jobs\Ninja\BankTransactionSync;
 | 
					use App\Jobs\Ninja\BankTransactionSync;
 | 
				
			||||||
@ -47,14 +48,23 @@ class Kernel extends ConsoleKernel
 | 
				
			|||||||
        /* Check for the latest version of Invoice Ninja */
 | 
					        /* Check for the latest version of Invoice Ninja */
 | 
				
			||||||
        $schedule->job(new VersionCheck)->daily();
 | 
					        $schedule->job(new VersionCheck)->daily();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Checks and cleans redundant files */
 | 
					        /* Returns the number of jobs in the queue */
 | 
				
			||||||
        $schedule->job(new DiskCleanup)->dailyAt('02:10')->withoutOverlapping()->name('disk-cleanup-job')->onOneServer();
 | 
					        $schedule->job(new QueueSize)->everyFiveMinutes()->withoutOverlapping()->name('queue-size-job')->onOneServer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Send reminders */
 | 
					        /* Send reminders */
 | 
				
			||||||
        $schedule->job(new ReminderJob)->hourly()->withoutOverlapping()->name('reminder-job')->onOneServer();
 | 
					        $schedule->job(new ReminderJob)->hourly()->withoutOverlapping()->name('reminder-job')->onOneServer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Returns the number of jobs in the queue */
 | 
					        /* Sends recurring invoices*/
 | 
				
			||||||
        $schedule->job(new QueueSize)->everyFiveMinutes()->withoutOverlapping()->name('queue-size-job')->onOneServer();
 | 
					        $schedule->job(new RecurringInvoicesCron)->hourly()->withoutOverlapping()->name('recurring-invoice-job')->onOneServer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Checks for scheduled tasks */
 | 
				
			||||||
 | 
					        $schedule->job(new TaskScheduler())->hourlyAt(10)->withoutOverlapping()->name('task-scheduler-job')->onOneServer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Stale Invoice Cleanup*/
 | 
				
			||||||
 | 
					        $schedule->job(new CleanStaleInvoiceOrder)->hourlyAt(30)->withoutOverlapping()->name('stale-invoice-job')->onOneServer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Stale Invoice Cleanup*/
 | 
				
			||||||
 | 
					        $schedule->job(new UpdateCalculatedFields)->hourlyAt(40)->withoutOverlapping()->name('update-calculated-fields-job')->onOneServer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Checks for large companies and marked them as is_large */
 | 
					        /* Checks for large companies and marked them as is_large */
 | 
				
			||||||
        $schedule->job(new CompanySizeCheck)->dailyAt('23:20')->withoutOverlapping()->name('company-size-job')->onOneServer();
 | 
					        $schedule->job(new CompanySizeCheck)->dailyAt('23:20')->withoutOverlapping()->name('company-size-job')->onOneServer();
 | 
				
			||||||
@ -65,33 +75,26 @@ class Kernel extends ConsoleKernel
 | 
				
			|||||||
        /* Runs cleanup code for subscriptions */
 | 
					        /* Runs cleanup code for subscriptions */
 | 
				
			||||||
        $schedule->job(new SubscriptionCron)->dailyAt('00:01')->withoutOverlapping()->name('subscription-job')->onOneServer();
 | 
					        $schedule->job(new SubscriptionCron)->dailyAt('00:01')->withoutOverlapping()->name('subscription-job')->onOneServer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Sends recurring invoices*/
 | 
					 | 
				
			||||||
        $schedule->job(new RecurringInvoicesCron)->hourly()->withoutOverlapping()->name('recurring-invoice-job')->onOneServer();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* Stale Invoice Cleanup*/
 | 
					 | 
				
			||||||
        $schedule->job(new CleanStaleInvoiceOrder)->hourlyAt(30)->withoutOverlapping()->name('stale-invoice-job')->onOneServer();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* Sends recurring invoices*/
 | 
					        /* Sends recurring invoices*/
 | 
				
			||||||
        $schedule->job(new RecurringExpensesCron)->dailyAt('00:10')->withoutOverlapping()->name('recurring-expense-job')->onOneServer();
 | 
					        $schedule->job(new RecurringExpensesCron)->dailyAt('00:10')->withoutOverlapping()->name('recurring-expense-job')->onOneServer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Fires notifications for expired Quotes */
 | 
					 | 
				
			||||||
        $schedule->job(new QuoteCheckExpired)->dailyAt('05:10')->withoutOverlapping()->name('quote-expired-job')->onOneServer();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* Fires webhooks for overdue Invoice */
 | 
					 | 
				
			||||||
        $schedule->job(new InvoiceCheckLateWebhook)->dailyAt('07:00')->withoutOverlapping()->name('invoice-overdue-job')->onOneServer();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* Performs auto billing */
 | 
					 | 
				
			||||||
        $schedule->job(new AutoBillCron)->dailyAt('06:20')->withoutOverlapping()->name('auto-bill-job')->onOneServer();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* Checks the status of the scheduler */
 | 
					        /* Checks the status of the scheduler */
 | 
				
			||||||
        $schedule->job(new SchedulerCheck)->dailyAt('01:10')->withoutOverlapping();
 | 
					        $schedule->job(new SchedulerCheck)->dailyAt('01:10')->withoutOverlapping();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Checks for scheduled tasks */
 | 
					        /* Checks and cleans redundant files */
 | 
				
			||||||
        $schedule->job(new TaskScheduler())->hourlyAt(10)->withoutOverlapping()->name('task-scheduler-job')->onOneServer();
 | 
					        $schedule->job(new DiskCleanup)->dailyAt('02:10')->withoutOverlapping()->name('disk-cleanup-job')->onOneServer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Performs system maintenance such as pruning the backup table */
 | 
					        /* Performs system maintenance such as pruning the backup table */
 | 
				
			||||||
        $schedule->job(new SystemMaintenance)->sundays()->at('02:30')->withoutOverlapping()->name('system-maintenance-job')->onOneServer();
 | 
					        $schedule->job(new SystemMaintenance)->sundays()->at('02:30')->withoutOverlapping()->name('system-maintenance-job')->onOneServer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Fires notifications for expired Quotes */
 | 
				
			||||||
 | 
					        $schedule->job(new QuoteCheckExpired)->dailyAt('05:10')->withoutOverlapping()->name('quote-expired-job')->onOneServer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Performs auto billing */
 | 
				
			||||||
 | 
					        $schedule->job(new AutoBillCron)->dailyAt('06:20')->withoutOverlapping()->name('auto-bill-job')->onOneServer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Fires webhooks for overdue Invoice */
 | 
				
			||||||
 | 
					        $schedule->job(new InvoiceCheckLateWebhook)->dailyAt('07:00')->withoutOverlapping()->name('invoice-overdue-job')->onOneServer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (Ninja::isSelfHost()) {
 | 
					        if (Ninja::isSelfHost()) {
 | 
				
			||||||
            $schedule->call(function () {
 | 
					            $schedule->call(function () {
 | 
				
			||||||
@ -106,9 +109,6 @@ class Kernel extends ConsoleKernel
 | 
				
			|||||||
            /* Pulls in bank transactions from third party services */
 | 
					            /* Pulls in bank transactions from third party services */
 | 
				
			||||||
            $schedule->job(new BankTransactionSync)->dailyAt('04:10')->withoutOverlapping()->name('bank-trans-sync-job')->onOneServer();
 | 
					            $schedule->job(new BankTransactionSync)->dailyAt('04:10')->withoutOverlapping()->name('bank-trans-sync-job')->onOneServer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            //not used @deprecate
 | 
					 | 
				
			||||||
            // $schedule->job(new SendFailedEmails)->daily()->withoutOverlapping();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $schedule->command('ninja:check-data --database=db-ninja-01')->dailyAt('02:10')->withoutOverlapping()->name('check-data-db-1-job')->onOneServer();
 | 
					            $schedule->command('ninja:check-data --database=db-ninja-01')->dailyAt('02:10')->withoutOverlapping()->name('check-data-db-1-job')->onOneServer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $schedule->command('ninja:check-data --database=db-ninja-02')->dailyAt('02:20')->withoutOverlapping()->name('check-data-db-2-job')->onOneServer();
 | 
					            $schedule->command('ninja:check-data --database=db-ninja-02')->dailyAt('02:20')->withoutOverlapping()->name('check-data-db-2-job')->onOneServer();
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										96
									
								
								app/Jobs/Cron/UpdateCalculatedFields.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								app/Jobs/Cron/UpdateCalculatedFields.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,96 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Invoice Ninja (https://invoiceninja.com).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @link https://github.com/invoiceninja/invoiceninja source repository
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @license https://www.elastic.co/licensing/elastic-license
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Jobs\Cron;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Models\Project;
 | 
				
			||||||
 | 
					use App\Libraries\MultiDB;
 | 
				
			||||||
 | 
					use Illuminate\Foundation\Bus\Dispatchable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UpdateCalculatedFields
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    use Dispatchable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Create a new job instance.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return void
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function __construct()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Execute the job.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return void
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function handle() : void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        nlog("Updating calculated fields");
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if (! config('ninja.db.multi_db_enabled')) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Project::with('tasks')->where('updated_at', '>', now()->subHours(2))
 | 
				
			||||||
 | 
					                ->cursor()
 | 
				
			||||||
 | 
					                ->each(function ($project) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    $project->current_hours = $this->calculateDuration($project);
 | 
				
			||||||
 | 
					                    $project->save();
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            //multiDB environment, need to
 | 
				
			||||||
 | 
					            foreach (MultiDB::$dbs as $db) {
 | 
				
			||||||
 | 
					                MultiDB::setDB($db);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Project::with('tasks')->where('updated_at', '>', now()->subHours(2))
 | 
				
			||||||
 | 
					                ->cursor()
 | 
				
			||||||
 | 
					                ->each(function ($project) {
 | 
				
			||||||
 | 
					                    $project->current_hours = $this->calculateDuration($project);
 | 
				
			||||||
 | 
					                    $project->save();
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private function calculateDuration($project): int
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $duration = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $project->tasks->each(function ($task) use (&$duration) {
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					            foreach(json_decode($task->time_log) as $log){
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                $start_time = $log[0];
 | 
				
			||||||
 | 
					                $end_time = $log[1] == 0 ? time() : $log[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                $duration += $end_time - $start_time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            return round(($duration/60/60), 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -62,6 +62,7 @@ class ProjectTransformer extends EntityTransformer
 | 
				
			|||||||
            'custom_value3' => (string) $project->custom_value3 ?: '',
 | 
					            'custom_value3' => (string) $project->custom_value3 ?: '',
 | 
				
			||||||
            'custom_value4' => (string) $project->custom_value4 ?: '',
 | 
					            'custom_value4' => (string) $project->custom_value4 ?: '',
 | 
				
			||||||
            'color' => (string) $project->color ?: '',
 | 
					            'color' => (string) $project->color ?: '',
 | 
				
			||||||
 | 
					            'current_hours' => (int) $project->current_hours ?: 0,
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -244,6 +244,11 @@ class Number
 | 
				
			|||||||
            $precision = 2;
 | 
					            $precision = 2;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //04-04-2023 if currency = JPY override precision to 0
 | 
				
			||||||
 | 
					        if($currency->code == 'JPY') {
 | 
				
			||||||
 | 
					            $precision = 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $value = number_format($v, $precision, $decimal, $thousand);
 | 
					        $value = number_format($v, $precision, $decimal, $thousand);
 | 
				
			||||||
        $symbol = $currency->symbol;
 | 
					        $symbol = $currency->symbol;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -27,6 +27,11 @@ return new class extends Migration
 | 
				
			|||||||
            $table->dropColumn('tax_all_products');
 | 
					            $table->dropColumn('tax_all_products');
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Schema::table('projects', function (Illuminate\Database\Schema\Blueprint $table) {
 | 
				
			||||||
 | 
					            $table->unsignedInteger('current_hours')->nullable();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Company::query()
 | 
					        Company::query()
 | 
				
			||||||
               ->cursor()
 | 
					               ->cursor()
 | 
				
			||||||
               ->each(function ($company) {
 | 
					               ->each(function ($company) {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user