3

I'm using Laravel 5.8 and I like to auto-generate Invoices should be generated auto from Monday - Sunday. every Sunday night at 23:59:00

Let's say I have

"23:59:00 according to the region time zone".

Every store is related to a region, from the region table you'll find the time zone.

Questions How should I set the CRON JOB so I can generate invoices automatically according to the list of timezone I will get from the table?.

2 Answers2

2

I have two suggestions;

if you want it to be static, define each command with the corresponding timezone from your database. Different timezones may have same time such as Europe/Amsterdam and Europe/Berlin

$schedule->command('generate:report')->timezone('one-of-the-timezone')->at('23:59');
$schedule->command('generate:report')->timezone('another-timezone')->at('23:59');
$schedule->command('generate:report')->timezone('yet-another-timezone')->at('23:59');
$schedule->command('generate:report')->timezone('some-other-timezone')->at('23:59');

If you want it to be dynamic, make it run every 59. min hourly and try to match it with the timezones via using hour.

$schedule->command('generate:report')->hourlyAt(59);

Inside your command class;

public function handle(TimezoneRepository $timezoneRepository)
{
    $timezones = $timezoneRepository->getUniqueTimezones(); // the unique timezones in your database - cache if you want

    foreach ($timezones as $timezone) {
        $date = Carbon::now($timezone); // Carbon::now('Europe/Moscow'), Carbon::now('Europe/Amsterdam') etc..

        if ($date->hour === 23) { // you are in that timezone
            $currentTimezone = $date->getTimezone();
            dispatch(new ReportMaker($currentTimezone)); // dispatch your report maker job
        }
    }
}

With the dynamic one, you will hit to multiple timezones at one iteration(when generate:report is executed) as i said at then beginning.

  • one of the possible flaw may be; if the execution of getting timezones etc takes more than 1 minute you may be in 00:00 instead of 23:59. It is better to calculate your report asynchronous and cache the list of timezones to not face problems while executing this loop.

  • Another possible flaw;

According to wiki;

A few zones are offset by 30 or 45 minutes (e.g. Newfoundland Standard Time is UTC−03:30, Nepal Standard Time is UTC+05:45, Indian Standard Time is UTC+05:30 and Myanmar Standard Time is UTC+06:30).

If you want to cover any of these, then it is better to execute the command like this

$schedule->command('generate:report')->cron('14,29,44,59 * * * *');

and make both hour and minute comparison such as;

$date->hour === 23 && $date->hour === 59

Ersoy
  • 8,816
  • 6
  • 34
  • 48
  • and Basically I want to run that job from Monday to Sunday so how i can set that it runs automatically and get orders from Monday to Sunday and generate invoice base on different regions – Muhammad Ikram UL Mustafa May 21 '20 at 08:18
  • @MuhammadIkramULMustafa as i stated in the example code you will dispatch ReportMaker and put that logic to generate invoices. In this job you will have timezone and inside the job you may fetch current day. – Ersoy May 21 '20 at 17:15
1

You can use the timezone() method in your task Schedulding

Using the timezone method, you may specify that a scheduled task's time should be interpreted within a given timezone:

$schedule->command('report:generate')
         ->timezone('America/New_York')
         ->at('02:00')
Christophe Hubert
  • 2,833
  • 1
  • 12
  • 25