Пример #1
0
    def get_context_data(self, **kwargs):
        context = super(HourlyReport, self).get_context_data(**kwargs)

        # Sum the hours totals for each user & interval.
        entries = context['entries']
        date_headers = context['date_headers']

        summaries = []
        if context['entries']:
            summaries.append(
                ('By User',
                 get_project_totals(entries.order_by('user__last_name',
                                                     'user__id', 'date'),
                                    date_headers,
                                    'total',
                                    total_column=True,
                                    by='user')))

            entries = entries.order_by('project__type__label', 'project__name',
                                       'project__id', 'date')
            func = lambda x: x['project__type__label']
            for label, group in groupby(entries, func):
                title = label + ' Projects'
                summaries.append((
                    title,
                    get_project_totals(
                        list(group),
                        date_headers,
                        'total',
                        total_column=True,
                        by='project',
                    ),
                ))

        # Adjust date headers & create range headers.
        from_date = context['from_date']
        from_date = utils.add_timezone(from_date) if from_date else None
        to_date = context['to_date']
        to_date = utils.add_timezone(to_date) if to_date else None
        trunc = context['trunc']
        date_headers, range_headers = self.get_headers(date_headers, from_date,
                                                       to_date, trunc)

        context.update({
            'date_headers': date_headers,
            'summaries': OrderedDict(summaries),
            'range_headers': range_headers,
        })
        return context
Пример #2
0
    def get_context_data(self, **kwargs):
        context = super(HourlyReport, self).get_context_data(**kwargs)

        # Sum the hours totals for each user & interval.
        entries = context['entries']
        date_headers = context['date_headers']

        summaries = []
        if context['entries']:
            summaries.append(('By User', get_project_totals(
                entries.order_by('user__last_name', 'user__id', 'date'),
                date_headers, 'total', total_column=True, by='user')))

            entries = entries.order_by('project__type__label', 'project__name',
                                       'project__id', 'date')
            func = lambda x: x['project__type__label']
            for label, group in groupby(entries, func):
                title = label + ' Projects'
                summaries.append((
                    title,
                    get_project_totals(
                        list(group),
                        date_headers,
                        'total',
                        total_column=True,
                        by='project',
                    ),
                ))

        # Adjust date headers & create range headers.
        from_date = context['from_date']
        from_date = utils.add_timezone(from_date) if from_date else None
        to_date = context['to_date']
        to_date = utils.add_timezone(to_date) if to_date else None
        trunc = context['trunc']
        date_headers, range_headers = self.get_headers(
            date_headers, from_date, to_date, trunc)

        context.update({
            'date_headers': date_headers,
            'summaries': OrderedDict(summaries),
            'range_headers': range_headers,
        })
        return context
Пример #3
0
def report_payroll_summary(request):
    date = timezone.now() - relativedelta(months=1)
    from_date = utils.get_month_start(date).date()
    to_date = from_date + relativedelta(months=1)

    year_month_form = PayrollSummaryReportForm(request.GET or None,
                                               initial={
                                                   'month': from_date.month,
                                                   'year': from_date.year
                                               })

    if year_month_form.is_valid():
        from_date, to_date = year_month_form.save()
    last_billable = utils.get_last_billable_day(from_date)
    projects = utils.get_setting('TIMEPIECE_PAID_LEAVE_PROJECTS')
    weekQ = Q(end_time__gt=utils.get_week_start(from_date),
              end_time__lt=last_billable + relativedelta(days=1))
    monthQ = Q(end_time__gt=from_date, end_time__lt=to_date)
    workQ = ~Q(project__in=projects.values())
    statusQ = Q(status=Entry.INVOICED) | Q(status=Entry.APPROVED)
    # Weekly totals
    week_entries = Entry.objects.date_trunc('week').filter(
        weekQ, statusQ, workQ)
    date_headers = generate_dates(from_date, last_billable, by='week')
    weekly_totals = list(
        get_project_totals(week_entries, date_headers, 'total', overtime=True))
    # Monthly totals
    leave = Entry.objects.filter(monthQ,
                                 ~workQ).values('user', 'hours',
                                                'project__name')
    extra_values = ('project__type__label', )
    month_entries = Entry.objects.date_trunc('month', extra_values)
    month_entries_valid = month_entries.filter(monthQ, statusQ, workQ)
    labels, monthly_totals = get_payroll_totals(month_entries_valid, leave)
    # Unapproved and unverified hours
    entries = Entry.objects.filter(monthQ).order_by()  # No ordering
    user_values = ['user__pk', 'user__first_name', 'user__last_name']
    unverified = entries.filter(status=Entry.UNVERIFIED, user__is_active=True) \
                        .values_list(*user_values).distinct()
    unapproved = entries.filter(status=Entry.VERIFIED) \
                        .values_list(*user_values).distinct()
    return render(
        request, 'timepiece/reports/payroll_summary.html', {
            'from_date': from_date,
            'year_month_form': year_month_form,
            'date_headers': date_headers,
            'weekly_totals': weekly_totals,
            'monthly_totals': monthly_totals,
            'unverified': unverified,
            'unapproved': unapproved,
            'labels': labels,
        })
Пример #4
0
 def get_project_totals(self, date_headers, trunc, query=Q(),
                        hour_type='total'):
     """Helper function for testing project_totals utility directly"""
     entries = Entry.objects.date_trunc(trunc).filter(query)
     if entries:
         pj_totals = get_project_totals(entries, date_headers, hour_type)
         pj_totals = list(pj_totals)
         rows = pj_totals[0][0]
         hours = [hours for name, user_id, hours in rows]
         totals = pj_totals[0][1]
         return hours, totals
     else:
         return ''
Пример #5
0
def report_payroll_summary(request):
    date = timezone.now() - relativedelta(months=1)
    from_date = utils.get_month_start(date).date()
    to_date = from_date + relativedelta(months=1)

    year_month_form = PayrollSummaryReportForm(request.GET or None, initial={
        'month': from_date.month,
        'year': from_date.year,
    })

    if year_month_form.is_valid():
        from_date, to_date = year_month_form.save()
    last_billable = utils.get_last_billable_day(from_date)
    projects = utils.get_setting('TIMEPIECE_PAID_LEAVE_PROJECTS')
    weekQ = Q(end_time__gt=utils.get_week_start(from_date),
              end_time__lt=last_billable + relativedelta(days=1))
    monthQ = Q(end_time__gt=from_date, end_time__lt=to_date)
    workQ = ~Q(project__in=projects.values())
    statusQ = Q(status=Entry.INVOICED) | Q(status=Entry.APPROVED)
    # Weekly totals
    week_entries = Entry.objects.date_trunc('week').filter(
        weekQ, statusQ, workQ
    )
    date_headers = generate_dates(from_date, last_billable, by='week')
    weekly_totals = list(get_project_totals(week_entries, date_headers,
                                            'total', overtime=True))
    # Monthly totals
    leave = Entry.objects.filter(monthQ, ~workQ)
    leave = leave.values('user', 'hours', 'project__name')
    extra_values = ('project__type__label',)
    month_entries = Entry.objects.date_trunc('month', extra_values)
    month_entries_valid = month_entries.filter(monthQ, statusQ, workQ)
    labels, monthly_totals = get_payroll_totals(month_entries_valid, leave)
    # Unapproved and unverified hours
    entries = Entry.objects.filter(monthQ).order_by()  # No ordering
    user_values = ['user__pk', 'user__first_name', 'user__last_name']
    unverified = entries.filter(status=Entry.UNVERIFIED, user__is_active=True) \
                        .values_list(*user_values).distinct()
    unapproved = entries.filter(status=Entry.VERIFIED) \
                        .values_list(*user_values).distinct()
    return render(request, 'timepiece/reports/payroll_summary.html', {
        'from_date': from_date,
        'year_month_form': year_month_form,
        'date_headers': date_headers,
        'weekly_totals': weekly_totals,
        'monthly_totals': monthly_totals,
        'unverified': unverified,
        'unapproved': unapproved,
        'labels': labels,
    })
Пример #6
0
    def get_hours_data(self, entries, date_headers):
        """Sum billable and non-billable hours across all users."""
        project_totals = get_project_totals(
            entries, date_headers, total_column=False) if entries else []

        data_map = {}
        for rows, totals in project_totals:
            for user, user_id, periods in rows:
                for period in periods:
                    day = period['day']
                    if day not in data_map:
                        data_map[day] = {'billable': 0, 'nonbillable': 0}
                    data_map[day]['billable'] += period['billable']
                    data_map[day]['nonbillable'] += period['nonbillable']

        return data_map
Пример #7
0
    def get_hours_data(self, entries, date_headers):
        """Sum billable and non-billable hours across all users."""
        project_totals = get_project_totals(
            entries, date_headers, total_column=False) if entries else []

        data_map = {}
        for rows, totals in project_totals:
            for user, user_id, periods in rows:
                for period in periods:
                    day = period['day']
                    if day not in data_map:
                        data_map[day] = {'billable': 0, 'nonbillable': 0}
                    data_map[day]['billable'] += period['billable']
                    data_map[day]['nonbillable'] += period['nonbillable']

        return data_map
Пример #8
0
 def get_project_totals(self,
                        date_headers,
                        trunc,
                        query=Q(),
                        hour_type='total'):
     """Helper function for testing project_totals utility directly"""
     entries = Entry.objects.date_trunc(trunc).filter(query)
     if entries:
         pj_totals = get_project_totals(entries, date_headers, hour_type)
         pj_totals = list(pj_totals)
         rows = pj_totals[0][0]
         hours = [hours for name, user_id, hours in rows]
         totals = pj_totals[0][1]
         return hours, totals
     else:
         return ''