Repository navigation
MSPCA-8/create & withdraw match endpoints - #7
Merged
Merged
Conversation
POST /matches creates a PENDING match from a volunteer and Chameleon animal ID, then emails the volunteer's assigned foster coordinator. Volunteers with no assigned coordinator still get a match; the send is logged and skipped. Email failures are logged rather than surfaced, since the match is already committed by then. PATCH /matches/:matchId/withdraw sets a match to WITHDRAWN. The record is kept so volunteers can still see their withdrawn applications. Registers MatchesModule in AppModule, which previously imported only CognitoModule, so no match route was mounted.
Once a coordinator has approved, denied or cancelled an application, reversing it is their call rather than the volunteer's, so withdraw now rejects any match that is not PENDING with a 400.
Covers the From address from AWS_SES_SENDER_EMAIL, To/Cc in both the SES Destination and the MIME headers, Bcc in Destination only, empty address lists omitted from Destination, attachment encoding, and error propagation from the SES client.
columnName was declared with a single parameter, so it never received TypeORM's customName argument and discarded every explicit @column({ name: '...' }). Queries used the TS property name instead of the real column, e.g. "column Match.matchId does not exist" against a table whose column is match_id. DefaultNamingStrategy already resolves customName || propertyName. The tableName override was also redundant: every entity passes an explicit name to @entity(), so the pluralization branch never ran.
Yurika-Kan
commented
Sep 30, 2026
dburkhart07
requested changes
Oct 1, 2026
dburkhart07
left a comment
Collaborator
There was a problem hiding this comment.
mostly some small nits, but looking great. thanks for adding in docstrings for service tests too!
Bring back the naming strategy, keeping only the tableName override. The columnName and relationName overrides stay out: columnName was declared with a single parameter, so it never received TypeORM's customName argument and discarded every explicit @column({ name: '...' }), producing errors like "column Match.matchId does not exist". DefaultNamingStrategy already resolves customName || propertyName, so the mapping is correct without those overrides.
Assert the coordinator email subject and body name the volunteer and animal, and run the real SendEmailDTO decorators over the payload the service builds, since EmailsService is stubbed in these tests.
Yurika-Kan
force-pushed
the
yk/mspca-8-create-withdraw-match
branch
from
October 1, 2026 06:36
2954e38 to
736bf48
Compare
Swap @min(1) for @ispositive on volunteerId and chameleonAnimalId to match the validators used in the other PRs. Also tighten the controller spec: mocks are now set per test, invalid bodies run through the real ValidationPipe, and service exceptions are asserted to pass through the handler untouched.
Tag the controller as Matches and add an ApiOperation, happy-path ApiResponse, and ApiParam where there is a path param, so the endpoints are readable in Swagger without opening the repo.
Set mock return values inside the tests that need them, assert the volunteer and match lookups get the right arguments, rename the email failure test to say it still creates the match, and keep one non-pending status case instead of all five.
Note that it never throws, since the match is already committed when it runs and the email is best-effort.
dburkhart07
approved these changes
Oct 2, 2026
dburkhart07
left a comment
Collaborator
There was a problem hiding this comment.
mostly small comments so imma approve. tested both endpoints, emails are working, yay!!!!
dburkhart07
approved these changes
Oct 3, 2026
shreeyaadhikari
requested changes
Oct 5, 2026
…hdraw-match # Conflicts: # apps/backend/src/app.module.ts # apps/backend/src/matches/matches.service.spec.ts # apps/backend/src/matches/matches.service.ts
- use the volunteers service findActiveOrFail instead of a local active check - load the assigned coordinator relation in findByIdOrFail so match emails still go out - use the httpstatus enum and document 400/404 responses on both match endpoints - define mock implementations per test in the match service spec
shreeyaadhikari
approved these changes
Oct 6, 2026
shreeyaadhikari
left a comment
There was a problem hiding this comment.
everything looks good to me!!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ℹ️ Issue
Closes MSPCA-8
📝 Description
Volunteers can apply to foster an animal and withdraw their own application without going through a coordinator. The assigned coordinator is emailed on each new application.
POST /matches: creates a match from a volunteer ID and a Chameleon animal ID. Status is alwaysPENDING, set server-side.CreateMatchDtovalidates both IDs, andwhitelist: truestrips extra body fields so a client can't setstatusitself.assignedCoordinatorrelation. Placeholder body for now.PATCH /matches/:matchId/withdraw: sets status toWITHDRAWN. OnlyPENDINGmatches qualify, anything else is a 400. The record is kept, so volunteers still see withdrawn applications.validateIdin the controller: 400 on a bad ID, 404 when not found.MatchesModuleandCoordinatorsModuleinAppModule; no match route was mounted before.If the volunteer has no coordinator, or the send fails, the match is still created and the problem is logged.
✔️ Verification
yarn testandyarn prepushpass. No AWS setup needed:EmailsServiceno-ops unlessSES_ENABLED=true. SetAUTH_DISABLED=truelocally, so no bearer token is required.curl -X POST http://localhost:3000/api/matches -H 'Content-Type: application/json' -d '{"volunteerId":1,"chameleonAnimalId":42}'→ 201,"Pending"curl -X PATCH http://localhost:3000/api/matches/1/withdraw→ 200,"Withdrawn"0→ 400. ID9999→ 404.🏕️ (Optional) Future Work / Notes
Align with PR-3
Out of scope: no duplicate-match check, no authorization (any volunteer can withdraw another's application), and
VolunteersModuleis still unregistered inAppModule.