def test_weekly_total(self): start = utils.add_timezone(datetime.datetime(2011, 1, 3)) end = utils.add_timezone(datetime.datetime(2011, 1, 6)) self.bulk_entries(start, end) trunc = 'week' date_headers = generate_dates(start, end, trunc) pj_totals = self.get_project_totals(date_headers, trunc) self.assertEqual(pj_totals[0][0], [48]) self.assertEqual(pj_totals[0][1], [24]) self.assertEqual(pj_totals[1], [72])
def bulk_entries(self, start=datetime.datetime(2011, 1, 2), end=datetime.datetime(2011, 1, 4)): start = utils.add_timezone(start) end = utils.add_timezone(end) dates = generate_dates(start, end, 'day') projects = [self.p1, self.p2, self.p2, self.p4, self.p5, self.sick] self.make_entries(projects=projects, dates=dates, user=self.user, hours=2) self.make_entries(projects=projects, dates=dates, user=self.user2, hours=1)
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, })
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, })
def test_daily_total(self): start = utils.add_timezone(datetime.datetime(2011, 1, 1)) day2 = utils.add_timezone(datetime.datetime(2011, 1, 2)) end = utils.add_timezone(datetime.datetime(2011, 1, 3)) self.log_daily(start, day2, end) trunc = 'day' date_headers = generate_dates(start, end, trunc) pj_totals = self.get_project_totals(date_headers, trunc) self.assertEqual(pj_totals[0][0], [Decimal('1.00'), Decimal('1.50'), '']) self.assertEqual(pj_totals[0][1], ['', Decimal('3.00'), Decimal('2.00')]) self.assertEqual(pj_totals[1], [Decimal('1.00'), Decimal('4.50'), Decimal('2.00')])
def test_monthly_total(self): start = utils.add_timezone(datetime.datetime(2011, 1, 1)) end = utils.add_timezone(datetime.datetime(2011, 3, 1)) trunc = 'month' last_day = randint(5, 10) worked1 = randint(1, 3) worked2 = randint(1, 3) for month in xrange(1, 7): for day in xrange(1, last_day + 1): day = utils.add_timezone(datetime.datetime(2011, month, day)) self.log_time(start=day, delta=(worked1, 0), user=self.user) self.log_time(start=day, delta=(worked2, 0), user=self.user2) date_headers = generate_dates(start, end, trunc) pj_totals = self.get_project_totals(date_headers, trunc) for hour in pj_totals[0][0]: self.assertEqual(hour, last_day * worked1) for hour in pj_totals[0][1]: self.assertEqual(hour, last_day * worked2)
def test_daily_total(self): start = utils.add_timezone(datetime.datetime(2011, 1, 1)) day2 = utils.add_timezone(datetime.datetime(2011, 1, 2)) end = utils.add_timezone(datetime.datetime(2011, 1, 3)) self.log_daily(start, day2, end) trunc = 'day' date_headers = generate_dates(start, end, trunc) pj_totals = self.get_project_totals(date_headers, trunc) self.assertEqual( pj_totals[0][0], [Decimal('1.00'), Decimal('1.50'), '']) self.assertEqual( pj_totals[0][1], ['', Decimal('3.00'), Decimal('2.00')]) self.assertEqual(pj_totals[1], [Decimal('1.00'), Decimal('4.50'), Decimal('2.00')])
def test_billable_nonbillable(self): start = utils.add_timezone(datetime.datetime(2011, 1, 1)) day2 = utils.add_timezone(datetime.datetime(2011, 1, 2)) end = utils.add_timezone(datetime.datetime(2011, 1, 3)) self.log_daily(start, day2, end) trunc = 'day' billableQ = Q(project__type__billable=True) non_billableQ = Q(project__type__billable=False) date_headers = generate_dates(start, end, trunc) pj_billable = self.get_project_totals(date_headers, trunc, Q(), 'billable') pj_billable_q = self.get_project_totals(date_headers, trunc, billableQ, 'total') pj_non_billable = self.get_project_totals(date_headers, trunc, Q(), 'non_billable') pj_non_billable_q = self.get_project_totals(date_headers, trunc, non_billableQ, 'total') self.assertEqual(list(pj_billable), list(pj_billable_q)) self.assertEqual(list(pj_non_billable), list(pj_non_billable_q))
def get_context_data(self, **kwargs): """Processes form data to get relevant entries & date_headers.""" context = super(ReportMixin, self).get_context_data(**kwargs) form = self.get_form() if form.is_valid(): data = form.cleaned_data start, end = form.save() entryQ = self.get_entry_query(start, end, data) trunc = data['trunc'] if entryQ: vals = ('pk', 'activity', 'project', 'project__name', 'project__status', 'project__type__label') entries = Entry.objects.date_trunc( trunc, extra_values=vals).filter(entryQ) else: entries = Entry.objects.none() end = end - relativedelta(days=1) date_headers = generate_dates(start, end, by=trunc) context.update({ 'from_date': start, 'to_date': end, 'date_headers': date_headers, 'entries': entries, 'filter_form': form, 'trunc': trunc, }) else: context.update({ 'from_date': None, 'to_date': None, 'date_headers': [], 'entries': Entry.objects.none(), 'filter_form': form, 'trunc': '', }) return context
def check_generate_dates(self, start, end, trunc, dates): for index, day in enumerate(generate_dates(start, end, trunc)): if isinstance(day, datetime.datetime): day = day.date() self.assertEqual(day, dates[index].date())