Create a daily for loop at a certain time

Please help,I have a daily record of a hotel reservation and I want the context(s) below to be able to query the record everyday @ 2am to create records (more like a for loop).Please how do I go about it.Thank you.

class AccountSummary(generic.ListView):

today = datetime.now().date()

model = Reservation

def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)


    context['total_sales'] = Reservation.objects.filter(roomstatus="checkin").aggregate(
        Sum('room_price')).get('room_price__sum')

    # Paying at checkin 1 day

    context['total_paying'] = Reservation.objects.filter(
        payment_type="P").filter(paid_date__date=self.today).aggregate(Sum('total_cost')).get('total_cost__sum')

    context['total_paying_tf'] = Reservation.objects.filter(
        payment_mode="TF").filter(paid_date__date=self.today).aggregate(Sum('total_cost')).get('total_cost__sum')

    context['total_paying_cash'] = Reservation.objects.filter(
        payment_mode="C").filter(paid_date__date=self.today).aggregate(Sum('total_cost')).get('total_cost__sum')

    context['total_paying_pos'] = Reservation.objects.filter(
        payment_mode="P").filter(paid_date__date=self.today).aggregate(Sum('total_cost')).get('total_cost__sum')

    context['total_non_paying'] = Reservation.objects.filter(roomstatus__contains="checkin").filter(
        payment_type="NP").aggregate(Sum('total_cost')).get('total_cost__sum')
    context['total_paying_debtor'] = Reservation.objects.filter(roomstatus__contains="checkin").filter(
        payment_type="PD").aggregate(Sum('total_cost')).get('total_cost__sum')



    return context

template_name = 'reservations/reservation_accsum.html'

I’m sorry, I think you’re going to need to provide more details and be more specific about what you’re trying to achieve here.

A context in the way it’s being used within the view here is executed when the view is called. They’re only called when someone makes a request for that view. Specifically, what you’re explicitly asking for doesn’t make sense in the way that Django works.

What is your actual objective?

This is a hotel management system.Guests checks in and out.I have a model for this and I would share that shortly.Amongs these guests are those who pay immedieately using different modes of payment and those who pay later(debtors).2AM is when we’re scheduled to close the account for the day.So at exactly 2am of each day,we want to be able to see the total money made for that day,those that paid and their means of payment and those who are debtors.My problem is,I don’t know how to write a for loop to collect this information and populate a table with it daily e.g table head is,Date,Total Sales,Money Received,Transfers,Cash,POS,Non-Paying,Debtors, and the table data would be each collected info at 2am.The earlier message I share showed the views for each section of this account summary.I would be looking forward to your response.

from django.db import models
from django.conf import settings
from rooms.models import Room
from django.urls import reverse
from django.utils import timezone
from django.core.exceptions import ValidationError
from datetime import datetime, date, timedelta, time

import math
from django.contrib.postgres.fields import DateRangeField
from django.utils import timezone

Create your models here.

class Reservation(models.Model):

discount_types = (
    (None, 'No Discount'),
    ('10', '10%'),
    ('20', '20%'),
    ('30', '30%'),
    ('Oth', 'Other'),
)

room_stat_types = (
    ('reserve', 'reserve'),
    ('checkin', 'checkin'),
    ('checkout', 'checkout'),
)

roomstatus = models.CharField(
    max_length=20, choices=room_stat_types, null=True, blank=True, default='reserve')

room_price = models.IntegerField(null=True, blank=True)
check_in = models.DateTimeField(
    blank=True, null=True)
# check_in_in = models.DateTimeField(blank=True, null=True)
check_out = models.DateTimeField(
    blank=True, null=True)
book_date = models.DateTimeField(default=timezone.now)
customer_name = models.CharField(max_length=225)
customer_address = models.CharField(max_length=225)
customer_number = models.CharField(max_length=225)
no_of_days = models.IntegerField(null=True, blank=True)
checking_in_now = models.BooleanField(default=False)
total_cost = models.IntegerField()

roomNumber = models.ForeignKey(
    Room, related_name="guest_reserve", on_delete=models.CASCADE)  # reservations

pay_types = (
    ('P', 'Paying'),
    ('PD', 'Paying Debtor'),
    ('NP', 'Non Paying'),
)

mode_pay_types = (
    ('C', 'Cash'),
    ('P', 'POS'),
    ('TF', 'Transfer'),
)
discount = models.CharField(
    max_length=20, choices=discount_types, null=True, blank=True, default=None)
Other_amount = models.IntegerField(null=True, blank=True, default=None)
payment_type = models.CharField(
    max_length=20, choices=pay_types, default="NP")
paid_date = models.DateTimeField(auto_now=True)
payment_mode = models.CharField(
    max_length=20, choices=mode_pay_types, null=True, blank=True)

credit_balance = models.IntegerField(default=0)


def __str__(self):
    return self.customer_name


def checkin(self):
    self.check_in = timezone.now()
    self.roomstatus = 'checkin'
    self.save()

def checkout(self):
    self.check_out = timezone.now()
    self.roomstatus = 'checkout'
    self.save()

# checking radion button when form is being filled
def check_in_now(self):
    if self.checking_in_now == True:
        self.check_in = timezone.now()
        self.roomstatus = 'checkin'
    # self.save()

def paid_date_update(self):
    if self.payment_type == 'P':
        self.paid_date == datetime.now()
    # self.save()

def value(self):
    if self.discount == '10':
        price = self.roomNumber.roomtype.price
        x = (price - (price*0.1))
        return x
    if self.discount == '20':
        price = self.roomNumber.roomtype.price
        x = (price - (price*0.2))
        return x
    if self.discount == '30':
        price = self.roomNumber.roomtype.price
        x = (price - (price*0.3))
        return x
    if self.discount == None:
        x = self.roomNumber.roomtype.price
        return x
    # self.save()

def no_of_days_booked(self):

    test_value = (
        math.modf(abs(self.check_out - self.check_in).total_seconds()/60/60/24))

    if ((test_value[0] > 0) and (test_value[0]) < 1):
        # print(math.modf(test_value)[0])

        return (test_value)[1] + 1
    else:

        return (test_value)[1]


def save(self, *args, **kwargs):

    if self.Other_amount is not None:
        self.room_price = self.Other_amount
    else:
        self.room_price = self.value()

    if self.id:
        print('updating')
    else:
        print('creating')
    self.no_of_days = self.no_of_days_booked()
    self.total_cost = self.no_of_days * self.room_price
    if self.roomstatus == 'checkin':
        self.credit_balance = self.total_cost - self.room_price
    else:
        self.credit_balance = self.total_cost
    self.paid_date_update()
    # print(datetime.now.date())
    self.check_in_now()

    super().save(*args, **kwargs)

def get_absolute_url(self):
    return reverse('reservations:all')

The easiest way to write something that you want to run once each day would be to create it as a custom Django management command, and then schedule it to run once each day using your systems job scheduler (e.g. cron).

If you are already using Celery, you could set this up using Celery Beats, but if this is the only scheduled task within the system, I wouldn’t both setting up those two components just for this requirement.

1 Like

Thank you Mr Ken,

I would begin looking up custom django management command,cron and celery right away.

Good morning Mr Ken,
I’ve been looking into Celery and other ways of executing this task but I’m yet to find a solution.Can you please respond with a solution?

How do I dynamically populate this table with the above contexts from the views.py on a daily basis at a certain time e.g every 2AM.

    <tbody>
      <tr class="">
        <td>{{date}}</td>
        <td>{{total_sales}}</td>
        <td>{{total_paying}}</td>
        <td>{{total_paying_tf}}</td>
        <td>{{total_paying_cash}}</td>
        <td>{{total_paying_pos}}</td> 
        <td>{{total_non_paying}}</td>
        <td>{{total_paying_debtor}}</td> 
      </tr>
    </tbody>

Thank you.

The implementation of the solution for this task has nothing to do with your current view or template.

See the first paragraph at Create a daily for loop at a certain time - #4 by KenWhitesell.

You are going to want to write completely new code to calculate these values and add them to the database. This code will reside in the custom management command you will be writing.

Than you or your assistance Mr Ken.

I’ve done it.I created a python script that creates a new object,that is,the keys from the context dict I shared above.Then I populate a new table with this script using a cron job that runs everyday at my desired time.

1 Like