Skip to content
This repository has been archived by the owner on Oct 30, 2021. It is now read-only.

[BB-3173] Fix calculating vacations and commitments #59

Merged
merged 4 commits into from
Nov 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compose/local/django/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.8-alpine
FROM python:3.9-alpine

ENV PYTHONUNBUFFERED 1

Expand Down
2 changes: 1 addition & 1 deletion compose/production/django/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.8-alpine
FROM python:3.9-alpine

ENV PYTHONUNBUFFERED 1

Expand Down
2 changes: 1 addition & 1 deletion compose/production/postgres/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM postgres:10.3
FROM postgres:10

COPY ./compose/production/postgres/maintenance /usr/local/bin/maintenance
RUN chmod +x /usr/local/bin/maintenance/*
Expand Down
7 changes: 4 additions & 3 deletions config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -518,8 +518,8 @@
# Group 1. cell's key
# Group 2. issue number
SPRINT_ISSUE_REGEX = env.str("SPRINT_ISSUE_REGEX", r"(\w+)-(\d+)")
# An UTC hour at which the sprint meeting starts.
SPRINT_MEETING_HOUR_UTC = env.int("SPRINT_MEETING_HOUR_UTC", 16)
# UTC time at which a new sprint starts (format: `%H:%M`).
SPRINT_START_TIME_UTC = env.int("SPRINT_START_TIME_UTC", "00:00")
# Exact name of the tickets for logging the clean sprint hints.
SPRINT_MEETINGS_TICKET = env.str("SPRINT_MEETINGS_TICKET", "Meetings")

Expand All @@ -545,7 +545,8 @@
GOOGLE_SPILLOVER_SPREADSHEET = env.str("GOOGLE_SPILLOVER_SPREADSHEET")
GOOGLE_CONTACT_SPREADSHEET = env.str("GOOGLE_CONTACT_SPREADSHEET")
GOOGLE_AVAILABILITY_RANGE = env.str("GOOGLE_AVAILABILITY_RANGE")
GOOGLE_AVAILABILITY_REGEX = env.str("GOOGLE_AVAILABILITY_REGEX", r"(\d+).*(pm|am)-(\d+).*(pm|am)")
# Regex for retrieving users' availability from the "Contact" sheet.
GOOGLE_AVAILABILITY_REGEX = env.str("GOOGLE_AVAILABILITY_REGEX", r"\d+(?::\d+)?.*?(?:pm|am)")
GOOGLE_AVAILABILITY_TIME_FORMAT = env.str("GOOGLE_AVAILABILITY_TIME_FORMAT", "%I%p")
GOOGLE_SPILLOVER_SPREADSHEET_URL = f"https://docs.google.com/spreadsheets/d/{GOOGLE_SPILLOVER_SPREADSHEET}"
# Spreadsheet with the cell rotations.
Expand Down
19 changes: 0 additions & 19 deletions config/settings/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,6 @@
# https://docs.djangoproject.com/en/dev/ref/settings/#email-port
EMAIL_PORT = 1025

# django-debug-toolbar
# ------------------------------------------------------------------------------
# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#prerequisites
INSTALLED_APPS += ["debug_toolbar"] # noqa F405
# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#middleware
MIDDLEWARE += ["debug_toolbar.middleware.DebugToolbarMiddleware"] # noqa F405
# https://django-debug-toolbar.readthedocs.io/en/latest/configuration.html#debug-toolbar-config
DEBUG_TOOLBAR_CONFIG = {
"DISABLE_PANELS": ["debug_toolbar.panels.redirects.RedirectsPanel"],
"SHOW_TEMPLATE_CONTEXT": True,
}
# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#internal-ips
INTERNAL_IPS = ["127.0.0.1", "10.0.2.2"]
if env("USE_DOCKER") == "yes":
import socket

hostname, _, ips = socket.gethostbyname_ex(socket.gethostname())
INTERNAL_IPS += [ip[:-1] + "1" for ip in ips]

# django-extensions
# ------------------------------------------------------------------------------
# https://django-extensions.readthedocs.io/en/latest/installation_instructions.html#configuration
Expand Down
35 changes: 2 additions & 33 deletions config/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
from django.conf.urls import url
from django.conf.urls.static import static
from django.contrib import admin
from django.shortcuts import redirect
from django.urls import (
include,
path,
)
from django.views import defaults as default_views
from django.views.generic import TemplateView
from drf_yasg import openapi
from drf_yasg.views import get_schema_view
from rest_framework import permissions
Expand All @@ -29,14 +29,9 @@
)

urlpatterns = [
path("", TemplateView.as_view(template_name="pages/home.html"), name="home"),
path(
"about/", TemplateView.as_view(template_name="pages/about.html"), name="about"
),
path("", lambda request: redirect('/swagger')),
# Django Admin, use {% url 'admin:index' %}
path(settings.ADMIN_URL, admin.site.urls),
# User management
path("users/", include("sprints.users.urls", namespace="users")),
# Dashboard
path("dashboard/", include("sprints.dashboard.urls", namespace="dashboard")),
# Sustainability Dashboard
Expand Down Expand Up @@ -69,29 +64,3 @@
url(r'^redoc/$', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
# Your stuff: custom urls includes go here
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

if settings.DEBUG:
# This allows the error pages to be debugged during development, just visit
# these url in browser to see how these error pages look like.
urlpatterns += [
path(
"400/",
default_views.bad_request,
kwargs={"exception": Exception("Bad Request!")},
),
path(
"403/",
default_views.permission_denied,
kwargs={"exception": Exception("Permission Denied")},
),
path(
"404/",
default_views.page_not_found,
kwargs={"exception": Exception("Page not Found")},
),
path("500/", default_views.server_error),
]
if "debug_toolbar" in settings.INSTALLED_APPS:
import debug_toolbar

urlpatterns = [path("__debug__/", include(debug_toolbar.urls))] + urlpatterns
35 changes: 18 additions & 17 deletions requirements/base.txt
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
pytz~=2019.1 # https://github.com/stub42/pytz
python-slugify~=3.0.2 # https://github.com/un33k/python-slugify
Pillow~=6.0.0 # https://github.com/python-pillow/Pillow
pytz~=2020.4 # https://github.com/stub42/pytz
python-slugify~=4.0.1 # https://github.com/un33k/python-slugify
Pillow~=8.0.1 # https://github.com/python-pillow/Pillow
argon2-cffi~=20.1.0 # https://github.com/hynek/argon2_cffi
redis~=3.2.1 # https://github.com/antirez/redis
celery~=4.3.0 # pyup: < 5.0 # https://github.com/celery/celery
flower~=0.9.3 # https://github.com/mher/flower
redis~=3.5.3 # https://github.com/antirez/redis
celery~=4.4.7 # pyup: < 5.0 # https://github.com/celery/celery
flower~=0.9.5 # https://github.com/mher/flower
psycopg2==2.8.6 --no-binary psycopg2 # https://github.com/psycopg/psycopg2

# Django
# ------------------------------------------------------------------------------
django~=2.2.1 # pyup: < 3.0 # https://www.djangoproject.com/
django~=3.1.3 # pyup: < 3.0 # https://www.djangoproject.com/
django-environ~=0.4.5 # https://github.com/joke2k/django-environ
django-model-utils~=3.1.2 # https://github.com/jazzband/django-model-utils
django-allauth~=0.39.1 # https://github.com/pennersr/django-allauth
django-crispy-forms~=1.7.2 # https://github.com/django-crispy-forms/django-crispy-forms
django-redis~=4.10.0 # https://github.com/niwinz/django-redis
django-cors-headers~=3.0.2 # https://github.com/ottoyiu/django-cors-headers
django-model-utils~=4.0.0 # https://github.com/jazzband/django-model-utils
django-allauth~=0.43.0 # https://github.com/pennersr/django-allauth
django-crispy-forms~=1.9.2 # https://github.com/django-crispy-forms/django-crispy-forms
django-redis~=4.12.1 # https://github.com/niwinz/django-redis
django-cors-headers~=3.5.0 # https://github.com/ottoyiu/django-cors-headers

# Django REST Framework
# ------------------------------------------------------------------------------
djangorestframework~=3.9.4 # https://github.com/encode/django-rest-framework
djangorestframework~=3.12.2 # https://github.com/encode/django-rest-framework
djangorestframework-jwt~=1.11.0 # https://github.com/GetBlimp/django-rest-framework-jwt
djangorestframework_simplejwt~=4.3.0 # https://github.com/davesque/django-rest-framework-simplejwt
djangorestframework_simplejwt~=4.6.0 # https://github.com/davesque/django-rest-framework-simplejwt
coreapi~=2.3.3 # https://github.com/core-api/python-client
drf-yasg~=1.17.0 # https://github.com/axnsan12/drf-yasg
drf-yasg~=1.20.0 # https://github.com/axnsan12/drf-yasg

# REST auth
# ------------------------------------------------------------------------------
Expand All @@ -33,6 +34,6 @@ git+https://github.com/open-craft/django-rest-auth.git@0.10.0 # fork of https:/
jira~=2.0.1.0rc1 # https://github.com/pycontribs/jira

# Google API
google-api-python-client~=1.7.9 # https://github.com/googleapis/google-api-python-client
google-api-python-client~=1.12.5 # https://github.com/googleapis/google-api-python-client
oauth2client~=4.1.3 # https://github.com/googleapis/oauth2client
more-itertools==8.2.0
more-itertools==8.6.0
27 changes: 13 additions & 14 deletions requirements/local.txt
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
-r ./base.txt

Werkzeug==0.15.4 # https://github.com/pallets/werkzeug
ipdb==0.12 # https://github.com/gotcha/ipdb
pdbpp==0.10.0 # https://github.com/pdbpp/pdbpp
ipdb==0.13.4 # https://github.com/gotcha/ipdb
pdbpp==0.10.2 # https://github.com/pdbpp/pdbpp
Sphinx==2.0.1 # https://github.com/sphinx-doc/sphinx
psycopg2==2.8 --no-binary psycopg2 # https://github.com/psycopg/psycopg2

# Testing
# ------------------------------------------------------------------------------
mypy==0.740 # https://github.com/python/mypy
pytest==4.5.0 # https://github.com/pytest-dev/pytest
pytest-sugar==0.9.2 # https://github.com/Frozenball/pytest-sugar
mypy==0.790 # https://github.com/python/mypy
pytest==6.1.2 # https://github.com/pytest-dev/pytest
pytest-sugar==0.9.4 # https://github.com/Frozenball/pytest-sugar
pytest-env~=0.6.2 # https://github.com/MobileDynasty/pytest-env

# Code quality
# ------------------------------------------------------------------------------
flake8==3.7.7 # https://github.com/PyCQA/flake8
coverage==4.5.3 # https://github.com/nedbat/coveragepy
black==19.3b0 # https://github.com/ambv/black
pylint-django==2.0.9 # https://github.com/PyCQA/pylint-django
flake8==3.8.4 # https://github.com/PyCQA/flake8
coverage==5.3 # https://github.com/nedbat/coveragepy
black==20.8b1 # https://github.com/ambv/black
pylint-django==2.3.0 # https://github.com/PyCQA/pylint-django
pylint-celery==0.3 # https://github.com/PyCQA/pylint-celery

# Django
# ------------------------------------------------------------------------------
factory-boy==2.12.0 # https://github.com/FactoryBoy/factory_boy

django-debug-toolbar==1.11 # https://github.com/jazzband/django-debug-toolbar
django-extensions==2.1.7 # https://github.com/django-extensions/django-extensions
django-coverage-plugin==1.6.0 # https://github.com/nedbat/django_coverage_plugin
pytest-django==3.4.8 # https://github.com/pytest-dev/pytest-django
django-debug-toolbar==3.1.1 # https://github.com/jazzband/django-debug-toolbar
django-extensions==3.0.9 # https://github.com/django-extensions/django-extensions
django-coverage-plugin==1.8.0 # https://github.com/nedbat/django_coverage_plugin
pytest-django==4.1.0 # https://github.com/pytest-dev/pytest-django
7 changes: 3 additions & 4 deletions requirements/production.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@

-r ./base.txt

gunicorn==19.9.0 # https://github.com/benoitc/gunicorn
psycopg2==2.8 --no-binary psycopg2 # https://github.com/psycopg/psycopg2
gunicorn==20.0.4 # https://github.com/benoitc/gunicorn
Collectfast==0.6.2 # https://github.com/antonagestam/collectfast
sentry-sdk==0.13.5 # https://github.com/getsentry/sentry-python
sentry-sdk==0.19.3 # https://github.com/getsentry/sentry-python

# Django
# ------------------------------------------------------------------------------
django-storages[boto3]==1.7.1 # https://github.com/jschneier/django-storages
django-storages[boto3]==1.10.1 # https://github.com/jschneier/django-storages
django-anymail[mailgun]==6.0 # https://github.com/anymail/django-anymail
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ max-line-length = 120
exclude = .tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules

[mypy]
python_version = 3.8
python_version = 3.9
check_untyped_defs = True
ignore_errors = False
ignore_missing_imports = True
Expand Down
9 changes: 8 additions & 1 deletion sprints/dashboard/libs/google.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import re
from contextlib import contextmanager
from datetime import timedelta
from typing import (
Dict,
Iterator,
List,
Union,
)

from dateutil.parser import parse
from django.conf import settings
from google.oauth2 import service_account
from googleapiclient import discovery
Expand Down Expand Up @@ -47,7 +49,7 @@ def get_vacations(from_: str, to: str) -> List[Dict[str, Union[int, str, Dict[st
calendarId=calendar,
timeZone='Europe/London',
timeMin=f'{from_}T00:00:00Z',
timeMax=f'{to}T00:00:00Z',
timeMax=f'{to}T23:59:59Z',
fields='items(end/date, start/date, summary)'
).execute()

Expand All @@ -57,6 +59,11 @@ def get_vacations(from_: str, to: str) -> List[Dict[str, Union[int, str, Dict[st
search = re.match(regex, event['summary'], re.IGNORECASE).groupdict() # type: ignore
# Only `All day` events are taken into account.
if {'start', 'end'} <= event.keys():
# The end date of the `All day` event includes a day after that event. The assumption is that we
# want to count only inclusive dates, so this "subtracts" one day from the event.
event["end"]["date"] = (parse(event["end"]["date"]) - timedelta(days=1)).strftime(
settings.JIRA_API_DATE_FORMAT
)
user = search.get('user')
event['user'] = user
event['seconds'] = int(search.get('hours', 0) or 0) * SECONDS_IN_HOUR
Expand Down
Loading