Skip to content

Commit

Permalink
[ORG-18] Update event endpoint (#7)
Browse files Browse the repository at this point in the history
Create endpoint with the path:

POST /organizator-api/events/update/<event_id>
  • Loading branch information
carlotacb authored Nov 26, 2023
1 parent 5604656 commit f62ace7
Show file tree
Hide file tree
Showing 13 changed files with 359 additions and 9 deletions.
2 changes: 1 addition & 1 deletion docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ services:
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "sh -c 'pg_isready -U admin -d postgres'"]
interval: 20s
interval: 10s
timeout: 10s
retries: 5
networks:
Expand Down
5 changes: 5 additions & 0 deletions organizator_api/app/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from django.contrib import admin

from app.events.infrastructure.persistance.models.orm_event import ORMEvent as Event

admin.site.register(Event)
12 changes: 12 additions & 0 deletions organizator_api/app/events/application/requests.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from dataclasses import dataclass
from datetime import datetime
from typing import Optional


@dataclass
Expand All @@ -11,3 +12,14 @@ class CreateEventRequest:
end_date: datetime
location: str
header_image: str


@dataclass
class UpdateEventRequest:
name: Optional[str] = None
url: Optional[str] = None
description: Optional[str] = None
start_date: Optional[datetime] = None
end_date: Optional[datetime] = None
location: Optional[str] = None
header_image: Optional[str] = None
1 change: 1 addition & 0 deletions organizator_api/app/events/domain/repositories.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import uuid
from abc import ABC, abstractmethod
from datetime import datetime
from typing import List

from app.events.domain.models.event import Event
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import uuid
from datetime import timezone, datetime

from app.events.infrastructure.repository_factories import EventRepositoryFactory
from app.events.domain.models.event import Event
from app.events.application.requests import UpdateEventRequest


class UpdateEventUseCase:
def __init__(self) -> None:
self.event_repository = EventRepositoryFactory.create()

def execute(self, event_id: uuid.UUID, event: UpdateEventRequest) -> Event:
original_event = self.event_repository.get(event_id)
new_event = Event(
id=event_id,
name=event.name if event.name else original_event.name,
description=event.description
if event.description
else original_event.description,
url=event.url if event.url else original_event.url,
start_date=event.start_date
if event.start_date
else original_event.start_date,
end_date=event.end_date if event.end_date else original_event.end_date,
location=event.location if event.location else original_event.location,
header_image=event.header_image
if event.header_image
else original_event.header_image,
created_at=original_event.created_at,
updated_at=datetime.now(tz=timezone.utc),
)

self.event_repository.update(new_event)

return new_event
2 changes: 2 additions & 0 deletions organizator_api/app/events/infrastructure/http/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
create_new_event,
get_all_events,
get_event,
update_event,
)

urlpatterns = [
path("new", create_new_event),
path("", get_all_events),
path("<uuid:event_id>", get_event),
path("update/<uuid:event_id>", update_event),
]
41 changes: 38 additions & 3 deletions organizator_api/app/events/infrastructure/http/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,19 @@
from django.http import HttpRequest, HttpResponse
from django.views.decorators.http import require_http_methods

from app.events.application.requests import CreateEventRequest
from app.events.application.requests import CreateEventRequest, UpdateEventRequest
from app.events.domain.use_cases.create_event_use_case import CreateEventUseCase
from app.events.domain.exceptions import EventAlreadyExists, EventNotFound
from app.events.domain.use_cases.get_all_events_use_case import GetAllEventsUseCase
from app.events.application.response import EventResponse
from app.events.domain.use_cases.get_event_use_case import GetEventUseCase
from app.events.domain.use_cases.update_event_use_case import UpdateEventUseCase


@require_http_methods(["POST"])
def create_new_event(request: HttpRequest) -> HttpResponse:
json_body = json.loads(request.body)

print(request)

try:
name = json_body["name"]
url = json_body["url"]
Expand Down Expand Up @@ -73,3 +72,39 @@ def get_event(request: HttpRequest, event_id: uuid.UUID) -> HttpResponse:
return HttpResponse(
status=200, content=json.dumps(event_response), content_type="application/json"
)


@require_http_methods(["POST"])
def update_event(request: HttpRequest, event_id: uuid.UUID) -> HttpResponse:
json_body = json.loads(request.body)

name = json_body["name"] if "name" in json_body else None
url = json_body["url"] if "url" in json_body else None
description = json_body["description"] if "description" in json_body else None
start_date = json_body["start_date"] if "start_date" in json_body else None
end_date = json_body["end_date"] if "end_date" in json_body else None
location = json_body["location"] if "location" in json_body else None
header_image = json_body["header_image"] if "header_image" in json_body else None

event_data = UpdateEventRequest(
name=name,
url=url,
description=description,
start_date=datetime.strptime(start_date, "%Y-%m-%dT%H:%M:%SZ")
if start_date
else None,
end_date=datetime.strptime(end_date, "%Y-%m-%dT%H:%M:%SZ")
if end_date
else None,
location=location,
header_image=header_image,
)

try:
UpdateEventUseCase().execute(event_id=event_id, event=event_data)
except EventAlreadyExists:
return HttpResponse(status=409, content="Event already exists")
except EventNotFound:
return HttpResponse(status=404, content="Event does not exist")

return HttpResponse(status=201, content="Event modified correctly")
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import uuid
from datetime import datetime, timezone
from typing import List

from django.db import IntegrityError
Expand All @@ -17,7 +18,21 @@ def create(self, event: Event) -> None:
raise EventAlreadyExists()

def update(self, event: Event) -> None:
pass # pragma: no cover
try:
orm_event = ORMEvent.objects.get(id=event.id)
orm_event.name = event.name
orm_event.description = event.description
orm_event.url = event.url
orm_event.start_date = event.start_date
orm_event.end_date = event.end_date
orm_event.location = event.location
orm_event.header_image = event.header_image
orm_event.updated_at = event.updated_at
orm_event.save()
except ORMEvent.DoesNotExist:
raise EventNotFound()
except IntegrityError:
raise EventAlreadyExists()

def delete(self, event_id: uuid.UUID) -> None:
pass # pragma: no cover
Expand All @@ -27,7 +42,7 @@ def get(self, event_id: uuid.UUID) -> Event:
event = self._to_domain_model(ORMEvent.objects.get(id=event_id))
return event
except ORMEvent.DoesNotExist:
raise EventNotFound
raise EventNotFound()

def get_all(self) -> List[Event]:
return [self._to_domain_model(event) for event in ORMEvent.objects.all()]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import uuid
from datetime import datetime, timezone

from tests.events.domain.EventFactory import EventFactory
from app.events.domain.use_cases.get_all_events_use_case import GetAllEventsUseCase
Expand All @@ -11,7 +10,10 @@ def setUp(self) -> None:
super().setUp()
self.event_repository.clear()
event = EventFactory().create()
event2 = EventFactory().create(name="HackUPC 2022")
event2 = EventFactory().create(
new_id=uuid.UUID("fb95bfb6-3361-4628-8037-999d58b7183a"),
name="HackUPC 2022",
)
self.event_repository.create(event)
self.event_repository.create(event2)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import uuid
from datetime import datetime

from app.events.application.requests import UpdateEventRequest
from app.events.domain.use_cases.update_event_use_case import UpdateEventUseCase
from tests.events.domain.EventFactory import EventFactory
from tests.api_tests import ApiTests


class TestUpdateEventUseCase(ApiTests):
def setUp(self) -> None:
super().setUp()
self.event_repository.clear()
event = EventFactory().create()
event2 = EventFactory().create(
new_id=uuid.UUID("fb95bfb6-3361-4628-8037-999d58b7183a"),
name="HackUPC 2022",
)
self.event_repository.create(event)
self.event_repository.create(event2)

def test__given_a_update_event_request_with_only_name__when_update_an_event_with_the_data__then_the_event_is_updated(
self,
) -> None:
# Given
new_event = UpdateEventRequest(
name="HackUPC 2021",
)

# When
event = UpdateEventUseCase().execute(
uuid.UUID("fb95bfb6-3361-4628-8037-999d58b7183a"), new_event
)

# Then
self.assertEqual(event.name, "HackUPC 2021")

def test__given_a_update_event_request_with_all_data__when_update_an_event_with_the_data__then_the_event_is_updated(
self,
) -> None:
# Given
new_event = UpdateEventRequest(
name="HackUPC 2021",
description="Hackathon in Barcelona 2021",
url="https://2021.hackupc.com",
start_date=datetime.strptime("2021-10-15T16:00:00Z", "%Y-%m-%dT%H:%M:%SZ"),
end_date=datetime.strptime("2021-10-17T16:00:00Z", "%Y-%m-%dT%H:%M:%SZ"),
location="The best city in the world",
)

# When
event = UpdateEventUseCase().execute(
uuid.UUID("fb95bfb6-3361-4628-8037-999d58b7183a"), new_event
)

# Then
self.assertEqual(event.name, "HackUPC 2021")
self.assertEqual(event.description, "Hackathon in Barcelona 2021")
self.assertEqual(event.url, "https://2021.hackupc.com")
self.assertEqual(
event.start_date,
datetime.strptime("2021-10-15T16:00:00Z", "%Y-%m-%dT%H:%M:%SZ"),
)
self.assertEqual(
event.end_date,
datetime.strptime("2021-10-17T16:00:00Z", "%Y-%m-%dT%H:%M:%SZ"),
)
self.assertEqual(event.location, "The best city in the world")
113 changes: 113 additions & 0 deletions organizator_api/tests/events/infrastructure/http/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,116 @@ def test__when_get_event_by_nonexistent_id__then_returns_the_event(
response.content,
b"Event does not exist",
)

def test__given_information_to_update_an_event__when_update_event__then_the_event_is_updated(
self,
) -> None:
# Given
event = EventFactory().create()
self.event_repository.create(event)
request_body = {
"name": "HackNight Ep.VI",
"url": "https://www.hacknights.dev",
"description": "The best hack-night ever",
"start_date": "2023-11-17T21:00:00Z",
"end_date": "2023-11-18T05:00:00Z",
"location": "Aula d'estudis Campus Nord",
"header_image": "https://www.hacknights.dev/images/hacknight.png",
}

# When
response = self.client.post(
"/organizator-api/events/update/ef6f6fb3-ba12-43dd-a0da-95de8125b1cc",
json.dumps(request_body),
content_type="application/json",
)

# Then
self.assertEqual(response.status_code, 201)
self.assertEqual(response.content, b"Event modified correctly")

events = self.event_repository.get_all()
self.assertEqual(len(events), 1)
event = events.pop()
self.assertEqual(event.name, "HackNight Ep.VI")
self.assertEqual(event.url, "https://www.hacknights.dev")
self.assertEqual(event.description, "The best hack-night ever")
self.assertEqual(event.start_date, datetime(2023, 11, 17, 21, 0))
self.assertEqual(event.end_date, datetime(2023, 11, 18, 5, 0))
self.assertEqual(event.location, "Aula d'estudis Campus Nord")
self.assertEqual(
event.header_image, "https://www.hacknights.dev/images/hacknight.png"
)

def test__given_only_some_information_to_update_an_event__when_update_event__then_the_event_is_updated(
self,
) -> None:
# Given
event = EventFactory().create()
self.event_repository.create(event)
request_body = {
"description": "The biggest student hackathon in Europe taking place in Barcelona",
"url": "https://2023.hackupc.com/",
}

# When
response = self.client.post(
"/organizator-api/events/update/ef6f6fb3-ba12-43dd-a0da-95de8125b1cc",
json.dumps(request_body),
content_type="application/json",
)

# Then
self.assertEqual(response.status_code, 201)
self.assertEqual(response.content, b"Event modified correctly")

events = self.event_repository.get_all()
self.assertEqual(len(events), 1)
event = events.pop()
self.assertEqual(event.url, "https://2023.hackupc.com/")
self.assertEqual(
event.description,
"The biggest student hackathon in Europe taking place in Barcelona",
)

def test__given_a_event_with_the_same_name_as_one_already_created__when_update_event__then_returns_409(
self,
) -> None:
# Given
event = EventFactory().create()
event2 = EventFactory().create(
new_id=uuid.UUID("be0f4c18-4a7c-4c1e-8a62-fc50916b6c88"),
name="HackUPC 2022",
)
self.event_repository.create(event)
self.event_repository.create(event2)

request_body = {"name": "HackUPC 2022"}

# When
response = self.client.post(
"/organizator-api/events/update/ef6f6fb3-ba12-43dd-a0da-95de8125b1cc",
json.dumps(request_body),
content_type="application/json",
)

# Then
self.assertEqual(response.status_code, 409)
self.assertEqual(response.content, b"Event already exists")

def test__given_no_event_in_db__when_update_event__then_returns_404(
self,
) -> None:
# Given
request_body = {"name": "HackUPC 2022"}

# When
response = self.client.post(
"/organizator-api/events/update/ef6f6fb3-ba12-43dd-a0da-95de8125b1cc",
json.dumps(request_body),
content_type="application/json",
)

# Then
self.assertEqual(response.status_code, 404)
self.assertEqual(response.content, b"Event does not exist")
Loading

0 comments on commit f62ace7

Please sign in to comment.