feat(invoice): add e-invoice support with XRechnung/ZUGFeRD and advanced export features
This commit is contained in:
351
ts/skr.invoice.entity.ts
Normal file
351
ts/skr.invoice.entity.ts
Normal file
@@ -0,0 +1,351 @@
|
||||
import type { TSKRType } from './skr.types.js';
|
||||
|
||||
/**
|
||||
* Invoice direction
|
||||
*/
|
||||
export type TInvoiceDirection = 'inbound' | 'outbound';
|
||||
|
||||
/**
|
||||
* Supported e-invoice formats
|
||||
*/
|
||||
export type TInvoiceFormat = 'xrechnung' | 'zugferd' | 'facturx' | 'peppol' | 'ubl';
|
||||
|
||||
/**
|
||||
* Invoice status in the system
|
||||
*/
|
||||
export type TInvoiceStatus = 'draft' | 'validated' | 'posted' | 'partially_paid' | 'paid' | 'cancelled' | 'error';
|
||||
|
||||
/**
|
||||
* Tax scenario classification
|
||||
*/
|
||||
export type TTaxScenario =
|
||||
| 'domestic_taxed' // Standard domestic with VAT
|
||||
| 'domestic_exempt' // Domestic tax-exempt
|
||||
| 'reverse_charge' // §13b UStG
|
||||
| 'intra_eu_supply' // Intra-EU supply
|
||||
| 'intra_eu_acquisition' // Intra-EU acquisition
|
||||
| 'export' // Export outside EU
|
||||
| 'small_business'; // §19 UStG small business
|
||||
|
||||
/**
|
||||
* VAT rate categories
|
||||
*/
|
||||
export interface IVATCategory {
|
||||
code: string; // S (Standard), Z (Zero), E (Exempt), AE (Reverse charge), etc.
|
||||
rate: number; // Tax rate percentage
|
||||
exemptionReason?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Party information (supplier/customer)
|
||||
*/
|
||||
export interface IInvoiceParty {
|
||||
id: string;
|
||||
name: string;
|
||||
address: {
|
||||
street?: string;
|
||||
city?: string;
|
||||
postalCode?: string;
|
||||
countryCode: string;
|
||||
};
|
||||
vatId?: string;
|
||||
taxId?: string;
|
||||
email?: string;
|
||||
phone?: string;
|
||||
bankAccount?: {
|
||||
iban: string;
|
||||
bic?: string;
|
||||
accountHolder?: string;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoice line item
|
||||
*/
|
||||
export interface IInvoiceLine {
|
||||
lineNumber: number;
|
||||
description: string;
|
||||
quantity: number;
|
||||
unitPrice: number;
|
||||
netAmount: number;
|
||||
vatCategory: IVATCategory;
|
||||
vatAmount: number;
|
||||
grossAmount: number;
|
||||
accountNumber?: string; // SKR account for booking
|
||||
costCenter?: string;
|
||||
productCode?: string;
|
||||
allowances?: IAllowanceCharge[];
|
||||
charges?: IAllowanceCharge[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Allowance or charge
|
||||
*/
|
||||
export interface IAllowanceCharge {
|
||||
reason: string;
|
||||
amount: number;
|
||||
percentage?: number;
|
||||
vatCategory?: IVATCategory;
|
||||
vatAmount?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Payment terms
|
||||
*/
|
||||
export interface IPaymentTerms {
|
||||
dueDate: Date;
|
||||
paymentTermsNote?: string;
|
||||
skonto?: {
|
||||
percentage: number;
|
||||
days: number;
|
||||
baseAmount: number;
|
||||
}[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validation result
|
||||
*/
|
||||
export interface IValidationResult {
|
||||
isValid: boolean;
|
||||
syntax: {
|
||||
valid: boolean;
|
||||
errors: string[];
|
||||
warnings: string[];
|
||||
};
|
||||
semantic: {
|
||||
valid: boolean;
|
||||
errors: string[];
|
||||
warnings: string[];
|
||||
};
|
||||
businessRules: {
|
||||
valid: boolean;
|
||||
errors: string[];
|
||||
warnings: string[];
|
||||
};
|
||||
countrySpecific?: {
|
||||
valid: boolean;
|
||||
errors: string[];
|
||||
warnings: string[];
|
||||
};
|
||||
validatedAt: Date;
|
||||
validatorVersion: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Booking information
|
||||
*/
|
||||
export interface IBookingInfo {
|
||||
journalEntryId: string;
|
||||
transactionIds: string[];
|
||||
bookedAt: Date;
|
||||
bookedBy: string;
|
||||
bookingRules: {
|
||||
vendorAccount?: string;
|
||||
customerAccount?: string;
|
||||
expenseAccounts?: string[];
|
||||
revenueAccounts?: string[];
|
||||
vatAccounts?: string[];
|
||||
};
|
||||
confidence: number; // 0-100
|
||||
autoBooked: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Payment information
|
||||
*/
|
||||
export interface IPaymentInfo {
|
||||
paymentId: string;
|
||||
paymentDate: Date;
|
||||
amount: number;
|
||||
currency: string;
|
||||
bankTransactionId?: string;
|
||||
endToEndId?: string;
|
||||
remittanceInfo?: string;
|
||||
skontoTaken?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main invoice entity
|
||||
*/
|
||||
export interface IInvoice {
|
||||
// Identity
|
||||
id: string;
|
||||
direction: TInvoiceDirection;
|
||||
format: TInvoiceFormat;
|
||||
|
||||
// EN16931 Business Terms
|
||||
invoiceNumber: string; // BT-1
|
||||
issueDate: Date; // BT-2
|
||||
invoiceTypeCode?: string; // BT-3 (380=Invoice, 381=Credit note)
|
||||
currencyCode: string; // BT-5
|
||||
taxCurrencyCode?: string; // BT-6
|
||||
taxPointDate?: Date; // BT-7 (Leistungsdatum)
|
||||
paymentDueDate?: Date; // BT-9
|
||||
buyerReference?: string; // BT-10
|
||||
projectReference?: string; // BT-11
|
||||
contractReference?: string; // BT-12
|
||||
orderReference?: string; // BT-13
|
||||
sellerOrderReference?: string; // BT-14
|
||||
|
||||
// Parties
|
||||
supplier: IInvoiceParty;
|
||||
customer: IInvoiceParty;
|
||||
payee?: IInvoiceParty; // If different from supplier
|
||||
|
||||
// Line items
|
||||
lines: IInvoiceLine[];
|
||||
|
||||
// Document level allowances/charges
|
||||
allowances?: IAllowanceCharge[];
|
||||
charges?: IAllowanceCharge[];
|
||||
|
||||
// Amounts
|
||||
lineNetAmount: number; // Sum of line net amounts
|
||||
allowanceTotalAmount?: number;
|
||||
chargeTotalAmount?: number;
|
||||
taxExclusiveAmount: number; // BT-109
|
||||
taxInclusiveAmount: number; // BT-112
|
||||
prepaidAmount?: number; // BT-113
|
||||
payableAmount: number; // BT-115
|
||||
|
||||
// VAT breakdown
|
||||
vatBreakdown: {
|
||||
vatCategory: IVATCategory;
|
||||
taxableAmount: number; // BT-116
|
||||
taxAmount: number; // BT-117
|
||||
}[];
|
||||
totalVATAmount: number; // BT-110
|
||||
|
||||
// Payment
|
||||
paymentTerms?: IPaymentTerms;
|
||||
paymentMeans?: {
|
||||
code: string; // 30=Bank transfer, 48=Card, etc.
|
||||
account?: IInvoiceParty['bankAccount'];
|
||||
};
|
||||
payments?: IPaymentInfo[];
|
||||
|
||||
// Notes
|
||||
invoiceNote?: string; // BT-22
|
||||
|
||||
// Processing metadata
|
||||
status: TInvoiceStatus;
|
||||
taxScenario?: TTaxScenario;
|
||||
skrType?: TSKRType;
|
||||
|
||||
// Storage
|
||||
contentHash: string; // SHA-256 of normalized XML
|
||||
xmlContent?: string;
|
||||
pdfHash?: string;
|
||||
pdfContent?: Buffer;
|
||||
|
||||
// Validation
|
||||
validationResult?: IValidationResult;
|
||||
|
||||
// Booking
|
||||
bookingInfo?: IBookingInfo;
|
||||
|
||||
// Audit trail
|
||||
createdAt: Date;
|
||||
createdBy: string;
|
||||
modifiedAt?: Date;
|
||||
modifiedBy?: string;
|
||||
|
||||
// Additional metadata
|
||||
metadata?: {
|
||||
importSource?: string;
|
||||
importedAt?: Date;
|
||||
parserVersion?: string;
|
||||
originalFilename?: string;
|
||||
originalFormat?: string;
|
||||
[key: string]: any;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoice import options
|
||||
*/
|
||||
export interface IInvoiceImportOptions {
|
||||
autoBook?: boolean;
|
||||
confidenceThreshold?: number;
|
||||
validateOnly?: boolean;
|
||||
skipDuplicateCheck?: boolean;
|
||||
bookingRules?: {
|
||||
vendorDefaults?: Record<string, string>;
|
||||
customerDefaults?: Record<string, string>;
|
||||
productCategoryMapping?: Record<string, string>;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoice export options
|
||||
*/
|
||||
export interface IInvoiceExportOptions {
|
||||
format: TInvoiceFormat;
|
||||
embedInPdf?: boolean;
|
||||
sign?: boolean;
|
||||
validate?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoice search filter
|
||||
*/
|
||||
export interface IInvoiceFilter {
|
||||
direction?: TInvoiceDirection;
|
||||
status?: TInvoiceStatus;
|
||||
format?: TInvoiceFormat;
|
||||
dateFrom?: Date;
|
||||
dateTo?: Date;
|
||||
supplierId?: string;
|
||||
customerId?: string;
|
||||
minAmount?: number;
|
||||
maxAmount?: number;
|
||||
invoiceNumber?: string;
|
||||
reference?: string;
|
||||
isPaid?: boolean;
|
||||
isOverdue?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicate check result
|
||||
*/
|
||||
export interface IDuplicateCheckResult {
|
||||
isDuplicate: boolean;
|
||||
matchedInvoiceId?: string;
|
||||
matchedContentHash?: string;
|
||||
matchedFields?: string[];
|
||||
confidence: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Booking rules configuration
|
||||
*/
|
||||
export interface IBookingRules {
|
||||
skrType: TSKRType;
|
||||
|
||||
// Control accounts
|
||||
vendorControlAccount: string;
|
||||
customerControlAccount: string;
|
||||
|
||||
// VAT accounts
|
||||
vatAccounts: {
|
||||
inputVAT19: string;
|
||||
inputVAT7: string;
|
||||
outputVAT19: string;
|
||||
outputVAT7: string;
|
||||
reverseChargeVAT: string;
|
||||
};
|
||||
|
||||
// Default accounts
|
||||
defaultExpenseAccount: string;
|
||||
defaultRevenueAccount: string;
|
||||
|
||||
// Mappings
|
||||
productCategoryMapping?: Record<string, string>;
|
||||
vendorMapping?: Record<string, string>;
|
||||
customerMapping?: Record<string, string>;
|
||||
|
||||
// Skonto
|
||||
skontoMethod?: 'net' | 'gross';
|
||||
skontoExpenseAccount?: string;
|
||||
skontoRevenueAccount?: string;
|
||||
}
|
Reference in New Issue
Block a user