# 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
