Feature/251 waitlist landing page#330
Merged
bllr777 merged 23 commits intoMay 25, 2026
Merged
Conversation
…gration fix(api): populate empty AddEmployeeRoleAssignment migration
…gration refactor(api): replace EmployeeInvite.RoleIdsCsv with EmployeeInviteRoleAssignments join table
…tus-default fix(api): default EmployeeInvite.Status to Pending so accept-by-code works
…oints-allow-anonymous fix(api): allow anonymous access to invite lookup and accept endpoints
StripePaymentProcessor.RefundPaymentAsync previously let StripeException propagate to ErrorHandlingMiddleware, which converted every Stripe error into a generic STRIPE_UNAVAILABLE 503. Now the processor catches StripeException and returns a PaymentOperationResult failure with the actual Stripe error message, which the controller surfaces as a 400 BadRequest. Changes: [1] Wrapped refundService.CreateAsync in try/catch(StripeException) — returns failure result with ex.StripeError?.Message References: [1] [JobFlow.Infrastructure/PaymentGateways/Stripe/StripePaymentProcessor.cs:155](https://github.com/Katharix/JobFlow.API/blob/feature/288-fix-stripe-refund-exception-handling/JobFlow.Infrastructure/PaymentGateways/Stripe/StripePaymentProcessor.cs#L155)
…xception-handling fix(api): Catch StripeException in RefundPaymentAsync [AB#288]
Added an early-return guard in PaymentController.RefundPayment: if the provider is Stripe and the org's StripeConnectAccountId is null or whitespace, return a 400 with a descriptive message before attempting the refund. This prevents the 'No such payment_intent' error that occurs when the refund is sent to the platform account instead of the connected account. Changes: [1] Early BadRequest when StripeConnectAccountId is missing for a Stripe refund References: [1] [JobFlow.API/Controllers/PaymentController.cs:457](https://github.com/Katharix/JobFlow.API/blob/feature/288-fix-stripe-refund-exception-handling/JobFlow.API/Controllers/PaymentController.cs#L457)
…xception-handling fix(api): [AB#288] guard null StripeConnectAccountId before refund
Fixed the invite redirect URL to point to the correct Angular route, and changed resend behaviour to revoke the existing pending invite rather than rejecting the request.
Changes:
[1] Revoke existing pending invite on resend instead of returning AlreadyInvited error
[2] Fixed redirect URL from /invite/{token} to /i/{shortCode} to match Angular route
References:
[1] [JobFlow.Business/Services/EmployeeInviteService.cs:52](https://github.com/Katharix/JobFlow.API/blob/feature/288-fix-stripe-refund-exception-handling/JobFlow.Business/Services/EmployeeInviteService.cs#L52)
[2] [JobFlow.Business/Services/EmployeeInviteService.cs:207](https://github.com/Katharix/JobFlow.API/blob/feature/288-fix-stripe-refund-exception-handling/JobFlow.Business/Services/EmployeeInviteService.cs#L207)
…xception-handling fix(api): [AB#288] fix employee invite redirect and resend
…ccount linking - Add EmployeeInvite email template (id 7) with friendlier copy including org and role - Add AcceptInviteRequest DTO carrying firebaseUid, firstName, lastName - Introduce IFirebaseUserManager abstraction in Business + FirebaseUserManager impl in Infrastructure (keeps FirebaseAdmin out of Business) - Rewrite AcceptInviteAsync to link Firebase UID to a new User + Employee, assign OrganizationEmployee role, and set custom claims - Add EmployeeInviteErrors.FirebaseUidRequired and AccountLinkFailed
…xception-handling feat(api): [AB#288] redesign employee invitation flow with Firebase account linking
AcceptInviteAsync now finds existing Employee by Email+OrgId and updates in place (clears + re-adds RoleAssignments), preventing duplicate rows when admin resends an invite to a previously-orphaned employee.
…xception-handling feat(api): [AB#288] de-dupe Employee on invite accept
Added POST /assignments/{id}/en-route endpoint for client en-route notifications and fixed assignment DTO to fall back to client address when assignment has no address set.
Changes:
[1] Added POST en-route endpoint in AssignmentController calling NotifyEnRouteAsync
[2] Added NotifyEnRouteAsync in AssignmentService to send client en-route notification
[3] Added client address fallback in MapToDtoAsync when assignment address fields are empty
[4] Added BuildClientJobTrackingEnRoute notification message builder
[5] Added SendClientJobTrackingEnRouteNotificationAsync to notification service
[6] Updated interfaces and test stub for new notification method
References:
[1] [JobFlow.API/Controllers/AssignmentController.cs:126](https://github.com/Katharix/JobFlow.API/blob/fix/mobile-bugs-backend/JobFlow.API/Controllers/AssignmentController.cs#L126)
[2] [JobFlow.Business/Services/AssignmentService.cs:349](https://github.com/Katharix/JobFlow.API/blob/fix/mobile-bugs-backend/JobFlow.Business/Services/AssignmentService.cs#L349)
[3] [JobFlow.Business/Services/AssignmentService.cs:425](https://github.com/Katharix/JobFlow.API/blob/fix/mobile-bugs-backend/JobFlow.Business/Services/AssignmentService.cs#L425)
[4] [JobFlow.Business/Notifications/Builders/NotificationMessageBuilder.cs:213](https://github.com/Katharix/JobFlow.API/blob/fix/mobile-bugs-backend/JobFlow.Business/Notifications/Builders/NotificationMessageBuilder.cs#L213)
[5] [JobFlow.Business/Notifications/NotificationService.cs:135](https://github.com/Katharix/JobFlow.API/blob/fix/mobile-bugs-backend/JobFlow.Business/Notifications/NotificationService.cs#L135)
[6] [JobFlow.Tests/FollowUpAutomationServiceTests.cs:275](https://github.com/Katharix/JobFlow.API/blob/fix/mobile-bugs-backend/JobFlow.Tests/FollowUpAutomationServiceTests.cs#L275)
feat(api): En-route client notification and address fallback [AB#266]
- Add EmailTemplate.WaitlistConfirmation = 8 - Add BrevoListIds.Waitlist = 5 to BrevoService - Add INotificationMessageBuilder.BuildWaitlistSignup + implementation (confirmation email: founding-member $19/mo rate reserved) - Add INotificationService.SendWaitlistSignupNotificationAsync + implementation - Add POST /api/email/waitlist-signup endpoint: Turnstile verify (waitlist-signup), adds contact to Brevo list 5 (hardcoded, not client-supplied), fires confirmation email fire-and-forget with CancellationToken.None - Add SendWaitlistSignupNotificationAsync stub to NoOpNotificationService in tests ADO: #251, #254
- Add FoundingMemberInvite domain model and EF configuration - Add FoundingMemberInviteStatus enum (Queued, InviteSent, Redeemed, Expired) - Add FoundingMemberService with capacity check, waitlist join, invite send, redeem logic - Add FoundingMemberController with endpoints: capacity (anon), waitlist join, invite send (admin), redeem, list - Add FoundingMemberInviteJob (Hangfire recurring): ProcessPendingInvites + ExpireStaleInvites - Add FoundingMemberErrors model errors - Add FoundingMemberInviteDto - Add FoundingMemberGoPrice to StripeSettings - Register DI and Hangfire recurring jobs in Program.cs - Add EF migration: AddFoundingMemberInvites - Extend Organization model with IsFoundingMember, FoundingMemberSince, FoundingMemberForfeitedAt - Wire founding member redemption into stripe webhook (subscription created event) - Add waitlist invite email template
…t stub ## Summary WaitlistConfirmation was mapped to Brevo template ID 8 (the invoice template), causing waitlist signup emails to render invoice content. Corrected to template ID 2. Also adds missing SendFoundingMemberInviteNotificationAsync stub to test NoOpNotificationService. ## Changes ### Business - EmailTemplate.WaitlistConfirmation: 8 -> 2 ### Tests - NoOpNotificationService: add SendFoundingMemberInviteNotificationAsync stub
…ites ## Summary The initial AddFoundingMemberInvites migration created Token, SentAt, ExpiresAt, and RedeemedAt as non-nullable, but the domain model defines them as nullable. This migration corrects the column nullability and recreates the unique index on Token with a null filter. ## Changes ### Infrastructure.Persistence - Migration FoundingMemberInviteSentinel: alter Token/SentAt/ExpiresAt/RedeemedAt to nullable; recreate IX_FoundingMemberInvites_Token with IS NOT NULL filter - Update model snapshot
…ging ## Summary If MigrateAsync() throws at startup (e.g. transient DB connectivity issue, schema mismatch on staging), the entire process was crashing before UseCors ran — causing 503 on ALL endpoints and no CORS headers on any response. Wrap MigrateAsync in try-catch so the app starts and serves requests even if the migration step fails. The error is logged for ops visibility. ## Changes ### API - Program.cs: wrap startup MigrateAsync in try-catch with error logging
6aaac5c
into
fix/employee-role-assignment-migration
10 checks passed
bllr777
added a commit
that referenced
this pull request
May 25, 2026
…gration Merge pull request #330 from Katharix/feature/251-waitlist-landing-page
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.
No description provided.