<commit_before>import datetime
from decimal import Decimal

from django.conf import settings
from django.core.urlresolvers import reverse

from timepiece import models as timepiece
from timepiece import forms as timepiece_forms
from timepiece import utils
from timepiece.tests.base import TimepieceDataTestCase

from dateutil.relativedelta import relativedelta


class PayrollTest(TimepieceDataTestCase):
    def make_logs(self):
        sick = self.create_project()
        vacation = self.create_project()
        settings.TIMEPIECE_PROJECTS = {
            'sick': sick.pk, 'vacation': vacation.pk
        }
        billable = self.log_time(delta=(3, 30), status='approved')
        non_billable = self.log_time(delta=(2, 0),
            billable=False, status='approved')
        #summary['total'] does not increase from unapproved hours
        unapproved = self.log_time(delta=(5, 0), status='verified')
        sick = self.log_time(delta=(8, 0), project=sick, status='approved')
        vacation = self.log_time(delta=(4, 0), project=vacation,
            status='approved')
        #make an entry on the very last day no matter the current time 
        #but start in the morning to stay in the billing period.
        end_day = datetime.datetime.now() + \
            relativedelta(months=1, day=1, hour=0) - \
            relativedelta(days=1)
        last_day = self.log_time(start=end_day, status='approved', delta=(8,0))

    def testPersonSummary(self):
        self.make_logs()
        rp = self.create_person_repeat_period({'user': self.user})
        start = datetime.date.today().replace(day=1)
        end = start + relativedelta(months=1)
        summary = rp.summary(start, end)
        self.check_summary(summary)
    
    def testPersonSummaryView(self):
        from timepiece.templatetags import timepiece_tags as tags
        self.client.login(username='superuser', password='<PASSWORD>')
        self.make_logs()
        rp = self.create_person_repeat_period({'user': self.user})
        response = self.client.get(reverse('payroll_summary'), follow=True)
        context = response.context
        date_filters = tags.date_filters(context, 'months')
        this_month = date_filters['filters'].values()[0][-1]
        this_month_url = this_month[1]
        response = self.client.get(this_month_url, follow=True)
        start = context['from_date']
        end = context['to_date']
        this_user = context['periods'].get(user=self.user.pk)
        summary = this_user.summary(start, end)
        self.check_summary(summary)

    def check_summary(self, summary):
        self.assertEqual(summary['billable'], Decimal('11.50'))
        self.assertEqual(summary['non_billable'], Decimal('2.00'))
        self.assertEqual(summary['paid_leave']['sick'], Decimal('8.00'))
        self.assertEqual(summary['paid_leave']['vacation'], Decimal('4.00'))
        self.assertEqual(summary['total'], Decimal('25.50'))

    def testPersonSummaryDropZeroHours(self):
        """Test that users with no hours for the period are not listed"""
        self.client.login(username='superuser', password='<PASSWORD>')
        self.make_logs()
        #user 1 has hours logged, but not user2
        rp = self.create_person_repeat_period({'user': self.user2})
        response = self.client.get(reverse('payroll_summary'), follow=True)
        self.assertEqual(len(response.context['periods']), 0)

        #TODO Make a test to verify that overtime shows from last month
        #even if there are no hours from this month

    def testWeeklyHours(self):
        """ Test basic functionality of hours worked per week """
        rp = self.create_person_repeat_period({'user': self.user})
        p1 = self.create_project()
        start = datetime.datetime(2011, 1, 3)
        self.log_time(project=p1, start=start, delta=(8, 0), status='approved')
        start = datetime.datetime(2011, 1, 4)
        self.log_time(project=p1, start=start, delta=(8, 0), status='approved')<commit_msg>[#63] Added tests to verify conditions for appearing on payroll<commit_after>import datetime
from decimal import Decimal

from django.conf import settings
from django.core.urlresolvers import reverse

from timepiece import models as timepiece
from timepiece import forms as timepiece_forms
from timepiece import utils
from timepiece.tests.base import TimepieceDataTestCase

from dateutil.relativedelta import relativedelta


class PayrollTest(TimepieceDataTestCase):
    def make_logs(self):
        sick = self.create_project()
        vacation = self.create_project()
        settings.TIMEPIECE_PROJECTS = {
            'sick': sick.pk, 'vacation': vacation.pk
        }
        billable = self.log_time(delta=(3, 30), status='approved')
        non_billable = self.log_time(delta=(2, 0),
            billable=False, status='approved')
        #summary['total'] does not increase from unapproved hours
        unapproved = self.log_time(delta=(5, 0), status='verified')
        sick = self.log_time(delta=(8, 0), project=sick, status='approved')
        vacation = self.log_time(delta=(4, 0), project=vacation,
            status='approved')
        #make an entry on the very last day no matter the current time 
        #but start in the morning to stay in the billing period.
        end_day = datetime.datetime.now() + \
            relativedelta(months=1, day=1, hour=0) - \
            relativedelta(days=1)
        last_day = self.log_time(start=end_day, status='approved', delta=(8,0))

    def testPersonSummary(self):
        self.make_logs()
        rp = self.create_person_repeat_period({'user': self.user})
        start = datetime.date.today().replace(day=1)
        end = start + relativedelta(months=1)
        summary = rp.summary(start, end)
        self.check_summary(summary)
    
    def testPersonSummaryView(self):
        from timepiece.templatetags import timepiece_tags as tags
        self.client.login(username='superuser', password='<PASSWORD>')
        self.make_logs()
        rp = self.create_person_repeat_period({'user': self.user})
        response = self.client.get(reverse('payroll_summary'), follow=True)
        context = response.context
        date_filters = tags.date_filters(context, 'months')
        this_month = date_filters['filters'].values()[0][-1]
        this_month_url = this_month[1]
        response = self.client.get(this_month_url, follow=True)
        start = context['from_date']
        end = context['to_date']
        this_user = context['periods'].get(user=self.user.pk)
        summary = this_user.summary(start, end)
        self.check_summary(summary)

    def check_summary(self, summary):
        self.assertEqual(summary['billable'], Decimal('11.50'))
        self.assertEqual(summary['non_billable'], Decimal('2.00'))
        self.assertEqual(summary['paid_leave']['sick'], Decimal('8.00'))
        self.assertEqual(summary['paid_leave']['vacation'], Decimal('4.00'))
        self.assertEqual(summary['total'], Decimal('25.50'))

    def testPersonSummaryShowWithHours(self):
        """Test that users with hours for the period are listed"""
        self.client.login(username='superuser', password='<PASSWORD>')
        self.make_logs()
        rp = self.create_person_repeat_period({'user': self.user})
        response = self.client.get(reverse('payroll_summary'), follow=True)
        self.assertEqual(len(response.context['periods']), 1)

    def testPersonSummaryNoShowWithoutHours(self):
        """Test that users with no hours for the period are not listed"""
        self.client.login(username='superuser', password='<PASSWORD>')
        self.make_logs()
        #user 1 has hours logged, but not user2. User2 should not appear
        rp = self.create_person_repeat_period({'user': self.user2})
        response = self.client.get(reverse('payroll_summary'), follow=True)
        self.assertEqual(len(response.context['periods']), 0)

    def testPersonSummaryOvertimeBefore(self):
        """
        Users with overtime from the last week of last month should appear
        (even if they have no hours for this month)
        """
        rp = self.create_person_repeat_period({'user': self.user})
        self.client.login(username='superuser', password='<PASSWORD>')
        #Find the day after the last billable day of the previous month
        #This is the first day to consider for overtime this period
        now = datetime.datetime.now()
        first = now - relativedelta(day=1, months=1)
        first = utils.get_last_billable_day(first) + relativedelta(days=1)
        self.log_time(start=first, delta=(44, 00), status='approved')
        response = self.client.get(reverse('payroll_summary'))
        self.assertEqual(len(response.context['periods']), 1)

    def testPersonSummaryNoOvertimeBefore(self):
        """
        Users with no hours this period, that worked last week of last period
        but have no overtime shoud not appear
        """
        rp = self.create_person_repeat_period({'user': self.user})
        self.client.login(username='superuser', password='<PASSWORD>')
        now = datetime.datetime.now()
        first = now - relativedelta(day=1, months=1)
        first = utils.get_last_billable_day(first) + relativedelta(days=1)
        self.log_time(start=first, delta=(40, 00), status='approved')
        response = self.client.get(reverse('payroll_summary'))
        self.assertEqual(len(response.context['periods']), 0)

    def testWeeklyHours(self):
        """ Test basic functionality of hours worked per week """
        rp = self.create_person_repeat_period({'user': self.user})
        p1 = self.create_project()
        start = datetime.datetime(2011, 1, 3)
        self.log_time(project=p1, start=start, delta=(8, 0), status='approved')
        start = datetime.datetime(2011, 1, 4)
        self.log_time(project=p1, start=start, delta=(8, 0), status='approved')
{'fraction_non_alphanumeric': 0.12180587819412181, 'fraction_numerical': 0.014543985456014544, 'mean_word_length': 3.3014769765421375, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5419276', 'n_tokens_mistral': 2976, 'n_tokens_neox': 2845, 'n_words': 664}