thrownewDomainException("INVOICE_NOT_FOUND","Invoice does not exist","Faktura findes ikke");
if(!_status.CanModify())
thrownewDomainException("INVOICE_NOT_MODIFIABLE",$"Cannot modify invoice in status {_status}",$"Kan ikke ændre faktura med status {_status}");
if(!_lines.Any(l=>l.LineNumber==lineNumber))
thrownewDomainException("LINE_NOT_FOUND",$"Line {lineNumber} not found",$"Linje {lineNumber} findes ikke");
Emit(newInvoiceLineUpdatedEvent(
lineNumber,
description.Trim(),
quantity,
unit,
unitPrice,
discountPercent,
vatCode,
accountId));
}
publicvoidRemoveLine(intlineNumber)
{
if(!_isCreated)
thrownewDomainException("INVOICE_NOT_FOUND","Invoice does not exist","Faktura findes ikke");
if(!_status.CanModify())
thrownewDomainException("INVOICE_NOT_MODIFIABLE",$"Cannot modify invoice in status {_status}",$"Kan ikke ændre faktura med status {_status}");
if(!_lines.Any(l=>l.LineNumber==lineNumber))
thrownewDomainException("LINE_NOT_FOUND",$"Line {lineNumber} not found",$"Linje {lineNumber} findes ikke");
Emit(newInvoiceLineRemovedEvent(lineNumber));
}
publicvoidSend(
stringledgerTransactionId,
stringsentBy)
{
if(!_isCreated)
thrownewDomainException("INVOICE_NOT_FOUND","Invoice does not exist","Faktura findes ikke");
if(!_status.CanSend())
thrownewDomainException("INVOICE_NOT_SENDABLE",$"Cannot send invoice in status {_status}",$"Kan ikke sende faktura med status {_status}");
if(_lines.Count==0)
thrownewDomainException("NO_LINES","Invoice must have at least one line","Faktura skal have mindst én linje");
varamountExVat=_lines.Sum(l=>l.AmountExVat);
varamountVat=_lines.Sum(l=>l.AmountVat);
varamountTotal=_lines.Sum(l=>l.AmountTotal);
Emit(newInvoiceSentEvent(
ledgerTransactionId,
amountExVat,
amountVat,
amountTotal,
sentBy,
DateTimeOffset.UtcNow));
}
publicvoidReceivePayment(
decimalamount,
string?bankTransactionId,
string?ledgerTransactionId,
string?paymentReference,
DateOnlypaymentDate,
stringrecordedBy)
{
if(!_isCreated)
thrownewDomainException("INVOICE_NOT_FOUND","Invoice does not exist","Faktura findes ikke");
if(!_status.CanReceivePayment())
thrownewDomainException("CANNOT_RECEIVE_PAYMENT",$"Cannot receive payment for invoice in status {_status}",$"Kan ikke modtage betaling for faktura med status {_status}");
if(amount<=0)
thrownewDomainException("INVALID_AMOUNT","Payment amount must be positive","Betalingsbeløb skal være positivt");
thrownewDomainException("COMPANY_REQUIRED","Company ID is required","Virksomheds-ID er påkrævet");
if(string.IsNullOrWhiteSpace(customerId))
thrownewDomainException("CUSTOMER_REQUIRED","Customer ID is required","Kunde-ID er påkrævet");
if(string.IsNullOrWhiteSpace(creditNoteNumber))
thrownewDomainException("CREDIT_NOTE_NUMBER_REQUIRED","Credit note number is required","Kreditnotanummer er påkrævet");
// Credit notes typically have no due date - set to same as issue date
Emit(newInvoiceCreatedEvent(
companyId,
fiscalYearId,
customerId,
customerName,
customerNumber,
creditNoteNumber,
creditNoteDate,
creditNoteDate,// Due date = issue date for credit notes
0,// No payment terms for credit notes
currency,
vatCode,
notes,
reference,
createdBy,
InvoiceType.CreditNote,
originalInvoiceId,
originalInvoiceNumber,
creditReason));
}
/// <summary>
/// Issue the credit note (post to ledger).
/// This is the credit note equivalent of Send() for invoices.
/// </summary>
publicvoidIssue(
stringledgerTransactionId,
stringissuedBy)
{
if(!_isCreated)
thrownewDomainException("CREDIT_NOTE_NOT_FOUND","Credit note does not exist","Kreditnota findes ikke");
if(_type!=InvoiceType.CreditNote)
thrownewDomainException("NOT_CREDIT_NOTE","This operation is only valid for credit notes","Denne handling er kun gyldig for kreditnotaer");
if(!_status.CanIssue())
thrownewDomainException("CREDIT_NOTE_NOT_ISSUABLE",$"Cannot issue credit note in status {_status}",$"Kan ikke udstede kreditnota med status {_status}");
if(_lines.Count==0)
thrownewDomainException("NO_LINES","Credit note must have at least one line","Kreditnota skal have mindst én linje");
// Credit note amounts are stored as negative (opposite of invoice)
varamountExVat=-_lines.Sum(l=>l.AmountExVat);
varamountVat=-_lines.Sum(l=>l.AmountVat);
varamountTotal=-_lines.Sum(l=>l.AmountTotal);
// We reuse InvoiceSentEvent but the status will be set to Issued
Emit(newInvoiceSentEvent(
ledgerTransactionId,
amountExVat,
amountVat,
amountTotal,
issuedBy,
DateTimeOffset.UtcNow));
}
/// <summary>
/// Apply this credit note to an invoice.
/// </summary>
publicvoidApplyCredit(
stringtargetInvoiceId,
stringtargetInvoiceNumber,
decimalamount,
DateOnlyappliedDate,
stringappliedBy,
string?ledgerTransactionId=null)
{
if(!_isCreated)
thrownewDomainException("CREDIT_NOTE_NOT_FOUND","Credit note does not exist","Kreditnota findes ikke");
if(_type!=InvoiceType.CreditNote)
thrownewDomainException("NOT_CREDIT_NOTE","This operation is only valid for credit notes","Denne handling er kun gyldig for kreditnotaer");
if(!_status.CanApplyCredit())
thrownewDomainException("CANNOT_APPLY_CREDIT",$"Cannot apply credit note in status {_status}",$"Kan ikke anvende kreditnota med status {_status}");
if(amount<=0)
thrownewDomainException("INVALID_AMOUNT","Credit amount must be positive","Kreditbeløb skal være positivt");