Add all backend domain, commands, repositories, and tests
This commit includes all previously untracked backend files:
Domain:
- Accounts, Attachments, BankConnections, Customers
- FiscalYears, Invoices, JournalEntryDrafts
- Orders, Products, UserAccess
Commands & Handlers:
- Full CQRS command structure for all domains
Repositories:
- PostgreSQL repositories for all read models
- Bank transaction and ledger repositories
GraphQL:
- Input types, scalars, and types for all entities
- Mutations and queries
Infrastructure:
- Banking integration (Enable Banking client)
- File storage, Invoicing, Reporting, SAF-T export
- Database migrations (003-029)
Tests:
- Integration tests for GraphQL endpoints
- Domain tests
- Invoicing and reporting tests
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 22:19:42 +01:00
|
|
|
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
|
Audit v4: VAT calc, SAF-T compliance, security hardening, frontend quality
Backend (17 files):
- VAT: REP 25% deductibility (§42), EU reverse charge double-entry (IEUV/IEUY/IVY),
IVY rate 0%→25%, VatReport Box C/D populated, Basis1 from real revenue
- SAF-T: correct OECD namespace, closing balance net calc, zero-amount fallback,
credit note auto-numbering (§52)
- Security: BankingController CSRF state token + company auth check,
attachment canonical path traversal check, discount 0-100% validation,
deactivated product/customer update guard
- Quality: redact bank API logs, remove dead code (VatCalcService,
PaymentMatchingService), CompanyAggregate IEmit interfaces, fix URL encoding
Frontend (15 files):
- Fix double "kr." in AmountText and Dashboard Statistic components
- Fix UserSettings Switch defaultChecked desync with Form state
- Remove dual useCompany/useCompanyStore pattern (Dashboard, Moms, Bank)
- Correct SKAT VAT deadline calculation per period type
- Add half-yearly/yearly VAT period options
- Guard console.error with import.meta.env.DEV
- Use shared formatDate in BankConnectionsTab
- Remove dead NONE vatCode check, purge 7 legacy VAT codes from type union
- Migrate S25→U25, K25→I25 across all pages
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 01:38:52 +01:00
|
|
|
IVY => 0.25m, // Reverse charge for imported services (Momsloven §46)
|
Add all backend domain, commands, repositories, and tests
This commit includes all previously untracked backend files:
Domain:
- Accounts, Attachments, BankConnections, Customers
- FiscalYears, Invoices, JournalEntryDrafts
- Orders, Products, UserAccess
Commands & Handlers:
- Full CQRS command structure for all domains
Repositories:
- PostgreSQL repositories for all read models
- Bank transaction and ledger repositories
GraphQL:
- Input types, scalars, and types for all entities
- Mutations and queries
Infrastructure:
- Banking integration (Enable Banking client)
- File storage, Invoicing, Reporting, SAF-T export
- Database migrations (003-029)
Tests:
- Integration tests for GraphQL endpoints
- Domain tests
- Invoicing and reporting tests
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 22:19:42 +01:00
|
|
|
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)
|
Audit v4: VAT calc, SAF-T compliance, security hardening, frontend quality
Backend (17 files):
- VAT: REP 25% deductibility (§42), EU reverse charge double-entry (IEUV/IEUY/IVY),
IVY rate 0%→25%, VatReport Box C/D populated, Basis1 from real revenue
- SAF-T: correct OECD namespace, closing balance net calc, zero-amount fallback,
credit note auto-numbering (§52)
- Security: BankingController CSRF state token + company auth check,
attachment canonical path traversal check, discount 0-100% validation,
deactivated product/customer update guard
- Quality: redact bank API logs, remove dead code (VatCalcService,
PaymentMatchingService), CompanyAggregate IEmit interfaces, fix URL encoding
Frontend (15 files):
- Fix double "kr." in AmountText and Dashboard Statistic components
- Fix UserSettings Switch defaultChecked desync with Form state
- Remove dual useCompany/useCompanyStore pattern (Dashboard, Moms, Bank)
- Correct SKAT VAT deadline calculation per period type
- Add half-yearly/yearly VAT period options
- Guard console.error with import.meta.env.DEV
- Use shared formatDate in BankConnectionsTab
- Remove dead NONE vatCode check, purge 7 legacy VAT codes from type union
- Migrate S25→U25, K25→I25 across all pages
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 01:38:52 +01:00
|
|
|
IVY => 1.0m, // 100% deductible (reverse charge, Momsloven §46)
|
Add all backend domain, commands, repositories, and tests
This commit includes all previously untracked backend files:
Domain:
- Accounts, Attachments, BankConnections, Customers
- FiscalYears, Invoices, JournalEntryDrafts
- Orders, Products, UserAccess
Commands & Handlers:
- Full CQRS command structure for all domains
Repositories:
- PostgreSQL repositories for all read models
- Bank transaction and ledger repositories
GraphQL:
- Input types, scalars, and types for all entities
- Mutations and queries
Infrastructure:
- Banking integration (Enable Banking client)
- File storage, Invoicing, Reporting, SAF-T export
- Database migrations (003-029)
Tests:
- Integration tests for GraphQL endpoints
- Domain tests
- Invoicing and reporting tests
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 22:19:42 +01:00
|
|
|
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),
|
Audit v4: VAT calc, SAF-T compliance, security hardening, frontend quality
Backend (17 files):
- VAT: REP 25% deductibility (§42), EU reverse charge double-entry (IEUV/IEUY/IVY),
IVY rate 0%→25%, VatReport Box C/D populated, Basis1 from real revenue
- SAF-T: correct OECD namespace, closing balance net calc, zero-amount fallback,
credit note auto-numbering (§52)
- Security: BankingController CSRF state token + company auth check,
attachment canonical path traversal check, discount 0-100% validation,
deactivated product/customer update guard
- Quality: redact bank API logs, remove dead code (VatCalcService,
PaymentMatchingService), CompanyAggregate IEmit interfaces, fix URL encoding
Frontend (15 files):
- Fix double "kr." in AmountText and Dashboard Statistic components
- Fix UserSettings Switch defaultChecked desync with Form state
- Remove dual useCompany/useCompanyStore pattern (Dashboard, Moms, Bank)
- Correct SKAT VAT deadline calculation per period type
- Add half-yearly/yearly VAT period options
- Guard console.error with import.meta.env.DEV
- Use shared formatDate in BankConnectionsTab
- Remove dead NONE vatCode check, purge 7 legacy VAT codes from type union
- Migrate S25→U25, K25→I25 across all pages
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 01:38:52 +01:00
|
|
|
new(IVY, "Import ydelser", "Import Services", 0.25m),
|
Add all backend domain, commands, repositories, and tests
This commit includes all previously untracked backend files:
Domain:
- Accounts, Attachments, BankConnections, Customers
- FiscalYears, Invoices, JournalEntryDrafts
- Orders, Products, UserAccess
Commands & Handlers:
- Full CQRS command structure for all domains
Repositories:
- PostgreSQL repositories for all read models
- Bank transaction and ledger repositories
GraphQL:
- Input types, scalars, and types for all entities
- Mutations and queries
Infrastructure:
- Banking integration (Enable Banking client)
- File storage, Invoicing, Reporting, SAF-T export
- Database migrations (003-029)
Tests:
- Integration tests for GraphQL endpoints
- Domain tests
- Invoicing and reporting tests
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 22:19:42 +01:00
|
|
|
new(REP, "Repræsentation", "Entertainment", 0.25m),
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public record VatCodeInfo(string Code, string NameDanish, string NameEnglish, decimal Rate);
|