using System; namespace FrenchExDev.Net.State.Economy.Dsl; /// /// Ratio de déficit public rapporté au PIB. Domaine borné [0, 1] en décimal /// (0.03m = 3%). L'usage d'un garantit la précision /// des comparaisons compile-time dans l'analyzer ECO001. /// public readonly struct DeficitRatio : IEquatable { /// Seuil Maastricht (art. 126 TFUE + protocole n°12) : 3% du PIB. public const decimal MaastrichtThreshold = 0.03m; public decimal Value { get; } private DeficitRatio(decimal value) { if (value < 0m) throw new ArgumentOutOfRangeException(nameof(value), "Un déficit ne peut pas être négatif (un excédent est un DeficitRatio de 0)."); if (value > 1m) throw new ArgumentOutOfRangeException(nameof(value), "Un déficit > 100% du PIB est irréaliste — vérifiez l'unité."); Value = value; } public static DeficitRatio Of(decimal value) => new(value); public bool ExceedsMaastricht() => Value > MaastrichtThreshold; public bool Equals(DeficitRatio other) => Value == other.Value; public override bool Equals(object? obj) => obj is DeficitRatio other && Equals(other); public override int GetHashCode() => Value.GetHashCode(); public override string ToString() => $"{Value:P2}"; } /// /// Ratio d'endettement public rapporté au PIB. Seuil Maastricht : 60%. /// public readonly struct DebtRatio : IEquatable { public const decimal MaastrichtThreshold = 0.60m; public decimal Value { get; } private DebtRatio(decimal value) { if (value < 0m) throw new ArgumentOutOfRangeException(nameof(value)); Value = value; } public static DebtRatio Of(decimal value) => new(value); public bool ExceedsMaastricht() => Value > MaastrichtThreshold; public bool Equals(DebtRatio other) => Value == other.Value; public override bool Equals(object? obj) => obj is DebtRatio other && Equals(other); public override int GetHashCode() => Value.GetHashCode(); public override string ToString() => $"{Value:P2}"; } /// /// Atteste qu'un acte budgétaire projetant un déficit supérieur au seuil /// Maastricht est accompagné d'une justification au sens art. 126 TFUE /// (recommandation du Conseil de l'UE dans le cadre de la procédure pour /// déficit excessif). Sans cet attribut, l'analyzer ECO001 lève un /// diagnostic au build. /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] public sealed class Article126TfeuJustificationAttribute : Attribute { /// Date de la recommandation du Conseil (ISO 8601). public string CouncilRecommendation { get; } /// Échéance de correction fixée par le Conseil (ISO 8601). public string CorrectiveDeadline { get; } public Article126TfeuJustificationAttribute(string councilRecommendation, string correctiveDeadline) { CouncilRecommendation = councilRecommendation ?? throw new ArgumentNullException(nameof(councilRecommendation)); CorrectiveDeadline = correctiveDeadline ?? throw new ArgumentNullException(nameof(correctiveDeadline)); } } /// /// Marque une classe comme loi de finances (budget annuel) pour un pays donné. /// L'analyzer ECO001 scanne les propriétés retournant /// sur toute classe portant cet attribut. /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] public sealed class LoiDeFinancesAttribute : Attribute { public int Year { get; } public LoiDeFinancesAttribute(int year) { Year = year; } } /// /// Marque une classe comme soumise à une procédure pour déficit excessif /// (PDE) ouverte par la Commission européenne au titre de l'art. 126 TFUE. /// Substitut à quand la /// PDE est formellement déclarée ouverte. /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] public sealed class ExcessiveDeficitProcedureAttribute : Attribute { public bool Opened { get; } public string OpenedDate { get; } public ExcessiveDeficitProcedureAttribute(bool opened, string openedDate) { Opened = opened; OpenedDate = openedDate ?? throw new ArgumentNullException(nameof(openedDate)); } }