Skip to main content

Documentation Index

Fetch the complete documentation index at: https://memberpulseptyltd.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Set up Continuing Professional Development (CPD) tracking for your members with customizable categories, point requirements, and approval workflows.

Spreadsheet intent cross-check

The supplied spreadsheet indicates that:
  • Courses and Events both support selecting CPD Category (cpdCategories).
  • Membership plans may specify required CPD points (spreadsheet: MembershipPlan.requiredCpdPoints).

Data Model Cross‑Reference (Entities)

Capabilities

ActionROLE_CLIENT_ADMINROLE_CLIENT_USER
View CPD settings
Create categories
Edit categories
Set requirements
Approve member CPD

Features

CPD Categories

Define categories for different types of professional development:
1

Create Category

Add a new CPD category with name and description.Examples:
  • Technical Skills
  • Professional Ethics
  • Leadership Development
  • Industry Knowledge
2

Set Requirements

Configure required points per calendar year for each category.
  • Points must be greater than 0
  • Points must be divisible by 0.5
  • Set if category is required for certification
3

Configure Display

Set display order and whether category is active.

Acceptance Criteria

Frontend
  • CPD categories list with CRUD operations
  • Member CPD summary view
  • Drag-and-drop category reordering
  • Requirements configuration per category
  • Bulk approve/reject functionality
Backend / API
  • Backend behavior supports this feature as documented.
Permissions
  • Access is restricted per the Capabilities matrix on this page (or equivalent role rules).
Business Rules
  • Category names must be unique per organization
  • At least one category must be marked as required for certification
  • Cannot delete category with existing member records
  • Rejected submissions can be resubmitted by member
Error Handling
  • Error states return clear messages and appropriate HTTP status codes.

Point Assignment Rules

Configure how points are automatically assigned:
  • Set default CPD points per event
  • Override points for specific events
  • Points awarded on attendance confirmation

Acceptance Criteria

Frontend
  • Points allocation rules interface
  • Validation for point values (0.5 increments)
Backend / API
  • Backend behavior supports this feature as documented.
Permissions
  • Access is restricted per the Capabilities matrix on this page (or equivalent role rules).
Business Rules
  • Required points must be > 0 and divisible by 0.5
  • Points are assigned to the calendar year of the activity date
Error Handling
  • Error states return clear messages and appropriate HTTP status codes.

Approval Workflow

For manually submitted CPD:
  1. Member submits CPD claim with evidence
  2. Claim appears in approval queue
  3. Admin reviews submission
  4. Approve or reject with reason
  5. Member notified of decision
  6. Points added to member’s record (if approved)

Acceptance Criteria

Frontend
  • Approval queue with filtering
Backend / API
  • Backend behavior supports this feature as documented.
Permissions
  • Access is restricted per the Capabilities matrix on this page (or equivalent role rules).
Business Rules
  • All business rules for this feature are enforced.
Error Handling
  • Error states return clear messages and appropriate HTTP status codes.

Export CPD Records

Client admins often need to export CPD data for annual audits/compliance reporting. Export capabilities:
  • Export member CPD summary (per member totals by year and category)
  • Export raw CPD records (event/course/manual) with approvals and evidence links
  • Filter by date range, category, member, and status

Acceptance Criteria

Frontend
  • CPD export action exists from the CPD admin area.
  • Export can be filtered (year/date range, category, member, status) before generating.
  • Export formats include CSV (minimum) and optionally Excel.
Backend / API
  • Exports are generated server-side and returned as a downloadable file.
Permissions
  • Only ROLE_CLIENT_ADMIN (and permitted ROLE_CLIENT_USER roles if enabled) can export CPD data.
Business Rules
  • Export respects tenant isolation and only includes the client’s members.
Error Handling
  • Large exports either stream or generate asynchronously with progress/error feedback.

Implementation Contracts

Backend (API)

GET    /api/cpd/categories                   # List all categories
POST   /api/cpd/categories                   # Create category
PUT    /api/cpd/categories/{id}              # Update category
DELETE /api/cpd/categories/{id}              # Delete category
PUT    /api/cpd/categories/reorder           # Reorder categories

GET    /api/cpd/settings                     # Get CPD settings
PUT    /api/cpd/settings                     # Update settings

GET    /api/cpd/approvals                    # Pending approvals
POST   /api/cpd/approvals/{id}/approve       # Approve submission
POST   /api/cpd/approvals/{id}/reject        # Reject submission
POST   /api/cpd/approvals/bulk               # Bulk approve/reject

GET    /api/cpd/members/{id}/summary         # Member CPD summary
GET    /api/cpd/members/{id}/records         # Member CPD records
POST   /api/cpd/export/summary               # Export CPD summaries (CSV/Excel)
POST   /api/cpd/export/records               # Export CPD records (CSV/Excel)

Data Model

interface CpdCategory {
  id: string;
  name: string;
  description: string;
  requiredPointsPerYear: number;
  requiredForCertification: boolean;
  displayOrder: number;
  active: boolean;
  createdAt: string;
  updatedAt: string;
}

interface CpdApproval {
  id: string;
  memberId: string;
  memberName: string;
  categoryId: string;
  categoryName: string;
  points: number;
  activityDate: string;
  description: string;
  evidenceUrl?: string;
  status: 'pending' | 'approved' | 'rejected';
  reviewedBy?: string;
  reviewedAt?: string;
  rejectionReason?: string;
  submittedAt: string;
}

Validation Rules

// Category validation
{
  name: z.string().min(2).max(100),
  requiredPointsPerYear: z.number()
    .positive()
    .multipleOf(0.5),
  requiredForCertification: z.boolean()
}

// At least one category must be required
const hasRequiredCategory = categories.some(c => c.requiredForCertification);

Error Handling

ErrorHTTP StatusMessage
Duplicate name409”A category with this name already exists”
Invalid points400”Points must be a positive number divisible by 0.5”
Has records400”Cannot delete category with existing records”
No required category400”At least one category must be required for certification”