IDA Module — Technical Report
1. Introduction
The IDA (International Diplomatic Alliance) module is a full-stack application subsystem within the RCI Card project. It manages the complete lifecycle of IDA membership applications: from applicant registration and form submission, through payment verification and admin review, to PDF generation, HQ workflow, and completion.
Purpose: Allow officers/cadets to apply for IDA membership, pay fees (where applicable), and track status; allow admins to review applications, verify payments, update status, and generate official 8-page PDF forms. The system supports messaging between applicants and admins, comments on applications, and automated reminders.
2. Architecture Overview
2.1 Route Structure
- Applicant (IDA) routes — under
app/(ida)/:ida/apply,ida/application,ida/dashboard,ida/payment,ida/messages. - Admin routes — under
app/(admin)/admin/:ida-applications,ida-applications/[userId],ida-payments,ida-payment-config,ida-analytics,ida-dashboard,ida-payments/reports.
2.2 Layout & Guards
app/(ida)/layout.tsx wraps IDA pages with IDALayoutGuard, Sidebar, TopNavbar, and IDAMobileNav. IDALayoutGuard enforces that the user is authenticated and has access to the IDA section (e.g. officer/cadet role).
2.3 Key Libraries
lib/ida-status-workflow.ts— status transitions, role permissions, progress.lib/ida-pdf-generator.ts— 8-page IDA application PDF (pdf-lib / PDFKit).lib/ida-payment-utils.ts— expected payment amount by membership level.lib/ida-validation.ts— form validation (phone, email, dates, signature, etc.).lib/ida-notifications.ts— in-app and push notifications per status/event.lib/ida-reminders.ts— pending payments and overdue reviews; notifies admins.lib/ida-cloudinary-naming.ts— Cloudinary public_id and download filenames for PDFs.
3. Data Models
3.1 User (IDA fields)
IDA application data lives primarily on the User model (MongoDB). Key fields include:
idaApplicationStatus,idaMembershipLevel,idaExpectedPaymentAmountidaApplicationSubmittedAt,idaApplicationLocked- Passport:
idaPassportCountryOfIssue,idaPassportNumber,idaPassportExpirationDate - Employment:
idaPositionsHeld,idaDuties,idaSpecialSkillsTraining,idaAwardsRecognitions,idaNumberOfYearsInService,idaYearReceivedPension - Background:
idaHasBeenUnderTrial,idaTrialDetails,idaHasBeenMemberOfLawEnforcementGroups,idaLawEnforcementGroupsDetails,idaHasBeenMemberOfUNOrganizations,idaUNOrganizationsDetails - Terms:
idaMembershipStatementAccepted,idaTermsAndConditionsVersion,idaTermsAndConditionsAcceptedAt,idaTermsAndConditionsAcceptedIP,idaApplicationDate,idaSignature idaFamilyMembers(array),idaCvDocumentUrl,idaSupportingDocuments,idaAdditionalDocuments- Admin:
idaAdminNotes,idaReviewedBy,idaReviewedAt - PDFs:
idaPdfUrl,idaPdfPublicId(official),idaPreliminaryPdfUrl,idaPreliminaryPdfPublicId(on submit).
Personal/contact data (name, nationality, address, phone, DOB, etc.) is on the Officer model, linked via User.officerId.
3.2 IDAStatusHistory
Each status change is recorded: userId, previousStatus, newStatus, changedBy, changeReason, timestamp. Used for audit trail and timeline UI.
3.3 IDAPayment
Payment records: userId, paymentAmount, expectedAmount, currency, paymentProofUrl, paymentProofPublicId, verificationStatus (pending | verified | rejected), verifiedBy, verificationNotes, verificationTimestamp.
3.4 IDAMessage
Applicant–admin messaging: userId, threadId, senderId, recipientId, message, messageType (admin_to_applicant | applicant_to_admin), priority, isResolved, parentMessageId, attachments.
3.5 IDAComment
Admin comments on applications: userId, comment, authorId, parentCommentId, mentions, isEdited.
3.6 Supporting Models
PaymentConfig stores idaPaymentAmounts (per membership level). IDADashboardPreference and FilterPreset support admin dashboard and list filters.
4. Status Workflow
Status is stored on User.idaApplicationStatus. Valid values and transitions (from lib/ida-status-workflow.ts):
| Current Status | Valid Next Statuses |
|---|---|
| Waiting | In Progress, Sent to HQ |
| In Progress | Ready for HQ, Sent to HQ, Approved by HQ / Pending Materials |
| Ready for HQ | Sent to HQ |
| Sent to HQ | Approved by HQ / Pending Materials, Ready for Pickup |
| Approved by HQ / Pending Materials | Ready for Pickup |
| Ready for Pickup | Completed / Picked Up |
| Completed / Picked Up | (terminal) |
Role permissions: ida_admin can review and basic actions; ida_assistant_director and ida_director can approve and send to HQ; ida_director and just_awesome can set “Approved by HQ / Pending Materials”. Override (bypass transition rules) is allowed for ida_assistant_director, ida_director, just_awesome.
Editing the application is only allowed when status is null (draft) or Waiting. Payment submission is allowed when status is Waiting.
5. Applicant Flow
- Apply — User fills multi-page form (
ida/applyorida/application). Data saved viaPOST /api/ida/application(save draft). - Submit —
POST /api/ida/application/submitvalidates required fields, setsidaApplicationLocked = true,idaApplicationStatus = 'Waiting', creates initialIDAStatusHistoryentry, generates preliminary PDF and uploads to Cloudinary, sends submission notification. - Payment — If membership level has a fee, user goes to
ida/payment, uploads payment proof;POST /api/ida/paymentcreatesIDAPayment(pending). Admin verifies; on verify, status can move to “In Progress” and user is notified. - Dashboard —
ida/dashboardshows current status, timeline (IDAStatusTimeline), and links to application, payment, and messages. - Messages —
ida/messagesandGET/POST /api/ida/messagesfor applicant–admin thread.
PDF preview is available via POST /api/ida/application/preview-pdf (form payload) and GET /api/ida/application/official-pdf for the official generated PDF when available.
6. Admin Flow
- Applications list —
admin/ida-applications, backed byGET /api/admin/ida/applications(filter, search, pagination). Bulk actions and filter presets supported. - Application detail —
admin/ida-applications/[userId]: view application, status history, payments, comments, messages; update status (PUT /api/admin/ida/applications/[userId]/status), approve, reject, flag; download PDF. - Status update — Validates transition and role; on “Ready for HQ” or “Sent to HQ”, ensures PDF exists (generates via
generateIDAPdfand uploads to Cloudinary if missing), then updates status and notifies applicant. - Payments —
admin/ida-payments, verify/reject with notes; verification triggers status change to “In Progress” when applicable and notifications. - Payment config —
admin/ida-payment-configto setidaPaymentAmountsper membership level. - Analytics & dashboard —
admin/ida-analytics,admin/ida-dashboardfor counts and widgets; preferences and filter presets via dedicated APIs.
7. PDF Generation
lib/ida-pdf-generator.ts produces an 8-page A4 IDA application form PDF.
- Input — Either
{ user, officer }(from DB) or a preview payload (form POST). Data is normalized toIDAPdfDatavianormalizeFromUserAndOfficerornormalizeFromPreviewPayload. - Content — Page 1: IDA logo, title, pledge, membership & procedure text. Pages 2–8: applicant data (personal info, membership level, passport, employment, background, family members, signature), with optional photo and signature image fetched from URLs.
- Implementation — Uses PDFKit (or pdf-lib where noted). Typography: Helvetica, fixed sizes for titles/body/notes. Footer “Page N of 8” on each page.
- Storage — On submit, preliminary PDF is generated and uploaded to Cloudinary (
ida-application-pdfs), URLs stored inidaPreliminaryPdfUrl/idaPreliminaryPdfPublicId. When status moves to “Ready for HQ” or “Sent to HQ”, official PDF is generated (if not already present) and uploaded with naming fromlib/ida-cloudinary-naming.ts(IDA-Surname-Name-{shortId}.pdf), stored inidaPdfUrl/idaPdfPublicId.
8. Payments
lib/ida-payment-utils.ts: calculateExpectedPaymentAmount(membershipLevel, amountsMap) uses PaymentConfig.idaPaymentAmounts or built-in defaults (e.g. Chaplain: 100, Active: 150). Display text in Naira via getPaymentAmountText.
Applicant submits payment proof (image/PDF) via upload; POST /api/ida/payment creates IDAPayment with verificationStatus: 'pending'. Admin verifies or rejects via api/admin/ida/payments/[paymentId]/verify and reject; on verify, application status can be set to “In Progress” and notifyPaymentVerified is called.
9. Notifications & Reminders
lib/ida-notifications.ts — For each status and key events (submit, payment verified/rejected, application approved/rejected/flagged), creates in-app notifications and, where applicable, browser push notifications (sendPushNotification). notifyStatusChange(userId, newStatus) dispatches to the right message and push.
lib/ida-reminders.ts — getPendingPaymentReminders() returns payments in “pending” older than 24 hours; getOverdueReviewReminders() returns applications in “Waiting” older than 3 days. sendReminderNotifications() notifies all IDA admins (roles including ida_admin, ida_assistant_director, etc.) with a single in-app notification. The cron endpoint GET /api/cron/ida-reminders is secured by Authorization: Bearer CRON_SECRET and invokes sendReminderNotifications (e.g. daily via Vercel Cron).
10. Validation & Security
lib/ida-validation.ts provides validators for: telephone (E.164-style with +), email, required fields, date of birth (past, age 18–120), passport expiration (future), numeric and length constraints, and signature (URL). Friendly field names for errors via getFieldName.
API routes use verifyToken for auth; admin routes use hasPermission(role, 'REVIEW_IDA_APPLICATIONS') (or equivalent). Status changes validate both transition rules and role via ida-status-workflow. Application updates check idaApplicationLocked to prevent edits after submit.
11. API Reference
| Method | Path | Purpose |
|---|---|---|
| POST | /api/ida/application | Save draft (IDA form data on User) |
| POST | /api/ida/application/submit | Lock & submit; set status Waiting; preliminary PDF; notify |
| GET | /api/ida/application/me | Current user’s application data |
| POST | /api/ida/application/preview-pdf | Generate PDF from form payload (preview) |
| GET | /api/ida/application/official-pdf | Stream official PDF for applicant |
| GET | /api/ida/application/status-history | Status history for current user |
| POST | /api/ida/payment | Submit payment proof (create IDAPayment) |
| GET/POST | /api/ida/messages | List/send applicant–admin messages |
| GET | /api/ida/membership-levels | Membership levels (e.g. for dropdown) |
| GET | /api/admin/ida/applications | List applications (filter, search) |
| GET/PUT | /api/admin/ida/applications/[userId] | Get/update application |
| PUT | /api/admin/ida/applications/[userId]/status | Update status (workflow + PDF if needed) |
| GET | /api/admin/ida/applications/[userId]/pdf | Admin download PDF |
| GET | /api/admin/ida/applications/[userId]/pdf-download | Download with Content-Disposition filename |
| POST | /api/admin/ida/applications/[userId]/approve | Approve application |
| POST | /api/admin/ida/applications/[userId]/reject | Reject application |
| POST | /api/admin/ida/applications/[userId]/flag | Flag for corrections |
| GET/POST | /api/admin/ida/applications/[userId]/comments | Comments on application |
| GET/POST | /api/admin/ida/applications/[userId]/messages | Admin side of messages |
| GET | /api/admin/ida/payments | List payments (e.g. pending) |
| POST | /api/admin/ida/payments/[paymentId]/verify | Verify payment |
| POST | /api/admin/ida/payments/[paymentId]/reject | Reject payment |
| GET/PUT | /api/admin/ida/payment-config | Get/update PaymentConfig (idaPaymentAmounts) |
| GET | /api/admin/ida/analytics | Analytics for dashboard |
| GET | /api/cron/ida-reminders | Cron: send IDA reminder notifications (Bearer CRON_SECRET) |