Skip to content

Commit

Permalink
feat(backend): Timestamps made utcnow and serialization done with utc…
Browse files Browse the repository at this point in the history
… aware

* fix: All Teams Pagination fixed
* fix: Json response for task split small area error message
* fix: Timestamps serialization in messages, comments, and notifications
  • Loading branch information
prabinoid committed Nov 13, 2024
1 parent d2ad9c3 commit 4d64e02
Show file tree
Hide file tree
Showing 15 changed files with 126 additions and 106 deletions.
9 changes: 5 additions & 4 deletions backend/api/campaigns/resources.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
from databases import Database
from fastapi import APIRouter, Depends, Request

from backend.db import get_db
from backend.models.dtos.campaign_dto import (
CampaignDTO,
CampaignListDTO,
NewCampaignDTO,
)
from backend.models.dtos.user_dto import AuthUserDTO
from backend.services.campaign_service import CampaignService
from backend.services.organisation_service import OrganisationService
from fastapi import APIRouter, Depends, Request
from backend.db import get_db
from databases import Database
from backend.services.users.authentication_service import login_required
from backend.models.dtos.user_dto import AuthUserDTO

router = APIRouter(
prefix="/campaigns",
Expand Down
19 changes: 10 additions & 9 deletions backend/api/comments/resources.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from datetime import datetime

from backend.models.postgis.utils import timestamp
from databases import Database
from fastapi import APIRouter, Depends, Request
from loguru import logger
Expand Down Expand Up @@ -76,14 +75,13 @@ async def post(
content={"Error": "User is on read only mode", "SubCode": "ReadOnly"},
status_code=403,
)

request_json = await request.json()
message = request_json.get("message")
chat_dto = ChatMessageDTO(
message=message,
user_id=user.id,
project_id=project_id,
timestamp=datetime.utcnow(),
timestamp=timestamp(),
username=user.username,
)
try:
Expand Down Expand Up @@ -345,15 +343,18 @@ async def get(request: Request, project_id, task_id):
task_comment.validate()
except Exception as e:
logger.error(f"Error validating request: {str(e)}")
return {
"Error": "Unable to fetch task comments",
"SubCode": "InvalidData",
}, 400
return JSONResponse(
content={
"Error": "Unable to fetch task comments",
"SubCode": "InvalidData",
},
status_code=400,
)

try:
# NEW FUNCTION HAS TO BE ADDED
# task = MappingService.add_task_comment(task_comment)
# return task.model_dump(by_alias=True), 200
return
except MappingServiceError as e:
return {"Error": str(e)}, 403
return JSONResponse(content={"Error": str(e)}, status_code=403)
19 changes: 7 additions & 12 deletions backend/api/teams/resources.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
from backend.models.postgis.team import Team
from databases import Database
from distutils.util import strtobool
from fastapi import APIRouter, Depends, Request, Body

from databases import Database
from fastapi import APIRouter, Body, Depends, Request
from fastapi.responses import JSONResponse
from loguru import logger

from backend.db import get_db
from backend.models.dtos.team_dto import (
NewTeamDTO,
UpdateTeamDTO,
TeamSearchDTO,
)
from backend.services.team_service import TeamService, TeamServiceError
from backend.models.dtos.team_dto import NewTeamDTO, TeamSearchDTO, UpdateTeamDTO
from backend.models.dtos.user_dto import AuthUserDTO
from backend.models.postgis.team import Team
from backend.services.organisation_service import OrganisationService
from backend.services.team_service import TeamService, TeamServiceError
from backend.services.users.authentication_service import login_required
from backend.services.users.user_service import UserService
from backend.models.dtos.user_dto import AuthUserDTO


router = APIRouter(
prefix="/teams",
Expand Down Expand Up @@ -329,7 +325,6 @@ async def list_teams(
search_dto.page = int(request.query_params.get("page", 1))
search_dto.per_page = int(request.query_params.get("perPage", 10))
search_dto.user_id = user.id

teams = await TeamService.get_all_teams(search_dto, db)
return teams

Expand Down
8 changes: 7 additions & 1 deletion backend/models/dtos/mapping_dto.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from backend.models.postgis.statuses import TaskStatus
from backend.models.dtos.mapping_issues_dto import TaskMappingIssueDTO
from backend.models.dtos.task_annotation_dto import TaskAnnotationDTO
from pydantic import BaseModel, Field, ValidationError, validator
from pydantic import BaseModel, Field, ValidationError, validator, root_validator
from typing import List, Optional


Expand Down Expand Up @@ -66,6 +66,12 @@ class TaskHistoryDTO(BaseModel):
class Config:
populate_by_name = True

@root_validator(pre=True)
def format_sent_date(cls, values):
if "action_date" in values and values["action_date"]:
values["action_date"] = values["action_date"].isoformat() + "Z"
return values


class TaskStatusDTO(BaseModel):
"""Describes a DTO for the current status of the task"""
Expand Down
18 changes: 16 additions & 2 deletions backend/models/dtos/message_dto.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from backend.models.dtos.stats_dto import Pagination
from pydantic import BaseModel, Field
from datetime import datetime
from typing import List, Optional

from pydantic import BaseModel, Field, root_validator

from backend.models.dtos.stats_dto import Pagination


class MessageDTO(BaseModel):
"""DTO used to define a message that will be sent to a user"""
Expand All @@ -23,6 +25,12 @@ class MessageDTO(BaseModel):
class Config:
populate_by_name = True

@root_validator(pre=True)
def format_sent_date(cls, values):
if "sent_date" in values and values["sent_date"]:
values["sent_date"] = values["sent_date"].isoformat() + "Z"
return values


class MessagesDTO(BaseModel):
"""DTO used to return all user messages"""
Expand Down Expand Up @@ -53,6 +61,12 @@ class ChatMessageDTO(BaseModel):
class Config:
populate_by_name = True

def dict(self, **kwargs):
data = super().dict(**kwargs)
if self.timestamp:
data["timestamp"] = self.timestamp.isoformat() + "Z"
return data


class ProjectChatDTO(BaseModel):
"""DTO describing all chat messages on one project"""
Expand Down
2 changes: 2 additions & 0 deletions backend/models/postgis/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ async def save(self, db: Database):
project_id=self.project_id,
task_id=self.task_id,
message_type=self.message_type,
read=self.read,
date=self.date,
)
)

Expand Down
16 changes: 9 additions & 7 deletions backend/models/postgis/notification.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
from datetime import datetime, timedelta

from databases import Database
from sqlalchemy import (
Column,
Integer,
BigInteger,
Column,
DateTime,
ForeignKey,
ForeignKeyConstraint,
Integer,
)
from sqlalchemy.orm import relationship

from backend.db import Base, get_session
from backend.models.dtos.notification_dto import NotificationDTO
from backend.models.postgis.user import User
from backend.models.postgis.utils import timestamp
from backend.models.dtos.notification_dto import NotificationDTO
from datetime import datetime, timedelta
from backend.db import Base, get_session
from databases import Database

session = get_session()

Expand Down Expand Up @@ -62,7 +64,7 @@ async def get_unread_message_count(user_id: int, db: Database) -> int:
notification = await db.fetch_one(query, {"user_id": user_id})

if notification is None:
date_value = datetime.today() - timedelta(days=30)
date_value = datetime.utcnow() - timedelta(days=30)
insert_query = """
INSERT INTO notifications (user_id, unread_count, date)
VALUES (:user_id, :unread_count, :date)
Expand Down
11 changes: 6 additions & 5 deletions backend/models/postgis/project_chat.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import bleach
from markdown import markdown
from databases import Database
from loguru import logger
from sqlalchemy import Column, Integer, BigInteger, String, DateTime, ForeignKey
from markdown import markdown
from sqlalchemy import BigInteger, Column, DateTime, ForeignKey, Integer, String
from sqlalchemy.orm import relationship

from backend.db import Base, get_session
from backend.models.dtos.message_dto import ChatMessageDTO, Pagination, ProjectChatDTO
from backend.models.postgis.user import User
from backend.models.postgis.utils import timestamp
from backend.models.dtos.message_dto import ChatMessageDTO, ProjectChatDTO, Pagination
from backend.db import Base, get_session
from databases import Database

session = get_session()

Expand Down
2 changes: 1 addition & 1 deletion backend/models/postgis/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -998,7 +998,7 @@ async def set_task_history(
"project_id": project_id,
"action": action_name,
"action_text": action_text,
"action_date": datetime.datetime.utcnow(),
"action_date": timestamp(),
}
task_history = await db.fetch_one(query=query, values=values)

Expand Down
3 changes: 1 addition & 2 deletions backend/models/postgis/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,7 @@ class ST_Y(GenericFunction):

def timestamp():
"""Used in SQL Alchemy models to ensure we refresh timestamp when new models initialised"""
return datetime.datetime.now(datetime.timezone.utc).replace(tzinfo=None)
# return datetime.datetime.now(datetime.timezone.utc)
return datetime.datetime.utcnow()


# Based on https://stackoverflow.com/a/51916936
Expand Down
4 changes: 2 additions & 2 deletions backend/services/grid/split_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# from flask import current_app
from geoalchemy2 import shape
from geoalchemy2.elements import WKBElement
from loguru import logger
from shapely.geometry import LineString, MultiPolygon, Polygon
from shapely.geometry import shape as shapely_shape
from shapely.ops import split
Expand All @@ -18,8 +19,7 @@ class SplitServiceError(Exception):
"""Custom Exception to notify callers an error occurred when handling splitting tasks"""

def __init__(self, message):
if current_app:
current_app.logger.debug(message)
logger.debug(message)


class SplitService:
Expand Down
13 changes: 6 additions & 7 deletions backend/services/interests_service.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
from backend.models.postgis.project import Project
from databases import Database
from fastapi import HTTPException

from backend.models.dtos.interests_dto import (
InterestDTO,
InterestRateDTO,
InterestRateListDTO,
InterestsListDTO,
InterestDTO,
)
from backend.models.postgis.interests import (
Interest,
)
from backend.models.postgis.interests import Interest
from backend.models.postgis.project import Project
from backend.services.project_service import ProjectService
from databases import Database
from fastapi import HTTPException


class InterestService:
Expand Down
2 changes: 1 addition & 1 deletion backend/services/messaging/chat_service.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import threading

from databases import Database

from backend.exceptions import NotFound
Expand Down Expand Up @@ -74,6 +73,7 @@ async def post_message(
chat_message.message,
chat_dto.project_id,
project_name,
db,
),
).start()
# Ensure we return latest messages after post
Expand Down
Loading

0 comments on commit 4d64e02

Please sign in to comment.