---
# System prepended metadata

title: Pagga.Remuneration - Rapports F/H

---

# Pagga.Remuneration - Rapports F/H

# Contrat d'API

Services dédié pour les rapports d'égalité H/F

Note importante : on prend l'établissement de la personne à la date de fin de période

## Filtres & modèle de rapport



#### Dto

```csharp
abstract class ReportTemplate {
    int Id;
    string Name;
    abstract ReportType ReportType;    
}
class ReportTemplateTop : ReportTemplate {
    List<Establishment> Establishments; // Simplified Establishments
    List<Department> Departments; // Simplified Dept
    List<OccupationCategory> Occu   
    List<VariableRemunerationNature> VariableRemunerationNatures;     
    List<FixedRemunerationNature> FixedRemunerationNatures; 
    List<WorkContractType> WorkContractTypes
}
class ReportTemplateGenderGap : ReportTemplate{
    OccupationCategoryGroups OccupationCategoryGroups;
    List<Establishment> Establishments; // Simplified Establishments
    List<Department> Departments; // Simplified Dept
    List<VariableRemunerationNature> VariableRemunerationNatures;     
    List<FixedRemunerationNature> FixedRemunerationNatures; 
    List<WorkContractType> WorkContractTypes
}
class OccupationCategoryGroups {
    List<Group<OccupationCategories>> OccupationCategoryGroups;
}
class Group<T> { // Si trop complexe avec le swagger, on passe sur une classe par groupe
    int Id,
    string Name,
    T[] Items
}

enum ReportType {
    Top,
    GenderGap
}
```

### Apis

#### GET - /remuneration/api/report-templates/top

- Response : ReportTemplateTop[]

#### GET - /remuneration/api/report-templates/top/{id}

- Response : ReportTemplateTop

#### GET - /remuneration/api/report-templates/gender-gap

- Response : ReportTemplateGenderGap[]

#### GET - /remuneration/api/report-templates/gender-gap/{id}

- Response : ReportTemplateGenderGap

#### POST - /remuneration/api/report-templates/gender-gap

- Payload

    ```json=
    {    
        name: "nom du modèle",
        establishmentIds: [1, 2, 3],
        departmentIds: [1, 2],
        ...
    }
    ```

#### PUT - /remuneration/api/report-templates/gender-gap/{id}

- Payload

    ```json=
    {   
        id : 1,
        name: "nom du modèle",
        establishmentIds: [1, 2, 3],
        departmentIds: [1, 2],
        ...
    }
    ```

#### POST - /remuneration/api/report-templates/top

- Payload
    ```json=
    {    
        name: "nom du modèle",        
        establishmentIds: [1, 2, 3],
        departmentIds: [1, 2],
        occupationCategoryGroups: [ // A revoir ce point là -> l'interface de gestion des groupes serait interessante, notament pour les Apis
            {
                name : "groupe 1",
                ids : [1, 2, 3]
            }
        ],
        ... 
    }
    ```

#### PUT - /remuneration/api/report-templates/top/{id}

- Payload : idem Post

#### DELETE - /remuneration/api/report-templates/{id}

### Notes pour le front

#### APIs a utiliser

- modèles de contrat :
https://demoprem1.ilucca.net/directory/api/work-contract-types
- établissements : https://demoprem1.ilucca.net/organization/structure/api/establishments
- departements : https://demoprem1.ilucca.net/api/v3/departments/tree?fields=id,name,code,head[id,name,dtContractEnd],isActive,currentUsersCount&isActive=true
- CSP : https://demoprem1.ilucca.net/organization/structure/api/occupation-categories
- natures EFP : https://demoprem1.ilucca.net/api/v3/fixedRemunerationNatures
- natures EVP : https://demoprem1.ilucca.net/api/v3/variableRemunerationNatures?typeId=1

Todo :
- Voir le picker du departement de Poplee-Engagement @f2x
- Faire un establishmentPicker custom Bu-Pay pour prendre en compte les LU et les devises

## Générer un rapport - Top

**⚠️Pas de pagination sur cette API⚠️**

### Apis

#### POST - /remuneration/api/reports/top

- payload

    ```json=
    {
        endDate : "2023-01-03",
        template : 
        {    
            name: "nom du modèle",        
            establishmentIds: [1, 2, 3],
            departmentIds: [1, 2],
            ... 
        }
    }
    ```

- response : TopReport

### Dto

```csharp
class TopReport {
    DateOnly StartDate;
    DateOnly EndDate;
    List<TopRankedRemuneration> TopRankedRemunerations;
}
class TopRankedRemuneration {
    User User;
    Establishment Establishment;
    int Rank;
    RemunerationAmount RemunerationAmount;
}
class RemunerationAmount {
    decimal Amount;
    Currency Currency
}
```

## Générer un rapport - Gender Gap

**⚠️Pas de pagination sur cette API⚠️**

### Apis

#### POST - /remuneration/api/reports/gender-gap

- payload

    ```json=
    {
        endDate : "2023-01-03",
        template : 
        {    
            name: "nom du modèle",        
            establishmentIds: [1, 2, 3],
            departmentIds: [1, 2],
            occupationCategoryGroups: [ // A revoir ce point là -> l'interface de gestion des groupes serait interessante, notament pour les Apis
                {
                    name : "groupe 1",
                    ids : [1, 2, 3]
                }
            ],
            ... 
        }
    }
    ```

#### GET - /remuneration/api/reports/gender-gap/details?OccupationCategoryIds=1,2,3,4&ageMin=18&ageMax=55

- RequiredField : OccupationCategoryIds & ageMin
- response : UserRemunerationPage

### Dto

```csharp
class GenderGapReport {
    DateOnly StartDate;
    DateOnly EndDate;
    List<GenderGapReportItem> Items;
    GenderGapReportMetrics Total
}

class GenderGapReportItem {
    OccupationCategoryCriteria OccupationCategory;
    AgeRangeCriterion AgeRange;
    GenderGapReportMetrics Metrics;
}

class GenderGapReportMetrics {
    GenderMetrics MaleMetrics;
    GenderMetrics FemaleMetrics;
    decimal PercentageGap
}
class AgeRangeCriterion {
    int Min,
    int? Max
}

class OccupationCategoryCriteria {
    string Name;
    List<OccupationCategory> OccupationCategories; // liste simplifiée de OccupationCategory       
}

class GenderMetrics {
    RemunerationAmount AverageAmount,
    int Count
}

class RemunerationAmount {
    decimal Amount;
    Currency Currency
}

class UserRemuneration {
    User User;
    RemunerationAmount Amount;
}
```

### APIS des warnings

#### POST - /remuneration/api/reports/gender-gap/warnings

- payload

    ```json=
    {
        endDate : "2023-01-03",
        template : 
        {    
            name: "nom du modèle",        
            establishmentIds: [1, 2, 3],
            departmentIds: [1, 2],
            occupationCategoryGroups: [ // A revoir ce point là -> l'interface de gestion des groupes serait interessante, notament pour les Apis
                {
                    name : "groupe 1",
                    ids : [1, 2, 3]
                }
            ],
            ... 
        }
    }
    ```

- response : GenderGapWarningPage

#### Dto

```csharp
    class GenderGapWarningPage : Page<GenderGapWarning> {
        int MissingOccupationCategoryCount;
        int UndefinedGenderCount;
    }
    class GenderGapWarning {
        User User;
        GenderGapWarningType WarningType;
    }
    enum GenderGapWarningType {
        MissingOccupationCategory,
        UndefinedGender
    }
```

# Moteur de calcul de Remuneration


## Découpage des services

- Service propre au rapport (un pour chaque rapport)
- Service de filtrage de population
- Service d'extraction des données nécessaires au moteur
- Service de calcul des rémunerations (moteur de calcul)

```plantuml
@startuml


database "Database" {
    (RemunerationDataFunction)
}
package "Lucca.Core" {
  [Infra PopulationFilter]
}
package "RemunerationCalculations" {
    [Domain Calculation]
    [Infra Calculation] --> (RemunerationDataFunction)
}
package "Reports/GenderGap" {
    [Domain GenderGap] <--> [Infra GenderGap]
    [Infra GenderGap] <--> [Infra PopulationFilter]
    [Domain GenderGap] <--> [Domain Calculation]

    [Infra GenderGap] --> [Infra Calculation]
    cloud {
      [Web GenderGap] <--> [Domain GenderGap]
    } 
}
package "Reports/Top" {
    [Domain Top] <--> [Infra Top]
    [Infra Top] <--> [Infra PopulationFilter]
    [Domain Top] <--> [Domain Calculation]

    [Infra Top] --> [Infra Calculation]
    
    cloud {
      [Web Top] <--> [Domain Top]
    } 
}



@enduml

```


## Filtrage de Population

Filtre de population : 
- nombre de jour de présence sur l'année (> 182 jours). présence calendaire/contractuelle


### Entrées

On donne les filtres correspondant au rapport en question. 
Uniquement les données associées aux workcontracts :  
- Establishments
- Departments
- OccupationCategories
- WorkContractTypes
- Qualication (pas MVP)
- Période sur laquelle les contrats sont éligibles (Date de début/date de fin)
- Collaborateurs présent sur la fin de la période (true/false) 


### Sortie possible

- Liste de workcontracts (pas nécessaire pour notre cas ?)
- Liste de workcontracts paginée (pas nécessaire pour notre cas ?)
- Expression/Prédicat permettant de récupérer cette liste des workcontracts 


## Récupération des données de rémunérations

On va utiliser une fonction SQL pour récupérer les données de rémunération (EVP/EFP) qui sont nécessaires au moteur de calcul. Cette fonction nous permet de récupérer les données de manière "propre".
POC de cette fonction

**Entrée**  
- Date de début
- Date de fin

**Sortie**


wc1 efp1 2000 12  
wc2 efp1 2000 15
wc2 evp2 500 15


## Moteur de calcul

### Entrée du moteur 
- liste d'élements permettant le calcul
- liste de règles de transformation d'éléments optionnelles
- une règle d'aggrégation
- une liste de règles de transformations d'aggregats optionnelles

### Sortie du moteur

- Aggregation  

### Process d'éxecution du moteur

Pour chaque ligne, on applique toute les règles chainables.
Une fois le chainage terminé, on applique la règle d'aggrégation.
Pour terminer on applique les règles de transformations. 
    

*3 types de règles :*
- Item Transformation
- Aggregation
- Aggregate transformation

Toutes les règles *Item Transformation* ont les mêmes interfaces
- Entrée : Une ligne (ComputedRemunerationItem) 
    - `ComputedRemunerationItem`
- Sortie : La même ligne (ComputedRemunerationItem) avec le montant calculé mis à jour
    - `ComputedRemunerationItem`


### Nos règles pour notre Remuneration sans nom 
- Règle 1 (*Item Transformation*) : Reconstitué equivalent temps plein
    - Calcul : `Montant / ETP` 
    - Condition d'application : sur tous les éléments (EFP & EVP) et si ETP différent de 0

- Règle 2 (*Item Transformation*) : Proratisation Calendaire
    - Calcul : `Montant / (présence contractuelle calendaire sur la période / Nombre de jour calendaire de la période)`
    - Condition d'application : Uniquement pour les EFP et si il ne dure pas une période (mois) complete

    
- Règle 3 (*aggregation*) : Reconstitution annuelle
    - Calcul : 
        - reconstituer les tranches possibles par rapports à tous les éléments de rémunération sur la période (voir exemple plus bas)
        - Par tranche on prend tous les éléments qui intersect cette tranche. 
        - Somme de tous les élements par tranche et on renvois le nombre de tranche (weight)
     
    - Condition d'application : n/a
    - Entrée : Une liste de lignes (ComputedRemunerationItem) (un contrat (ou user) / une période)
        - `List<ComputedRemunerationItem>`
    - Sortie : Sortie custom AggregatedRemunerationItem

    exemple règle 3 : 
    > Mois de Janvier  (1 user / contrat)
    > 
    > - EFP SB 2000 du 1 au 8
    > 
    > - EFP SB 3000 du 9 au 31
    > 
    > - EFP AN 100  du 1 au 12
    > 
    > - EFP AN 150  du 13 au 20
    > 
    > - EFP AN 200  du 21 au 31
    > 
    > 0 8 8 31 0 12 12 20 20 31
    > 
    > 0 8 12 20 31
    > 
    > 2000 + 3000 + 3000 + 100 + 150 + 200
    > 
    > 1 période => 4 périodes


### Modèle de donnée 
```csharp
class ComputedRemunerationItem {
    decimal ComputedAmount; // montant utilisé par les règles 
    RemunerationItem SourceItem;
}

class AggregatedRemunerationItem {
    int Weight; // A rediscuter au moment de l'implem
    decimal Sum;
}

interface IItemTransformationRule {
    ComputedRemunerationItem Apply(ComputedRemunerationItem item);
}
interface IAggregateRule {
    AggregatedRemunerationItem Apply(ComputedRemunerationItem item);
}
interface IAggregateTransformationRule {
     AggregatedRemunerationItem Apply(AggregatedRemunerationItem aggregatedItem);
}
```


## Service Top-Ranked 


### Entrées

```csharp
class PeriodRemunerationItem {
    WorkContract WorkContract;
    RemunerationItem Item;
    Period Period;
}

class RemunerationItem {
    decimal Amount;
    Nature RemunerationNature;
}

abstract class RemunerationNature {
    int Id;
    string Name;
    ValueType ValueType;
    abstract NatureType NatureType;
    abstract IsInActualRemuneration;
    abstract IsInTheoricalRemuneration;
    abstract NoFullTimeEquivalent;
    abstract IsPonctual;
}

enum NatureType {
    Fixed,
    Variable
}
enum ValueType
{
    Amount,
    Number
}
```



### Sortie possible

- une liste de UserRemuneration
```csharp
class UserRemuneration {
    User User;
    RemunerationAmount Amount;
}

```

## Service Gender-Gap
