espace-paie-odentas/types/salaires.ts
odentas 31459f3c10 feat: Ajout fonctionnalité salaires par date avec JSONB
 Nouvelle fonctionnalité
- Ajout mode 'Saisir le salaire par date' dans création de contrat
- Interface de saisie compacte et moderne par représentation/répétition/jour
- Stockage en JSONB dans colonne salaires_par_date
- Affichage détaillé dans contrats/[id] et staff/contrats/[id]

🗄️ Base de données
- Migration SQL : ajout colonne salaires_par_date JSONB
- Index GIN pour requêtes performantes sur JSONB
- Index partial sur le champ mode
- Fonction de validation validate_salaires_par_date()

🎨 Interface utilisateur
- Design en ligne (inline) au lieu de tableau traditionnel
- Labels courts (R1, R2 pour représentations, S1, S2 pour services)
- Cartes par catégorie avec codes couleur (indigo/purple/green)
- Calculatrice et Minima accessibles dans les deux modes
- Calculatrice désactivée en mode par_date (pas de champ unique)
- Minimum conventionnel retiré du menu déroulant en mode par_date
- Calcul automatique du total

💻 Code
- Types TypeScript : SalaireParDate avec interfaces complètes
- Fonction convertSalariesByDateToJSON() pour conversion formulaire → JSONB
- Validation adaptée selon le mode (global vs par_date)
- API /api/cddu-contracts : support du champ salaires_par_date
- API /api/contrats/[id] : retour du champ salaires_par_date
- Contournement temporaire de la RPC pour utiliser service_role

📝 Fichiers modifiés
- migrations/add_salaires_par_date_column.sql (nouveau)
- types/salaires.ts (nouveau)
- components/contrats/NouveauCDDUForm.tsx
- app/api/cddu-contracts/route.ts
- app/api/contrats/[id]/route.ts
- app/(app)/contrats/[id]/page.tsx
- components/staff/contracts/ContractEditor.tsx
2025-10-29 23:12:15 +01:00

92 lines
2.5 KiB
TypeScript

// types/salaires.ts
// Types pour la saisie de salaires par date/représentation/répétition
export type SalaryMode = "global" | "par_date";
export type SalaryType = "Brut" | "Net avant PAS" | "Coût total employeur" | "Minimum conventionnel";
export interface RepresentationSalaryItem {
index: number; // Numéro de la représentation (1, 2, 3)
montant: number; // Montant en euros
}
export interface RepresentationSalaryDate {
date: string; // Format ISO "2025-11-15"
date_display: string; // Format d'affichage "15/11"
items: RepresentationSalaryItem[];
}
export interface RepetitionSalaryItem {
index: number; // Numéro du service de répétition
montant: number; // Montant en euros
duree?: 3 | 4; // Durée en heures (optionnel, pour info)
}
export interface RepetitionSalaryDate {
date: string; // Format ISO "2025-11-10"
date_display: string; // Format d'affichage "10/11"
items: RepetitionSalaryItem[];
}
export interface JourTravailSalary {
date: string; // Format ISO "2025-11-05"
date_display: string; // Format d'affichage "05/11"
montant: number; // Montant en euros
heures?: number; // Nombre d'heures (optionnel, pour info)
}
export interface SalaireParDate {
mode: SalaryMode;
type_salaire: SalaryType;
representations?: RepresentationSalaryDate[];
repetitions?: RepetitionSalaryDate[];
jours_travail?: JourTravailSalary[];
total_calcule?: number; // Total calculé automatiquement
}
// Helper pour créer une structure vide
export function createEmptySalaireParDate(
mode: SalaryMode,
type_salaire: SalaryType
): SalaireParDate {
return {
mode,
type_salaire,
representations: [],
repetitions: [],
jours_travail: [],
total_calcule: 0,
};
}
// Helper pour calculer le total
export function calculateTotalSalaire(data: SalaireParDate): number {
let total = 0;
// Représentations
if (data.representations) {
for (const dateGroup of data.representations) {
for (const item of dateGroup.items) {
total += item.montant || 0;
}
}
}
// Répétitions
if (data.repetitions) {
for (const dateGroup of data.repetitions) {
for (const item of dateGroup.items) {
total += item.montant || 0;
}
}
}
// Jours de travail
if (data.jours_travail) {
for (const jour of data.jours_travail) {
total += jour.montant || 0;
}
}
return total;
}