2

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.

m-ketan
  • 1,258
  • 2
  • 17
  • 23
Shubham Srivastava
  • 1,190
  • 14
  • 28
  • 1
    How i did this task: Get the first day of the next month (12:01am), convert to dt obj and subtract 5 minutes. I don't think there is an easy "run every" as that is relative to the month. If you "run at" this can work. My exp is not in celery as I have generally written my own wrappers and cron tasks from scratch, so this solution may not convert cleanly. We had the exact same problem in a start-up and this approach worked great. – Marc Dec 06 '17 at 19:21

2 Answers2

2

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.

oxalorg
  • 2,768
  • 1
  • 16
  • 27
-1

Update your get_last_date() function as follows.

def get_last_date():
    today = datetime.date.today()
    year = today.year
    month = today.month
    last_date = calendar.monthrange(year, month)
    return str(last_date)
Atul Rokade
  • 156
  • 1
  • 4