books/backend/Books.Api/AiBookkeeper/IAiBookkeeperClient.cs

247 lines
6.5 KiB
C#
Raw Normal View History

using System.Text.Json.Serialization;
namespace Books.Api.AiBookkeeper;
/// <summary>
/// Client for the AI Bookkeeper service that analyzes documents
/// and suggests bookkeeping entries.
/// </summary>
public interface IAiBookkeeperClient
{
/// <summary>
/// Process a document (invoice, receipt, etc.) and get AI-suggested bookkeeping.
/// </summary>
/// <param name="document">The document file stream</param>
/// <param name="fileName">Original filename</param>
/// <param name="contentType">MIME type of the document</param>
/// <param name="chartOfAccounts">Chart of accounts data</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>AI extraction and suggested bookkeeping</returns>
Task<AiBookkeeperResponse> ProcessDocumentAsync(
Stream document,
string fileName,
string contentType,
ChartOfAccountsDto chartOfAccounts,
CancellationToken cancellationToken = default);
}
/// <summary>
/// Response from AI Bookkeeper document processing.
/// </summary>
public class AiBookkeeperResponse
{
/// <summary>
/// Whether the document was successfully analyzed.
/// </summary>
public bool Success { get; set; }
/// <summary>
/// Error message if processing failed.
/// </summary>
public string? ErrorMessage { get; set; }
/// <summary>
/// Extracted document information.
/// </summary>
public DocumentExtraction? Extraction { get; set; }
/// <summary>
/// Suggested bookkeeping entry.
/// </summary>
public BookkeepingSuggestion? Suggestion { get; set; }
}
/// <summary>
/// Extracted information from the document.
/// </summary>
public class DocumentExtraction
{
/// <summary>
/// Detected document type (invoice, receipt, credit_note, etc.)
/// </summary>
[JsonPropertyName("documentType")]
public string? DocumentType { get; set; }
/// <summary>
/// Vendor/supplier name.
/// </summary>
[JsonPropertyName("vendor")]
public string? Vendor { get; set; }
/// <summary>
/// Vendor CVR number (Danish company registration).
/// </summary>
[JsonPropertyName("vendorCvr")]
public string? VendorCvr { get; set; }
/// <summary>
/// Invoice/receipt number.
/// </summary>
[JsonPropertyName("invoiceNumber")]
public string? InvoiceNumber { get; set; }
/// <summary>
/// Document date.
/// </summary>
[JsonPropertyName("date")]
public DateOnly? Date { get; set; }
/// <summary>
/// Due date (for invoices).
/// </summary>
[JsonPropertyName("dueDate")]
public DateOnly? DueDate { get; set; }
/// <summary>
/// Total amount including VAT.
/// </summary>
[JsonPropertyName("totalAmount")]
public decimal? TotalAmount { get; set; }
/// <summary>
/// Amount excluding VAT.
/// </summary>
[JsonPropertyName("amountExVat")]
public decimal? AmountExVat { get; set; }
/// <summary>
/// VAT amount.
/// </summary>
[JsonPropertyName("vatAmount")]
public decimal? VatAmount { get; set; }
/// <summary>
/// Currency code (default DKK).
/// </summary>
[JsonPropertyName("currency")]
public string Currency { get; set; } = "DKK";
/// <summary>
/// Extracted line items.
/// </summary>
[JsonPropertyName("lineItems")]
public List<ExtractedLineItem> LineItems { get; set; } = [];
/// <summary>
/// Payment reference (FIK, girocard number, etc.)
/// </summary>
[JsonPropertyName("paymentReference")]
public string? PaymentReference { get; set; }
/// <summary>
/// Raw text extracted from the document.
/// </summary>
[JsonPropertyName("rawText")]
public string? RawText { get; set; }
}
/// <summary>
/// Extracted line item from invoice/receipt.
/// </summary>
public class ExtractedLineItem
{
[JsonPropertyName("description")]
public string? Description { get; set; }
[JsonPropertyName("quantity")]
public decimal? Quantity { get; set; }
[JsonPropertyName("unitPrice")]
public decimal? UnitPrice { get; set; }
[JsonPropertyName("amount")]
public decimal? Amount { get; set; }
[JsonPropertyName("vatRate")]
public decimal? VatRate { get; set; }
}
/// <summary>
/// AI-suggested bookkeeping entry.
/// </summary>
public class BookkeepingSuggestion
{
/// <summary>
/// Suggested description for the journal entry.
/// </summary>
public string? Description { get; set; }
/// <summary>
/// Suggested account lines.
/// </summary>
public List<SuggestedLine> Lines { get; set; } = [];
/// <summary>
/// Overall confidence in the suggestion (0.0 - 1.0).
/// </summary>
public decimal Confidence { get; set; }
}
/// <summary>
/// A suggested bookkeeping line with standard account number.
/// </summary>
public class SuggestedLine
{
/// <summary>
/// Standard account number from Erhvervsstyrelsen.
/// </summary>
public string? StandardAccountNumber { get; set; }
/// <summary>
/// Suggested account name/description.
/// </summary>
public string? AccountName { get; set; }
/// <summary>
/// Debit amount.
/// </summary>
public decimal DebitAmount { get; set; }
/// <summary>
/// Credit amount.
/// </summary>
public decimal CreditAmount { get; set; }
/// <summary>
/// VAT code (I25, U25, etc.)
/// </summary>
public string? VatCode { get; set; }
/// <summary>
/// Confidence in this specific line (0.0 - 1.0).
/// </summary>
public decimal Confidence { get; set; }
}
/// <summary>
/// AI service's single account suggestion.
/// The AI analyzes the document and suggests the most appropriate expense account.
/// </summary>
public class AiAccountSuggestion
{
/// <summary>
/// Company account number suggested by AI (e.g., "6080" for parking).
/// </summary>
public required string AccountNumber { get; init; }
/// <summary>
/// Account name (e.g., "Parkering (gulplade)").
/// </summary>
public required string AccountName { get; init; }
/// <summary>
/// VAT code for this account (e.g., "I25" for 25% input VAT).
/// </summary>
public string? VatCode { get; init; }
/// <summary>
/// Confidence in the suggestion (0.0 - 1.0).
/// </summary>
public decimal Confidence { get; init; }
/// <summary>
/// AI's reasoning for why this account was chosen.
/// </summary>
public string? Reasoning { get; init; }
}