✨ 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
92 lines
2.5 KiB
TypeScript
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;
|
|
}
|