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));
}
}