Skip to content

Commit 388ac89

Browse files
committed
participant intake form for backend is complete, still need to add in processing in backend for volunteer intakes
1 parent 25b80b9 commit 388ac89

8 files changed

+693
-21
lines changed

backend/app/models/UserData.py

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import uuid
2-
from sqlalchemy import Column, Date, String, Table, ForeignKey, Integer
2+
from sqlalchemy import Column, Date, String, Table, ForeignKey, Integer, Text, JSON
33
from sqlalchemy.dialects.postgresql import UUID
44
from sqlalchemy.orm import relationship
55

@@ -20,16 +20,72 @@
2020
Column("experience_id", Integer, ForeignKey("experiences.id"))
2121
)
2222

23+
# Bridge tables for loved one many-to-many relationships
24+
user_loved_one_treatments = Table(
25+
"user_loved_one_treatments",
26+
Base.metadata,
27+
Column("user_data_id", UUID(as_uuid=True), ForeignKey("user_data.id")),
28+
Column("treatment_id", Integer, ForeignKey("treatments.id"))
29+
)
30+
31+
user_loved_one_experiences = Table(
32+
"user_loved_one_experiences",
33+
Base.metadata,
34+
Column("user_data_id", UUID(as_uuid=True), ForeignKey("user_data.id")),
35+
Column("experience_id", Integer, ForeignKey("experiences.id"))
36+
)
37+
2338

2439
class UserData(Base):
2540
__tablename__ = "user_data"
2641

2742
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
28-
# Single-valued fields
43+
44+
# Personal Information
45+
first_name = Column(String(80), nullable=True)
46+
last_name = Column(String(80), nullable=True)
2947
date_of_birth = Column(Date, nullable=True)
3048
email = Column(String(120), nullable=True)
3149
phone = Column(String(20), nullable=True)
50+
city = Column(String(100), nullable=True)
51+
province = Column(String(50), nullable=True)
52+
postal_code = Column(String(10), nullable=True)
53+
54+
# Demographics
55+
gender_identity = Column(String(50), nullable=True)
56+
pronouns = Column(JSON, nullable=True) # Array of strings
57+
ethnic_group = Column(JSON, nullable=True) # Array of strings
58+
marital_status = Column(String(50), nullable=True)
59+
has_kids = Column(String(10), nullable=True)
60+
61+
# Cancer Experience
62+
diagnosis = Column(String(100), nullable=True)
63+
date_of_diagnosis = Column(Date, nullable=True)
64+
65+
# "Other" text fields for custom entries
66+
other_treatment = Column(Text, nullable=True)
67+
other_experience = Column(Text, nullable=True)
68+
other_ethnic_group = Column(Text, nullable=True)
69+
gender_identity_custom = Column(Text, nullable=True)
70+
71+
# Flow control fields
72+
has_blood_cancer = Column(String(10), nullable=True)
73+
caring_for_someone = Column(String(10), nullable=True)
74+
75+
# Loved One Demographics
76+
loved_one_gender_identity = Column(String(50), nullable=True)
77+
loved_one_age = Column(String(10), nullable=True)
78+
79+
# Loved One Cancer Experience
80+
loved_one_diagnosis = Column(String(100), nullable=True)
81+
loved_one_date_of_diagnosis = Column(Date, nullable=True)
82+
loved_one_other_treatment = Column(Text, nullable=True)
83+
loved_one_other_experience = Column(Text, nullable=True)
3284

3385
# Many-to-many relationships
3486
treatments = relationship("Treatment", secondary=user_treatments, back_populates="users")
35-
experiences = relationship("Experience", secondary=user_experiences, back_populates="users")
87+
experiences = relationship("Experience", secondary=user_experiences, back_populates="users")
88+
89+
# Loved one many-to-many relationships
90+
loved_one_treatments = relationship("Treatment", secondary=user_loved_one_treatments)
91+
loved_one_experiences = relationship("Experience", secondary=user_loved_one_experiences)

backend/app/routes/intake.py

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from app.schemas.user import UserRole
1111
from app.models import FormSubmission, Form, User
1212
from app.utilities.db_utils import get_db
13+
from app.services.implementations.intake_form_processor import IntakeFormProcessor
1314

1415
# ===== Schemas =====
1516

@@ -48,8 +49,6 @@ def is_owner_or_admin(user_id: UUID):
4849
Custom dependency that checks if the current user is either:
4950
1. The owner of the resource (matching user_id)
5051
2. An admin
51-
52-
This allows users to access their own data while admins can access everything.
5352
"""
5453
async def validator(
5554
request: Request,
@@ -58,24 +57,16 @@ async def validator(
5857
) -> bool:
5958
# Get current user info from request state (set by auth middleware)
6059
current_user_auth_id = request.state.user_id
61-
62-
# Get the current user from database
6360
current_user = db.query(User).filter(User.auth_id == current_user_auth_id).first()
61+
6462
if not current_user:
6563
raise HTTPException(status_code=401, detail="User not found")
6664

67-
# Check if user is admin (role_id 3)
68-
if current_user.role_id == 3: # Admin role
69-
return True
70-
71-
# Check if user is the owner
72-
if str(current_user.id) == str(user_id):
65+
# Check if user is admin or the owner of the resource
66+
if current_user.role.name == "admin" or current_user.id == user_id:
7367
return True
7468

75-
raise HTTPException(
76-
status_code=403,
77-
detail="Access denied: You can only access your own submissions"
78-
)
69+
raise HTTPException(status_code=403, detail="Access denied")
7970

8071
return Depends(validator)
8172

@@ -98,7 +89,7 @@ async def create_form_submission(
9889
authorized: bool = has_roles([UserRole.ADMIN, UserRole.PARTICIPANT, UserRole.VOLUNTEER])
9990
):
10091
"""
101-
Create a new form submission.
92+
Create a new form submission and process it into structured data.
10293
10394
Users can only create submissions for themselves.
10495
"""
@@ -117,14 +108,24 @@ async def create_form_submission(
117108
if not form:
118109
raise HTTPException(status_code=404, detail="Intake form not found")
119110

120-
# Create the submission
111+
# Create the raw form submission record
121112
db_submission = FormSubmission(
122113
form_id=submission.form_id,
123114
user_id=current_user.id, # Always use the current user's ID
124115
answers=submission.answers
125116
)
126117

127118
db.add(db_submission)
119+
db.flush() # Get the submission ID without committing
120+
121+
# Process the form data into structured tables
122+
processor = IntakeFormProcessor(db)
123+
user_data = processor.process_form_submission(
124+
user_id=str(current_user.id),
125+
form_data=submission.answers
126+
)
127+
128+
# Commit everything together
128129
db.commit()
129130
db.refresh(db_submission)
130131

@@ -134,7 +135,7 @@ async def create_form_submission(
134135
raise
135136
except Exception as e:
136137
db.rollback()
137-
raise HTTPException(status_code=500, detail=str(e))
138+
raise HTTPException(status_code=500, detail=f"Error processing form submission: {str(e)}")
138139

139140

140141
@router.get("/submissions", response_model=FormSubmissionListResponse)
@@ -326,4 +327,4 @@ async def get_intake_forms(
326327
]
327328

328329
except Exception as e:
329-
raise HTTPException(status_code=500, detail=str(e))
330+
raise HTTPException(status_code=500, detail=str(e))

0 commit comments

Comments
 (0)