Example №1
Task | Deadline |
---|---|
[CITY-13] Issue creation and retrieval | 29/12/2024 |
Problem
Users cannot report issues in their city, view existing issues within a specific area, or retrieve detailed information about an issue. Additionally, images attached to issues are not stored securely in AWS under the issues backet.
Solution
Implement functionality that allows users to:
- Report new issues with details, location, and images stored securely in AWS.
- View all issues within a specific radius and filter by category or other criteria.
- Retrieve detailed information about a specific issue, including associated comments and metadata.
Acceptance Criteria
- Users can create a new issue by providing a title, description, category, location, and images.
- Images are uploaded to AWS and linked to the issue.
- Users can view issues within a specific radius and apply filters (e.g., category, date).
- Users can retrieve details of a specific issue, including comments and metadata.
- AWS is fully integrated for secure and scalable image storage.
Database Changes
Issues Table
Column Name | Column Type | Nullable | Default |
---|---|---|---|
id |
UUID |
No | Generated UUID |
title |
VARCHAR(255) |
No | - |
description |
TEXT |
Yes | - |
location |
JSON (or GEOGRAPHY(Point, 4326) ) |
No | - |
status |
ENUM |
No | active |
category_id |
FOREIGN KEY(Categories.id) |
No | - |
citizen_id |
FOREIGN KEY(Citizen.id) |
No | - |
created_at |
DATETIME |
No | auto_now_add=True |
updated_at |
DATETIME |
No | auto_now=True |
Issue Images Table
Column Name | Column Type | Nullable | Default |
---|---|---|---|
issue_id |
FOREIGN KEY(Issues.id) |
No | - |
photo |
TEXT (URL to AWS) |
No | - |
Integration with AWS
All images related to an issue will be uploaded to AWS S3. The URLs of these images will be stored in the issue_image
table for retrieval.
Models
from django.contrib.gis.db import models
class IssueStatusChoices(Enum):
ACTIVE = "active"
IN_PROGRESS = "in progress"
RESOLVED = "resolved"
CANCELLED = "cancelled"
@classmethod
def choices(cls):
return [(choice.name, choice.value) for choice in cls]
class Issue(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
title = models.CharField(max_length=255)
description = models.TextField(null=True, blank=True)
location = models.JSONField() # Optionally use GEOGRAPHY(Point, 4326)
status = models.CharField(max_length=20, choices=IssueStatusChoices.choices(), default=IssueStatusChoices.ACTIVE.name)
category = models.ForeignKey('Categories', on_delete=models.PROTECT)
citizen = models.ForeignKey('Citizen', on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class IssueImage(models.Model):
issue = models.ForeignKey('Issue', on_delete=models.CASCADE)
photo = models.TextField() # URL to AWS S3
Endpoints
- [POST] /api/v1/issues
Description: Create a new issue report.
Request:
{
"title": "Broken streetlight on main road",
"category": "road works",
"description": "There's a deep pothole in the middle of Maple Drive...",
"location": {
"latitude": 55.9533,
"longitude": -3.1883,
"city": "Edinburgh",
"county": "Yorkshire"
},
"pictures": ["picture1", "picture2"]
}
Response:
{
"issue_id": 123,
"message": "Issue report created successfully."
}
Notes:
- Insert issue into the issue table
- Insert pictures into the pictures table
-[GET] /api/v1/issues
Description: GET all issues report.
Request Params:
radius=10
limit=15
type=Enum(Road works/etc..)
latitude = 55.123
logtitute = -3.12
Response:
[
{
"id": 123,
"title": "Broken streetlight on main road",
"description": "There's a deep pothole in the middle of Maple Drive...",
"category": "road works",
"pictures": ["picture1", "picture2"],
"location": {
"latitude": 55.9533,
"longitude": -3.1883,
"city": "Edinburgh",
"county": "Yorkshire"
},
"created_at": "2024-11-03T10:30:00Z",
"upvotes": 1000
},
]
Notes:
-
Filter the list of issues within the radius of the specific location, with a limit and types.
-
Use PostGIS extension for these issues.
SELECT id, title, description, category, pictures, location, created_at, upvotes
FROM issues
WHERE ST_DWithin(
location,
ST_MakePoint(-3.12, 55.123)::geography, -- User's longitude and latitude
10000 -- Radius in meters (10 km here)
)
AND category = 'road works' -- Filter by type if provided
ORDER BY created_at DESC
LIMIT 15;
- [GET] /api/v1/issues/{issue_id}
Description: Retrieve details of a specific issue.
Response:
{
"id": 123,
"title": "Broken streetlight on main road",
"description": "There's a deep pothole in the middle of Maple Drive...",
"category": "road works",
"pictures": ["picture1", "picture2"],
"location": {
"city": "Edinburgh",
"county": "Yorkshire"
},
"created_at": "2024-11-03T10:30:00Z",
"upvotes": 1000
}
Notes:
Load the comments and users who left this comment, for the specific issue
Views
1. Create Issue
class CreateIssueView(APIView):
permission_classes = [permissions.IsAuthenticated, isCitizen]
def post(self, request):
# 1. Get the issue data from request.FILES.getlist
# 2. Serialize results of the issue
# 3. Add images to the separate table
2. Retrieve Issues
class RetrieveIssuesView(APIView):
permission_classes = [permissions.AllowAny]
def get(self, request):
# 1. Get latitude , longitude , radius , category from the request param for filtration
# 2. Filter with Geoposix query
# 3. Return serialized results of the issue with loaded pictures
3. Retrieve Issue Details
class RetrieveIssueDetailView(APIView):
permission_classes = [permissions.AllowAny]
def get(self, request, id):
# 1. Get the issue by id
# 2. Serialize issue and prefetch images
AWS Integration
-
File Upload to S3
class S3Service: def upload_file(self, file, folder, user_id): file_name = f"{folder}/{user_id}/{uuid.uuid4()}_{file.name}" self.s3.upload_fileobj(file, BUCKET_NAME, file_name, ExtraArgs={"ACL": "public-read"}) return f"https://{BUCKET_NAME}.s3.amazonaws.com/{file_name}"
-
Storing URLs in the
IssueImage
Table -
Save the returned S3 URL in the
photo
column. -
Retrieve Images
- Query the
IssueImage
table for all images related to a specific issue.
Tests
Name | Purpose |
---|---|
test_create_issue |
Tests issue creation, including AWS upload. |
test_retrieve_issues |
Tests retrieval of issues with filters. |
test_retrieve_issue_detail |
Tests detailed issue retrieval with images. |
Checklist
- Implement database migrations for
issue
andissue_image
tables. - Integrate PostGIS for geospatial queries.
- Implement file uploads to AWS S3.
- Write unit tests for all endpoints.
- Update API documentation with new endpoints.