Search code examples
pythondjangodjango-celeryperiodic-task

How to run Celery Periodic task at every end of the month


Basically, I have a task to generate Invoice. So I have created a function generate_invoice() in my tasks.py file.

Now, I am using @periodic_task to call the function. But I need my task to run only on the last date of the month around 11:55 pm - 11:57 pm.

I am getting the last date of month using this function:

def get_last_date():
        today = timezone.now()
        year = today.year
        month = today.month
        last_date = calendar.monthrange(year, month)[1]
        return str(last_date)

My code for task looks like this:

@periodic_task(run_every=(crontab(day_of_month=get_last_date())), name="invoice_simulation", ignore_result=True)
def invoice_simulation():
    generate_invoice()

But this is not working!

Or is there any better way to implement this feature then please suggest.


Solution

  • A rather simpler solution would be to run the schedule every day at 11:55 PM, and check inside the task if today is the last day of the month. If so, generate the invoice. If not then simply do nothing.

    Something like:

    @periodic_task(run_every=(crontab(hour=23, minute=55)), name="invoice_simulation", ignore_result=True)
    def invoice_simulation():
        if timezone.now().day == get_last_date():
            generate_invoice()
    

    Just make sure that timezone and crontab do not conflict each other. Both must either be TZ aware (or in UTC), or use naive times for both.