Calculate complete duration of several time periods

Hi once more, folks,

my “daily problem” today is a quite simple one i think and i should have managed it by myself but it seems my brains has quit working for today…

i try to automatically calculate the Sum of active Duration of one or more Employments an Employee had over the time within a company.

This is the model for it:

class Employments(models.Model):

    status = models.CharField(max_length=50)
    work_time_model = models.CharField(max_length=50)
    weekly_hours = models.FloatField(default=41)
    percent = models.FloatField(default=100)
    duty_begin = models.DateField(blank=True)
    duty_end = models.DateField(null=True, blank=True)
    employee = models.ForeignKey(Employees, on_delete=models.CASCADE)

    objects = WorkYearsManager()

and i try to achieve it with this WorkYearsManage :

class WorkYearsManager(models.Manager):

    def with_ongoing_years(self):
        today = datetime.date.today()
        return self.annotate(
            ongoing_years=ExpressionWrapper(
                (today - F('duty_begin')), output_field=fields.FloatField()
                # Sekunden auf Jahre umrechnen
                )/86400/365.2425/1000000*F('percent')/100
            )

    def with_past_years(self):
        return self.annotate(
            past_years=ExpressionWrapper(
                (F('duty_end') - F('duty_begin')), output_field=fields.FloatField()
                # Sekunden auf Jahre umrechnen
            ) / 86400 / 365.2425 / 1000000*F('percent')/100
        )

    def total_work_years(self, employee):
        ongoing_years =  self.with_ongoing_years().filter(employee=employee).aggregate(Sum('ongoing_years'))
        past_years = self.with_past_years().filter(employee=employee).aggregate(Sum('past_years'))
        total = ongoing_years | past_years
        total_work_years = sum(total.values())
        return total_work_years

so, concerning the past_years, everything is working as intended, concerning the ongoing_years ,I have to manage, that only the actual employment is calculated. At the moment, i get an result from the earliest duty_beginuntil today…

edit:
so, I am aware that the code will throw an error if either ongoing_years or past_years is None.

so I made some changes:


    def total_work_years(self, employee):
        ongoing_years = self.with_ongoing_years().filter(employee=employee).aggregate(Sum('ongoing_years'))
        past_years = self.with_past_years().filter(employee=employee).aggregate(Sum('past_years'))

        ongoing_years = {} if not all(ongoing_years.values()) is True else ongoing_years
        past_years = {} if not all(past_years.values()) is True else past_years
        total_work_years = sum((ongoing_years | past_years).values())

        return total_work_years

Thx to everyone who was thinking about it. solved it myself in the meantime:

class WorkYearsManager(models.Manager):

    def with_past_years(self):
        return self.annotate(
            past_years=ExpressionWrapper(
                (F('duty_end') - F('duty_begin')), output_field=fields.FloatField()
                # Sekunden auf Jahre umrechnen
            ) / 86400 / 365.2425 / 1000000*F('percent')/100
        )

    def total_work_years(self, employee):

        ongoing_years = {}
        today = datetime.date.today()
        latest_employment = self.filter(employee=employee).latest('duty_begin')
        if latest_employment.duty_end is None:
            percent = self.filter(employee=employee).latest('duty_begin').percent
            sum_ongoing = (today - latest_employment.duty_begin).days * (percent / 100) / 365.2425
            ongoing_years = {'ongoing_years__sum': sum_ongoing}

        past_years = self.with_past_years().filter(employee=employee).aggregate(Sum('past_years'))

        # if None in Dictionary:
        past_years = {} if not all(past_years.values()) is True else past_years

        total_work_years = sum((ongoing_years | past_years).values())
        return total_work_years