There are a few observations I would like to make to your code before answering:
- do not use
default='0'
argument with your ForeignKey
.
base_salary
is a IntegerField
so you should not use a string as the default value.
- Is your
base_salary
for each hour? Or per day? Or month?
- I suggest using Djangos
timezone
instead of pythons datetime
library.
- 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)