Skip to content

Referrals CRUD (DEV-52) #25

Open
petersenmatthew wants to merge 5 commits intomainfrom
feature/DEV-52/referrals-crud
Open

Referrals CRUD (DEV-52) #25
petersenmatthew wants to merge 5 commits intomainfrom
feature/DEV-52/referrals-crud

Conversation

@petersenmatthew
Copy link

@petersenmatthew petersenmatthew commented Mar 9, 2026

Jira ticket link

Jira ticket

Implementation description

  • Added CRUD Operations for Referal Schema via API Endpoint and Service File

Steps to test

  1. Create an agency
  2. Use agency_id to create a client
  3. Test swagger endpoints of:
  • GET /referrals
  • POST /referrals (use agency_id and client_id)
  • GET /referrals/:id
  • PUT /referrals/:id
  • DELETE /referrals/:id

What should reviewers focus on?

  • Test API routes on Swagger
  • Find any edge cases I missed lol

Checklist

Format for branch, commit, and PR title: docs/GIT.md.

  • My branch name includes the Jira ticket key
  • My PR name is descriptive and in imperative tense
  • My PR name includes the Jira ticket key
  • My commit messages are descriptive and in imperative tense. My commits are atomic and trivial commits are squashed or fixup'd into non-trivial commits
  • My commit messages include the Jira ticket key
  • I have run the appropriate linter(s)
  • I have requested a review from the PL, as well as other devs who have background knowledge on this PR or who will be building on top of this PR

Copy link
Contributor

@nuthanan06 nuthanan06 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just the exception handling, little nitpick, feel free to ignore, but afterwards lgtm

referral = Referral(**_prepare_payload(data))
db.add(referral)

try:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

really nitpick, but maybe another exception handler, so that it doesn't only handle integrity errors, but any error in general

    except Exception:
        await db.rollback()
        raise 

something like that just so we roll it back


try:
await db.commit()
except IntegrityError as e:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, a more broad exception handler


try:
await db.commit()
except IntegrityError as e:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, a more broad exception handler

return prepared


async def _validate_related_records(db: AsyncSession, data: dict[str, Any]) -> None:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i like this validation, @kenzysoror out of curiosity could we make this function a little more generic instead of beling specific to referrals so we can do the same validation for other CRUD models asw? like donations, furniture, etc, etc? just a thought

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i like this idea!! it would definitely reduce our code duplication in validating all the models

Copy link
Member

@kenzysoror kenzysoror left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great work matthew!!🙌

return await referrals_service.create_referral(db, payload)
except ValueError as e:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it looks like most of the CRUD implementations the team is working on use HTTP_400_BAD_REQUEST over HTTP_422_UNPROCESSABLE_ENTITY, so i think we should keep it consistent for now


async def _validate_related_records(db: AsyncSession, data: dict[str, Any]) -> None:
"""Ensure related client and agency records exist when provided."""
if "client_id" in data:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we maybe skip lookups when the FK is None or an empty string to avoid hitting the database for
"obviously" invalid values?

"""Ensure related client and agency records exist when provided."""
if "client_id" in data:
client_result = await db.execute(
select(Client).where(Client.id == data["client_id"])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if all we care about here is checking the existence of the client/agency, then we can select(Client.id) and select(Agency.id) instead of the full rows

db: AsyncSession, referral: Referral, payload: ReferralUpdate
) -> Referral:
"""Update an existing referral with validated, normalized data."""
data = payload.model_dump(exclude_unset=True)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

potentially add a check like

if not data:
    raise ValueError("No update fields were provided.")

to avoid committing without modifying anything (#17 for reference)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants