Aller au contenu

Story CP-029: Admin Console — Module Override + Country Config + Metrics

Module: control-plane Slice: Slice 12b from architecture (split from CP-012) Brand context: ALTARYS ENTERPRISE (Admin Console — corporate, data-dense, desktop-only) Priority: 14 Depends on: CP-012 Estimated complexity: M


Objective

Extend the ALTARYS operator admin console (built in CP-012) with four power-user features: module override (promotional access grants), country configuration editor (with unverified-rate highlighting), platform metrics dashboard, and CRM registration review (FR-CP-101). These features allow operators to fine-tune tenant access, manage regulatory reference data, monitor platform health, and review CRM-created tenants at a glance.


Backend Scope

API Endpoints (Admin-only)

All endpoints require PLATFORM_ADMIN role (Keycloak-managed, separate from tenant roles). The admin app shell, auth, and Keycloak client are already set up in CP-012.

Scheduled Jobs

PreHireTransitionJob (runs daily, iterates all tenants): - Scheduled service that transitions PRE_HIRE employees to ACTIVE on hire_date. - Per ADR-16: Uses ThreadLocal fallback for TenantContext propagation in @Scheduled context (ScopedValue is for HTTP requests only). Sets TenantContext before each tenant's queries, clears after. - Processes all tenants sequentially. For each tenant: query employees where status = PRE_HIRE AND hire_date <= today, transition each to ACTIVE, publish EmployeeStatusChanged.

Method Path Request Body Response Auth
POST /api/v1/admin/tenants/{id}/modules/{code}/override {status, expiryDate?} 204 PLATFORM_ADMIN
GET /api/v1/admin/metrics PlatformMetricsResponse PLATFORM_ADMIN
GET /api/v1/admin/config/countries/{code} CountryConfigResponse PLATFORM_ADMIN
PUT /api/v1/admin/config/countries/{code}/rates/{rateId} {value, isVerified} 204 PLATFORM_ADMIN
GET /api/v1/admin/crm-registrations ?week=&flagged= Page PLATFORM_ADMIN
POST /api/v1/admin/crm-registrations/{id}/flag {reason} 204 PLATFORM_ADMIN

Module override: Temporarily activates a module for a tenant (promotional access). Optional expiry date. Audit logged.

PlatformMetricsResponse:

public record PlatformMetricsResponse(
    Map<String, Integer> tenantsByStatus,    // e.g. {"ACTIVE": 80, "TRIAL": 30, ...}
    int totalActiveEmployees,
    BigDecimal mrr,                          // Monthly Recurring Revenue in XOF
    Map<String, Integer> modulePopularity,   // e.g. {"PAYROL": 95, "LEAVE": 110}
    List<WeeklyGrowthPoint> tenantGrowth,    // last 12 weeks
    Map<String, Integer> paymentMethodSplit   // e.g. {"MOBILE_MONEY": 60, "BANK_TRANSFER": 20}
) {}

public record WeeklyGrowthPoint(
    LocalDate weekStart,
    int newTenants,
    int totalTenants
) {}

Multi-Tenant Considerations

  • All endpoints query across ALL tenants (admin-scoped, not tenant-scoped)
  • Metrics are aggregated platform-wide — no tenant_id filter
  • Country config edits affect ALL tenants in that country

Frontend Scope

Pages & Routes

These pages are added to the existing admin app (AdminLayout from CP-012):

  • /metrics — Platform metrics dashboard
  • /config/country — Country configuration editor
  • /crm-registrations — CRM registration review (weekly report, flag suspicious)

Module override UI is added as a tab/action within the existing TenantDetailPage (built in CP-012).

Components

  • MetricsPage.tsx — KPI cards + charts
  • CountryConfigEditor.tsx — Two-panel layout: category selector + data table
  • CrmRegistrationReviewPage.tsx — Weekly report table with flag action
  • Module override section within TenantDetailPage.tsx Modules tab

UI States

Metrics Page:

State Behavior French Copy
Loading Skeleton cards and chart placeholders
Error Error banner "Impossible de charger les métriques"
Success KPI cards + charts

Country Config Editor:

State Behavior French Copy
Loading Table skeleton
Empty No rates for selected category "Aucun taux configuré pour cette catégorie"
Error Error banner "Erreur de chargement de la configuration"
Success Editable data table
Save success Toast notification "Configuration mise à jour"

CRM Registration Review:

State Behavior French Copy
Loading Table skeleton
Empty No CRM registrations this week "Aucune inscription CRM cette semaine"
Success Table with flag action
Flag confirm Confirmation dialog "Signaler cette inscription comme suspecte ?"

Module Override Dialog:

State Behavior French Copy
Form Module selector + optional expiry date "Accorder l'accès promotionnel"
Confirm Confirmation dialog "Confirmer l'accès au module {code} pour {tenant} ?"
Success Toast notification "Accès au module accordé"
Error Error banner in dialog "Impossible d'accorder l'accès"

Key Interactions

Country config editor: Left panel: country selector (CI) + config categories (e.g. CNPS, Impôts). Right panel: editable data table. Unverified rates (is_verified=false) shown with orange background + "Non verifie" badge. Admin can toggle is_verified. Save button per row or bulk save.

Module override (within TenantDetailPage Modules tab): "Accorder l'accès" button next to unsubscribed modules → dialog with optional expiry date → confirmation → audit logged.

Platform Metrics

Metric Display
Total tenants by status Horizontal stacked bar
Total active employees Big number with trend
MRR (Monthly Recurring Revenue) Big number with trend
Module popularity Horizontal bar chart
Tenant growth Line chart (last 12 weeks)
Payment method split Pie chart

Acceptance Criteria

AC-098: Admin overrides module access
Given tenant "TechCI" does not subscribe to PAYROL
When the admin grants promotional access with expiry 2026-04-01
Then PAYROL is ACTIVE for TechCI until 2026-04-01
And the override is recorded in audit

AC-099: Country config editor shows unverified rates
Given CNPS AV ceiling has is_verified=false
When the admin views country config
Then the AV row has orange background and "Non verifie" badge

AC-115: CRM registration review
Given 5 tenants were created via CRM channel this week
When the admin views /crm-registrations
Then all 5 CRM-created tenants are listed with creation date, company name, and channel
And the admin can flag a suspicious registration with a reason
And flagged registrations are visually marked

AC-100: Platform metrics display
Given the admin navigates to /metrics
Then KPI cards show total tenants, employees, MRR
And charts display tenant growth and module popularity

OHADA & Regulatory Rules

  • Module override is audit-logged — satisfies accountability requirements.
  • Country config rates have is_verified flag to track which regulatory rates need official confirmation. Unverified rates are visually flagged to prevent inadvertent use.

Standards & Conventions

  • docs/standards/react-typescript-guidelines.md — §Chart components, §Admin patterns
  • docs/standards/api-guidelines.md — §Admin endpoints
  • docs/standards/database-guidelines.md — §Country configuration tables

Testing Requirements

Unit Tests

  • Module override: expiry date handling, status transition, audit entry creation
  • Metrics aggregation: correct counts by status, MRR calculation (BigDecimal)
  • Country config: rate update with is_verified toggle

Integration Tests

  • Module override: grant → verify module active → expiry passes → module inactive
  • Metrics endpoint returns correct aggregated data
  • Country config update: edit rate → verify persisted → verify is_verified flag
  • Authorization: non-admin user → 403 on all endpoints

What QA Will Validate

  • Country config editor: view, edit, is_verified toggle, orange badge on unverified
  • Metrics dashboard shows data and charts render
  • Module override dialog flow end-to-end
  • All new pages accessible from admin sidebar navigation

Out of Scope

  • Admin app shell, layout, auth, tenant list, payments, suspension — CP-012 (already built)
  • Advanced reporting/analytics — V2
  • Automated alerts based on metrics — V2
  • Country config bulk import — V2
  • Module override auto-expiry cron job — V2 (manual check on access)

Definition of Done

  • [ ] All backend endpoints implemented and returning correct responses
  • [ ] All frontend pages render correctly at 1024px+ (desktop-only)
  • [ ] All UI states implemented (loading, empty, error, success) — no offline state needed
  • [ ] French copy correct
  • [ ] All acceptance criteria pass manually
  • [ ] Unit tests written and passing
  • [ ] Integration tests written and passing
  • [ ] Multi-tenant isolation verified — admin can see all, tenants cannot see admin
  • [ ] Offline write+sync works — N/A (admin console always online)
  • [ ] No TypeScript any — all types explicit
  • [ ] No Java raw types — all generics explicit
  • [ ] API responses follow standard envelope format
  • [ ] Audit trail entries created for every admin action (module override, config edit)