0

I want to calculate salary of employees through my equation

total_salary = (time_out - time_in )*base_salary + (time_out - 8PM)*base_salary*0.20

Here is my model:

class salary(models.Model):
    empname = models.ForeignKey('employee1',default='0',on_delete=models.CASCADE)
    base_salary = models.IntegerField(default='0', help_text="Base Salary")
    time_in = models.DateTimeField(default=datetime.now, blank=True)
    time_out = models.DateTimeField(default=datetime.now, blank=True)
    total_salary = models.CharField(max_length=20,default='0',blank=True,editable=False)

    def default_over_time():
        now = datetime.now()
        start = now.replace(hour=8, minute=0, second=0, microsecond=0)
        return start if start > now else start + timedelta(days=1)

    def save(self,*args,**kwargs):
        self.total_salary=(self.time_out - self.time_in)
        self.total_salary=(self.time_out - self.time_in )*  self.base_salary + (self.time_out - self.default_over_time) * self.base_salary*0.20
        self.total_salary=str(self.total_salary)
        super(salary,self).save(*args,**kwargs)
Ralf
  • 16,086
  • 4
  • 44
  • 68
Ashish
  • 3
  • 6
  • what do you mean by class? Do you want that in views? or you want it in models itself? also please arrange your code properly. If you are looking dor custom model fields then https://stackoverflow.com/questions/28529179/django-creating-a-custom-model-field – py-D Apr 18 '18 at 17:48
  • @py-D I Have Arranged my code now. I want to calculate salary using my equation --> total_salary=(time_out - time_in )* base_salary + (time_out - 8PM) * base_salary*0.20 – Ashish Apr 18 '18 at 18:07
  • what do you mean by class? Do you want that in views? or you want it in models itself? – py-D Apr 18 '18 at 18:09
  • @py-D models itself – Ashish Apr 18 '18 at 18:10
  • okz, it means you have to override django model save method. So refer this https://stackoverflow.com/questions/4269605/django-override-save-for-model – py-D Apr 18 '18 at 18:12
  • @py-D but my question is how to calculate salary my equation is not working – Ashish Apr 18 '18 at 18:15
  • ok... so please check your code by removing editable clause of total_salary field. And I will suggest that choose a variable in save method for calculation of salary rather than everytime assigning same value to filed. – py-D Apr 18 '18 at 18:23
  • @py-D Exception Value: unsupported operand type(s) for -: 'datetime.datetime' and 'method'.This error came when i tried to save the information – Ashish Apr 18 '18 at 18:54
  • Check out my answer – py-D Apr 18 '18 at 18:59
  • @Ralf can you help me with this too Please https://stackoverflow.com/questions/49909926/how-to-import-data-from-csv-file-to-django-sqlite-using-import-py – Ashish Apr 18 '18 at 22:30

2 Answers2

0

I don't know how you are going ot calculate salary from base salary but as far as your formula is concern self.time_out - self.time_in it will give you a datetime object.

So you have to convert it to seconds or hours. like

a1 = self.time_out - self.time_in
total_sec = a1.total_seconds() 

same for self.time_out - self.default_over_time

EDIT:

Four your case as per your comment you have to convert timedifference to hours and then you have to use the same in your formula for the same you can use divmod. ex.

a1 = self.time_out - self.time_in
total_sec = a1.total_seconds()
minutes,second = divmod(total_sec,60)
hours,minutes = divmod(minutes,60)

from above you will get total hours and can use the same in you formula.

EDIT 2:

convert time to datetime and then go for difference. ex.

datetime.strptime(self.time_out.strftime('%H:%I'),'%H:%I') - datetime.strptime(self.time_in.strftime('%H:%I'),'%H:%I') 
py-D
  • 661
  • 5
  • 8
  • Thank you But i need your help for the answer provided by Ralf below my question......my requirements are changed & i Have to change the DateTimeField To TimeField of timein & timeout........But when i make the changes in your given answer i face an error (Exception Value: unsupported operand type(s) for -: 'datetime.time' and 'datetime.time' ) – Ashish Apr 20 '18 at 16:19
  • convert time to datetime and then go for difference. ex. datetime.strptime(self.time_out.strftime('%H:%I'),'%H:%I') - datetime.strptime(self.time_in.strftime('%H:%I'),'%H:%I') @Ashish – py-D Apr 20 '18 at 18:36
0

There are a few observations I would like to make to your code before answering:

  1. do not use default='0' argument with your ForeignKey.
  2. base_salary is a IntegerField so you should not use a string as the default value.
  3. Is your base_salary for each hour? Or per day? Or month?
  4. I suggest using Djangos timezone instead of pythons datetime library.
  5. Are you sure you want a CharField for your total_salary?

Here is my suggestion as to how you could calculate your salary:

from datetime import timedelta
from django.db import models
from django.utils import timezone as tz

class Salary(models.Model):
    employee = models.ForeignKey('Employee', on_delete=models.CASCADE)
    base_salary = models.IntegerField(default=0)
    time_in = models.DateTimeField(default=tz.now, null=True, blank=True)
    time_out = models.DateTimeField(default=tz.now, null=True, blank=True)
    total_salary = models.CharField(max_length=20, default='0')

    def calculate_salary(self):
        worked_hours = (self.time_out - self.time_in).total_seconds() / 60 / 60
        overtime_hours = 0

        # make sure you use timezone aware objects
        # https://docs.djangoproject.com/en/2.0/topics/i18n/timezones/#naive-and-aware-datetime-objects
        same_day_8pm = self.time_out.replace(hour=20, minute=0, second=0, microsecond=0)
        if self.time_out > same_day_8pm:
            overtime_hours = (self.time_out - same_day_8pm).total_seconds() / 60 / 60

        salary_1 = worked_hours * self.base_salary
        salary_2 = overtime_hours * self.base_salary * 0.2
        total_salary = salary_1 + salary_2

        # careful: this will be a 'float', not an 'int'
        # with round() using 0 decimal digits you get an 'int'
        # total_salary = round(total_salary, 0)

        return total_salary

    def save(self,*args,**kwargs):
        # are you really sure that you want to save a string ???
        self.total_salary = str(self.calculate_salary())
        super().save(*args, **kwargs)

EDIT after @Ashish made the following comment:

my requirements are changed & i Have to change the DateTimeField To TimeField of timein & timeout........But when i make the changes in your given answer i face an error (Exception Value: unsupported operand type(s) for -: 'datetime.time' and 'datetime.time' )

I advise against using TimeField for this case because it makes the calculation a bit more complicated. And it doesn't hurt to have the extra date info stored with the DateTimeField (for example, when time_in and time_out are on different days, maybe just after midnight).

But if your hands are tied on this matter, then lets get you sorted out:

You are seeing the error because djangos TimeField uses pythons datetime.time, which does not support the - operation. See also this post for a similar task.

You could overcome this by converting to datetime.datetime objects like this:

import datetime as dt
new_time_in = dt.datetime(
    year=2000, month=1, day=1,  # choose an arbitrary date
    hour=time_in.hour,
    minute=time_in.minute,
    second=time_in.second,
    tzinfo=time_in.tzinfo)
new_time_out = dt.datetime(
    year=2000, month=1, day=1,  # use the same date as before
    hour=time_out.hour,
    minute=time_out.minute,
    second=time_out.second,
    tzinfo=time_out.tzinfo)
Ralf
  • 16,086
  • 4
  • 44
  • 68
  • Thank You So much @Ralf This was the perfect solution i was looking for since so many days Thanks alot – Ashish Apr 18 '18 at 20:21
  • can you help me with this too.. https://stackoverflow.com/questions/49909926/how-to-import-data-from-csv-file-to-django-sqlite-using-import-py – Ashish Apr 18 '18 at 22:29
  • Sir need one more help – Ashish Apr 20 '18 at 14:34
  • my requirements are changed & i Have to change the DateTimeField To TimeField of timein & timeout........But when i make the changes in your given answer i face an error (Exception Value: unsupported operand type(s) for -: 'datetime.time' and 'datetime.time' ) – Ashish Apr 20 '18 at 14:39
  • I added some thoughts to the end of my answer. – Ralf Apr 20 '18 at 18:35