1

I have a Django model called Attendance that has the clock in and clock in times of an employee along with the status of that entry, to see whether it's authorized or not. I then, am making another model called Payroll. I want this to check inside the Attendance entries to see all the Authorized entries and then do some action on them. How do I check all the status fields for all the entries in Attendance?

EDIT: Updated to better elaborate my question.

To better elaborate my question, this is how I've setup my Attendance model:

class CWorkAttendance(models.Model):
    AUTO_ATT = "AU"
    MANUAL_ATT = "MA"
    WORK_ENTRY_TYPES = (
        (AUTO_ATT, "Auto-Attendance"),
        (MANUAL_ATT, "Manual-Attendance"),
    )
    AUTHORIZED = "AU"
    UNAUTHORIZED = "UA"
    WORK_ENTRY_STATUSES = (
        (AUTHORIZED, "Athorized"),
        (UNAUTHORIZED, "Un-Authorized"),
    )
    #Thank you motatoes
    def face_locations_in(self, instance):
        now = datetime.datetime.now()
        return "attendance/{}/{}/in".format(instance.work_employee, now.strftime("%Y/%m/%d"))

    def face_locations_out(self, instance):
        now = datetime.datetime.now()
        return "attendance/{}/{}/out".format(instance.work_employee, now.strftime("%Y/%m/%d"))

    work_employee = models.ForeignKey('CEmployees', on_delete=models.CASCADE,)
    work_start_time = models.DateTimeField()
    work_end_time = models.DateTimeField(null=True)
    work_duration = models.IntegerField(null=True)
    work_entry_type = models.CharField(max_length=2,choices=WORK_ENTRY_TYPES)
    work_entry_status = models.CharField(max_length=2, choices=WORK_ENTRY_STATUSES, default=WORK_ENTRY_STATUSES[1][0])
    employee_face_captured_in = models.ImageField(upload_to=face_locations_in,)#////////
    employee_face_captured_out = models.ImageField(upload_to=face_locations_out,)

If you look closely at the work_entry_status, it's a choice CharField that will contain the status of the entry (UNAUTHORIZED by default).

I want to create a Payroll model that will check for all the rows in the CWorkAttendance model and check their work_entry_status fields to see if they are Authorized, which is what I want to learn how to do.

If those fields are authorized, I want the grab the row's work_employee, work_duration and also some details from the original CEmployees row for the employee.

This is what I want my Payslip/Payroll model to look like:

class Payslip(models.Model):
    GENERATED = "GEN"
    CONFIRMED = "CON" 
    PAYSLIP_STATUS = (
        (GENERATED, "Generated-UNSAVED"),
        (CONFIRMED, "Confirmed-SAVED"),
    )

    payslip_number = models.IntegerField()#MM/YY/AUTO_GENERATED_NUMBER(AUTO_INCREMENT)
    payslip_employee = models.ForeignKey('CEmployees', on_delete=models.CASCADE,)#Choose the employee from the master table CEmployees
    payslip_generation_date = models.DateTimeField(default=datetime.datetime.now())#Date of the payroll generation
    payslip_total_hours = models.IntegerField()#Total hours that the employee worked
    payslip_from_date = models.DateField()"""The date from when the payslip will be made. The payslip will be manual for now, so generate it after choosing a a date to generate from."""
    payslip_total_basic_seconds = models.IntegerField()#Total seconds the employee worked
    payslip_total_ot_seconds = models.IntegerField()#Total overtime seconds the employee worked
    payslip_basic_hourly_rate = models.IntegerField()#The basic hourly rate of the employee mentioned here. Take from the master employees table.
    payslip_basic_ot_rate = models.IntegerField()#Taking the basic overtime rate from the master table
    payslip_total_amount = models.FloatField()#The total amount of the payslip
    payslip_entry_status = models.CharField(max_length=3, default=GENERATED)#The status of the pay slip.

Thanks,

  • 1
    You can filter with `CWorkAttendance.objects.filter(work_entry_status=CWorkAttendance.AUTHORIZED)` to obtain all `CWorkAttencance` objects where `work_entry_status` is authroized. – Willem Van Onsem Aug 19 '19 at 13:54
  • Here are the relevant [docs](https://docs.djangoproject.com/en/2.2/topics/db/queries/#retrieving-specific-objects-with-filters). What you're asking is just standard Django queries, please read the docs first. – dirkgroten Aug 19 '19 at 14:10
  • Thank you, I'm just stupid. :) Sorry for the dumb question, though thanks for the help. I'll refer to the Docs more often. ^^ – Unknown Username Aug 19 '19 at 17:04
  • is there a `payslip_to_date` for the Payslip model ? AKA will it be generated for a range? – motatoes Aug 19 '19 at 19:31
  • 1
    There is. The payslip_generation_date will be the to date. For now, the payslip will only be to the time of creation, from either the beginning of when the employee first worked, or from the last payslip generated. – Unknown Username Aug 19 '19 at 19:34

1 Answers1

0

Not sure if I understand your requirements well, so let me know if I misunderstood.

# `employee` is the work_employee in question

# if you don't want to filter by employee, remove `work_employee=employee`
attendances = CWorkAttendance.objects.filter(work_entry_status=CWorkAttendance.AUTHORIZED, work_employee=employee)

for attendances in attendances:
    # do things with this attendance record
    attendance.work_duration 
    attendance.employee
    # ....

Update

Since you would like to do it manually, I would suggest having a separate view to generate the Payslip. The important thing is to know the date_from and the date_to for this payslip. I imagine that it is the managers who would have access to this view, so you would need the proper access controls set for it. I also think you need to have a payslip_to_date even if you are going to generate it until the current date, which will be useful for record keeping. I assume you have that column in the code below.

views.py:

from django.views import View


class GeneratePayslip(View):
    """
     make sure you have the right access controls set to this view
    """
    def post(self, request, **kwargs):
       employee_id = kwags.POST.get("employee_id")
       date_from = kwargs.POST.get("from_date")
       date_to = kwargs.POST.get("to_date")

       # we fetch all the objects within range
       attendances = CWorkAttendance.objects.filter( \
                work_entry_status=CWorkAttendance.AUTHORIZED, \
                work_employee_id=employee_id, \
                work_start_time__gte=date_from, \
                work_end_time__lte=date_to \
       )

       hours = 0
       for attendance in attendances:
           # perform calculations to compute total sum and rate
           pass

       # create the payslip object here ..

       # redirect to a success page and return

If you wanted to do it automatically later on, you may want to generate payslips automatically, once a month. For that you could use something like Celery to have periodic tasks that run in the background, for each employee. If this is the case you could move the above code to a file such as utils.py. you can create a method which takes employee_id, from_date, to_date, and then generate the payslip object, returning the payslip_id to the calling method

motatoes
  • 828
  • 11
  • 26
  • Sure. That is exactly what I meant. First of all, thank you for you reply. I haven't gone through the Django Docs completely (Completely my fault) but I would appreciate it if you could tell me what the correct way of doing all this is. Do I make a new .py file and do all the payroll calculation and stuff, or do I do it all inside the models.py file. This is something that has been bothering me for a while. Also, I see that there are if conditions inside the model's `save` function. – Unknown Username Aug 19 '19 at 17:00
  • Also, one more thing. So you see how I have this field ```work_start_time = models.DateTimeField()```, how do I retrieve the Date from the datetime field. And how do I check the closest date among all the `work_start_time` field to the current date? Like decide which one is the closest to the current date among all the entries in the table. – Unknown Username Aug 19 '19 at 17:01
  • Just tell me this: How do I check for the first and latest authorized row for the employee? – Unknown Username Aug 19 '19 at 17:06
  • You could check it with attendances = CWorkAttendance.objects.filter(work_entry_status=CWorkAttendance.AUTHORIZED, work_employee=employee).order_by(‘work_start_date’) – motatoes Aug 19 '19 at 17:13
  • Then you could access the first and last entry using attendances.first() and attendances.last() – motatoes Aug 19 '19 at 17:14
  • I want to understand your requirements better, could you update your question with what the Payroll model looks like, what needs to be calculated, and how often? What would trigger a payroll? Is it once a month run automatically? Or does the manager request it for example? – motatoes Aug 19 '19 at 17:15
  • Sure. I'll do that. Just one more thing. I have `face_location_in = "attendance/{}/%Y%m%%d/in".format(str(self.work_employee),)` as the location for the faces for my facial recognition. `employee_face_captured_in = models.ImageField(upload_to=face_location_in)` This code doesn't work. I'm trying to have a separate folder with the attendance/`employee's id`/`the Y/M/D, in which I'll put in the pictures. – Unknown Username Aug 19 '19 at 17:51
  • This is a different question, but what you want to do is generate this path using a function [like this](https://stackoverflow.com/a/1190866/1765562). in Your case: `def face_location_fn(self, instance): now = datetime.datetime.now(); return "attendance/{}/{}/in".format(instance.work_employee.first_name, now.strftime("%Y/%m/%d"))` – motatoes Aug 19 '19 at 18:34
  • and you would pass it as `employee_face_captured_in = models.ImageField(upload_to=face_location_fn)` – motatoes Aug 19 '19 at 18:35
  • Thank you. You are a very genuine person keeping up with me this far. I've updated the question. – Unknown Username Aug 19 '19 at 19:04
  • Cool, please upvote my comments and answer to help with my ratings :) – motatoes Aug 19 '19 at 19:28
  • I will. For sure. – Unknown Username Aug 19 '19 at 19:32
  • Cool, please see my updated answer and let me know if you have any further questions – motatoes Aug 19 '19 at 20:29
  • Oooo that's nice. Just three things. What is the post method doing? What does `work_employee_id=employee_id` mean? Like I know work_employee_id is the column in the Attendance table. And this is inside the views.py so I'm guessing that I create a view, with three fields? One of them is employee_id so this allows me to chose which employee's payroll o want to generate? And last but not least, why are there these slashes(/) in the filter? – Unknown Username Aug 20 '19 at 00:40
  • 1. `work_employee_id` is the ID of the employee. but it could also be `work_employee__username` which will filter by employee username, or `work_employee__email`. – motatoes Aug 20 '19 at 08:30
  • 2. That's a [class-based view](https://docs.djangoproject.com/en/2.2/ref/class-based-views/). the post method is just the one that is dispatched from a POST submission of the form. You could use a function view that is also fine – motatoes Aug 20 '19 at 08:34
  • 3. Yes, I think you will need to create a form and render it in one page from that view (look into FormView, or use what is comfortable). In that form you would have a Select field for the employees, or something like that. this will submit the ID to the form – motatoes Aug 20 '19 at 08:38
  • The backslashes are just used to split a long line into multiple lines. In this case I don't think its needed by I added them out of habit haha – motatoes Aug 20 '19 at 08:38
  • Thanks for accepting the answer, don't forget to upvote all my comments and answer as it could up me by another +30! – motatoes Aug 20 '19 at 08:39
  • I will definitely upvote all your stuff. I can't do it with this account as I'm under 15 rep. But I'll do it form my other account in like 30 minutes. – Unknown Username Aug 20 '19 at 10:14
  • Just one last thing. About 1. I haven't really defined a username or anything. I understand that this may be very simple but I'm just stupid. Could you explain or refer me to the docs? I won't bother you again xD – Unknown Username Aug 20 '19 at 10:14
  • And what is __gte and __lte after the names? (Inside your answer) – Unknown Username Aug 20 '19 at 10:17
  • the double underscore `__` syntax follows a foreign key to search by any column from the referred field. You would need this to filter by any column in the Employee model. The form you build for the managers will submit some attribute of the employee like his name or email. From there you can filter by that employee using this double underscore syntax like this: https://stackoverflow.com/questions/1981524/django-filtering-on-foreign-key-properties – motatoes Aug 20 '19 at 10:21
  • lte and gte stand for less than or equals, and greater than or equals. They are for querying ranges that match your check-in check-out dates https://stackoverflow.com/a/5245459/1765562 – motatoes Aug 20 '19 at 10:23