Premier commit
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
namespace SIFinance.Shared;
|
||||
|
||||
// Section "AzureAd" de appsettings*.json — App registration Azure AD "SI Finance",
|
||||
// utilisée à la fois pour le flux OAuth2 (authorization code + PKCE, connexion
|
||||
// utilisateur) dans EntraAuthEndpoints et pour l'appel Graph "app-only" (client
|
||||
// credentials) dans EntraSyncService/EntraGraphTokenProvider. ClientSecret et GroupId
|
||||
// sont renseignés dans appsettings.Development.json (secrets, non commités).
|
||||
public class AzureAdOptions
|
||||
{
|
||||
public const string SectionName = "AzureAd";
|
||||
|
||||
public string TenantId { get; set; } = "";
|
||||
public string ClientId { get; set; } = "";
|
||||
public string ClientSecret { get; set; } = "";
|
||||
public string RedirectUri { get; set; } = "";
|
||||
public string GroupId { get; set; } = "";
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using SIFinance.Shared.Entities;
|
||||
|
||||
namespace SIFinance.Shared;
|
||||
|
||||
public class CurrentUserService(IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
public Task<int> GetOrCreateCurrentUserIdAsync(CancellationToken ct = default)
|
||||
{
|
||||
var principal = httpContextAccessor.HttpContext?.User
|
||||
?? throw new InvalidOperationException("Aucun contexte HTTP disponible pour résoudre l'utilisateur courant.");
|
||||
|
||||
var idClaim = principal.FindFirst("id")?.Value
|
||||
?? throw new UnauthorizedAccessException("Le jeton ne contient pas de claim 'id' — utilisateur non identifiable.");
|
||||
|
||||
return Task.FromResult(int.Parse(idClaim));
|
||||
}
|
||||
|
||||
// Vérifie si l'utilisateur courant possède le rôle donné (ex. "FINANCE").
|
||||
// Passe par une jointure utilisateurs <-> utilisateur_roles via azure_oid, car
|
||||
// le JWT ne porte que l'Id interne, pas l'azure_oid.
|
||||
public async Task<bool> HasRoleAsync(string role, SIFinanceDbContext db, CancellationToken ct = default)
|
||||
{
|
||||
var userId = await GetOrCreateCurrentUserIdAsync(ct);
|
||||
|
||||
// Les habilitations fonctionnelles viennent exclusivement de
|
||||
// core.utilisateur_roles. Un profil Entra ou le statut Responsable ne donne
|
||||
// jamais à lui seul l'accès aux écrans ou actions Finance.
|
||||
return await db.UtilisateurRoles
|
||||
.AsNoTracking()
|
||||
.Join(db.Utilisateurs.AsNoTracking(),
|
||||
ur => ur.AzureOid,
|
||||
u => u.AzureOid,
|
||||
(ur, u) => new { u.Id, ur.Role })
|
||||
.AnyAsync(x => x.Id == userId && x.Role == role, ct);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
public partial class Acompte
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int FactureId { get; set; }
|
||||
|
||||
public decimal Montant { get; set; }
|
||||
|
||||
public DateOnly DatePrevue { get; set; }
|
||||
|
||||
public DateOnly? DateVerse { get; set; }
|
||||
|
||||
public string Statut { get; set; } = null!;
|
||||
|
||||
public int? JustificatifId { get; set; }
|
||||
|
||||
public string? Commentaire { get; set; }
|
||||
|
||||
public int SaisieParId { get; set; }
|
||||
|
||||
public DateTime? DateCreation { get; set; }
|
||||
|
||||
public virtual Facture Facture { get; set; } = null!;
|
||||
|
||||
public virtual PiecesJointe? Justificatif { get; set; }
|
||||
|
||||
public virtual Utilisateur SaisiePar { get; set; } = null!;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
public partial class AffectationsAvoir
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int AvoirId { get; set; }
|
||||
|
||||
public int FactureId { get; set; }
|
||||
|
||||
public decimal MontantAffecte { get; set; }
|
||||
|
||||
public int AffecteParId { get; set; }
|
||||
|
||||
public DateTime? DateAffectation { get; set; }
|
||||
|
||||
public virtual Utilisateur AffectePar { get; set; } = null!;
|
||||
|
||||
public virtual Avoir Avoir { get; set; } = null!;
|
||||
|
||||
public virtual Facture Facture { get; set; } = null!;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
public partial class Audit
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public string EntiteType { get; set; } = null!;
|
||||
|
||||
public int EntiteId { get; set; }
|
||||
|
||||
public int UtilisateurId { get; set; }
|
||||
|
||||
public string Action { get; set; } = null!;
|
||||
|
||||
public string? DetailJson { get; set; }
|
||||
|
||||
public string? IpAdresse { get; set; }
|
||||
|
||||
public DateTime DateAction { get; set; }
|
||||
|
||||
public virtual Utilisateur Utilisateur { get; set; } = null!;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
public partial class Avoir
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int FournisseurId { get; set; }
|
||||
|
||||
public string NumeroAvoir { get; set; } = null!;
|
||||
|
||||
public DateOnly DateAvoir { get; set; }
|
||||
|
||||
public decimal MontantInitial { get; set; }
|
||||
|
||||
public decimal SoldeDisponible { get; set; }
|
||||
|
||||
public int? FactureId { get; set; }
|
||||
|
||||
public int? JustificatifId { get; set; }
|
||||
|
||||
public int SaisieParId { get; set; }
|
||||
|
||||
public DateTime? DateCreation { get; set; }
|
||||
|
||||
public virtual ICollection<AffectationsAvoir> AffectationsAvoirs { get; set; } = new List<AffectationsAvoir>();
|
||||
|
||||
public virtual Facture? Facture { get; set; }
|
||||
|
||||
public virtual Fournisseur Fournisseur { get; set; } = null!;
|
||||
|
||||
public virtual PiecesJointe? Justificatif { get; set; }
|
||||
|
||||
public virtual Utilisateur SaisiePar { get; set; } = null!;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
// Budget annuel d'un service pour le module Achats. Exercice non calendaire (1er
|
||||
// septembre au 31 août) — ExerciceAnnee porte l'année de démarrage (ex. 2026 = exercice
|
||||
// du 01/09/2026 au 31/08/2027). Le montant "actif" du budget est MontantInitial tant
|
||||
// qu'aucune révision n'existe, sinon la révision la plus récente (cf. Revisions) —
|
||||
// chaque révision est conservée pour l'historique, jamais écrasée.
|
||||
public partial class BudgetService
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int ServiceId { get; set; }
|
||||
|
||||
public int ExerciceAnnee { get; set; }
|
||||
|
||||
public decimal MontantInitial { get; set; }
|
||||
|
||||
public int SaisieParId { get; set; }
|
||||
|
||||
public DateTime? DateCreation { get; set; }
|
||||
|
||||
public DateTime? DateDerniereMaj { get; set; }
|
||||
|
||||
public virtual Service Service { get; set; } = null!;
|
||||
|
||||
public virtual Utilisateur SaisiePar { get; set; } = null!;
|
||||
|
||||
public virtual ICollection<BudgetServiceRevision> Revisions { get; set; } = new List<BudgetServiceRevision>();
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
// Historique des révisions d'un budget de service (augmentation en cours d'exercice,
|
||||
// décidée par un responsable Finance) — une ligne par révision, jamais écrasée, pour
|
||||
// garder la traçabilité complète de qui a changé le budget et pourquoi.
|
||||
public partial class BudgetServiceRevision
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int BudgetServiceId { get; set; }
|
||||
|
||||
public decimal MontantRevise { get; set; }
|
||||
|
||||
public string? Commentaire { get; set; }
|
||||
|
||||
public int RevisePar { get; set; }
|
||||
|
||||
public DateTime DateRevision { get; set; }
|
||||
|
||||
public virtual BudgetService BudgetService { get; set; } = null!;
|
||||
|
||||
public virtual Utilisateur ReviseParUtilisateur { get; set; } = null!;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
public partial class Campus
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Libelle { get; set; } = null!;
|
||||
public bool Actif { get; set; }
|
||||
public virtual ICollection<ContratFournisseur> ContratsFournisseurs { get; set; } = new List<ContratFournisseur>();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
public partial class ContratEcheance
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int ContratId { get; set; }
|
||||
|
||||
public DateOnly DateEcheance { get; set; }
|
||||
|
||||
public decimal Montant { get; set; }
|
||||
|
||||
public string Statut { get; set; } = null!;
|
||||
|
||||
public int? JustificatifId { get; set; }
|
||||
|
||||
public DateTime? DateCreation { get; set; }
|
||||
|
||||
public virtual ContratFournisseur Contrat { get; set; } = null!;
|
||||
|
||||
public virtual PiecesJointe? Justificatif { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
public partial class ContratFournisseur
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int FournisseurId { get; set; }
|
||||
|
||||
public int? ServiceId { get; set; }
|
||||
|
||||
public int? CampusId { get; set; }
|
||||
|
||||
public string? Reference { get; set; }
|
||||
|
||||
public string Objet { get; set; } = null!;
|
||||
|
||||
public DateOnly? DateSignature { get; set; }
|
||||
|
||||
public DateOnly DateDebut { get; set; }
|
||||
|
||||
public DateOnly DateFin { get; set; }
|
||||
|
||||
public DateOnly? DateResiliation { get; set; }
|
||||
|
||||
public string? MotifResiliation { get; set; }
|
||||
|
||||
public decimal MontantTotal { get; set; }
|
||||
|
||||
public string Periodicite { get; set; } = null!;
|
||||
|
||||
public string Statut { get; set; } = null!;
|
||||
|
||||
public int SaisieParId { get; set; }
|
||||
|
||||
public DateTime? DateCreation { get; set; }
|
||||
|
||||
public DateTime? DateDerniereMaj { get; set; }
|
||||
|
||||
public virtual Fournisseur Fournisseur { get; set; } = null!;
|
||||
|
||||
public virtual Service? Service { get; set; }
|
||||
|
||||
public virtual Campus? Campus { get; set; }
|
||||
|
||||
public virtual Utilisateur SaisiePar { get; set; } = null!;
|
||||
|
||||
public virtual ICollection<ContratEcheance> Echeances { get; set; } = new List<ContratEcheance>();
|
||||
|
||||
public virtual ICollection<Facture> Factures { get; set; } = new List<Facture>();
|
||||
|
||||
public virtual ICollection<ContratFournisseurHistorique> Historique { get; set; } = new List<ContratFournisseurHistorique>();
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
public partial class ContratFournisseurHistorique
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int ContratId { get; set; }
|
||||
public string? AncienStatut { get; set; }
|
||||
public string NouveauStatut { get; set; } = null!;
|
||||
public string? Commentaire { get; set; }
|
||||
public int UtilisateurId { get; set; }
|
||||
public DateTime DateAction { get; set; }
|
||||
public virtual ContratFournisseur Contrat { get; set; } = null!;
|
||||
public virtual Utilisateur Utilisateur { get; set; } = null!;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
public partial class ContratPrestataire
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int OrganismeId { get; set; }
|
||||
|
||||
public string Reference { get; set; } = null!;
|
||||
|
||||
public string Objet { get; set; } = null!;
|
||||
|
||||
public DateOnly? DateSignature { get; set; }
|
||||
|
||||
public DateOnly DateDebut { get; set; }
|
||||
|
||||
public DateOnly DateFin { get; set; }
|
||||
|
||||
public decimal MontantTotal { get; set; }
|
||||
|
||||
public string Statut { get; set; } = null!;
|
||||
|
||||
public int SaisieParId { get; set; }
|
||||
|
||||
public DateTime? DateCreation { get; set; }
|
||||
|
||||
public virtual Organisme Organisme { get; set; } = null!;
|
||||
|
||||
public virtual Utilisateur SaisiePar { get; set; } = null!;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
public partial class DemandesAchat
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Reference { get; set; } = null!;
|
||||
|
||||
public int ServiceId { get; set; }
|
||||
|
||||
public string Objet { get; set; } = null!;
|
||||
|
||||
public string? Description { get; set; }
|
||||
|
||||
public int? FournisseurId { get; set; }
|
||||
|
||||
public string? FournisseurLibre { get; set; }
|
||||
|
||||
public string? CategorieFournisseurLibre { get; set; }
|
||||
|
||||
public int TypeDepenseId { get; set; }
|
||||
|
||||
public decimal MontantHt { get; set; }
|
||||
|
||||
public decimal TauxTva { get; set; }
|
||||
|
||||
public decimal MontantTva { get; set; }
|
||||
|
||||
public decimal MontantTtc { get; set; }
|
||||
|
||||
public DateOnly DatePrevisionnelle { get; set; }
|
||||
|
||||
public int ModePaiementId { get; set; }
|
||||
|
||||
public string Statut { get; set; } = null!;
|
||||
|
||||
public int DemandeurId { get; set; }
|
||||
|
||||
public int? ValideurId { get; set; }
|
||||
|
||||
public decimal SeuilApplicable { get; set; }
|
||||
|
||||
public DateTime? DateCreation { get; set; }
|
||||
|
||||
public DateTime? DateSoumission { get; set; }
|
||||
|
||||
public DateTime? DateDerniereMaj { get; set; }
|
||||
|
||||
public virtual Utilisateur Demandeur { get; set; } = null!;
|
||||
|
||||
public virtual ICollection<Facture> Factures { get; set; } = new List<Facture>();
|
||||
|
||||
public virtual Fournisseur? Fournisseur { get; set; }
|
||||
|
||||
public virtual ModesPaiement ModePaiement { get; set; } = null!;
|
||||
|
||||
public virtual Service Service { get; set; } = null!;
|
||||
|
||||
public virtual TypesDepense TypeDepense { get; set; } = null!;
|
||||
|
||||
public virtual Utilisateur? Valideur { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
public partial class Facture
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string SourceType { get; set; } = null!;
|
||||
|
||||
public int? DemandeAchatId { get; set; }
|
||||
|
||||
public int? ContratId { get; set; }
|
||||
|
||||
public int FournisseurId { get; set; }
|
||||
|
||||
public string NumeroFacture { get; set; } = null!;
|
||||
|
||||
public DateOnly DateFacture { get; set; }
|
||||
|
||||
public DateOnly DateEcheance { get; set; }
|
||||
|
||||
public decimal MontantHt { get; set; }
|
||||
|
||||
public decimal TauxTva { get; set; }
|
||||
|
||||
public decimal MontantTva { get; set; }
|
||||
|
||||
public decimal MontantTtc { get; set; }
|
||||
|
||||
public int? CategorieDepenseId { get; set; }
|
||||
|
||||
public int ServiceId { get; set; }
|
||||
|
||||
public int ModePaiementId { get; set; }
|
||||
|
||||
public string Statut { get; set; } = null!;
|
||||
|
||||
public bool? EstDoublonSignale { get; set; }
|
||||
|
||||
public string? Commentaire { get; set; }
|
||||
|
||||
public int SaisieParId { get; set; }
|
||||
|
||||
public int? ValideBapParId { get; set; }
|
||||
|
||||
public DateTime? DateValidationBap { get; set; }
|
||||
|
||||
public DateTime? DateCreation { get; set; }
|
||||
|
||||
public DateTime? DateDerniereMaj { get; set; }
|
||||
|
||||
public virtual ICollection<Acompte> Acomptes { get; set; } = new List<Acompte>();
|
||||
|
||||
public virtual ICollection<AffectationsAvoir> AffectationsAvoirs { get; set; } = new List<AffectationsAvoir>();
|
||||
|
||||
public virtual ICollection<Avoir> Avoirs { get; set; } = new List<Avoir>();
|
||||
|
||||
public virtual TypesDepense? CategorieDepense { get; set; }
|
||||
|
||||
public virtual DemandesAchat? DemandeAchat { get; set; }
|
||||
|
||||
public virtual ContratFournisseur? Contrat { get; set; }
|
||||
|
||||
public virtual Fournisseur Fournisseur { get; set; } = null!;
|
||||
|
||||
public virtual ModesPaiement ModePaiement { get; set; } = null!;
|
||||
|
||||
public virtual ICollection<Paiement> Paiements { get; set; } = new List<Paiement>();
|
||||
|
||||
public virtual Utilisateur SaisiePar { get; set; } = null!;
|
||||
|
||||
public virtual Service Service { get; set; } = null!;
|
||||
|
||||
public virtual Utilisateur? ValideBapPar { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
public partial class FichiersXml
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string NomFichier { get; set; } = null!;
|
||||
|
||||
public string SharepointUrl { get; set; } = null!;
|
||||
|
||||
public DateTime? DateGeneration { get; set; }
|
||||
|
||||
public int GenereParId { get; set; }
|
||||
|
||||
public int NombreVirements { get; set; }
|
||||
|
||||
public decimal MontantTotal { get; set; }
|
||||
|
||||
public virtual Utilisateur GenerePar { get; set; } = null!;
|
||||
|
||||
public virtual ICollection<Paiement> Paiements { get; set; } = new List<Paiement>();
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
public partial class Fournisseur
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string RaisonSociale { get; set; } = null!;
|
||||
|
||||
public string? Siret { get; set; }
|
||||
|
||||
public string? Email { get; set; }
|
||||
|
||||
public string? Telephone { get; set; }
|
||||
|
||||
public string? Adresse { get; set; }
|
||||
|
||||
public byte[]? IbanChiffre { get; set; }
|
||||
|
||||
public string? Bic { get; set; }
|
||||
|
||||
public string? TitulaireCompte { get; set; }
|
||||
|
||||
public string Statut { get; set; } = null!;
|
||||
|
||||
public DateTime? DateCreation { get; set; }
|
||||
|
||||
public virtual ICollection<Avoir> Avoirs { get; set; } = new List<Avoir>();
|
||||
|
||||
public virtual ICollection<ContratFournisseur> ContratsFournisseurs { get; set; } = new List<ContratFournisseur>();
|
||||
|
||||
public virtual ICollection<DemandesAchat> DemandesAchats { get; set; } = new List<DemandesAchat>();
|
||||
|
||||
public virtual ICollection<Facture> Factures { get; set; } = new List<Facture>();
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
public partial class HistoriqueAction
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string EntiteType { get; set; } = null!;
|
||||
|
||||
public int EntiteId { get; set; }
|
||||
|
||||
public int UtilisateurId { get; set; }
|
||||
|
||||
public string Action { get; set; } = null!;
|
||||
|
||||
public string? Commentaire { get; set; }
|
||||
|
||||
public string? AncienStatut { get; set; }
|
||||
|
||||
public string? NouveauStatut { get; set; }
|
||||
|
||||
public DateTime? DateAction { get; set; }
|
||||
|
||||
public virtual Utilisateur Utilisateur { get; set; } = null!;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
public partial class ModesPaiement
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Libelle { get; set; } = null!;
|
||||
|
||||
public bool NecessiteXml { get; set; }
|
||||
|
||||
public bool Actif { get; set; }
|
||||
|
||||
public virtual ICollection<DemandesAchat> DemandesAchats { get; set; } = new List<DemandesAchat>();
|
||||
|
||||
public virtual ICollection<Facture> Factures { get; set; } = new List<Facture>();
|
||||
|
||||
public virtual ICollection<Paiement> Paiements { get; set; } = new List<Paiement>();
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
public partial class Organisme
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string RaisonSociale { get; set; } = null!;
|
||||
|
||||
public string? Siret { get; set; }
|
||||
|
||||
public string? Email { get; set; }
|
||||
|
||||
public string? Telephone { get; set; }
|
||||
|
||||
public string? Adresse { get; set; }
|
||||
|
||||
public string Statut { get; set; } = null!;
|
||||
|
||||
public DateTime? DateCreation { get; set; }
|
||||
|
||||
public virtual ICollection<ContratPrestataire> ContratsPrestataires { get; set; } = new List<ContratPrestataire>();
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
public partial class Paiement
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int FactureId { get; set; }
|
||||
|
||||
public decimal MontantPaye { get; set; }
|
||||
|
||||
public DateOnly DatePaiement { get; set; }
|
||||
|
||||
public int ModeReglementId { get; set; }
|
||||
|
||||
public string? ReferencePaiement { get; set; }
|
||||
|
||||
public int? FichierXmlId { get; set; }
|
||||
|
||||
public int EnregistreParId { get; set; }
|
||||
|
||||
public DateTime? DateSaisie { get; set; }
|
||||
|
||||
public string Statut { get; set; } = null!;
|
||||
|
||||
public bool Rapproche { get; set; }
|
||||
|
||||
public virtual Utilisateur EnregistrePar { get; set; } = null!;
|
||||
|
||||
public virtual Facture Facture { get; set; } = null!;
|
||||
|
||||
public virtual FichiersXml? FichierXml { get; set; }
|
||||
|
||||
public virtual ModesPaiement ModeReglement { get; set; } = null!;
|
||||
|
||||
public virtual ICollection<Rapprochement> Rapprochements { get; set; } = new List<Rapprochement>();
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
public partial class Parametre
|
||||
{
|
||||
public string Cle { get; set; } = null!;
|
||||
|
||||
public string Valeur { get; set; } = null!;
|
||||
|
||||
public string? Description { get; set; }
|
||||
|
||||
public int? ModifiePar { get; set; }
|
||||
|
||||
public DateTime? DateModif { get; set; }
|
||||
|
||||
public virtual Utilisateur? ModifieParNavigation { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
public partial class PiecesJointe
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string EntiteType { get; set; } = null!;
|
||||
|
||||
public int EntiteId { get; set; }
|
||||
|
||||
public string TypePiece { get; set; } = null!;
|
||||
|
||||
public string NomFichier { get; set; } = null!;
|
||||
|
||||
public string SharepointUrl { get; set; } = null!;
|
||||
|
||||
public string SharepointItemId { get; set; } = null!;
|
||||
|
||||
public long TailleOctets { get; set; }
|
||||
|
||||
public int UploaderId { get; set; }
|
||||
|
||||
public DateTime? DateUpload { get; set; }
|
||||
|
||||
public virtual ICollection<Acompte> Acomptes { get; set; } = new List<Acompte>();
|
||||
|
||||
public virtual ICollection<Avoir> Avoirs { get; set; } = new List<Avoir>();
|
||||
|
||||
public virtual ICollection<ContratEcheance> ContratEcheances { get; set; } = new List<ContratEcheance>();
|
||||
|
||||
public virtual Utilisateur Uploader { get; set; } = null!;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
public partial class Rapprochement
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int? PaiementId { get; set; }
|
||||
|
||||
public string? ReferenceBancaire { get; set; }
|
||||
|
||||
public DateOnly DateOperationBanq { get; set; }
|
||||
|
||||
public string? LibelleBanque { get; set; }
|
||||
|
||||
public decimal MontantBanque { get; set; }
|
||||
|
||||
public string Statut { get; set; } = null!;
|
||||
|
||||
public string? Commentaire { get; set; }
|
||||
|
||||
public int? TraiteParId { get; set; }
|
||||
|
||||
public DateTime? DateTraitement { get; set; }
|
||||
|
||||
public virtual Paiement? Paiement { get; set; }
|
||||
|
||||
public virtual Utilisateur? TraitePar { get; set; }
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
public partial class Service
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Libelle { get; set; } = null!;
|
||||
|
||||
public bool Actif { get; set; }
|
||||
|
||||
public virtual ICollection<DemandesAchat> DemandesAchats { get; set; } = new List<DemandesAchat>();
|
||||
|
||||
public virtual ICollection<Facture> Factures { get; set; } = new List<Facture>();
|
||||
|
||||
public virtual ICollection<Utilisateur> Utilisateurs { get; set; } = new List<Utilisateur>();
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
public partial class TypesDepense
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Libelle { get; set; } = null!;
|
||||
|
||||
public bool Actif { get; set; }
|
||||
|
||||
public bool EstMateriel { get; set; }
|
||||
|
||||
public virtual ICollection<DemandesAchat> DemandesAchats { get; set; } = new List<DemandesAchat>();
|
||||
|
||||
public virtual ICollection<Facture> Factures { get; set; } = new List<Facture>();
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SIFinance.Shared.Entities;
|
||||
|
||||
public partial class Utilisateur
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string AzureOid { get; set; } = null!;
|
||||
|
||||
public string Nom { get; set; } = null!;
|
||||
|
||||
public string Prenom { get; set; } = null!;
|
||||
|
||||
public string Email { get; set; } = null!;
|
||||
|
||||
public string Profil { get; set; } = null!;
|
||||
|
||||
public int? ServiceId { get; set; }
|
||||
|
||||
// Manager direct, synchronisé depuis Entra ID (EntraSyncService) — c'est cette
|
||||
// personne, et non le rôle FINANCE, qui a le droit de valider/refuser les demandes
|
||||
// d'achat du collaborateur.
|
||||
public int? ResponsableId { get; set; }
|
||||
|
||||
public bool Actif { get; set; }
|
||||
|
||||
public DateTime? DateCreation { get; set; }
|
||||
|
||||
public DateTime? DateDerniereConnexion { get; set; }
|
||||
|
||||
public virtual ICollection<Acompte> Acomptes { get; set; } = new List<Acompte>();
|
||||
|
||||
public virtual ICollection<AffectationsAvoir> AffectationsAvoirs { get; set; } = new List<AffectationsAvoir>();
|
||||
|
||||
public virtual ICollection<Audit> Audits { get; set; } = new List<Audit>();
|
||||
|
||||
public virtual ICollection<Avoir> Avoirs { get; set; } = new List<Avoir>();
|
||||
|
||||
public virtual ICollection<ContratFournisseur> ContratsFournisseurs { get; set; } = new List<ContratFournisseur>();
|
||||
|
||||
public virtual ICollection<ContratPrestataire> ContratsPrestataires { get; set; } = new List<ContratPrestataire>();
|
||||
|
||||
public virtual ICollection<DemandesAchat> DemandesAchatDemandeurs { get; set; } = new List<DemandesAchat>();
|
||||
|
||||
public virtual ICollection<DemandesAchat> DemandesAchatValideurs { get; set; } = new List<DemandesAchat>();
|
||||
|
||||
public virtual ICollection<Facture> FactureSaisiePars { get; set; } = new List<Facture>();
|
||||
|
||||
public virtual ICollection<Facture> FactureValideBapPars { get; set; } = new List<Facture>();
|
||||
|
||||
public virtual ICollection<FichiersXml> FichiersXmls { get; set; } = new List<FichiersXml>();
|
||||
|
||||
public virtual ICollection<HistoriqueAction> HistoriqueActions { get; set; } = new List<HistoriqueAction>();
|
||||
|
||||
public virtual ICollection<Paiement> Paiements { get; set; } = new List<Paiement>();
|
||||
|
||||
public virtual ICollection<Parametre> Parametres { get; set; } = new List<Parametre>();
|
||||
|
||||
public virtual ICollection<PiecesJointe> PiecesJointes { get; set; } = new List<PiecesJointe>();
|
||||
|
||||
public virtual ICollection<Rapprochement> Rapprochements { get; set; } = new List<Rapprochement>();
|
||||
|
||||
public virtual Service? Service { get; set; }
|
||||
|
||||
public virtual Utilisateur? Responsable { get; set; }
|
||||
|
||||
public virtual ICollection<Utilisateur> Collaborateurs { get; set; } = new List<Utilisateur>();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SIFinance.Shared.Entities
|
||||
{
|
||||
public partial class UtilisateurRole
|
||||
{
|
||||
public string AzureOid { get; set; } = null!;
|
||||
public string Role { get; set; } = null!;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace SIFinance.Shared;
|
||||
|
||||
// Jeton Graph "app-only" (client_credentials) pour les appels serveur-à-serveur
|
||||
// (synchro du groupe Entra ID, envoi d'emails de notification, etc.). Mis en cache 55
|
||||
// minutes pour éviter un aller-retour Azure AD à chaque appel. Vit dans SIFinance.Shared
|
||||
// (et non SIFinance.Api) car les modules en ont besoin eux aussi (ex. notification par
|
||||
// email à la création d'une demande), et référencer SIFinance.Api depuis un module
|
||||
// créerait un cycle.
|
||||
public class EntraGraphTokenProvider(IHttpClientFactory httpClientFactory, IOptions<AzureAdOptions> options)
|
||||
{
|
||||
private string? _token;
|
||||
private DateTime _expiresAt;
|
||||
|
||||
public async Task<string> GetTokenAsync(CancellationToken ct)
|
||||
{
|
||||
if (_token is not null && DateTime.UtcNow < _expiresAt) return _token;
|
||||
|
||||
var opts = options.Value;
|
||||
var http = httpClientFactory.CreateClient();
|
||||
var response = await http.PostAsync(
|
||||
$"https://login.microsoftonline.com/{opts.TenantId}/oauth2/v2.0/token",
|
||||
new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
["grant_type"] = "client_credentials",
|
||||
["client_id"] = opts.ClientId,
|
||||
["client_secret"] = opts.ClientSecret,
|
||||
["scope"] = "https://graph.microsoft.com/.default",
|
||||
}), ct);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
var payload = await response.Content.ReadFromJsonAsync<TokenResponse>(cancellationToken: ct)
|
||||
?? throw new InvalidOperationException("Réponse de jeton Graph vide.");
|
||||
|
||||
_token = payload.AccessToken;
|
||||
_expiresAt = DateTime.UtcNow.AddMinutes(55);
|
||||
return _token;
|
||||
}
|
||||
|
||||
private class TokenResponse
|
||||
{
|
||||
[JsonPropertyName("access_token")]
|
||||
public string AccessToken { get; set; } = "";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
using System.Text;
|
||||
using iText.Kernel.Colors;
|
||||
using iText.Kernel.Pdf;
|
||||
using iText.Kernel.Pdf.Filespec;
|
||||
using iText.Layout;
|
||||
using iText.Layout.Element;
|
||||
using iText.Pdfa;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using s2industries.ZUGFeRD;
|
||||
|
||||
namespace SIFinance.Shared;
|
||||
|
||||
public record FacturXLigne(string Designation, decimal Quantite, decimal PrixUnitaireHt);
|
||||
|
||||
public record FacturXPartie(string Nom, string? Rue, string? CodePostal, string? Ville, string PaysCode, string? NumeroTva);
|
||||
|
||||
public record FacturXEmissionRequest(
|
||||
string NumeroFacture,
|
||||
DateOnly DateFacture,
|
||||
FacturXPartie Vendeur,
|
||||
FacturXPartie Acheteur,
|
||||
List<FacturXLigne> Lignes,
|
||||
decimal TauxTva);
|
||||
|
||||
// Moteur réutilisable d'émission de factures électroniques Factur-X/ZUGFeRD (norme
|
||||
// EN16931) : XML structuré via ZUGFeRD-csharp, assemblage PDF/A-3 + attachement du XML
|
||||
// via iText7. Vit dans SIFinance.Shared pour être appelable depuis n'importe quel
|
||||
// module (Achats, Sous-Traitants, futur Contrat Étudiant) une fois qu'un cas d'usage
|
||||
// concret d'émission est identifié — voir appels dans les endpoints des modules.
|
||||
//
|
||||
// Nécessite un profil colorimétrique ICC sRGB valide (obligatoire pour la conformité
|
||||
// PDF/A-3, "PdfOutputIntent") — fichier binaire non fourni ici (voir
|
||||
// SIFinance.Shared/Resources/README.md pour comment se le procurer et où le déposer).
|
||||
public class FacturXEmissionService(IConfiguration configuration)
|
||||
{
|
||||
private string CheminProfilIcc =>
|
||||
configuration["FacturX:ProfilIccSrgb"] ?? Path.Combine(AppContext.BaseDirectory, "Resources", "sRGB.icc");
|
||||
|
||||
public byte[] Generer(FacturXEmissionRequest request)
|
||||
{
|
||||
if (request.Lignes.Count == 0)
|
||||
throw new ArgumentException("Une facture électronique doit contenir au moins une ligne.", nameof(request));
|
||||
|
||||
var montantHt = request.Lignes.Sum(l => Math.Round(l.Quantite * l.PrixUnitaireHt, 2));
|
||||
var montantTva = Math.Round(montantHt * request.TauxTva / 100m, 2);
|
||||
var montantTtc = montantHt + montantTva;
|
||||
|
||||
var xmlBytes = GenererXml(request, montantHt, montantTva, montantTtc);
|
||||
return AssemblerPdfA3(request, xmlBytes, montantHt, montantTva, montantTtc);
|
||||
}
|
||||
|
||||
private static byte[] GenererXml(FacturXEmissionRequest request, decimal montantHt, decimal montantTva, decimal montantTtc)
|
||||
{
|
||||
var desc = InvoiceDescriptor.CreateInvoice(request.NumeroFacture, request.DateFacture.ToDateTime(TimeOnly.MinValue), CurrencyCodes.EUR);
|
||||
|
||||
desc.SetSeller(
|
||||
request.Vendeur.Nom, request.Vendeur.CodePostal ?? "", request.Vendeur.Ville ?? "", request.Vendeur.Rue ?? "",
|
||||
ParsePays(request.Vendeur.PaysCode), request.Vendeur.NumeroTva);
|
||||
desc.SetBuyer(
|
||||
request.Acheteur.Nom, request.Acheteur.CodePostal ?? "", request.Acheteur.Ville ?? "", request.Acheteur.Rue ?? "",
|
||||
ParsePays(request.Acheteur.PaysCode), request.Acheteur.NumeroTva);
|
||||
|
||||
foreach (var ligne in request.Lignes)
|
||||
{
|
||||
desc.AddTradeLineItem(
|
||||
name: ligne.Designation,
|
||||
netUnitPrice: ligne.PrixUnitaireHt,
|
||||
unitCode: QuantityCodes.C62,
|
||||
billedQuantity: ligne.Quantite,
|
||||
taxType: TaxTypes.VAT,
|
||||
categoryCode: TaxCategoryCodes.S,
|
||||
taxPercent: request.TauxTva);
|
||||
}
|
||||
|
||||
desc.AddApplicableTradeTax(montantHt, request.TauxTva, montantTva, TaxTypes.VAT, TaxCategoryCodes.S);
|
||||
desc.SetTotals(
|
||||
lineTotalAmount: montantHt, taxBasisAmount: montantHt, taxTotalAmount: montantTva,
|
||||
grandTotalAmount: montantTtc, duePayableAmount: montantTtc);
|
||||
|
||||
using var xmlStream = new MemoryStream();
|
||||
desc.Save(xmlStream, ZUGFeRDVersion.Version23, Profile.Comfort);
|
||||
return xmlStream.ToArray();
|
||||
}
|
||||
|
||||
private byte[] AssemblerPdfA3(FacturXEmissionRequest request, byte[] xmlBytes, decimal montantHt, decimal montantTva, decimal montantTtc)
|
||||
{
|
||||
var cheminIcc = CheminProfilIcc;
|
||||
if (!File.Exists(cheminIcc))
|
||||
throw new InvalidOperationException(
|
||||
$"Profil ICC sRGB introuvable ({cheminIcc}) — requis pour générer un PDF/A-3 conforme. " +
|
||||
"Voir SIFinance.Shared/Resources/README.md.");
|
||||
|
||||
using var pdfMemStream = new MemoryStream();
|
||||
using (var iccStream = File.OpenRead(cheminIcc))
|
||||
{
|
||||
var outputIntent = new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1", iccStream);
|
||||
using var writer = new PdfWriter(pdfMemStream);
|
||||
using var pdfDoc = new PdfADocument(writer, PdfAConformance.PDF_A_3B, outputIntent);
|
||||
pdfDoc.SetTagged();
|
||||
|
||||
using (var document = new Document(pdfDoc))
|
||||
{
|
||||
document.Add(new Paragraph($"Facture {request.NumeroFacture}").SetFontSize(18).SimulateBold());
|
||||
document.Add(new Paragraph($"Date : {request.DateFacture:dd/MM/yyyy}"));
|
||||
document.Add(new Paragraph(" "));
|
||||
|
||||
document.Add(new Paragraph("Émetteur").SimulateBold());
|
||||
document.Add(new Paragraph($"{request.Vendeur.Nom}\n{request.Vendeur.Rue}\n{request.Vendeur.CodePostal} {request.Vendeur.Ville}"));
|
||||
document.Add(new Paragraph(" "));
|
||||
|
||||
document.Add(new Paragraph("Destinataire").SimulateBold());
|
||||
document.Add(new Paragraph($"{request.Acheteur.Nom}\n{request.Acheteur.Rue}\n{request.Acheteur.CodePostal} {request.Acheteur.Ville}"));
|
||||
document.Add(new Paragraph(" "));
|
||||
|
||||
var table = new Table(4).UseAllAvailableWidth();
|
||||
table.AddHeaderCell("Désignation");
|
||||
table.AddHeaderCell("Qté");
|
||||
table.AddHeaderCell("PU HT");
|
||||
table.AddHeaderCell("Total HT");
|
||||
foreach (var ligne in request.Lignes)
|
||||
{
|
||||
table.AddCell(ligne.Designation);
|
||||
table.AddCell(ligne.Quantite.ToString("N2"));
|
||||
table.AddCell($"{ligne.PrixUnitaireHt:N2} €");
|
||||
table.AddCell($"{(ligne.Quantite * ligne.PrixUnitaireHt):N2} €");
|
||||
}
|
||||
document.Add(table);
|
||||
|
||||
document.Add(new Paragraph(" "));
|
||||
document.Add(new Paragraph($"Total HT : {montantHt:N2} €"));
|
||||
document.Add(new Paragraph($"TVA ({request.TauxTva:N0}%) : {montantTva:N2} €"));
|
||||
document.Add(new Paragraph($"Total TTC : {montantTtc:N2} €").SimulateBold());
|
||||
}
|
||||
|
||||
var fileSpec = PdfFileSpec.CreateEmbeddedFileSpec(
|
||||
pdfDoc, xmlBytes, "Facture électronique Factur-X", "factur-x.xml", PdfName.ApplicationXml, null, PdfName.Data);
|
||||
pdfDoc.AddFileAttachment("factur-x.xml", fileSpec);
|
||||
}
|
||||
|
||||
return pdfMemStream.ToArray();
|
||||
}
|
||||
|
||||
private static s2industries.ZUGFeRD.CountryCodes ParsePays(string code) =>
|
||||
Enum.TryParse<s2industries.ZUGFeRD.CountryCodes>(code, true, out var parsed) ? parsed : s2industries.ZUGFeRD.CountryCodes.FR;
|
||||
}
|
||||
+1716
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,148 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace SIFinance.Shared.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddContratsAndPaiementStatut : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "statut",
|
||||
schema: "fin",
|
||||
table: "paiements",
|
||||
type: "varchar(20)",
|
||||
unicode: false,
|
||||
maxLength: 20,
|
||||
nullable: false,
|
||||
defaultValue: "PROGRAMME");
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "rapproche",
|
||||
schema: "fin",
|
||||
table: "paiements",
|
||||
type: "bit",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "contrats_fournisseurs",
|
||||
schema: "achats",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("SqlServer:Identity", "1, 1"),
|
||||
fournisseur_id = table.Column<int>(type: "int", nullable: false),
|
||||
reference = table.Column<string>(type: "varchar(50)", unicode: false, maxLength: 50, nullable: true),
|
||||
objet = table.Column<string>(type: "varchar(255)", unicode: false, maxLength: 255, nullable: false),
|
||||
date_signature = table.Column<DateOnly>(type: "date", nullable: true),
|
||||
date_debut = table.Column<DateOnly>(type: "date", nullable: false),
|
||||
date_fin = table.Column<DateOnly>(type: "date", nullable: false),
|
||||
montant_total = table.Column<decimal>(type: "decimal(18,2)", nullable: false),
|
||||
periodicite = table.Column<string>(type: "varchar(20)", unicode: false, maxLength: 20, nullable: false, defaultValue: "mensuelle"),
|
||||
statut = table.Column<string>(type: "varchar(20)", unicode: false, maxLength: 20, nullable: false, defaultValue: "ACTIF"),
|
||||
saisie_par_id = table.Column<int>(type: "int", nullable: false),
|
||||
date_creation = table.Column<DateTime>(type: "datetime", nullable: true, defaultValueSql: "(getdate())"),
|
||||
date_derniere_maj = table.Column<DateTime>(type: "datetime", nullable: true, defaultValueSql: "(getdate())")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK__contrats_fournisseurs", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "FK__contrats_fournisseurs__fournisseur",
|
||||
column: x => x.fournisseur_id,
|
||||
principalSchema: "ref",
|
||||
principalTable: "fournisseurs",
|
||||
principalColumn: "id");
|
||||
table.ForeignKey(
|
||||
name: "FK__contrats_fournisseurs__saisie_par",
|
||||
column: x => x.saisie_par_id,
|
||||
principalSchema: "core",
|
||||
principalTable: "utilisateurs",
|
||||
principalColumn: "id");
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "contrats_echeances",
|
||||
schema: "achats",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("SqlServer:Identity", "1, 1"),
|
||||
contrat_id = table.Column<int>(type: "int", nullable: false),
|
||||
date_echeance = table.Column<DateOnly>(type: "date", nullable: false),
|
||||
montant = table.Column<decimal>(type: "decimal(18,2)", nullable: false),
|
||||
statut = table.Column<string>(type: "varchar(20)", unicode: false, maxLength: 20, nullable: false, defaultValue: "A_VENIR"),
|
||||
justificatif_id = table.Column<int>(type: "int", nullable: true),
|
||||
date_creation = table.Column<DateTime>(type: "datetime", nullable: true, defaultValueSql: "(getdate())")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK__contrats_echeances", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "FK__contrats_echeances__contrat",
|
||||
column: x => x.contrat_id,
|
||||
principalSchema: "achats",
|
||||
principalTable: "contrats_fournisseurs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK__contrats_echeances__justificatif",
|
||||
column: x => x.justificatif_id,
|
||||
principalSchema: "core",
|
||||
principalTable: "pieces_jointes",
|
||||
principalColumn: "id");
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ctf_fournisseur",
|
||||
schema: "achats",
|
||||
table: "contrats_fournisseurs",
|
||||
column: "fournisseur_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ctf_saisie_par",
|
||||
schema: "achats",
|
||||
table: "contrats_fournisseurs",
|
||||
column: "saisie_par_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_cte_contrat",
|
||||
schema: "achats",
|
||||
table: "contrats_echeances",
|
||||
column: "contrat_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_cte_justif",
|
||||
schema: "achats",
|
||||
table: "contrats_echeances",
|
||||
column: "justificatif_id");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "contrats_echeances",
|
||||
schema: "achats");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "contrats_fournisseurs",
|
||||
schema: "achats");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "rapproche",
|
||||
schema: "fin",
|
||||
table: "paiements");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "statut",
|
||||
schema: "fin",
|
||||
table: "paiements");
|
||||
}
|
||||
}
|
||||
}
|
||||
+1721
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,31 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace SIFinance.Shared.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddCategorieFournisseurLibre : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "categorie_fournisseur_libre",
|
||||
schema: "achats",
|
||||
table: "demandes_achat",
|
||||
type: "nvarchar(100)",
|
||||
maxLength: 100,
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "categorie_fournisseur_libre",
|
||||
schema: "achats",
|
||||
table: "demandes_achat");
|
||||
}
|
||||
}
|
||||
}
|
||||
+1899
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,104 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace SIFinance.Shared.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddSousTraitantsOrganismesContrats : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.EnsureSchema(
|
||||
name: "st");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "organismes",
|
||||
schema: "st",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("SqlServer:Identity", "1, 1"),
|
||||
raison_sociale = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false),
|
||||
siret = table.Column<string>(type: "varchar(20)", unicode: false, maxLength: 20, nullable: true),
|
||||
email = table.Column<string>(type: "varchar(255)", unicode: false, maxLength: 255, nullable: true),
|
||||
telephone = table.Column<string>(type: "varchar(30)", unicode: false, maxLength: 30, nullable: true),
|
||||
adresse = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: true),
|
||||
statut = table.Column<string>(type: "varchar(20)", unicode: false, maxLength: 20, nullable: false, defaultValue: "ACTIF"),
|
||||
date_creation = table.Column<DateTime>(type: "datetime", nullable: true, defaultValueSql: "(getdate())")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK__organismes", x => x.id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "contrats_prestataires",
|
||||
schema: "st",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("SqlServer:Identity", "1, 1"),
|
||||
organisme_id = table.Column<int>(type: "int", nullable: false),
|
||||
reference = table.Column<string>(type: "varchar(50)", unicode: false, maxLength: 50, nullable: false),
|
||||
objet = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false),
|
||||
date_signature = table.Column<DateOnly>(type: "date", nullable: true),
|
||||
date_debut = table.Column<DateOnly>(type: "date", nullable: false),
|
||||
date_fin = table.Column<DateOnly>(type: "date", nullable: false),
|
||||
montant_total = table.Column<decimal>(type: "decimal(18,2)", nullable: false),
|
||||
statut = table.Column<string>(type: "varchar(20)", unicode: false, maxLength: 20, nullable: false, defaultValue: "ACTIF"),
|
||||
saisie_par_id = table.Column<int>(type: "int", nullable: false),
|
||||
date_creation = table.Column<DateTime>(type: "datetime", nullable: true, defaultValueSql: "(getdate())")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK__contrats_prestataires", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "FK__contrats_prestataires__organisme",
|
||||
column: x => x.organisme_id,
|
||||
principalSchema: "st",
|
||||
principalTable: "organismes",
|
||||
principalColumn: "id");
|
||||
table.ForeignKey(
|
||||
name: "FK__contrats_prestataires__saisie_par",
|
||||
column: x => x.saisie_par_id,
|
||||
principalSchema: "core",
|
||||
principalTable: "utilisateurs",
|
||||
principalColumn: "id");
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ctp_organisme",
|
||||
schema: "st",
|
||||
table: "contrats_prestataires",
|
||||
column: "organisme_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ctp_saisie_par",
|
||||
schema: "st",
|
||||
table: "contrats_prestataires",
|
||||
column: "saisie_par_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "UQ_ctp_reference",
|
||||
schema: "st",
|
||||
table: "contrats_prestataires",
|
||||
column: "reference",
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "contrats_prestataires",
|
||||
schema: "st");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "organismes",
|
||||
schema: "st");
|
||||
}
|
||||
}
|
||||
}
|
||||
+1914
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,55 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace SIFinance.Shared.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddResponsableToUtilisateurs : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "responsable_id",
|
||||
schema: "core",
|
||||
table: "utilisateurs",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_utilisateurs_responsable_id",
|
||||
schema: "core",
|
||||
table: "utilisateurs",
|
||||
column: "responsable_id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK__utilisateurs__responsable",
|
||||
schema: "core",
|
||||
table: "utilisateurs",
|
||||
column: "responsable_id",
|
||||
principalSchema: "core",
|
||||
principalTable: "utilisateurs",
|
||||
principalColumn: "id");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK__utilisateurs__responsable",
|
||||
schema: "core",
|
||||
table: "utilisateurs");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_utilisateurs_responsable_id",
|
||||
schema: "core",
|
||||
table: "utilisateurs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "responsable_id",
|
||||
schema: "core",
|
||||
table: "utilisateurs");
|
||||
}
|
||||
}
|
||||
}
|
||||
+1919
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,31 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace SIFinance.Shared.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddCommentaireToFactures : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "commentaire",
|
||||
schema: "fin",
|
||||
table: "factures",
|
||||
type: "nvarchar(1000)",
|
||||
maxLength: 1000,
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "commentaire",
|
||||
schema: "fin",
|
||||
table: "factures");
|
||||
}
|
||||
}
|
||||
}
|
||||
+1935
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,56 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace SIFinance.Shared.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddContratIdToFactures : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "contrat_id",
|
||||
schema: "fin",
|
||||
table: "factures",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_factures_contrat_id",
|
||||
schema: "fin",
|
||||
table: "factures",
|
||||
column: "contrat_id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_factures_contrat",
|
||||
schema: "fin",
|
||||
table: "factures",
|
||||
column: "contrat_id",
|
||||
principalSchema: "achats",
|
||||
principalTable: "contrats_fournisseurs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_factures_contrat",
|
||||
schema: "fin",
|
||||
table: "factures");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_factures_contrat_id",
|
||||
schema: "fin",
|
||||
table: "factures");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "contrat_id",
|
||||
schema: "fin",
|
||||
table: "factures");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace SIFinance.Shared.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddBudgetsService : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "budgets_service",
|
||||
schema: "achats",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("SqlServer:Identity", "1, 1"),
|
||||
service_id = table.Column<int>(type: "int", nullable: false),
|
||||
exercice_annee = table.Column<int>(type: "int", nullable: false),
|
||||
montant_initial = table.Column<decimal>(type: "decimal(18,2)", nullable: false),
|
||||
montant_revise = table.Column<decimal>(type: "decimal(18,2)", nullable: true),
|
||||
date_revision = table.Column<DateTime>(type: "datetime", nullable: true),
|
||||
revise_par = table.Column<int>(type: "int", nullable: true),
|
||||
commentaire_revision = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: true),
|
||||
saisie_par_id = table.Column<int>(type: "int", nullable: false),
|
||||
date_creation = table.Column<DateTime>(type: "datetime", nullable: true, defaultValueSql: "(getdate())"),
|
||||
date_derniere_maj = table.Column<DateTime>(type: "datetime", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_budgets_service", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "FK_budgets_service_revise_par",
|
||||
column: x => x.revise_par,
|
||||
principalSchema: "core",
|
||||
principalTable: "utilisateurs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "FK_budgets_service_saisie_par",
|
||||
column: x => x.saisie_par_id,
|
||||
principalSchema: "core",
|
||||
principalTable: "utilisateurs",
|
||||
principalColumn: "id");
|
||||
table.ForeignKey(
|
||||
name: "FK_budgets_service_service",
|
||||
column: x => x.service_id,
|
||||
principalSchema: "ref",
|
||||
principalTable: "services",
|
||||
principalColumn: "id");
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_budgets_service_revise_par",
|
||||
schema: "achats",
|
||||
table: "budgets_service",
|
||||
column: "revise_par");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_budgets_service_saisie_par_id",
|
||||
schema: "achats",
|
||||
table: "budgets_service",
|
||||
column: "saisie_par_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_budgets_service_unique",
|
||||
schema: "achats",
|
||||
table: "budgets_service",
|
||||
columns: new[] { "service_id", "exercice_annee" },
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "budgets_service",
|
||||
schema: "achats");
|
||||
}
|
||||
}
|
||||
}
|
||||
+2065
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,141 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace SIFinance.Shared.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class SplitBudgetRevisionsHistory : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_budgets_service_revise_par",
|
||||
schema: "achats",
|
||||
table: "budgets_service");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_budgets_service_revise_par",
|
||||
schema: "achats",
|
||||
table: "budgets_service");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "commentaire_revision",
|
||||
schema: "achats",
|
||||
table: "budgets_service");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "date_revision",
|
||||
schema: "achats",
|
||||
table: "budgets_service");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "montant_revise",
|
||||
schema: "achats",
|
||||
table: "budgets_service");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "revise_par",
|
||||
schema: "achats",
|
||||
table: "budgets_service");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "budgets_service_revisions",
|
||||
schema: "achats",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("SqlServer:Identity", "1, 1"),
|
||||
budget_service_id = table.Column<int>(type: "int", nullable: false),
|
||||
montant_revise = table.Column<decimal>(type: "decimal(18,2)", nullable: false),
|
||||
commentaire = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: true),
|
||||
revise_par = table.Column<int>(type: "int", nullable: false),
|
||||
date_revision = table.Column<DateTime>(type: "datetime", nullable: false, defaultValueSql: "(getdate())")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_budgets_service_revisions", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "FK_budgets_service_revisions_budget",
|
||||
column: x => x.budget_service_id,
|
||||
principalSchema: "achats",
|
||||
principalTable: "budgets_service",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_budgets_service_revisions_revise_par",
|
||||
column: x => x.revise_par,
|
||||
principalSchema: "core",
|
||||
principalTable: "utilisateurs",
|
||||
principalColumn: "id");
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_budgets_service_revisions_budget_service_id",
|
||||
schema: "achats",
|
||||
table: "budgets_service_revisions",
|
||||
column: "budget_service_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_budgets_service_revisions_revise_par",
|
||||
schema: "achats",
|
||||
table: "budgets_service_revisions",
|
||||
column: "revise_par");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "budgets_service_revisions",
|
||||
schema: "achats");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "commentaire_revision",
|
||||
schema: "achats",
|
||||
table: "budgets_service",
|
||||
type: "nvarchar(1000)",
|
||||
maxLength: 1000,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "date_revision",
|
||||
schema: "achats",
|
||||
table: "budgets_service",
|
||||
type: "datetime",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<decimal>(
|
||||
name: "montant_revise",
|
||||
schema: "achats",
|
||||
table: "budgets_service",
|
||||
type: "decimal(18,2)",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "revise_par",
|
||||
schema: "achats",
|
||||
table: "budgets_service",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_budgets_service_revise_par",
|
||||
schema: "achats",
|
||||
table: "budgets_service",
|
||||
column: "revise_par");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_budgets_service_revise_par",
|
||||
schema: "achats",
|
||||
table: "budgets_service",
|
||||
column: "revise_par",
|
||||
principalSchema: "core",
|
||||
principalTable: "utilisateurs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
-- À exécuter une seule fois sur la base SIFinance.
|
||||
-- Le flag permet de rattacher n'importe quelle catégorie au circuit matériel,
|
||||
-- sans dépendre de son libellé.
|
||||
ALTER TABLE ref.types_depense
|
||||
ADD est_materiel bit NOT NULL
|
||||
CONSTRAINT DF_types_depense_est_materiel DEFAULT (0);
|
||||
GO
|
||||
|
||||
-- Les nouveaux statuts du workflow dépassent parfois la taille historique de 30.
|
||||
ALTER TABLE achats.demandes_achat
|
||||
ALTER COLUMN statut varchar(50) NOT NULL;
|
||||
GO
|
||||
|
||||
-- Catégories à traiter comme du matériel : adapte cette liste à tes règles métier.
|
||||
UPDATE ref.types_depense
|
||||
SET est_materiel = 1
|
||||
WHERE libelle IN ('Fournitures', 'Informatique', 'Mobilier');
|
||||
GO
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,50 @@
|
||||
using System.Net.Http.Headers;
|
||||
using System.Net.Http.Json;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace SIFinance.Shared;
|
||||
|
||||
// Envoie des notifications par email via Microsoft Graph (permission application
|
||||
// Mail.Send, déjà accordée) — envoie "au nom de" une boîte du tenant (ex. le
|
||||
// demandeur), pas besoin de boîte de service dédiée. Les échecs sont journalisés mais
|
||||
// n'interrompent jamais le flux appelant (une notification ratée ne doit pas faire
|
||||
// échouer la création d'une demande). Vit dans SIFinance.Shared car les modules
|
||||
// (Achats, Sous-Traitants...) doivent pouvoir l'appeler directement.
|
||||
public class NotificationEmailService(
|
||||
IHttpClientFactory httpClientFactory,
|
||||
EntraGraphTokenProvider tokenProvider,
|
||||
ILogger<NotificationEmailService> logger)
|
||||
{
|
||||
public async Task EnvoyerAsync(string expediteurEmail, string destinataireEmail, string sujet, string corpsHtml, CancellationToken ct)
|
||||
{
|
||||
try
|
||||
{
|
||||
var token = await tokenProvider.GetTokenAsync(ct);
|
||||
var http = httpClientFactory.CreateClient();
|
||||
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
|
||||
|
||||
var payload = new
|
||||
{
|
||||
message = new
|
||||
{
|
||||
subject = sujet,
|
||||
body = new { contentType = "HTML", content = corpsHtml },
|
||||
toRecipients = new[] { new { emailAddress = new { address = destinataireEmail } } },
|
||||
},
|
||||
saveToSentItems = false,
|
||||
};
|
||||
|
||||
var response = await http.PostAsJsonAsync(
|
||||
$"https://graph.microsoft.com/v1.0/users/{Uri.EscapeDataString(expediteurEmail)}/sendMail", payload, ct);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
var body = await response.Content.ReadAsStringAsync(ct);
|
||||
logger.LogWarning("Échec d'envoi d'email de notification ({Status}) : {Body}", response.StatusCode, body);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (ex is not OperationCanceledException)
|
||||
{
|
||||
logger.LogWarning(ex, "Échec d'envoi d'email de notification à {Destinataire}.", destinataireEmail);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="itext7" Version="9.7.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.9">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.9" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.9">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="ZUGFeRD-csharp" Version="18.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Nécessaire pour IHttpContextAccessor (CurrentUserService), partagé par l'API et les modules. -->
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user