Source: person.js

/**
 * @module person
 * @description Person/Member Management Router
 *
 * This router provides comprehensive endpoints for managing persons/members within the
 * member management system. It handles all aspects of person data management including
 * profile information, group memberships, historical tracking, and administrative functions.
 *
 * Key Features:
 * - Person profile creation and management
 * - Group membership management with historical tracking
 * - Age calculation and automatic updates
 * - Duplicate detection and merging
 * - Leadership role and job assignments
 * - Permission-based access control
 * - Family relationship management
 * - Contact information synchronization
 *
 * Business Rules:
 * - Persons can belong to multiple groups with different roles
 * - Family relationships sync contact information automatically
 * - Age is calculated from birth date and updated periodically
 * - Duplicate detection uses phonetic matching
 * - Historical data tracks all membership and role changes
 * - Permissions are hierarchical based on organizational structure
 *
 * @requires express - Web framework for routing
 * @requires @/utils/authChecks - Authentication and authorization utilities
 * @requires @/utils/requestLogger - Request logging middleware
 * @requires ./person/controller - Person business logic controller
 */

import express from 'express';
import { checkObjectAdmin, checkVisible, checkAdmin } from '../utils/authChecks.js';
import { requestUpdateLogger, readLogger } from '../utils/requestLogger.js';
import * as personController from './person/controller.js';

const api = express.Router();

/**
 * @route GET /api/kpe20/person/ageUpdate
 * @group Person Management
 * @description Update age for all persons in the organization based on their birth dates
 * This is typically run as a scheduled maintenance task
 * @returns {object} Update result
 * @returns {boolean} .success - Whether the operation was successful
 * @returns {number} .updated - Number of persons whose age was updated
 * @example
 * GET /api/kpe20/person/ageUpdate
 * Response: {"success": true, "updated": 150}
 */
api.get('/ageUpdate', checkAdmin, requestUpdateLogger, personController.ageUpdate);

// Update group membership for a person
/**
 * @route POST /api/kpe20/person/:group/:UID
 * @group Person Management
 * @description Update a person's membership in a specific group
 * @param {string} group - UUID of the group
 * @param {string} UID - UUID of the person
 * @param {object} body - Membership update data
 * @param {string} [body.role] - New role in the group (member, leader, guest)
 * @param {string} [body.startDate] - Membership start date (ISO format)
 * @param {string} [body.endDate] - Membership end date (ISO format)
 * @param {object} [body.additionalData] - Additional membership-specific data
 * @returns {object} Update result
 * @returns {boolean} .success - Whether the update was successful
 * @returns {object} .result - Updated membership information
 * @example
 * POST /api/kpe20/person/UUID-group-123/UUID-person-456
 * Body: {"role": "leader", "startDate": "2024-01-01"}
 */
api.post('/:group/:UID', requestUpdateLogger, personController.updateGroupMembership);

// Update person data
/**
 * @route POST /api/kpe20/person/:UID
 * @group Person Management
 * @description Update a person's profile information
 * @param {string} UID - UUID of the person to update
 * @param {object} body - Updated person data
 * @param {string} [body.firstName] - First name
 * @param {string} [body.lastName] - Last name
 * @param {string} [body.birthDate] - Birth date (ISO format)
 * @param {string} [body.gender] - Gender (M=Male, F=Female)
 * @param {object[]} [body.addresses] - Contact addresses
 * @param {object[]} [body.phoneNumbers] - Phone numbers
 * @param {object[]} [body.emails] - Email addresses
 * @param {object} [body.additionalData] - Additional profile data
 * @returns {object} Update result
 * @returns {boolean} .success - Whether the update was successful
 * @returns {object} .result - Updated person information
 * @example
 * POST /api/kpe20/person/UUID-person-123
 * Body: {"firstName": "John", "lastName": "Doe", "birthDate": "1990-01-01"}
 */
api.post('/:UID', requestUpdateLogger, personController.updatePerson);

// Create or update person in group
/**
 * @route PUT /api/kpe20/person/:group
 * @group Person Management
 * @description Create a new person and add them to a group, or update existing person
 * @param {string} group - UUID of the group to add the person to
 * @param {object} body - Person creation data
 * @param {string} body.firstName - First name (required)
 * @param {string} body.lastName - Last name (required)
 * @param {string} body.birthDate - Birth date (ISO format, required)
 * @param {string} body.gender - Gender (M=Male, F=Female, required)
 * @param {object[]} [body.addresses] - Contact addresses
 * @param {object[]} [body.phoneNumbers] - Phone numbers
 * @param {object[]} [body.emails] - Email addresses
 * @param {string} [body.familyUID] - UUID of existing family to join
 * @param {object} [body.additionalData] - Additional profile data
 * @returns {object} Creation result
 * @returns {boolean} .success - Whether the operation was successful
 * @returns {object} .result - Created/updated person information
 * @returns {string} .result.UID - Person's UUID
 * @returns {boolean} .result.isNew - Whether a new person was created
 * @example
 * PUT /api/kpe20/person/UUID-group-123
 * Body: {
 *   "firstName": "Jane",
 *   "lastName": "Smith",
 *   "birthDate": "1995-03-15",
 *   "gender": "F"
 * }
 */
api.put('/:group', requestUpdateLogger, checkObjectAdmin, personController.putPerson);

// Get person details with optional related data
/**
 * @route GET /api/kpe20/person/:UID
 * @group Person Management
 * @description Get detailed information about a person including profile, memberships, and related data
 * @param {string} UID - UUID of the person to retrieve
 * @param {string} [include] - Comma-separated list of related data to include (groups,family,jobs,history)
 * @returns {object} Person information
 * @returns {boolean} .success - Whether the request was successful
 * @returns {object} .result - Complete person data
 * @returns {string} .result.firstName - First name
 * @returns {string} .result.lastName - Last name
 * @returns {string} .result.birthDate - Birth date
 * @returns {number} .result.age - Calculated age
 * @returns {object[]} .result.groups - Group memberships (if included)
 * @returns {object} .result.family - Family information (if included)
 * @returns {object[]} .result.jobs - Leadership roles (if included)
 * @example
 * GET /api/kpe20/person/UUID-person-123?include=groups,family
 */
api.get('/:UID', readLogger, personController.getPerson);

// Get person's group membership history
/**
 * @route GET /api/kpe20/person/history/:UID
 * @group Person Management
 * @description Get the complete membership history for a person across all groups
 * @param {string} UID - UUID of the person
 * @param {string} [startDate] - Start date for history filter (ISO format)
 * @param {string} [endDate] - End date for history filter (ISO format)
 * @returns {object} Membership history
 * @returns {boolean} .success - Whether the request was successful
 * @returns {object[]} .result - Array of historical membership records
 * @returns {string} .result[].groupName - Name of the group
 * @returns {string} .result[].role - Role in the group
 * @returns {string} .result[].startDate - Membership start date
 * @returns {string} .result[].endDate - Membership end date (if applicable)
 * @example
 * GET /api/kpe20/person/history/UUID-person-123
 */
api.get('/history/:UID', checkVisible, personController.personHistorie);

// Check admin rights for person
/**
 * @route GET /api/kpe20/person/admin/:UID
 * @group Person Management
 * @description Check if the current user has admin privileges for the specified person
 * @param {string} UID - UUID of the person to check
 * @returns {object} Admin status
 * @returns {boolean} .success - Whether the request was successful
 * @returns {boolean} .result - Whether user has admin rights for this person
 * @example
 * GET /api/kpe20/person/admin/UUID-person-123
 * Response: {"success": true, "result": true}
 */
api.get('/admin/:UID', personController.personAdmin);

// Get person's leadership roles/jobs
/**
 * @route GET /api/kpe20/person/leaders/:UID
 * @group Person Management
 * @description Get all leadership roles and jobs held by a person
 * @param {string} UID - UUID of the person
 * @returns {object} Leadership information
 * @returns {boolean} .success - Whether the request was successful
 * @returns {object[]} .result - Array of leadership roles
 * @returns {string} .result[].title - Job/office title
 * @returns {string} .result[].groupName - Group where the role is held
 * @returns {string} .result[].startDate - Role start date
 * @returns {string} .result[].endDate - Role end date (if applicable)
 * @example
 * GET /api/kpe20/person/leaders/UUID-person-123
 */
api.get('/leaders/:UID', checkVisible, personController.doCheckVisible);

// Find duplicate persons by name
/**
 * @route GET /api/kpe20/person/duplicates/:firstName/:lastName
 * @group Person Management
 * @description Find potential duplicate persons using phonetic name matching
 * @param {string} firstName - First name to search for
 * @param {string} lastName - Last name to search for
 * @param {string} [birthDate] - Optional birth date filter (ISO format)
 * @returns {object} Duplicate search results
 * @returns {boolean} .success - Whether the search was successful
 * @returns {object[]} .result - Array of potential duplicate persons
 * @returns {string} .result[].UID - Person UUID
 * @returns {string} .result[].firstName - First name
 * @returns {string} .result[].lastName - Last name
 * @returns {string} .result[].birthDate - Birth date
 * @returns {number} .result[].similarity - Similarity score (0-100)
 * @example
 * GET /api/kpe20/person/duplicates/John/Doe
 */
api.get('/duplicates/:firstName/:lastName', personController.personDuplicates);

// Get person's jobs (ungrouped)
/**
 * @route GET /api/kpe20/person/jobs/:UID
 * @group Person Management
 * @description Get all jobs/roles held by a person (ungrouped list)
 * @param {string} UID - UUID of the person
 * @returns {object} Jobs information
 * @returns {boolean} .success - Whether the request was successful
 * @returns {object[]} .result - Array of all jobs held by the person
 * @returns {string} .result[].title - Job title
 * @returns {string} .result[].groupName - Associated group name
 * @returns {string} .result[].startDate - Job start date
 * @returns {string} .result[].endDate - Job end date (if applicable)
 * @example
 * GET /api/kpe20/person/jobs/UUID-person-123
 */
api.get('/jobs/:UID', checkVisible, personController.jobgroups('visible', false));

// Get person's job groups (grouped by main group)
/**
 * @route GET /api/kpe20/person/jobgroups/:UID
 * @group Person Management
 * @description Get person's jobs grouped by their main group
 * @param {string} UID - UUID of the person
 * @returns {object} Grouped jobs information
 * @returns {boolean} .success - Whether the request was successful
 * @returns {object} .result - Jobs grouped by main group
 * @returns {object} .result.mainGroup - Primary group jobs
 * @returns {object[]} .result.otherGroups - Jobs in other groups
 * @example
 * GET /api/kpe20/person/jobgroups/UUID-person-123
 */
api.get('/jobgroups/:UID', checkVisible, personController.jobgroups('visible', true));

// Get person's changeable job groups
/**
 * @route GET /api/kpe20/person/jobgroups/changeable/:UID
 * @group Person Management
 * @description Get person's jobs that can be modified by the current user
 * @param {string} UID - UUID of the person
 * @returns {object} Changeable jobs information
 * @returns {boolean} .success - Whether the request was successful
 * @returns {object} .result - Jobs the user can modify
 * @returns {object[]} .result.canModify - Jobs user has permission to change
 * @returns {object[]} .result.readOnly - Jobs user can only view
 * @example
 * GET /api/kpe20/person/jobgroups/changeable/UUID-person-123
 */
api.get('/jobgroups/changeable/:UID', checkVisible, personController.jobgroups('changeable', true));

// Export helper functions for other modules
export const publishChangeEvent = personController.publishChangeEvent;
export const updatePerson = personController.updatePerson;
export const getPerson = personController.getPerson;
export const personAdmin = personController.personAdmin;
export const personHistorie = personController.personHistorie;
export const personDuplicates = personController.personDuplicates;
export const ageUpdate = personController.ageUpdate;

export default api;