def test_absence_fill_worktime_reported_time_to_long(auth_client): """ Verify absence fill worktime is zero when reported time is too long. Too long is defined when reported time is longer than worktime per day. """ date = datetime.date(2017, 5, 10) user = auth_client.user EmploymentFactory.create( user=user, start_date=date, worktime_per_day=datetime.timedelta(hours=8) ) type = AbsenceTypeFactory.create(fill_worktime=True) ReportFactory.create( user=user, date=date, duration=datetime.timedelta(hours=8, minutes=30) ) data = { "data": { "type": "absences", "id": None, "attributes": {"date": date.strftime("%Y-%m-%d")}, "relationships": { "type": {"data": {"type": "absence-types", "id": type.id}} }, } } url = reverse("absence-list") response = auth_client.post(url, data) assert response.status_code == status.HTTP_201_CREATED json = response.json() assert json["data"]["attributes"]["duration"] == "00:00:00"
def test_absence_fill_worktime(auth_client): """Should create an absence which fills the worktime.""" date = datetime.date(2017, 5, 10) user = auth_client.user EmploymentFactory.create( user=user, start_date=date, worktime_per_day=datetime.timedelta(hours=8) ) type = AbsenceTypeFactory.create(fill_worktime=True) ReportFactory.create(user=user, date=date, duration=datetime.timedelta(hours=5)) data = { "data": { "type": "absences", "id": None, "attributes": {"date": date.strftime("%Y-%m-%d")}, "relationships": { "type": {"data": {"type": "absence-types", "id": type.id}} }, } } url = reverse("absence-list") response = auth_client.post(url, data) assert response.status_code == status.HTTP_201_CREATED json = response.json() assert json["data"]["attributes"]["duration"] == "03:00:00"
def test_worktime_balance_with_employments(auth_client, django_assert_num_queries): # Calculate over one week start_date = date(2017, 3, 19) end_date = date(2017, 3, 26) employment = EmploymentFactory.create(user=auth_client.user, start_date=start_date, worktime_per_day=timedelta( hours=8, minutes=30), end_date=date(2017, 3, 23)) EmploymentFactory.create(user=auth_client.user, start_date=date(2017, 3, 24), worktime_per_day=timedelta(hours=8), end_date=None) # Overtime credit of 10 hours OvertimeCreditFactory.create(user=auth_client.user, date=start_date, duration=timedelta(hours=10, minutes=30)) # One public holiday during workdays PublicHolidayFactory.create(date=start_date, location=employment.location) # One public holiday on weekend PublicHolidayFactory.create(date=start_date + timedelta(days=1), location=employment.location) # 2x 10 hour reported worktime ReportFactory.create(user=auth_client.user, date=start_date + timedelta(days=3), duration=timedelta(hours=10)) ReportFactory.create(user=auth_client.user, date=start_date + timedelta(days=4), duration=timedelta(hours=10)) # one absence AbsenceFactory.create(user=auth_client.user, date=start_date + timedelta(days=5)) url = reverse('worktime-balance-detail', args=[ '{0}_{1}'.format(auth_client.user.id, end_date.strftime('%Y-%m-%d')) ]) with django_assert_num_queries(12): result = auth_client.get(url) assert result.status_code == status.HTTP_200_OK # 4 workdays 8.5 hours, 1 workday 8 hours, minus one holiday 8.5 # minutes 10.5 hours overtime credit expected_worktime = timedelta(hours=23) # 2 x 10 reports hours + 1 absence of 8 hours expected_reported = timedelta(hours=28) json = result.json() assert json['data']['attributes']['balance'] == ( duration_string(expected_reported - expected_worktime))
def test_absence_update_owner(auth_client): user = auth_client.user date = datetime.date(2017, 5, 3) absence = AbsenceFactory.create( user=auth_client.user, date=datetime.date(2016, 5, 3) ) EmploymentFactory.create( user=user, start_date=date, worktime_per_day=datetime.timedelta(hours=8) ) data = { "data": { "type": "absences", "id": absence.id, "attributes": {"date": date.strftime("%Y-%m-%d")}, } } url = reverse("absence-detail", args=[absence.id]) response = auth_client.patch(url, data) assert response.status_code == status.HTTP_200_OK json = response.json() assert json["data"]["attributes"]["date"] == "2017-05-03"
def test_absence_create(auth_client): user = auth_client.user date = datetime.date(2017, 5, 4) EmploymentFactory.create( user=user, start_date=date, worktime_per_day=datetime.timedelta(hours=8) ) type = AbsenceTypeFactory.create() data = { "data": { "type": "absences", "id": None, "attributes": {"date": date.strftime("%Y-%m-%d")}, "relationships": { "type": {"data": {"type": "absence-types", "id": type.id}} }, } } url = reverse("absence-list") response = auth_client.post(url, data) assert response.status_code == status.HTTP_201_CREATED json = response.json() assert json["data"]["relationships"]["user"]["data"]["id"] == ( str(auth_client.user.id) )
def test_notify_supervisors(db, mailoutbox): """Test time range 2017-7-17 till 2017-7-23.""" start = date(2017, 7, 14) # supervisee with short time supervisee = UserFactory.create() supervisor = UserFactory.create() supervisee.supervisors.add(supervisor) EmploymentFactory.create(user=supervisee, start_date=start, percentage=100) workdays = rrule(DAILY, dtstart=start, until=date.today(), # range is excluding last byweekday=range(MO.weekday, FR.weekday + 1)) for dt in workdays: ReportFactory.create(user=supervisee, date=dt, duration=timedelta(hours=7)) call_command('notify_supervisors_shorttime') # checks assert len(mailoutbox) == 1 mail = mailoutbox[0] assert mail.to == [supervisor.email] body = mail.body assert 'Time range: 17.07.2017 - 23.07.2017\nRatio: 0.9' in body expected = ( '{0} 35.0/42.5 (Ratio 0.82 Delta -7.5 Balance -9.0)' ).format( supervisee.get_full_name() ) assert expected in body
def setUp(self): """Set the environment for the tests up.""" super().setUp() user = self.user other_user = User.objects.create_user(username='******', password='******') EmploymentFactory.create(user=user, start_date=datetime.date(2017, 5, 1), end_date=None) EmploymentFactory.create(user=other_user, start_date=datetime.date(2017, 5, 1), end_date=None) self.absences = [ AbsenceFactory.create(user=user, date=datetime.date(2017, 5, 1)), AbsenceFactory.create(user=user, date=datetime.date(2017, 5, 2)), AbsenceFactory.create(user=user, date=datetime.date(2017, 5, 3)) ] AbsenceFactory.create(user=other_user, date=datetime.date(2017, 5, 1)) AbsenceFactory.create(user=other_user, date=datetime.date(2017, 5, 2)) AbsenceFactory.create(user=other_user, date=datetime.date(2017, 5, 3))
def test_user_transfer(superadmin_client): user = UserFactory.create() EmploymentFactory.create(user=user, start_date=date(2017, 12, 28), percentage=100) AbsenceTypeFactory.create(fill_worktime=True) AbsenceTypeFactory.create(fill_worktime=False) absence_type = AbsenceTypeFactory.create(fill_worktime=False) AbsenceFactory.create(user=user, type=absence_type, date=date(2017, 12, 29)) url = reverse('user-transfer', args=[user.id]) response = superadmin_client.post(url) assert response.status_code == status.HTTP_204_NO_CONTENT # running transfer twice should lead to same result response = superadmin_client.post(url) assert response.status_code == status.HTTP_204_NO_CONTENT assert user.overtime_credits.count() == 1 overtime_credit = user.overtime_credits.first() assert overtime_credit.transfer assert overtime_credit.date == date(2018, 1, 1) assert overtime_credit.duration == timedelta(hours=-8, minutes=-30) assert overtime_credit.comment == 'Transfer 2017' assert user.absence_credits.count() == 1 absence_credit = user.absence_credits.first() assert absence_credit.transfer assert absence_credit.date == date(2018, 1, 1) assert absence_credit.days == -1 assert absence_credit.comment == 'Transfer 2017'
def test_worktime_balance_list_last_reported_date(auth_client, django_assert_num_queries): EmploymentFactory.create( user=auth_client.user, start_date=date(2017, 2, 1), end_date=date(2017, 2, 2), worktime_per_day=timedelta(hours=8), ) ReportFactory.create(user=auth_client.user, date=date(2017, 2, 1), duration=timedelta(hours=10)) # reports today and in the future should be ignored ReportFactory.create(user=auth_client.user, date=date(2017, 2, 2), duration=timedelta(hours=10)) ReportFactory.create(user=auth_client.user, date=date(2017, 2, 3), duration=timedelta(hours=10)) url = reverse('worktime-balance-list') with django_assert_num_queries(10): result = auth_client.get(url, data={'last_reported_date': 1}) assert result.status_code == status.HTTP_200_OK json = result.json() assert len(json['data']) == 1 entry = json['data'][0] assert entry['attributes']['date'] == '2017-02-01' assert entry['attributes']['balance'] == '02:00:00'
def test_absence_credit_balance(self): """Should calculate an absence credit balance.""" absence_credit = AbsenceCreditFactory.create( user=self.user, duration=timedelta(hours=30)) EmploymentFactory.create(user=self.user, start_date=absence_credit.date - timedelta(days=1), worktime_per_day=timedelta(hours=8)) AbsenceFactory.create(user=self.user, type=absence_credit.absence_type, date=absence_credit.date + timedelta(days=1)) AbsenceFactory.create(user=self.user, type=absence_credit.absence_type, date=absence_credit.date - timedelta(days=1), duration=timedelta(hours=8)) url = reverse('absence-credit-detail', args=[absence_credit.id]) res = self.client.get(url) result = self.result(res) assert result['data']['attributes']['duration'] == '1 06:00:00' assert result['data']['attributes']['used'] == '08:00:00' assert result['data']['attributes']['balance'] == '22:00:00'
def setUp(self): """Set the environment for the tests up.""" super().setUp() self.users = UserFactory.create_batch(3) for user in self.users + [self.user]: EmploymentFactory.create(user=user)
def test_employment_unique_active(db): """Should only be able to have one active employment per user.""" user = UserFactory.create() EmploymentFactory.create(user=user, end_date=None) employment = EmploymentFactory.create(user=user) form = EmploymentForm({"end_date": None}, instance=employment) with pytest.raises(ValueError): form.save()
def test_employment_list_superuser(superadmin_client): EmploymentFactory.create_batch(2) EmploymentFactory.create(user=superadmin_client.user) url = reverse('employment-list') result = superadmin_client.get(url) assert result.status_code == status.HTTP_200_OK json = result.json() assert len(json['data']) == 3
def setUp(self): """Set the environment for the tests up.""" super().setUp() self.employments = [ EmploymentFactory.create(user=self.user, start_date=datetime.date(2010, 1, 1), end_date=datetime.date(2015, 1, 1)), EmploymentFactory.create(user=self.user, start_date=datetime.date(2015, 1, 2)) ] EmploymentFactory.create_batch(10)
def test_employment_list_supervisor(auth_client): user = UserFactory.create() auth_client.user.supervisees.add(user) EmploymentFactory.create_batch(1) EmploymentFactory.create(user=auth_client.user) EmploymentFactory.create(user=user) url = reverse('employment-list') result = auth_client.get(url) assert result.status_code == status.HTTP_200_OK json = result.json() assert len(json['data']) == 2
def test_employment_list_filter_date(auth_client): EmploymentFactory.create(user=auth_client.user, start_date=date(2017, 1, 1), end_date=date(2017, 4, 1)) employment = EmploymentFactory.create(user=auth_client.user, start_date=date(2017, 4, 2), end_date=None) url = reverse("employment-list") result = auth_client.get(url, data={"date": "2017-04-05"}) assert result.status_code == status.HTTP_200_OK json = result.json() assert len(json["data"]) == 1 assert json["data"][0]["id"] == str(employment.id)
def test_absence_public_holiday(auth_client): """Should not be able to create an absence on a public holiday.""" date = datetime.date(2017, 5, 16) user = auth_client.user type = AbsenceTypeFactory.create() employment = EmploymentFactory.create( user=user, start_date=date, worktime_per_day=datetime.timedelta(hours=8) ) PublicHolidayFactory.create(location=employment.location, date=date) data = { "data": { "type": "absences", "id": None, "attributes": {"date": date.strftime("%Y-%m-%d")}, "relationships": { "type": {"data": {"type": "absence-types", "id": type.id}} }, } } url = reverse("absence-list") response = auth_client.post(url, data) assert response.status_code == status.HTTP_400_BAD_REQUEST
def test_employment_update_overlapping(superadmin_client): user = superadmin_client.user EmploymentFactory.create(user=user, end_date=None) employment = EmploymentFactory.create(user=user) data = { "data": { "type": "employments", "id": employment.id, "attributes": { "end_date": None }, } } url = reverse("employment-detail", args=[employment.id]) result = superadmin_client.patch(url, data) assert result.status_code == status.HTTP_400_BAD_REQUEST
def test_employment_update_overlapping(superadmin_client): user = superadmin_client.user EmploymentFactory.create(user=user, end_date=None) employment = EmploymentFactory.create(user=user) data = { 'data': { 'type': 'employments', 'id': employment.id, 'attributes': { 'end_date': None, } } } url = reverse('employment-detail', args=[employment.id]) result = superadmin_client.patch(url, data) assert result.status_code == status.HTTP_400_BAD_REQUEST
def test_employment_start_before_end(db): employment = EmploymentFactory.create() form = EmploymentForm({ 'start_date': date(2009, 1, 1), 'end_date': date(2016, 1, 1) }, instance=employment) with pytest.raises(ValueError): form.save()
def test_absence_balance_full_day(auth_client, django_assert_num_queries): day = date(2017, 2, 28) user = auth_client.user EmploymentFactory.create(user=user, start_date=day) absence_type = AbsenceTypeFactory.create() AbsenceCreditFactory.create(date=day, user=user, days=5, absence_type=absence_type) # credit on different user, may not show up AbsenceCreditFactory.create(date=date.today(), absence_type=absence_type) AbsenceFactory.create(date=day, user=user, type=absence_type) AbsenceFactory.create(date=day - timedelta(days=1), user=user, type=absence_type) url = reverse('absence-balance-list') with django_assert_num_queries(7): result = auth_client.get(url, data={ 'date': '2017-03-01', 'user': user.id, 'include': 'absence_credits,absence_type' }) assert result.status_code == status.HTTP_200_OK json = result.json() assert len(json['data']) == 1 entry = json['data'][0] assert (entry['id'] == '{0}_{1}_2017-03-01'.format(user.id, absence_type.id)) assert entry['attributes']['credit'] == 5 assert entry['attributes']['used-days'] == 2 assert entry['attributes']['used-duration'] is None assert entry['attributes']['balance'] == 3 assert len(json['included']) == 2
def test_employment_list_authenticated(auth_client): EmploymentFactory.create_batch(2) employment = EmploymentFactory.create(user=auth_client.user) url = reverse('employment-list') result = auth_client.get(url) assert result.status_code == status.HTTP_200_OK json = result.json() assert len(json['data']) == 1 assert json['data'][0]['id'] == str(employment.id)
def test_absence_balance_fill_worktime(auth_client, django_assert_num_queries): day = date(2017, 2, 28) user = UserFactory.create() user.supervisors.add(auth_client.user) EmploymentFactory.create(user=user, start_date=day, worktime_per_day=timedelta(hours=5)) absence_type = AbsenceTypeFactory.create(fill_worktime=True) ReportFactory.create(user=user, date=day + timedelta(days=1), duration=timedelta(hours=4)) AbsenceFactory.create(date=day + timedelta(days=1), user=user, type=absence_type) AbsenceFactory.create(date=day, user=user, type=absence_type) url = reverse('absence-balance-list') with django_assert_num_queries(12): result = auth_client.get(url, data={ 'date': '2017-03-01', 'user': user.id, 'include': 'absence_credits,absence_type' }) assert result.status_code == status.HTTP_200_OK json = result.json() assert len(json['data']) == 1 entry = json['data'][0] assert (entry['id'] == '{0}_{1}_2017-03-01'.format(user.id, absence_type.id)) assert entry['attributes']['credit'] is None assert entry['attributes']['balance'] is None assert entry['attributes']['used-days'] is None assert entry['attributes']['used-duration'] == '06:00:00'
def test_employment_list_filter_date(auth_client): EmploymentFactory.create( user=auth_client.user, start_date=date(2017, 1, 1,), end_date=date(2017, 4, 1,) ) employment = EmploymentFactory.create( user=auth_client.user, start_date=date(2017, 4, 2,), end_date=None ) url = reverse('employment-list') result = auth_client.get(url, data={ 'date': '2017-04-05' }) assert result.status_code == status.HTTP_200_OK json = result.json() assert len(json['data']) == 1 assert json['data'][0]['id'] == str(employment.id)
def test_absence_update_superadmin_date(superadmin_client): """Test that superadmin may not change date of absence.""" user = UserFactory.create() date = datetime.date(2017, 5, 3) absence = AbsenceFactory.create(user=user, date=datetime.date(2016, 5, 3)) EmploymentFactory.create( user=user, start_date=date, worktime_per_day=datetime.timedelta(hours=8) ) data = { "data": { "type": "absences", "id": absence.id, "attributes": {"date": date.strftime("%Y-%m-%d")}, } } url = reverse("absence-detail", args=[absence.id]) response = superadmin_client.patch(url, data) assert response.status_code == status.HTTP_400_BAD_REQUEST
def test_absence_balance_full_day(auth_client, django_assert_num_queries): day = date(2017, 2, 28) user = auth_client.user EmploymentFactory.create(user=user, start_date=day) absence_type = AbsenceTypeFactory.create() AbsenceCreditFactory.create(date=day, user=user, days=5, absence_type=absence_type) # credit on different user, may not show up AbsenceCreditFactory.create(date=date.today(), absence_type=absence_type) AbsenceFactory.create(date=day, user=user, type=absence_type) AbsenceFactory.create(date=day - timedelta(days=1), user=user, type=absence_type) url = reverse("absence-balance-list") with django_assert_num_queries(6): result = auth_client.get( url, data={ "date": "2017-03-01", "user": user.id, "include": "absence_credits,absence_type", }, ) assert result.status_code == status.HTTP_200_OK json = result.json() assert len(json["data"]) == 1 entry = json["data"][0] assert entry["id"] == "{0}_{1}_2017-03-01".format(user.id, absence_type.id) assert entry["attributes"]["credit"] == 5 assert entry["attributes"]["used-days"] == 2 assert entry["attributes"]["used-duration"] is None assert entry["attributes"]["balance"] == 3 assert len(json["included"]) == 2
def test_absence_balance_fill_worktime(auth_client, django_assert_num_queries): day = date(2017, 2, 28) user = UserFactory.create() user.supervisors.add(auth_client.user) EmploymentFactory.create( user=user, start_date=day, worktime_per_day=timedelta(hours=5) ) absence_type = AbsenceTypeFactory.create(fill_worktime=True) ReportFactory.create( user=user, date=day + timedelta(days=1), duration=timedelta(hours=4) ) AbsenceFactory.create(date=day + timedelta(days=1), user=user, type=absence_type) AbsenceFactory.create(date=day, user=user, type=absence_type) url = reverse("absence-balance-list") with django_assert_num_queries(11): result = auth_client.get( url, data={ "date": "2017-03-01", "user": user.id, "include": "absence_credits,absence_type", }, ) assert result.status_code == status.HTTP_200_OK json = result.json() assert len(json["data"]) == 1 entry = json["data"][0] assert entry["id"] == "{0}_{1}_2017-03-01".format(user.id, absence_type.id) assert entry["attributes"]["credit"] is None assert entry["attributes"]["balance"] is None assert entry["attributes"]["used-days"] is None assert entry["attributes"]["used-duration"] == "06:00:00"
def test_employment_get_at(db): """Should return the right employment on a date.""" user = UserFactory.create() employment = EmploymentFactory.create(user=user) assert Employment.objects.get_at(user, employment.start_date) == employment employment.end_date = employment.start_date + timedelta(days=20) employment.save() with pytest.raises(Employment.DoesNotExist): Employment.objects.get_at(user, employment.start_date + timedelta(days=21))
def test_notify_changed_employments(db, mailoutbox, freezer): email = "*****@*****.**" # employments changed too far in the past freezer.move_to("2017-08-27") EmploymentFactory.create_batch(2) # employments which should show up in report freezer.move_to("2017-09-03") finished = EmploymentFactory.create(end_date=date(2017, 10, 10), percentage=80) new = EmploymentFactory.create(percentage=100) freezer.move_to("2017-09-04") call_command("notify_changed_employments", email=email) # checks assert len(mailoutbox) == 1 mail = mailoutbox[0] assert mail.to == [email] print(mail.body) assert "80% {0}".format(finished.user.get_full_name()) in mail.body assert "None 100% {0}".format(new.user.get_full_name()) in mail.body
def test_employment_update_end_before_start(superadmin_client): employment = EmploymentFactory.create(user=superadmin_client.user) data = { 'data': { 'type': 'employments', 'id': employment.id, 'attributes': { 'start_date': '2017-03-01', 'end_date': '2017-01-01', } } } url = reverse('employment-detail', args=[employment.id]) result = superadmin_client.patch(url, data) assert result.status_code == status.HTTP_400_BAD_REQUEST