Back to home

IDA Module — Technical Report

RCI Card Project · International Diplomatic Alliance (IDA) Application Module · Document version 1.0

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, idaExpectedPaymentAmount
  • idaApplicationSubmittedAt, 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 StatusValid Next Statuses
WaitingIn Progress, Sent to HQ
In ProgressReady for HQ, Sent to HQ, Approved by HQ / Pending Materials
Ready for HQSent to HQ
Sent to HQApproved by HQ / Pending Materials, Ready for Pickup
Approved by HQ / Pending MaterialsReady for Pickup
Ready for PickupCompleted / 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

  1. Apply — User fills multi-page form (ida/apply or ida/application). Data saved via POST /api/ida/application (save draft).
  2. SubmitPOST /api/ida/application/submit validates required fields, sets idaApplicationLocked = true, idaApplicationStatus = 'Waiting', creates initial IDAStatusHistory entry, generates preliminary PDF and uploads to Cloudinary, sends submission notification.
  3. Payment — If membership level has a fee, user goes to ida/payment, uploads payment proof; POST /api/ida/payment creates IDAPayment (pending). Admin verifies; on verify, status can move to “In Progress” and user is notified.
  4. Dashboardida/dashboard shows current status, timeline (IDAStatusTimeline), and links to application, payment, and messages.
  5. Messagesida/messages and GET/POST /api/ida/messages for 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 listadmin/ida-applications, backed by GET /api/admin/ida/applications (filter, search, pagination). Bulk actions and filter presets supported.
  • Application detailadmin/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 generateIDAPdf and uploads to Cloudinary if missing), then updates status and notifies applicant.
  • Paymentsadmin/ida-payments, verify/reject with notes; verification triggers status change to “In Progress” when applicable and notifications.
  • Payment configadmin/ida-payment-config to set idaPaymentAmounts per membership level.
  • Analytics & dashboardadmin/ida-analytics, admin/ida-dashboard for 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 to IDAPdfData via normalizeFromUserAndOfficer or normalizeFromPreviewPayload.
  • 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 in idaPreliminaryPdfUrl / idaPreliminaryPdfPublicId. When status moves to “Ready for HQ” or “Sent to HQ”, official PDF is generated (if not already present) and uploaded with naming from lib/ida-cloudinary-naming.ts (IDA-Surname-Name-{shortId}.pdf), stored in idaPdfUrl / 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.tsgetPendingPaymentReminders() 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

MethodPathPurpose
POST/api/ida/applicationSave draft (IDA form data on User)
POST/api/ida/application/submitLock & submit; set status Waiting; preliminary PDF; notify
GET/api/ida/application/meCurrent user’s application data
POST/api/ida/application/preview-pdfGenerate PDF from form payload (preview)
GET/api/ida/application/official-pdfStream official PDF for applicant
GET/api/ida/application/status-historyStatus history for current user
POST/api/ida/paymentSubmit payment proof (create IDAPayment)
GET/POST/api/ida/messagesList/send applicant–admin messages
GET/api/ida/membership-levelsMembership levels (e.g. for dropdown)
GET/api/admin/ida/applicationsList applications (filter, search)
GET/PUT/api/admin/ida/applications/[userId]Get/update application
PUT/api/admin/ida/applications/[userId]/statusUpdate status (workflow + PDF if needed)
GET/api/admin/ida/applications/[userId]/pdfAdmin download PDF
GET/api/admin/ida/applications/[userId]/pdf-downloadDownload with Content-Disposition filename
POST/api/admin/ida/applications/[userId]/approveApprove application
POST/api/admin/ida/applications/[userId]/rejectReject application
POST/api/admin/ida/applications/[userId]/flagFlag for corrections
GET/POST/api/admin/ida/applications/[userId]/commentsComments on application
GET/POST/api/admin/ida/applications/[userId]/messagesAdmin side of messages
GET/api/admin/ida/paymentsList payments (e.g. pending)
POST/api/admin/ida/payments/[paymentId]/verifyVerify payment
POST/api/admin/ida/payments/[paymentId]/rejectReject payment
GET/PUT/api/admin/ida/payment-configGet/update PaymentConfig (idaPaymentAmounts)
GET/api/admin/ida/analyticsAnalytics for dashboard
GET/api/cron/ida-remindersCron: send IDA reminder notifications (Bearer CRON_SECRET)

End of document.