---
# System prepended metadata

title: Pagga.Remuneration - Approbation des EVP

---

# Pagga.Remuneration - Approbation des EVP

## Nouveaux droits

#### Doit déclarer des propositions d'evp 
- Specifique métier : Liste de natures
- Scope : `SupportedScopes.RelativeCollaborators`

`Must_Submit_Variable_Remuneration_Item_Proposal = 14`

#### Peut saisir des propositions d'evp
- Specifique métier : Liste de natures
- Scope : `SupportedScopes.RelativeDepartments`

`Can_Submit_Variable_Remuneration_Item_Proposal = 15`

#### Déclarer des EVPs à la place de ... 
- Specifique métier : N/A
- Scope : `SupportedScopes.AllNew | SupportedScopes.RelativeCollaborators`

`Submit_Variable_Remuneration_Item_Proposal_Instead_Of = 16`

#### Monitorer les déclarants 
- Specifique métier : N/A
- Scope : `SupportedScopes.None`

`Manage_Submitters = 17`

---

## Paramétrage saisie des propositions d’evp


#### Diagramme de classes
```plantuml
VariableRemunerationNatureList *-- VariableRemunerationNature
VariableRemunerationNatureList *-- Role

class VariableRemunerationNatureList
{
    int Id;
    string Name;
    VariableRemunerationNature[] Natures;
    Role[] Roles; // si aucun droit sur admin des roles, cette liste reste vide 
    int RoleCount;
}
class VariableRemunerationNature
{
    int Id, 
    string Name,
    RemunerationNatureType Type
    VariableRemunerationNatureCategory Category
    Establishment[] Establishments
}
class Role
{
    int Id, 
    string Name    
}

```
Si l'utilisateur connecté n'a pas accès à l'admin des rôles, la propriété `RoleNames` sera laissée vide. 

La propriété `RoleNames`  est uniquement présente dans la classe `VariableRemunerationNatureList` dans la couche Domain. Il n'y a pas de lien entre la table `dbo.Roles` existante et la future table `Remuneration.VariableRemunerationNatureList`. 
#### API

##### Récupération des rôles 
On utilise l'API V3 des permissions pour connaitre les différents rôles utilisant les opérations suivantes : 
- Must_Submit_Variable_Remuneration_Item_Proposal
- Can_Submit_Variable_Remuneration_Item_Proposal

Le retour de cet appel d'API permet de remplir la propriété `RoleNames` décrite plus haut. 
```
.../api/v3/permissions?fields=Id,role[id,name]&appinstanceid=16&operationid=14,15
```
Pagga Remuneration utilisera un token de webservice lui donnant accès à cette API. 

##### Responsable de saisie 
Nous devons connaitre tous les responsable de saisie pour remplir le UserPicker permettant de filtrer les listes. 

-> TODO : requete de récupération des rôles pour chaque manager

##### Listes de natures
Les APIs suivantes permettent de créer, récupérer, modifier ou supprimer une liste de nature. 


##### GET - /remuneration/api/VariableRemunerationNatureLists
- Response : VariableRemunerationNatureList[] (pagination)
    
##### GET - /remuneration/api/VariableRemunerationNatureLists/**{id}**
- QueryParams : id = Id de VariableRemunerationNatureLists
- Response : VariableRemunerationNatureList

##### POST - /remuneration/api/VariableRemunerationNatureLists 
- Payload
    ```json=
    {    
        name: "liste1",
        naturesId : [1, 2, 3, 4]    
    }
    ```
- Response
    - Code : 201

##### PUT - /remuneration/api/VariableRemunerationNatureLists/**{id}**
- QueryParams : id = Id de VariableRemunerationNatureLists
- Payload
    ```json=
    {    
        name: "liste2",
        naturesId : [4, 5, 6]    
    }
    ```
- Response
    - Code : 202

##### DELETE - /remuneration/api/VariableRemunerationNatureLists/**{id}**
- QueryParams : id = Id de VariableRemunerationNatureLists
- Response : 
    - code :
        - 202 
        - 409 : conflict si la liste est liée à au moins un rôle 


---

## Saisie des propositions d'evp

### Jalons
Aucune modification à apporter pour le moment. 
Les ajouts potentiels à faire seront spécifiés dans le lot 3. Avec notamment une sortie hors-monolithe de ce module. 

#### APIs de service des "Jalons"

On a besoin d'une API de service pour les Jalon pour permettre au front de faire son regroupement soit par date de collecte (et éventuellement date de paie ensuite) soit par soummissions déjà réalisées sur la période. 

```plantuml

class MilestoneSubmissionState {
    Submission? Submission // renvoyer un dto light (owner / author / date)
    int EstablishmentId
    DateTime EndItemsCollectionDate
}
```

##### GET - /api/milestoneSubmissionStates?period={period}&ownerId={ownerId}
 - query params:
   - period (required) DateTime
   - ownerId int?
 - Response :
   - MilestoneSubmissionState[]

Cette APIs doit retourner les MilestoneSubmissionStates correspondant aux établissements des utilisateurs pour lesquelles il DOIT faire une déclaration. Il faut donc appeler le service des scope. 


### Liste des périodes de paie

On a besoin d'une API pour determiner les périodes sur lesquelles on a une action à faire (Déclarer, suivre les proposition, suivre les déclarants). 

```plantuml
class PayPeriodRange {
    PayPeriod Start,
    PayPeriod Current
}

```

> Sur l'écran de déclaration:
>  - Start: Dernière période déclarée
>  - Current: Période en cours (mois courant) ou dernière periode non déclarée dans le passé
##### GET - /api/SubmissionPayPeriodRange
- Response : 
   - PayPeriodRange
   
   
   
> Sur l'écran de suivie des propositions : 
>  - Start: Première période où il y eu une déclaration
>  - Current: Période la plus ancienne sur laquelle il y a des propositions en attente
##### GET - /api/ProposalPayPeriodRange
- Response : 
   - PayPeriodRange


### Déclaration des EVPs

#### Liste des responsable de saisie
Permet de connaitre la liste des utilisateurs pour lesquels l'utilisateur courant peut déclarer la grille des EVPs. Correspond à l'opération *Déclarer à la place de ...*. 

####i GET - /api/v3/users/scope?appInstanceId={appInstanceId}&operations={operationId}&userId={userId}
periodra
- QueryParams : 
    - operationId ->  Operations "déclarer à la place de ..."
    - appInstanceId -> appInstanceId de PaggaRem
    - userId -> currentUser
- Response : User[]

### Scope/Authorized
#### Enums
```csharp=
// Type de proposition d'EVP à saisir. => doit et/ou peut
enum PropositionType {
    Recurring,
    Ponctual
}

// Types d'erreur rendant une "cellule" disabled dans la grille de saisie 
enum BlockingType {
    InsufficientPermission,
    OverlapItem
}
```
#### Diagramme de classes

Le regroupement Scope/Authorized concerne le domaine métier permettant de connaitre les droits et les possibilités sur les natures pour un utilisateur donné.  
Ce modèle nous permet de facilement construire les headers de la grille de saisie mensuelle mais aussi la liste des natures/utilisateurs pour lesquelles le manager PEUT saisir des EVPs. 

```plantuml
package "Core" #DDDDDD {
    class WorkContract {}
    class VariableRemunerationNature {}
}
package "Scope/Authorized" #F0FFF0 {
    RemunerationItemProposalScope *-- WorkContract
    RemunerationItemProposalScope *-- RemunerationNaturePropositionType
    RemunerationNaturePropositionType *-- VariableRemunerationNature
    RemunerationNaturePropositionType *-- BlockingReason

    BlockingReason <|-- InsufficientPermissionBlockingReason
    BlockingReason <|-- OverlapItemBlockingReason    
}

class RemunerationItemProposalScope {
    WorkContract WorkContract;
    RemunerationNaturePropositionType[] NaturePropositionTypes;
}

class RemunerationNaturePropositionType {
    VariableRemunerationNature Nature;
    PropositionType[] Types;
    BlockingReason BlockingReason;
}

abstract class BlockingReason {
    (abstract) BlockingType Type    
}
class InsufficientPermissionBlockingReason {}
class OverlapItemBlockingReason {
    // EVP / SubmittedProposal / DraftProposal
}
```
#### APIs

Api permettant de renvoyer tout les headers de la matrices ou on peut/doit saisir une proposition
##### GET - /remuneration/api/VariableRemunerationItemProposal/scope
- QueryString possible : 
    - submitterId -> si non spécifié : currentUser
    - establishmentId[]
    - propositionType[]
    - userClue 
- responses : 
    - Hors pagination
        - RemunerationNaturePropositionType[] 
        - Count    
    - Pagination
        - RemunerationItemProposalScope[] 

> exemple : /remuneration/api/VariableRemunerationItemProposal/scope?establishmentId=1,2,3&propositionType=0&userClue=jourda


### Submissions & Proposals
La submission concerne la soumission par le manager d'une liste d'evp.  
Nous avons identifié 4 types de soumission possibles : 
-    **Period** -> Déclaration de la grille sur la période
-    **EmployeeSettlement** -> Déclaration d'un solde tout compte *(Hors MVP mais on le note par anticipation pour ne pas se fermer cette porte).*
-    **Ponctual** -> Déclaration d'une saisie hors-grille
-    **FromDenied** -> Déclaration d'une nouvelle proposition issue d'une précédente proposition refusée
Ce typage va nous permettre de définir des règles métiers fortes par type (exemple : une seule submission de type Period par mois pour un déclarant). 


Les proposals correspondent aux propositions d'EVP. Il en existe deux types : 
- Draft
- Submitted  

Toutes les opérations (Get/Put/Post/Delete) sont possible sur un draft alors que sur le submitted seul le Get est disponible. 
Les objets Draft et Submitted héritent d'un classe abstraite commune et on beaucoup de propiétés communes. Le submitted se distingue par son statut et liaison indirecte à une BR (la BR porte le summitedProposal): `VariableRemunerationItemRequest`. 

Les drafts sont soumis par les Apis des Submissions. Une fois soumis chaque Draft devient Submitted et devient immutable. Seul sa BR peut la modifer en mettant sa propriété `Status` à jour. 

### Enums
```csharp=

// Statut liéé à l'état de la BR 
enum VariableRemunerationItemProposalStatus {
    Pending,
    Denied,
    Approved,
    ...
}

// Différentes façon de soumettre un lot d'EVP
enum SubmissionType {
    Period,
    EmployeeSettlement,
    Ponctual,
    FromDenied
}
```
#### Diagramme de classes

```plantuml
    RemunerationItemProposalSubmission -- VariableRemunerationItemProposal

    RemunerationItemProposalSubmission <|-- RemunerationItemProposalPeriodSubmission
    RemunerationItemProposalSubmission <|-- RemunerationItemProposalEmployeeSettlementSubmission
    RemunerationItemProposalSubmission <|-- RemunerationItemProposalPonctualSubmission
    RemunerationItemProposalSubmission <|-- RemunerationItemProposalFromDeniedSubmission


abstract class RemunerationItemProposalSubmission {
    Id int;
    (abstract) SubmissionType Type;
    DateTime Date;
    User Author;
    User Owner;
    VariableRemunerationItemProposal[] Proposals; 
    Period Period;
}
class RemunerationItemProposalPeriodSubmission {    
}
class RemunerationItemProposalEmployeeSettlementSubmission {    
    WorkContract WorkContract;
}

class RemunerationItemProposalPonctualSubmission {
}

class RemunerationItemProposalFromDeniedSubmission {
    RemunerationItemProposal DeniedProposal;  
}

abstract class VariableRemunerationItemProposal {
    WorkContract WorkContract;
    VariableRemunerationNature Nature;
    decimal Amount;
    Period Period;
    User CreatedBy;
    DateTime CreatedAt;
    string? comment;
}

```

```plantuml
package "Core" #DDDDDD {
    class WorkContract {}
    class VariableRemunerationNature {}
}

package "Submissions" #DFF2FF {
    RemunerationItemProposalPeriodSubmission -- VariableRemunerationItemDraftProposal
    RemunerationItemProposalEmployeeSettlementSubmission -- VariableRemunerationItemDraftProposal
    RemunerationItemProposalPonctualSubmission -- VariableRemunerationItemDraftProposal
    RemunerationItemProposalFromDeniedSubmission -- VariableRemunerationItemDraftProposal

    RemunerationItemProposalSubmission <|-- RemunerationItemProposalPeriodSubmission
    RemunerationItemProposalSubmission <|-- RemunerationItemProposalEmployeeSettlementSubmission
    RemunerationItemProposalSubmission <|-- RemunerationItemProposalPonctualSubmission
    RemunerationItemProposalSubmission <|-- RemunerationItemProposalFromDeniedSubmission
    
    VariableRemunerationItemDraftProposal -- VariableRemunerationNature
    VariableRemunerationItemDraftProposal -- WorkContract
    
VariableRemunerationItemProposal <|-- VariableRemunerationItemDraftProposal
VariableRemunerationItemProposal <|-- VariableRemunerationItemSubmittedProposal

}

abstract class RemunerationItemProposalSubmission {
    Id int;
    (abstract) SubmissionType Type;
    DateTime Date;
    User Author;
    User Owner;
    RemunerationItemProposal[] Proposals; 
    Period Period;
}

class RemunerationItemProposalPeriodSubmission {
}
class RemunerationItemProposalEmployeeSettlementSubmission {    
    WorkContract WorkContract;
}

class RemunerationItemProposalPonctualSubmission {
}

class RemunerationItemProposalFromDeniedSubmission {
    RemunerationItemProposal DeniedProposal;  
}

abstract class VariableRemunerationItemProposal {
    WorkContract WorkContract;
    VariableRemunerationNature Nature;
    decimal Amount;
    Period Period;
    User CreatedBy;
    DateTime CreatedAt;
    string? comment;
    PropositionType Type;
}

class VariableRemunerationItemSubmittedProposal {
    RemunerationItemProposalSubmission Submission;
    VariableRemunerationItem? Item; 
    VariableRemunerationItemProposalStatus Status;
}

class VariableRemunerationItemDraftProposal {
    DateTime LastModifiedAt;
    User LastModifiedBy;
    DateTime? DeletedAt;
    User? DeletedBy;
}
```

```plantuml
VariableRemunerationItemProposal <|-- VariableRemunerationItemDraftProposal
VariableRemunerationItemProposal <|-- VariableRemunerationItemSubmittedProposal
abstract class VariableRemunerationItemProposal {
    WorkContract WorkContract;
    VariableRemunerationNature Nature;
    decimal Amount;
    Period Period;
    User CreatedBy;
    DateTime CreatedAt;
    string? comment;
    PropositionType Type;
}

class VariableRemunerationItemSubmittedProposal {
    RemunerationItemProposalSubmission Submission;
    VariableRemunerationItem? Item; 
    VariableRemunerationItemProposalStatus Status;
}

class VariableRemunerationItemDraftProposal {
    DateTime LastModifiedAt;
    User LastModifiedBy;
    DateTime? DeletedAt;
    User? DeletedBy;
}
```

```csharp
abstract class RemunerationItemProposalSubmission {
    Id int;
    (abstract) SubmissionType Type;
    DateTime Date;
    User Author;
    User Owner;
    (abstract) VariableRemunerationItemProposal[] GetProposals(); 
    Period Period;
}
class RemunerationItemProposalPeriodSubmission : RemunerationItemProposalSubmission {    
    EstablishmentProposals[] EstablishmentProposals;
}

class RemunerationItemProposalEmployeeSettlementSubmission: RemunerationItemProposalSubmission {    
    WorkContract WorkContract;
    VariableRemunerationItemProposal[] Proposals; 
}

class RemunerationItemProposalPonctualSubmission : RemunerationItemProposalSubmission{
    VariableRemunerationItemProposal[] Proposals; 
}

class RemunerationItemProposalFromDeniedSubmission : RemunerationItemProposalSubmission{
    RemunerationItemProposal DeniedProposal;  
    VariableRemunerationItemProposal NewProposal; 
}

class EstablishmentProposals {    
    Establishment Estalishment;
    VariableRemunerationItemProposal[] Proposals; 
}

```

#### APIs des Submissions

##### GET  - /remuneration/api/RemunerationItemProposalSubmissions
- responses :
    -  RemunerationItemProposalSubmission[] 
    
##### GET  - /remuneration/api/RemunerationItemProposalPeriodSubmissions
- responses :
    -  RemunerationItemProposalPeriodSubmission[] 

##### POST - /remuneration/api/RemunerationItemProposalPeriodSubmissions
- payload : 
    ```json=
    {
        ownerId: 12, // Nullable - correspond au responsable de saisie devant faire la déclaration         
        period: 2022-06,
        establishmentId: 1 // un seul et unique
    }
    ```
- responses :
    - Code : 201 

##### POST - /remuneration/api/RemunerationItemProposalPeriodSubmissions/
- payload : 
    ```json=
    {
        [
            {
                ownerId: 12, // Nullable - correspond au responsable de saisie devant faire la déclaration         
                period: 2022-06,
                establishmentIds: 1
            },
            {
                ownerId: 12, // Nullable - correspond au responsable de saisie devant faire la déclaration         
                period: 2022-06,
                establishmentIds: 2
            }
        ]
    }
    ```
- responses :
    - Code : 201 


    *Note : PUT & DELETE - **interdit***
##### GET  - /remuneration/api/RemunerationItemProposalFromDeniedSubmissions
- responses :
    -  RemunerationItemProposalFromDeniedSubmission[] 
##### POST - /remuneration/api/RemunerationItemProposalFromDeniedSubmissions
- payload :
     ```json=
        {
            deniedProposalId: 56,
            draft: {             
                workContractId: 12, 
                natureId: 1,
                amount: 55.56,
                period: 2022/05/10,
                propositionType: 0, // Recurring or Ponctual,
                comments: "bla bla bla" // nullable
            }
        }
    ```
- responses :
    - Code : 201 

    *Note : PUT & DELETE - **interdit***

##### GET  - /remuneration/api/RemunerationItemProposalPonctualSubmissions
- responses :
    -  RemunerationItemProposalPonctualSubmission[] 
##### POST - /remuneration/api/RemunerationItemProposalPonctualSubmissions
- payload : 
    ```json=
    {
        ownerId: 12, 
        proposalIds: [1, 2, 3]
    }
    ```
- responses :
    - Code : 201 

    *Note : PUT & DELETE - **interdit***

#### APIs des Proposals

##### GET - /remuneration/api/VariableRemunerationItemProposals
- response :
    -  VariableRemunerationItemProposal[] 
##### GET - /remuneration/api/VariableRemunerationItemDraftProposals 
- QueryString possible :
    - workContractIds[]
    - period
- response :
    -  VariableRemunerationItemDraftProposal[] 

##### POST - /remuneration/api/VariableRemunerationItemDraftProposals 
- payload : 
    ```json=
        {
            workContractId: 12, 
            natureId: 1,
            amount: 55.56,
            period: 2022/05/10,
            propositionType: 0, // Recurring or Ponctual,
            comments: "bla bla bla" // nullable
        }
    ```
- Response : 
    - VariableRemunerationItemDraftProposal
    - code :
        - 200
        - 409 : conflit par concurrence : un élément existe déjà pour cet utilisateur sur cette période, pour cette nature.  

##### PUT - /remuneration/api/VariableRemunerationItemDraftProposals/{id}
- QueryParams : id = Id du draft
- payload : 
    ```json=
        {
            amount: 55.56,
            comments: "bla bla bla" // nullable
        }
    ```
- Response : 
    - VariableRemunerationItemDraftProposal
    - code :
        - 200
##### DELETE - /remuneration/api/VariableRemunerationItemDraftProposals/{id}
- QueryParams : id = Id du draft
- Response : 
    - code :
        - 202

##### GET - /remuneration/api/VariableRemunerationItemSubmittedProposals 
- response :
    -  VariableRemunerationItemSubmittedProposal[]

    *Note : POST & PUT & DELETE - **interdit***
---

## Suivis de la déclaration des EVPs

La soummision d'un Draft le transforme en Submitted. Cette action engendre la création d'une Buisness Request `VariableRemunerationItemRequests` liée à `VariableRemunerationItemSubmittedProposal`.  
Le suivi de déclaration consiste principalement à suivre l'avancement des BR dans le workflow.  

Le statut du Submitted est mis à jours par la BR et est persisté en base. 



```plantuml
class VariableRemunerationItemSubmittedProposal {
    RemunerationItemProposalSubmission Submission;
    VariableRemunerationItem? Item; 
    VariableRemunerationItemProposalStatus Status;
}
abstract class VariableRemunerationItemProposal {
    WorkContract WorkContract;
    VariableRemunerationNature Nature;
    decimal Amount;
    Period Period;    
}
class VariableRemunerationItem {    
    [...] // Aucun changement 
}

VariableRemunerationItemProposal <|-- VariableRemunerationItemSubmittedProposal
VariableRemunerationItemRequest *-- VariableRemunerationItemSubmittedProposal
VariableRemunerationItemSubmittedProposal *-- VariableRemunerationItem


class VariableRemunerationItemRequest {
    VariableRemunerationItemSubmittedProposal Proposal
    [...]
    int NextApproverId;
    int PreviousApproverId;
    WorkflowTemplate WorkflowTemplate;
    WorkflowAction[] WorkflowActions; 
    WorkflowApprovalState ApprovalState;
    [...]
}
```
Les propriétés liées au workflow de la buisness request `VariableRemunerationItemRequest` sont définies plus bas dans *Approbation / Refus / Transfert - Action du workflow*

L'API des `VariableRemunerationItemRequests` et son filtrage par statut nous permet de remonter toutes les informations nécessaires au suivi des propositions d'EVP. 

Note : La classe `VariableRemunerationItem` correspond à celle déjà présente dans Pagga Remuneration actuellement et ne subira aucune modification. 

##### GET - remuneration/api/VariableRemunerationItemRequests
- response : 
    - Hors pagination
        - deniedCount
        - pendingCount
        - approvedCount
        - Count
    - Pagination
        - VariableRemunerationItemRequest[] 
- queryString possible : 
    - Status  
    
    *Note : tri par défaut sur le statut (Dans l'ordre : Denied -> Pending -> Approved)*
    
    
## Paramétrage de l'approbation - Workflow

Les concepts et termes utilisés par la suite sont ceux définit par la norme [Lucca.Workflow](https://luccasoftware.atlassian.net/wiki/spaces/ProductDirection/pages/2824175690/Lucca.Workflow)    

### Manifest

Le manifest correspond à la déclaration du workflow, figé dans le code. 
Il faudra qu'il soit déclarer  dans l'injection de dépendance au moment de l'injection de la librairie back Lucca.Workflow.

Pour notre besoin : 
```csharp=
new WorkflowTemplateManifest 
    
    SupportedApproverTypes = new List<ApproverTypeDefinition>
    {
        ApproverTypeDefinitions.Manager,
        ApproverTypeDefinitions.ManagerOfManager,
        ApproverTypeDefinitions.HeadOfDepartment,
        ApproverTypeDefinitions.SpecificUser
    },
    NextApproverFailBehavior = NextApproverFailBehavior.PerStep,
    FinalMailRecipientTypes = new List<MailRecipientTypeDefinition>{},
}
```
#### Diagramme de classes

```plantuml
class WorkflowRegistration {
    string WorkflowId; // ex : "VariableRemunerationItemProposal"
    WorkflowTemplateManifest Manifest;
}  
WorkflowRegistration *-- WorkflowTemplateManifest
```
#### API

Cette APIs sera nécessaire pour le paramétrage du workflow pour définir les possibilités de paramétrage. 
##### GET - remuneration/api/workflow/{id}
- QueryParams : id = Id du workflow déclaré dans le back
- response : WorkflowTemplateManifest 


### Template
Le template correspond, pour un manifest donné, à la configuration faites pas l'administrateur dans l'écran de paramétrage de l'approbation. Comme décrit dans la norme Lucca.Workflow, un template est immuable : 
> Un Workflow Template est immuable. À chaque enregistrement, un nouveau WorkflowTemplate est créé.
>
> La mise à jour d’un WorkflowTemplate n’impacte pas les demandes en cours de traitement. Elle s’appliquera uniquement sur les demandes à venir.
    
#### Diagramme de classes

```plantuml
class WorkflowTemplate {
    int id;
    string WorkflowId;
    
    WorkflowTemplateStep[] Steps;
    WorkflowMailRecipientConfiguration[] FinalRecipients;
    ConditionDefinition[] Conditions;
    
    int AuthorId;
    DateTime CreatedAt;
}  
WorkflowTemplate *-- WorkflowTemplateStep
WorkflowTemplate *-- WorkflowMailRecipientConfiguration
WorkflowTemplate *-- ConditionDefinition
```

`WorkflowTemplateStep`, `WorkflowMailRecipientConfiguration`, et `ConditionDefinition` sont des classes définis par la librairie des workflows

#### API
##### GET - remuneration/api/workflow/{id}/templates
- QueryParams : id = Id du workflow déclaré dans le back
- response : WorkflowTemplate 
    - Retourne un seul et unique WorkflowTemplate. Le dernier créé pour un workflowId donné.  

##### POST - remuneration/api/workflow/{id}/templates
- QueryParams : id = Id du workflow déclaré dans le back
- Payload : 
    ```json=
        {
            workflowId : "VariableRemunerationItemProposal",
            steps: [
                ...
            ],
            finalRecipients: [
                ...
            ],
            conditions: [
                ...
            ]
        }
    ```
- Response : 
    - code :
        - 201
        
    *Note : PUT & DELETE - **interdit : Template immuable***

## Approbation / Refus / Transfert - Action du workflow

#### Enums issue de la norme workflow
```csharp=
enum WorkflowActionType
{
    Approval,
    Denial,
    Transfer,
    Delegation,
    SkippedApproval,
}
enum WorkflowActionSource
{
    Desktop = 0,
    API,
    Mobile,
    Mail,
    Migration
}
enum WorkflowApprovalMode
{
    Manual = 0,
    Auto
}
```

#### Diagramme de classes 
La classe `BuisnessRequest` est une classe abstraite fournis par la library Lucca.Workflow. 
Cette librairie nous fournis également une interface pour `WorkflowAction` que nous utiliserons. 

```plantuml
BuisnessRequest <|-- VariableRemunerationItemRequest
VariableRemunerationItemRequest *-- VariableRemunerationItemSubmittedProposal
VariableRemunerationItemRequest *-- WorkflowTemplate
VariableRemunerationItemRequest *-- WorkflowAction

WorkflowAction <|-- WorkflowActionApproval
WorkflowAction <|-- WorkflowActionTransfer
WorkflowAction <|-- WorkflowActionDenial
WorkflowAction <|-- WorkflowActionDelegation
WorkflowAction <|-- WorkflowSkippedApproval


abstract class BuisnessRequest {    
    int NextApproverId;
    int PreviousApproverId;
    WorkflowTemplate WorkflowTemplate;
    WorkflowAction[] WorkflowActions; 
    WorkflowApprovalState ApprovalState;
    [...]
}
class VariableRemunerationItemRequest {    
    int Id;
    VariableRemunerationItemSubmittedProposal Proposal
}

abstract class WorkflowAction {
    int Id;
    int CreatedById;
    DateTime CreatedAt;
    int StepNumber;
    string Comment;
    WorkflowActionSource Source; 
    (abstract) WorkflowActionType Type;
}
class WorkflowActionDenial { 
    int ApproverId;
    string ApproverTypeDefinitions;
}
class WorkflowActionApproval {
    int ApproverId;
    string ApproverTypeDefinitions;
    WorkflowApprovalMode WorkflowApprovalMode;
}
class WorkflowActionTransfer {
    int OldApproverId;
    int NewApproverId;
}
class WorkflowActionDelegation {
    int OldApproverId;
    int NewApproverId;
}
class WorkflowSkippedApproval { }
```

#### APIs
Les apis suivantes permettent d'effectuer les actions sur la BR. Nous avons besoin de gérer les actions (approbation/refus/transfer) multiples pour des besoin fonctionnels. Plutôt que de forcer le front à faire n appel à l'API unitaire nous fournissons une APIs pour chaque action prenant en payload une liste de request sur lesquels appliquer l'action. 

##### POST - remuneration/api/VariableRemunerationItemRequests/{id}/approvals
- QueryParams : id = Id de la request à approuver
- Response : 
    - code :
        - 201

##### POST - remuneration/api/VariableRemunerationItemRequests/approvals
- Payload : 
    ```json=
    {
        [
            {    
                variableRemunerationItemRequestId: 23, // Id de la request à approuver
            },
            {    
                variableRemunerationItemRequestId: 21, // Id de la request à approuver
            },
            {    
                variableRemunerationItemRequestId: 14, // Id de la request à approuver
            }
        ]        
    }
    ```
- Response : 
    - code :
        - 201


##### POST - remuneration/api/VariableRemunerationItemRequests/{id}/denials
- QueryParams : id = Id de la request à refuser
- Payload : 
```json=
{
    variableRemunerationItemRequestId: 23, // Id de la request à approuver
    comment: "un commentaire pour justifier le refus"  
}
```
- Response : 
    - code :
        - 201

##### POST - remuneration/api/VariableRemunerationItemRequests/denials
- Payload : 
    ```json=
    {
        [
            {    
                variableRemunerationItemRequestId: 23, // Id de la request à approuver
                comment: "un commentaire pour justifier le refus"       
            },
            {    
                variableRemunerationItemRequestId: 21, // Id de la request à approuver
                comment: "un autre commentaire pour justifier le refus"       
            }
        ]        
    }         
    ```
- Response : 
    - code :
        - 201
    


##### POST - remuneration/api/VariableRemunerationItemRequests/{id}/transfers
- QueryParams : id = Id de la request à transférer
- Payload : 
```json=
{
    variableRemunerationItemRequestId: 23, // Id de la request à approuver
    nextApproverId: 2,
    comment: "un commentaire pour justifier le transfert"
}
```
- Response : 
    - code :
        - 201
##### POST - remuneration/api/VariableRemunerationItemRequests/transfers
- Payload : 
    ```json=
    {
        [
            {    
                variableRemunerationItemRequestId: 23, // Id de la request à approuver
                nextApproverId: 2,
                comment: "un commentaire pour justifier le transfert"       
            },
            {    
                variableRemunerationItemRequestId: 21, // Id de la request à approuver
                nextApproverId: 2,
                comment: "un autre commentaire pour justifier le transfert"
            }
        ]        
    }       
    ```
- Response : 
    - code :
        - 201

## Suivis des déclarants
Est ce qu'il reste des managers qui n'ont pas fait leur déclaration ? 

Pour répondre à ce problème nous avons une API de service renvoyant des `PeriodSubmissionState`. 
Cette information est également accessible par le front en faisant les appels suivants décrits plus haut : 

- Un appel à l'api V3 des permissions pour connaitre les différents utilisateurs ayant l'opération
`Must_Submit_Variable_Remuneration_Item_Proposal`
- Pour chaque utilisateur, un appel à l'API des Submission sur la période souhaitée nous donne l'état des déclarations. 

Cette enchainement d'appels étant plus complexe et plus couteux, nous préviligions donc une API de service.  

```csharp=
enum SubmissionState {
    Empty,
    Draft,
    Submitted
} 
```

```plantuml
class PeriodSubmissionState {
    Period Period;
    User user;
    SubmissionState State; 
}
```

##### GET - remuneration/service/PeriodSubmissionStates?period={period}&userclue={clue}
- QueryString : 
    - period = Date représentant la période pour laquelle on souhaite avoir l'avancement des déclarations. Paramètre obligatoire. 
    - userclue = filtrage sur un user. Facultatif. 
- response : 
    - code : 
        - 200
        - 400 -> On retourne une erreur 400 si le paramètre period n'est pas remplis. 
    - PeriodSubmissionState[] (pagination)


## Warning sur l'export paie

On souhaite répondre à une question pour ajouter des warnings lors de la génération des exports. 
Est ce qu'il reste des  VariableRemunerationItemRequest en pending ? 
L'APIs des `VariableRemunerationItemRequest` décrite plus haut nous fournit cette information. 
##### GET - remuneration/api/VariableRemunerationItemRequests



```csharp=
class VariableRemunerationItemRequestPage {
    int DeniedCount { get; set; }
    int PendingCount { get; set; }
    int ApprovedCount { get; set; }
    int Count { get; set; }
    List<VariableRemunerationItemRequest> Items  { get; set; }
    // prev & next
} 


class UserxxxxxPage {
    int Count { get; set; }
    int ToApproveCount { get; set; }
    
    List<UserVariableRemunerationItemRequest> Items  { get; set; }
    // prev & next
} 
```

Relance : 
Utiliser le morning ping du monolithe. 

---

## Base de données

https://lucid.app/lucidchart/35ced00c-b046-4ee0-93b5-605d89eaf129/edit?from_internal=true

![](https://i.imgur.com/SAejWB7.png)

