Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Yiran li/feature/create shift api v2 #301

Merged
merged 43 commits into from
Oct 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
8acd0f5
create endpoint for shift
yiranlir Aug 12, 2024
c29aca0
modified wrong name
yiranlir Aug 12, 2024
38909f5
modified shift entity
yiranlir Aug 12, 2024
fb70492
add post method
yiranlir Aug 12, 2024
7626426
create two new tables
yiranlir Aug 23, 2024
8dd3e55
modified the api to fit new tables
yiranlir Aug 23, 2024
30cbe3a
modified the shift_request domain
yiranlir Aug 23, 2024
a19f034
modified the shift_request domain
yiranlir Aug 23, 2024
24ed8ae
modified the return information
yiranlir Aug 23, 2024
9e4c36c
modified class name
yiranlir Aug 23, 2024
5502e06
modified the datetime type
yiranlir Aug 24, 2024
ab99c2f
Reformat code
yiranlir Aug 25, 2024
39e2650
Add PUT endpoint to update volunteer status
anannnchim Aug 29, 2024
d06354f
add enum class and dataclass
yiranlir Aug 29, 2024
842e4e9
Merge branch 'YiranLI/feature/invoke-shift-data' of https://github.co…
yiranlir Aug 29, 2024
75738f2
create a record in unavailability_time when confirmed the shift
yiranlir Aug 29, 2024
52f3f63
Merge origin/main into YiranLI/feature/update-status-and-add-unavaila…
yiranlir Sep 9, 2024
1369406
detect conflict for shift
yiranlir Sep 23, 2024
3598f56
modified the unavailability time table to add a column of is_shift
yiranlir Sep 23, 2024
c2e6cf7
deal with some error
yiranlir Sep 26, 2024
1971bef
change the string type into enum type and also modified the conflict …
yiranlir Sep 26, 2024
408a5f7
delete unnecessary line
yiranlir Sep 26, 2024
34c97df
modified the status type
yiranlir Sep 26, 2024
a4e02e3
added vehicle flag to shift request, added post method to shift eposi…
5oappy Sep 26, 2024
57a673c
create new shift post endpoint
yiranlir Sep 26, 2024
eb5ef9b
Merge branch '5oappy/feature/shift-api-post' of https://github.com/Te…
yiranlir Sep 26, 2024
38746ee
added link from specific role to specific shift to match requirements
5oappy Sep 26, 2024
7c78ea2
Revert "added link from specific role to specific shift to match requ…
5oappy Sep 26, 2024
a9dd021
delete shift_id in role table
yiranlir Sep 26, 2024
c9930dd
Merge branch '5oappy/feature/shift-api-post' of https://github.com/Te…
yiranlir Sep 26, 2024
1ecc9b5
added postiong creation funciton ot be implemented
5oappy Sep 26, 2024
22e8c80
Merge branch '5oappy/feature/shift-api-post' of https://github.com/Te…
yiranlir Sep 26, 2024
59a99f8
add create position function
yiranlir Sep 30, 2024
d13bf6f
fix merged conflicts
yiranlir Sep 30, 2024
a87c0a1
Merge branch 'main' of https://github.com/TechlauncherFireApp/backend…
yiranlir Oct 1, 2024
30f8517
fix some error
yiranlir Oct 1, 2024
1239362
merged calculator v2 updates
yiranlir Oct 1, 2024
8818212
fix typing error
yiranlir Oct 1, 2024
d467f9c
fix error
yiranlir Oct 1, 2024
5070ad7
modified the return of no record found and add Authorization check
yiranlir Oct 4, 2024
006ea91
Merge branch 'main' into YiranLI/feature/create-shift-api-v2
yiranlir Oct 4, 2024
4fc2799
modified the test for the no record return
yiranlir Oct 4, 2024
0f80df1
Merge branch 'YiranLI/feature/create-shift-api-v2' of https://github.…
yiranlir Oct 4, 2024
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
42 changes: 33 additions & 9 deletions controllers/v2/shift/api.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from flask_restful import reqparse, Resource, marshal_with, inputs, marshal

from exception.client_exception import ConflictError
from .response_models import shift
from domain import UserType
from domain import UserType, ShiftVolunteerStatus
from repository.shift_repository import ShiftRepository
from services.jwk import requires_auth, is_user_or_has_role
from services.jwk import requires_auth, is_user_or_has_role, requires_admin, has_role
from controllers.v2.v2_blueprint import v2_api
import logging

Expand All @@ -11,7 +13,8 @@
parser.add_argument('title', type=str)
parser.add_argument('start', type=inputs.datetime_from_iso8601, required=True, help="Start time cannot be blank!")
parser.add_argument('end', type=inputs.datetime_from_iso8601, required=True, help="End time cannot be blank!")
parser.add_argument('roles', type=list, location='json', required=True, help="Roles cannot be blank!")
parser.add_argument('vehicle_type', type=int, required=True, help="Vehicle type cannot be blank!")

parser_modify_status = reqparse.RequestParser()
parser_modify_status.add_argument('status', type=str, location='json', required=True, help="Status cannot be blank!")

Expand All @@ -22,29 +25,50 @@ class VolunteerShiftV2(Resource):
def __init__(self, shift_repository: ShiftRepository = ShiftRepository()):
self.shift_repository = shift_repository

@requires_auth
@has_role(UserType.ROOT_ADMIN)
def post(self, user_id):
try:
args = parser.parse_args()
title = args['title']
start = args['start']
end = args['end']
vehicle_type = args['vehicle_type']
new_shift_id = self.shift_repository.post_shift_request(user_id, title, start, end, vehicle_type)
if new_shift_id:
return {"shift_id": new_shift_id}, 200
else:
return {"message": "Failed to create shift."}, 400
except Exception as e:
logging.error(f"Error creating new shift request: {e}")
return {"message": "Internal server error"}, 500


@requires_auth
@is_user_or_has_role(None, UserType.ROOT_ADMIN)
def get(self, user_id):
try:
shifts = self.shift_repository.get_shift(user_id)
if shifts:
return marshal(shifts, shift), 200
else:
return {"message": "No shift record found."}, 400
return marshal(shifts, shift), 200
except Exception as e:
logging.error(f"Error retrieving shifts for user {user_id}: {e}")
return {"message": "Internal server error"}, 500


@requires_auth
@is_user_or_has_role(None, UserType.ROOT_ADMIN)
def put(self, user_id, shift_id):
args = parser_modify_status.parse_args()
status = args["status"]
status_enum = ShiftVolunteerStatus[status.upper()]
try:
success = self.shift_repository.update_shift_status(user_id, shift_id, status)
success = self.shift_repository.update_shift_status(user_id, shift_id, status_enum)
if success:
return {"message": "Status updated successfully"}, 200
else:
return {"message": "No user or shift record is found, status not updated."}, 400
except ConflictError as e: # Handle conflict error
logging.error(f"Conflict when updating shift for user {user_id}: {e}")
return {"message": "Shift time conflict detected. Cannot confirm shift."}, 409
except Exception as e:
logging.error(f"Error updating shifts for user {user_id}: {e}")
return {"message": "Internal server error"}, 500
Expand Down
4 changes: 2 additions & 2 deletions controllers/v2/shift/response_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

shift = {
'shiftId': fields.Integer,
'status': fields.String,
'title': fields.String,
'start': fields.DateTime(dt_format='iso8601'),
'end': fields.DateTime(dt_format='iso8601')
'end': fields.DateTime(dt_format='iso8601'),
'status': fields.String
}
11 changes: 5 additions & 6 deletions controllers/v2/unavailability/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,11 @@ def __init__(self, event_repository: EventRepository = EventRepository()):
@requires_auth
@is_user_or_has_role(None, UserType.ROOT_ADMIN)
def get(self, user_id):
volunteer_unavailability_record = self.event_repository.get_event(user_id)
if volunteer_unavailability_record is not None and volunteer_unavailability_record != []:
return volunteer_unavailability_record
elif volunteer_unavailability_record == []:
return {"message": "No unavailability record found."}, 400
else:
try:
volunteer_unavailability_record = self.event_repository.get_event(user_id)
return volunteer_unavailability_record, 200
except Exception as e:
logging.error(f"Error retrieving shifts for user {user_id}: {e}")
return {"message": "Internal server error"}, 500

@requires_auth
Expand Down
3 changes: 1 addition & 2 deletions domain/entity/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,4 @@
from .shift_request import ShiftRequest
from .shift_request_volunteer import ShiftRequestVolunteer
from .shift_position import ShiftPosition
from .fcm_tokens import FCMToken

from .fcm_tokens import FCMToken
11 changes: 3 additions & 8 deletions domain/entity/shift_position.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
from datetime import datetime

from sqlalchemy import Column, String, DateTime, ForeignKey, Integer, Enum
from sqlalchemy import Column, String, ForeignKey, Integer
from sqlalchemy.orm import relationship

from domain.base import Base


class ShiftPosition(Base):
__tablename__ = 'shift_position'

id = Column(Integer, primary_key=True, autoincrement=True)
shift_id = Column(Integer, ForeignKey('shift_request.id'), nullable=False)
role_code = Column(String(256), ForeignKey('role.code'), nullable=False)
shift_id = Column(Integer, ForeignKey('shift_request.id'), name='shift_id', nullable=False)
role_code = Column(String(256), ForeignKey('role.code'), name='role_code', nullable=False)

# Many-to-one relationship with Role
role = relationship("Role")

# One-to-one relationship with ShiftRequestVolunteer using backref
volunteer = relationship("ShiftRequestVolunteer", uselist=False, backref="shift_position",
primaryjoin="ShiftPosition.id == ShiftRequestVolunteer.position_id")
10 changes: 5 additions & 5 deletions domain/entity/shift_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ class ShiftRequest(Base):
title = Column(String(29), name='title', nullable=False)
startTime = Column(DateTime, name='from', nullable=False)
endTime = Column(DateTime, name='to', nullable=False)
status = Column(Enum(ShiftStatus), name='status', default=ShiftStatus.WAITING, nullable=False)
status = Column(Enum(ShiftStatus), name='status', default=ShiftStatus.SUBMITTED, nullable=False)
update_date_time = Column(DateTime, name='last_update_datetime', default=datetime.now(), nullable=False)
insert_date_time = Column(DateTime, name='created_datetime', default=datetime.now(), nullable=False)
Column()
user = relationship("User")


user = relationship("User")
# One-to-many relationship: A shift can have multiple positions
positions = relationship("ShiftPosition", backref="shift_request")


# One-to-many relationship: A shift can be assigned to many volunteers
volunteers = relationship("ShiftRequestVolunteer", backref="shift_request")
1 change: 0 additions & 1 deletion domain/entity/shift_request_volunteer.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,4 @@ class ShiftRequestVolunteer(Base):
update_date_time = Column(DateTime, name='last_update_datetime', default=datetime.now(), nullable=False)
insert_date_time = Column(DateTime, name='created_datetime', default=datetime.now(), nullable=False)

shift_request = relationship("ShiftRequest")
user = relationship("User")
1 change: 1 addition & 0 deletions domain/entity/unavailability_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ class UnavailabilityTime(Base):
start = Column(DateTime, nullable=False, default=datetime.now())
end = Column(DateTime, nullable=False, default=datetime.now())
status = Column(Boolean, nullable=False, default=1)
is_shift = Column(Boolean, nullable=False, default=False)
UniqueConstraint(eventId, userId, name='event')
4 changes: 2 additions & 2 deletions domain/type/shift_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
@dataclass
class ShiftRecord:
shiftId: int
status: ShiftVolunteerStatus
title: str
start: datetime
end: datetime
end: datetime
status: ShiftVolunteerStatus
6 changes: 3 additions & 3 deletions domain/type/shift_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@


class ShiftStatus(Enum):
WAITING = "waiting"
UNSUBMITTED = "un-submitted"
INPROGRESS = "in-progress"
PENDING = "pending"
SUBMITTED = "submitted"
CONFIRMED = "confirmed"
COMPLETED = "completed"
2 changes: 1 addition & 1 deletion domain/type/shift_volunteer_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@

class ShiftVolunteerStatus(Enum):
PENDING = "pending"
CONFIRMED = "confirmed"
ACCEPTED = "accepted"
REJECTED = "rejected"
9 changes: 9 additions & 0 deletions exception/client_exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,12 @@ def __init__(self, *args):
def __str__(self):
# Optionally customize the string representation for this specific error
return f"InvalidArgumentError: unexpected values in the payload"

class ConflictError(FireAppException):
def __init__(self, *args):
# Call the superclass constructor with a default message and any additional arguments
super().__init__(f"Shift time conflict detected", *args)

def __str__(self):
# Optionally customize the string representation for this specific error
return f"ConflictError: This shift is conflict with other confirmed shift."
Loading
Loading