books/backend/Books.Api/Domain/VatCode.cs

91 lines
3.6 KiB
C#
Raw Normal View History

namespace Books.Api.Domain;
/// <summary>
/// Danish VAT (moms) codes for SKAT compliance.
/// These codes determine how transactions are reported in the VAT return.
/// </summary>
public static class VatCodes
{
// Output VAT (Udgående moms) - Sales
public const string U25 = "U25"; // Salg med 25% moms (standard)
public const string UEU = "UEU"; // EU-salg af varer/ydelser (momsfrit)
public const string UEXP = "UEXP"; // Eksport uden for EU (momsfrit)
// Input VAT (Indgående moms) - Purchases
public const string I25 = "I25"; // Køb med 25% moms (fuldt fradrag)
public const string IEUV = "IEUV"; // EU-erhvervelse varer (reverse charge)
public const string IEUY = "IEUY"; // EU-erhvervelse ydelser (reverse charge)
public const string IVV = "IVV"; // Import varer fra verden
public const string IVY = "IVY"; // Import ydelser fra verden
// Special codes
public const string REP = "REP"; // Repræsentation (25% fradrag)
public const string INGEN = "INGEN"; // Ingen moms / momsfrit
/// <summary>
/// Gets the VAT rate for a given code.
/// </summary>
public static decimal GetRate(string? vatCode) => vatCode switch
{
U25 => 0.25m,
I25 => 0.25m,
IEUV => 0.25m, // Reverse charge - calculated but offset
IEUY => 0.25m, // Reverse charge - calculated but offset
IVY => 0.25m, // Reverse charge for imported services (Momsloven §46)
REP => 0.25m, // 25% rate, but only 25% deductible
_ => 0m
};
/// <summary>
/// Gets the deductible percentage for a given code.
/// </summary>
public static decimal GetDeductiblePercent(string? vatCode) => vatCode switch
{
I25 => 1.0m, // 100% deductible
IEUV => 1.0m, // 100% deductible (reverse charge)
IEUY => 1.0m, // 100% deductible (reverse charge)
IVY => 1.0m, // 100% deductible (reverse charge, Momsloven §46)
REP => 0.25m, // Only 25% deductible
_ => 0m
};
/// <summary>
/// Validates if a VAT code is valid.
/// </summary>
public static bool IsValid(string? vatCode)
{
if (string.IsNullOrWhiteSpace(vatCode)) return true; // null/empty is allowed
return vatCode is U25 or UEU or UEXP or I25 or IEUV or IEUY or IVV or IVY or REP or INGEN;
}
/// <summary>
/// Determines if this is input VAT (købsmoms/fradrag) vs output VAT (salgsmoms/skyldig).
/// Input VAT is on purchases (assets), output VAT is on sales (liabilities).
/// </summary>
public static bool IsInputVat(string? vatCode) => vatCode switch
{
I25 or IEUV or IEUY or IVV or IVY or REP => true, // Purchase/input VAT codes
U25 or UEU or UEXP => false, // Sales/output VAT codes
_ => false
};
/// <summary>
/// All valid VAT codes for UI dropdowns.
/// </summary>
public static IReadOnlyList<VatCodeInfo> All { get; } =
[
new(INGEN, "Ingen moms", "No VAT", 0m),
new(U25, "Salg 25%", "Sales 25%", 0.25m),
new(UEU, "EU-salg", "EU Sales", 0m),
new(UEXP, "Eksport", "Export", 0m),
new(I25, "Køb 25%", "Purchase 25%", 0.25m),
new(IEUV, "EU-køb varer", "EU Purchase Goods", 0.25m),
new(IEUY, "EU-køb ydelser", "EU Purchase Services", 0.25m),
new(IVV, "Import varer", "Import Goods", 0m),
new(IVY, "Import ydelser", "Import Services", 0.25m),
new(REP, "Repræsentation", "Entertainment", 0.25m),
];
}
public record VatCodeInfo(string Code, string NameDanish, string NameEnglish, decimal Rate);