UNPKG

@invoiceddd/domain

Version:

Domain layer for the InvoiceDDD system - business logic, entities, and domain services

1,174 lines (1,156 loc) 68.1 kB
import * as effect_ParseResult from 'effect/ParseResult'; import * as effect_Cause from 'effect/Cause'; import * as effect_Types from 'effect/Types'; import { Schema, Effect, Context, Layer } from 'effect'; import * as effect_Effect from 'effect/Effect'; declare const CurrencySchema_base: Schema.TaggedClass<CurrencySchema, "CurrencySchema", { readonly _tag: Schema.tag<"CurrencySchema">; } & { code: Schema.Literal<["EUR"]>; symbol: Schema.Literal<["€"]>; }>; /** * Currency schema. * The business model currently supports EUR only. */ declare class CurrencySchema extends CurrencySchema_base { static euro: CurrencySchema; static quick(code: typeof CurrencySchema.fields.code.Type, symbol: typeof CurrencySchema.fields.symbol.Type): CurrencySchema; } type Currency = typeof CurrencySchema.Type; declare const InvalidMoneyCurrencies_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "InvalidMoneyCurrencies"; } & Readonly<A>; declare class InvalidMoneyCurrencies extends InvalidMoneyCurrencies_base<{ readonly given: Currency; readonly other: Currency; readonly message?: string; }> { } declare const MoneySchema_base: Schema.TaggedClass<MoneySchema, "Money", { readonly _tag: Schema.tag<"Money">; } & { currency: typeof CurrencySchema; amount: Schema.filter<Schema.filter<typeof Schema.Number>>; }>; /** * Money represents an amount of money in a given currency */ declare class MoneySchema extends MoneySchema_base { /** * Creates a new MoneySchema instance representing an amount in euros. * @param amount The amount in euros. * @returns A new MoneySchema instance. */ static EURO(amount: number): MoneySchema; static fromNumeric(amount: number, currency: CurrencySchema): MoneySchema; add(other: MoneySchema): MoneySchema; addMultiple(...others: MoneySchema[]): MoneySchema; addNumeric(amount: number): MoneySchema; subtract(other: MoneySchema): MoneySchema; subtractNumeric(amount: number): MoneySchema; multiply(factor: number): MoneySchema; /** * Divides the current amount by the given divisor. * * **NOTE**: because it's money, it ALWAYS rounds to two decimals! * @param divisor The divisor to divide the current amount * @returns */ divide(divisor: number): MoneySchema; roundTwoDecimals(): MoneySchema; isLess(than: MoneySchema, orEqual?: "orEqual" | undefined): boolean; isLessNumeric(than: number, orEqual?: "orEqual" | undefined): boolean; isMore(than: MoneySchema, orEqual?: "orEqual" | undefined): boolean; isMoreNumeric(than: number, orEqual?: "orEqual" | undefined): boolean; private assertSameCurrency; private roundTwoDecimalsRaw; } type Money = typeof MoneySchema.Type; /** * Pure domain logic for financial calculations (no external dependencies) * This belongs in the value object as it's pure business logic */ /** * Calculates the grand total based on it's smaller parts. * * @param subtotal * @param taxes * @param shippingCost * @param discount * @returns A {@link Money} object with the grand total and the currency of the parts. */ declare function calculateGrandTotal(subtotal: Money, taxes: Money, shippingCost: Money, discount: Money): Money; /** * Pure domain validation logic (no external dependencies) */ declare function validateGrandTotalCalculation(financials: { subtotal: Money; taxes: Money; shippingCost: Money; discount: Money; grandTotal: Money; }): boolean; /** * The schema for InvoiceFinancials with validation rules including grandTotal calculation validation. * * Note: This uses pure domain logic functions, not domain services, as it's part of * the value object's invariant validation. */ declare const InvoiceFinancialsSchema: Schema.filter<Schema.Struct<{ subtotal: typeof MoneySchema; discount: typeof MoneySchema; taxes: typeof MoneySchema; shippingCost: typeof MoneySchema; grandTotal: typeof MoneySchema; }>>; /** * Type derived from the schema */ type InvoiceFinancials = Schema.Schema.Type<typeof InvoiceFinancialsSchema>; /** * Factory function to create and validate InvoiceFinancials */ declare const createInvoiceFinancials: (data: unknown) => typeof InvoiceFinancialsSchema.Type; /** * Validation function that returns an Effect */ declare const validateInvoiceFinancials: (data: unknown) => effect_Effect.Effect<{ readonly subtotal: MoneySchema; readonly discount: MoneySchema; readonly taxes: MoneySchema; readonly shippingCost: MoneySchema; readonly grandTotal: MoneySchema; }, effect_ParseResult.ParseError, never>; /** * Factory function to create InvoiceFinancials with automatic grand total calculation * This uses pure domain logic, not domain services */ declare const createInvoiceFinancialsWithCalculation: (data: { subtotal: Money; taxes: Money; shippingCost: Money; discount: Money; }) => Schema.Schema.Encoded<typeof InvoiceFinancialsSchema>; interface ShippingPolicySchema { readonly isFreeShippingEligible: (financials: InvoiceFinancials) => Effect.Effect<boolean, never>; } declare const ShippingPolicy_base: Context.TagClass<ShippingPolicy, "ShippingPolicy", ShippingPolicySchema>; declare class ShippingPolicy extends ShippingPolicy_base { } declare const FinancialValidationError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "FinancialValidationError"; } & Readonly<A>; declare class FinancialValidationError extends FinancialValidationError_base<{ readonly violations: string[]; readonly message: string; }> { } declare const FinancialCalculationService_base: Context.TagClass<FinancialCalculationService, "FinancialCalculationService", { /** * Calculates the grand total according to business rules. * Delegates to pure domain logic in value objects. */ calculateGrandTotal(subtotal: Money, taxes: Money, shippingCost: Money, discount: Money): Money; /** * Validates that a discount amount doesn't exceed the maximum allowable discount. * Business rule: discount cannot exceed subtotal + taxes + shippingCost */ validateDiscountLimit(financials: { subtotal: Money; taxes: Money; shippingCost: Money; discount: Money; }): boolean; /** * Validates that the grand total calculation is correct according to business rules. * Delegates to pure domain logic in value objects. */ validateGrandTotalCalculation(financials: { subtotal: Money; taxes: Money; shippingCost: Money; discount: Money; grandTotal: Money; }): boolean; /** * Complex business rule: Validates financial consistency across an entire invoice. * This is a higher-level operation that coordinates multiple validations. */ validateInvoiceFinancialConsistency(financials: { subtotal: Money; taxes: Money; shippingCost: Money; discount: Money; grandTotal: Money; }, shippingPolicy: ShippingPolicySchema): Effect.Effect<{ isValid: boolean; }, FinancialValidationError>; }>; /** * Domain Service for financial calculations and business rule validation. * * This service encapsulates complex business rules that don't naturally belong * to a single entity or value object. It coordinates between multiple domain objects * and provides higher-level financial operations. * * In DDD, this service should be called by: * - Aggregate Roots (Invoice, Order) * - Application Services (when orchestrating domain operations) * - Other Domain Services (for complex domain operations) */ declare class FinancialCalculationService extends FinancialCalculationService_base { } /** * Default implementation of the FinancialCalculationService */ declare const FinancialCalculationServiceLive: Layer.Layer<FinancialCalculationService, never, never>; /** * Invoice configuration for domain services */ interface InvoiceConfig { readonly prefix?: string | undefined; } /** * Sanitizes invoice prefix to ensure it contains only alphanumeric characters and hyphens, * and is no longer than 10 characters */ declare const sanitizeInvoicePrefix: (prefix: string) => string; /** * Base interface for all domain errors in the invoice system. * * Domain errors represent business rule violations or domain-specific failures. * They are distinct from technical errors (network, database) and should be * meaningful to business stakeholders. */ interface BaseDomainErrorData { readonly cause?: unknown; readonly message: string; readonly timestamp?: Date; readonly context?: Record<string, unknown>; } /** * Generic validation error data */ interface ValidationErrorData extends BaseDomainErrorData { readonly field?: string; readonly value?: unknown; readonly violations?: string[]; } /** * Business rule violation error data */ interface BusinessRuleViolationErrorData extends BaseDomainErrorData { readonly rule: string; readonly violatedConstraint: string; } /** * Resource error data */ interface ResourceErrorData extends BaseDomainErrorData { readonly resourceType: string; readonly resourceId: string; readonly operation: string; } declare const ValidationError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/ValidationError"; } & Readonly<A>; /** * General validation error for schema or data validation failures */ declare class ValidationError extends ValidationError_base<ValidationErrorData> { } declare const MissingDataError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/MissingDataError"; } & Readonly<A>; /** * Error thrown when required data is missing */ declare class MissingDataError extends MissingDataError_base<ValidationErrorData & { readonly missingFields: string[]; }> { } declare const InvalidFormatError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/InvalidFormatError"; } & Readonly<A>; /** * Error thrown when data format is invalid */ declare class InvalidFormatError extends InvalidFormatError_base<ValidationErrorData & { readonly expectedFormat: string; readonly actualFormat: string; }> { } declare const OutOfRangeError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/OutOfRangeError"; } & Readonly<A>; /** * Error thrown when data is outside acceptable range */ declare class OutOfRangeError extends OutOfRangeError_base<ValidationErrorData & { readonly minValue?: number; readonly maxValue?: number; readonly actualValue: number; }> { } declare const InvalidLengthError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/InvalidLengthError"; } & Readonly<A>; /** * Error thrown when string length constraints are violated */ declare class InvalidLengthError extends InvalidLengthError_base<ValidationErrorData & { readonly minLength?: number; readonly maxLength?: number; readonly actualLength: number; }> { } declare const InvalidEnumValueError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/InvalidEnumValueError"; } & Readonly<A>; /** * Error thrown when enum value is not recognized */ declare class InvalidEnumValueError extends InvalidEnumValueError_base<ValidationErrorData & { readonly allowedValues: string[]; readonly providedValue: string; }> { } declare const SchemaValidationError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/SchemaValidationError"; } & Readonly<A>; /** * Error thrown when schema validation fails */ declare class SchemaValidationError extends SchemaValidationError_base<ValidationErrorData & { readonly schemaName: string; readonly validationErrors: string[]; }> { } declare const BusinessRuleViolationError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/BusinessRuleViolationError"; } & Readonly<A>; /** * General business rule violation error */ declare class BusinessRuleViolationError extends BusinessRuleViolationError_base<BusinessRuleViolationErrorData> { } declare const ImmutabilityViolationError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/ImmutabilityViolationError"; } & Readonly<A>; /** * Error thrown when an operation would violate immutability constraints */ declare class ImmutabilityViolationError extends ImmutabilityViolationError_base<BusinessRuleViolationErrorData & { readonly entityType: string; readonly entityId: string; readonly attemptedOperation: string; }> { } declare const UniquenessViolationError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/UniquenessViolationError"; } & Readonly<A>; /** * Error thrown when uniqueness constraints are violated */ declare class UniquenessViolationError extends UniquenessViolationError_base<BusinessRuleViolationErrorData & { readonly field: string; readonly value: string; readonly conflictingEntity?: string; }> { } declare const InvalidStateTransitionError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/InvalidStateTransitionError"; } & Readonly<A>; /** * Error thrown when state transition is invalid */ declare class InvalidStateTransitionError extends InvalidStateTransitionError_base<BusinessRuleViolationErrorData & { readonly entityType: string; readonly entityId: string; readonly currentState: string; readonly attemptedState: string; readonly allowedTransitions: string[]; }> { } declare const OperationNotAllowedError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/OperationNotAllowedError"; } & Readonly<A>; /** * Error thrown when operation is not allowed due to business rules */ declare class OperationNotAllowedError extends OperationNotAllowedError_base<BusinessRuleViolationErrorData & { readonly operation: string; readonly reason: string; readonly entityType: string; readonly entityId: string; }> { } declare const FinancialCalculationError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/FinancialCalculationError"; } & Readonly<A>; /** * Error thrown when financial calculations are incorrect */ declare class FinancialCalculationError extends FinancialCalculationError_base<BusinessRuleViolationErrorData & { readonly calculationType: string; readonly expectedValue: number; readonly actualValue: number; readonly tolerance?: number; }> { } declare const CurrencyMismatchError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/CurrencyMismatchError"; } & Readonly<A>; /** * Error thrown when currency operations are invalid */ declare class CurrencyMismatchError extends CurrencyMismatchError_base<BusinessRuleViolationErrorData & { readonly expectedCurrency: string; readonly actualCurrency: string; readonly operation: string; }> { } declare const ResourceError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/ResourceError"; } & Readonly<A>; /** * General resource error */ declare class ResourceError extends ResourceError_base<ResourceErrorData> { } declare const ResourceNotFoundError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/ResourceNotFoundError"; } & Readonly<A>; /** * Error thrown when a required resource is not found */ declare class ResourceNotFoundError extends ResourceNotFoundError_base<ResourceErrorData & { readonly searchCriteria?: Record<string, unknown>; }> { } declare const ResourceAccessDeniedError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/ResourceAccessDeniedError"; } & Readonly<A>; /** * Error thrown when resource access is denied */ declare class ResourceAccessDeniedError extends ResourceAccessDeniedError_base<ResourceErrorData & { readonly requiredPermission: string; readonly userRole?: string; }> { } declare const ResourceInUseError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/ResourceInUseError"; } & Readonly<A>; /** * Error thrown when resource is in use and cannot be modified */ declare class ResourceInUseError extends ResourceInUseError_base<ResourceErrorData & { readonly usedBy: string[]; readonly operation: string; }> { } declare const ResourceLockedError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/ResourceLockedError"; } & Readonly<A>; /** * Error thrown when resource is locked */ declare class ResourceLockedError extends ResourceLockedError_base<ResourceErrorData & { readonly lockedBy: string; readonly lockExpiry?: Date; }> { } declare const ResourceStateError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/ResourceStateError"; } & Readonly<A>; /** * Error thrown when resource is in invalid state for operation */ declare class ResourceStateError extends ResourceStateError_base<ResourceErrorData & { readonly currentState: string; readonly requiredState: string; readonly allowedStates: string[]; }> { } declare const InvoiceNumberConflictError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/InvoiceNumberConflictError"; } & Readonly<A>; /** * Error thrown when invoice number already exists */ declare class InvoiceNumberConflictError extends InvoiceNumberConflictError_base<BaseDomainErrorData & { readonly affectedInvoiceNumber: string; readonly existingInvoiceId?: string; }> { } declare const InvoiceValidationError_base$1: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/InvoiceValidationError"; } & Readonly<A>; /** * Error thrown when invoice validation fails */ declare class InvoiceValidationError$1 extends InvoiceValidationError_base$1<BaseDomainErrorData & { readonly invoiceId?: string; readonly validationErrors: string[]; }> { } declare const InvoiceImmutabilityError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/InvoiceImmutabilityError"; } & Readonly<A>; /** * Error thrown when attempting to modify immutable invoice */ declare class InvoiceImmutabilityError extends InvoiceImmutabilityError_base<BaseDomainErrorData & { readonly invoiceId: string; readonly attemptedOperation: string; }> { } declare const OrderNotFoundError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/OrderNotFoundError"; } & Readonly<A>; /** * Order-specific domain errors */ /** * Error thrown when order is not found */ declare class OrderNotFoundError extends OrderNotFoundError_base<BaseDomainErrorData & { readonly orderId: string; readonly searchCriteria?: Record<string, unknown>; }> { } declare const OrderValidationError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/OrderValidationError"; } & Readonly<A>; /** * Error thrown when order validation fails */ declare class OrderValidationError extends OrderValidationError_base<BaseDomainErrorData & { readonly orderId: string; readonly validationErrors: string[]; }> { } declare const OrderStateError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/OrderStateError"; } & Readonly<A>; /** * Error thrown when order is in invalid state for operation */ declare class OrderStateError extends OrderStateError_base<BaseDomainErrorData & { readonly orderId: string; readonly currentState: string; readonly requiredState: string; readonly operation: string; }> { } declare const StorageError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/StorageError"; } & Readonly<A>; /** * Storage-specific errors */ /** * Error thrown when storage operation fails */ declare class StorageError extends StorageError_base<BaseDomainErrorData & { readonly operation: string; readonly storageLocation?: string; readonly statusCode?: number; readonly retryable: boolean; }> { } declare const StorageUploadError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/StorageUploadError"; } & Readonly<A>; /** * Error thrown when storage upload fails */ declare class StorageUploadError extends StorageUploadError_base<BaseDomainErrorData & { readonly fileName: string; readonly fileSize: number; readonly storageProvider: string; readonly retryAttempt: number; readonly maxRetries: number; }> { } declare const RepositoryError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/RepositoryError"; } & Readonly<A>; /** * Repository and persistence errors */ /** * Error thrown when repository operation fails */ declare class RepositoryError extends RepositoryError_base<BaseDomainErrorData & { readonly repository: string; readonly operation: string; readonly entityType?: string; readonly entityId?: string; }> { } declare const DatabaseConstraintError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/DatabaseConstraintError"; } & Readonly<A>; /** * Error thrown when database constraint is violated */ declare class DatabaseConstraintError extends DatabaseConstraintError_base<BaseDomainErrorData & { readonly constraintName: string; readonly constraintType: "unique" | "foreign_key" | "check" | "not_null"; readonly tableName: string; readonly columnName?: string; }> { } declare const ErrorCategories: { readonly VALIDATION: readonly ["@/ValidationError", "@/MissingDataError", "@/InvalidFormatError", "@/OutOfRangeError", "@/InvalidLengthError", "@/InvalidEnumValueError", "@/SchemaValidationError"]; readonly BUSINESS_RULES: readonly ["@/BusinessRuleViolationError", "@/ImmutabilityViolationError", "@/UniquenessViolationError", "@/InvalidStateTransitionError", "@/OperationNotAllowedError", "@/FinancialCalculationError", "@/CurrencyMismatchError"]; readonly RESOURCES: readonly ["@/ResourceError", "@/ResourceNotFoundError", "@/ResourceAccessDeniedError", "@/ResourceInUseError", "@/ResourceLockedError", "@/ResourceStateError"]; readonly INVOICE: readonly ["@/InvoiceNumberFormatError", "@/InvoiceNumberConflictError", "@/InvoiceValidationError", "@/InvoiceImmutabilityError"]; readonly ORDER: readonly ["@/OrderNotFoundError", "@/OrderValidationError", "@/OrderStateError"]; readonly PDF: readonly ["@/PDFGenerationError", "@/PDFComplianceError"]; readonly STORAGE: readonly ["@/StorageError", "@/StorageUploadError"]; readonly REPOSITORY: readonly ["@/RepositoryError", "@/DatabaseConstraintError"]; }; declare const RetryStrategies: { readonly NON_RETRYABLE: readonly ["@/ValidationError", "@/MissingDataError", "@/InvalidFormatError", "@/OutOfRangeError", "@/InvalidLengthError", "@/InvalidEnumValueError", "@/SchemaValidationError", "@/BusinessRuleViolationError", "@/ImmutabilityViolationError", "@/UniquenessViolationError", "@/InvalidStateTransitionError", "@/OperationNotAllowedError", "@/FinancialCalculationError", "@/CurrencyMismatchError", "@/InvoiceNumberFormatError", "@/InvoiceNumberConflictError", "@/InvoiceValidationError", "@/InvoiceImmutabilityError", "@/OrderNotFoundError", "@/OrderValidationError", "@/OrderStateError"]; readonly RETRYABLE_WITH_BACKOFF: readonly ["@/StorageError", "@/StorageUploadError", "@/RepositoryError", "@/DatabaseConstraintError"]; readonly RETRYABLE_LINEAR: readonly ["@/ResourceError", "@/ResourceNotFoundError", "@/ResourceAccessDeniedError", "@/ResourceInUseError", "@/ResourceLockedError", "@/ResourceStateError"]; readonly CONDITIONAL_RETRY: readonly ["@/PDFGenerationError", "@/PDFComplianceError"]; }; declare const isValidationError: (errorTag: string) => boolean; declare const isBusinessRuleError: (errorTag: string) => boolean; declare const isResourceError: (errorTag: string) => boolean; declare const isRetryableError: (errorTag: string) => boolean; declare const isNonRetryableError: (errorTag: string) => boolean; declare const InvoiceNumberFormatError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/InvoiceNumberFormatError"; } & Readonly<A>; /** * When the invoice format is wrong */ declare class InvoiceNumberFormatError extends InvoiceNumberFormatError_base<{ readonly cause?: unknown; readonly message: string; readonly expected?: string; readonly received?: string; readonly diff?: string; }> { } /** * Domain service for validating invoice number formats according to business rules. * * Has no I/O. Can be (and should only be) used in the Domain. * * Validates: * - Format compliance (INV-1001 or 1221 patterns) */ interface InvoiceNumberFormatValidatorSchema { /** * Validates invoice number format * * @param invoiceNumber - The invoice number to validate * @returns Effect that succeeds if valid, fails with appropriate error if invalid */ readonly validate: (invoiceNumber: string) => Effect.Effect<void, InvoiceNumberFormatError | RepositoryError>; } declare const InvoiceNumberFormatValidator_base: Context.TagClass<InvoiceNumberFormatValidator, "@/InvoiceNumberFormatValidator", InvoiceNumberFormatValidatorSchema>; /** * Context tag for InvoiceNumberFormatValidator service */ declare class InvoiceNumberFormatValidator extends InvoiceNumberFormatValidator_base { } /** * Context tag for InvoiceConfig */ declare const InvoiceConfigTag: Context.Tag<InvoiceConfig, InvoiceConfig>; /** * Implementation of InvoiceNumberFormatValidator service */ declare const InvoiceNumberFormatValidatorLive: Layer.Layer<InvoiceNumberFormatValidator, never, InvoiceConfig>; /** * Schema for CustomerInfo with validation rules */ declare const CustomerInfoSchema: Schema.Struct<{ firstName: Schema.filter<typeof Schema.String>; lastName: Schema.filter<typeof Schema.String>; street: Schema.filter<typeof Schema.String>; zip: Schema.filter<typeof Schema.String>; city: Schema.filter<typeof Schema.String>; country: Schema.filter<typeof Schema.String>; email: Schema.filter<Schema.filter<typeof Schema.String>>; phone: Schema.optional<Schema.filter<typeof Schema.String>>; }>; /** * CustomerInfo value object representing customer data snapshot at invoice creation time. * This ensures immutability and captures customer information as it was when the invoice was created. */ type CustomerInfo = Schema.Schema.Type<typeof CustomerInfoSchema>; /** * Factory function to create and validate CustomerInfo */ declare const createCustomerInfo: (data: unknown) => Schema.Schema.Encoded<typeof CustomerInfoSchema>; /** * Validation function that returns an Effect */ declare const validateCustomerInfo: (data: unknown) => effect_Effect.Effect<{ readonly firstName: string; readonly lastName: string; readonly street: string; readonly zip: string; readonly city: string; readonly country: string; readonly email: string; readonly phone?: string | undefined; }, effect_ParseResult.ParseError, never>; /** * Schema for OrderItem with validation rules including financial validation */ declare const OrderItemSchema: Schema.filter<Schema.Struct<{ unitPrice: typeof MoneySchema; quantity: Schema.filter<Schema.filter<typeof Schema.Number>>; linePrice: typeof MoneySchema; name: Schema.filter<typeof Schema.String>; variant: Schema.optional<Schema.filter<typeof Schema.String>>; productNumber: Schema.optional<Schema.filter<typeof Schema.String>>; }>>; /** * OrderItem value object representing an item in an order with financial validation. * This ensures that linePrice = unitPrice * quantity and captures item data as a snapshot. */ type OrderItem = Schema.Schema.Type<typeof OrderItemSchema>; /** * Factory function to create and validate OrderItem */ declare const createOrderItem: (data: unknown) => Schema.Schema.Encoded<typeof OrderItemSchema>; /** * Validation function that returns an Effect */ declare const validateOrderItem: (data: unknown) => effect_Effect.Effect<{ readonly unitPrice: MoneySchema; readonly quantity: number; readonly linePrice: MoneySchema; readonly name: string; readonly variant?: string | undefined; readonly productNumber?: string | undefined; }, effect_ParseResult.ParseError, never>; /** * Helper function to calculate line price from unit price and quantity */ declare const calculateLinePrice: (unitPrice: Money, quantity: number) => Money; /** * Factory function to create OrderItem with automatic line price calculation */ declare const createOrderItemWithCalculation: (data: { unitPrice: Money; quantity: number; name: string; variant?: string; productNumber?: string; }) => Schema.Schema.Encoded<typeof OrderItemSchema>; declare const InvoiceValidationError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/InvoiceValidationError"; } & Readonly<A>; /** * Domain errors for Invoice operations */ declare class InvoiceValidationError extends InvoiceValidationError_base<{ readonly cause?: unknown; readonly message: string; }> { } /** * Schema for Invoice aggregate root with complete validation */ declare const InvoiceSchema: Schema.filter<Schema.filter<Schema.Struct<{ invoiceId: Schema.filter<Schema.filter<typeof Schema.String>>; orderId: Schema.filter<typeof Schema.String>; invoiceNumber: Schema.filter<typeof Schema.String>; customerSnapshot: Schema.Struct<{ firstName: Schema.filter<typeof Schema.String>; lastName: Schema.filter<typeof Schema.String>; street: Schema.filter<typeof Schema.String>; zip: Schema.filter<typeof Schema.String>; city: Schema.filter<typeof Schema.String>; country: Schema.filter<typeof Schema.String>; email: Schema.filter<Schema.filter<typeof Schema.String>>; phone: Schema.optional<Schema.filter<typeof Schema.String>>; }>; itemsSnapshot: Schema.filter<Schema.Array$<Schema.filter<Schema.Struct<{ unitPrice: typeof MoneySchema; quantity: Schema.filter<Schema.filter<typeof Schema.Number>>; linePrice: typeof MoneySchema; name: Schema.filter<typeof Schema.String>; variant: Schema.optional<Schema.filter<typeof Schema.String>>; productNumber: Schema.optional<Schema.filter<typeof Schema.String>>; }>>>>; financials: Schema.filter<Schema.Struct<{ subtotal: typeof MoneySchema; discount: typeof MoneySchema; taxes: typeof MoneySchema; shippingCost: typeof MoneySchema; grandTotal: typeof MoneySchema; }>>; createdOn: typeof Schema.DateFromSelf; createdBy: Schema.filter<typeof Schema.String>; pdfBytes: Schema.optional<Schema.instanceOf<Uint8Array<ArrayBuffer>>>; }>>>; /** * Invoice aggregate root representing an immutable invoice. * * Key characteristics: * - Immutable after creation (all properties readonly) * - Contains snapshots of customer and order data at creation time * - Enforces all business rules through validation * - Contains PDF bytes for the generated invoice document */ type Invoice = Schema.Schema.Type<typeof InvoiceSchema>; /** * Data required to create an Invoice */ interface CreateInvoiceData { readonly invoiceId: string; readonly orderId: string; readonly invoiceNumber: string; readonly customerSnapshot: CustomerInfo; readonly itemsSnapshot: OrderItem[]; readonly financials: InvoiceFinancials; readonly createdOn: Date; readonly createdBy: string; readonly pdfBytes?: Uint8Array | undefined; } /** * Invoice aggregate root class with factory methods and business operations */ declare class InvoiceAggregate { private readonly _data; private constructor(); /** * Factory method to create a new Invoice aggregate with full validation */ static create(data: CreateInvoiceData): Effect.Effect<InvoiceAggregate, InvoiceValidationError, FinancialCalculationService | ShippingPolicy | InvoiceNumberFormatValidator>; /** * Factory method to reconstruct an Invoice aggregate from validated data * (e.g., when loading from database) */ static fromValidatedData(data: Invoice): InvoiceAggregate; get invoiceId(): string; get orderId(): string; get invoiceNumber(): string; get customerSnapshot(): CustomerInfo; get itemsSnapshot(): readonly OrderItem[]; get financials(): InvoiceFinancials; get createdOn(): Date; get createdBy(): string; get pdfBytes(): Uint8Array | undefined; /** * Get the complete invoice data (for serialization/persistence) */ get data(): Invoice; /** * Business method: Check if invoice belongs to a specific order */ belongsToOrder(orderId: string): boolean; /** * Business method: Check if invoice has a specific invoice number */ hasInvoiceNumber(invoiceNumber: string): boolean; /** * Business method: Check if invoice was created by a specific user */ wasCreatedBy(userId: string): boolean; /** * Business method: Check if invoice was created within a date range */ wasCreatedBetween(startDate: Date, endDate: Date): boolean; /** * Business method: Check if invoice total is within a range */ hasTotalBetween(minTotal: number, maxTotal: number): boolean; /** * Business method: Get invoice age in days */ getAgeInDays(): number; /** * Business method: Check if invoice contains a specific product */ containsProduct(productNumber: string): boolean; /** * Business method: Get total quantity of all items */ getTotalQuantity(): number; /** * Business method: Get customer email for notifications */ getCustomerEmail(): string; /** * Business method: Get formatted invoice display name */ getDisplayName(): string; /** * Equality comparison based on invoice ID */ equals(other: InvoiceAggregate): boolean; /** * String representation for debugging */ toString(): string; } /** * Validation function that returns an Effect */ declare const validateInvoice: (data: unknown) => Effect.Effect<{ readonly invoiceNumber: string; readonly invoiceId: string; readonly orderId: string; readonly customerSnapshot: { readonly firstName: string; readonly lastName: string; readonly street: string; readonly zip: string; readonly city: string; readonly country: string; readonly email: string; readonly phone?: string | undefined; }; readonly itemsSnapshot: readonly { readonly unitPrice: MoneySchema; readonly quantity: number; readonly linePrice: MoneySchema; readonly name: string; readonly variant?: string | undefined; readonly productNumber?: string | undefined; }[]; readonly financials: { readonly subtotal: MoneySchema; readonly discount: MoneySchema; readonly taxes: MoneySchema; readonly shippingCost: MoneySchema; readonly grandTotal: MoneySchema; }; readonly createdOn: Date; readonly createdBy: string; readonly pdfBytes?: Uint8Array<ArrayBuffer> | undefined; }, effect_ParseResult.ParseError, never>; /** * Schema for Order entity with complete validation */ declare const OrderSchema: Schema.filter<Schema.filter<Schema.Struct<{ orderId: Schema.filter<typeof Schema.String>; createdOn: typeof Schema.DateFromSelf; shippingCost: typeof MoneySchema; items: Schema.filter<Schema.Array$<Schema.filter<Schema.Struct<{ unitPrice: typeof MoneySchema; quantity: Schema.filter<Schema.filter<typeof Schema.Number>>; linePrice: typeof MoneySchema; name: Schema.filter<typeof Schema.String>; variant: Schema.optional<Schema.filter<typeof Schema.String>>; productNumber: Schema.optional<Schema.filter<typeof Schema.String>>; }>>>>; customer: Schema.Struct<{ firstName: Schema.filter<typeof Schema.String>; lastName: Schema.filter<typeof Schema.String>; street: Schema.filter<typeof Schema.String>; zip: Schema.filter<typeof Schema.String>; city: Schema.filter<typeof Schema.String>; country: Schema.filter<typeof Schema.String>; email: Schema.filter<Schema.filter<typeof Schema.String>>; phone: Schema.optional<Schema.filter<typeof Schema.String>>; }>; subtotal: typeof MoneySchema; discount: typeof MoneySchema; taxes: typeof MoneySchema; grandTotal: typeof MoneySchema; }>>>; /** * Order entity representing a complete order with customer information and items. * This entity contains all the data needed to create an invoice. */ type Order = Schema.Schema.Type<typeof OrderSchema>; /** * Factory function to create and validate Order */ declare const createOrder: (data: unknown) => Schema.Schema.Encoded<typeof OrderSchema>; /** * Validation function that returns an Effect */ declare const validateOrder: (data: unknown) => effect_Effect.Effect<{ readonly subtotal: MoneySchema; readonly discount: MoneySchema; readonly taxes: MoneySchema; readonly shippingCost: MoneySchema; readonly grandTotal: MoneySchema; readonly orderId: string; readonly createdOn: Date; readonly items: readonly { readonly unitPrice: MoneySchema; readonly quantity: number; readonly linePrice: MoneySchema; readonly name: string; readonly variant?: string | undefined; readonly productNumber?: string | undefined; }[]; readonly customer: { readonly firstName: string; readonly lastName: string; readonly street: string; readonly zip: string; readonly city: string; readonly country: string; readonly email: string; readonly phone?: string | undefined; }; }, effect_ParseResult.ParseError, never>; /** * Helper function to calculate subtotal from order items */ declare const calculateSubtotal: (items: OrderItem[]) => Money; /** * Factory function to create Order with automatic calculations. * * The following values are automatically calculated: * - subtotal * - grand total */ declare const createOrderWithCalculations: (data: { orderId: string; createdOn: Date; shippingCost: Money; items: OrderItem[]; customer: CustomerInfo; taxes: Money; discount: Money; }) => Schema.Schema.Encoded<typeof OrderSchema>; declare const PDFGenerationError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/PDFGenerationError"; } & Readonly<A>; /** * Domain errors for PDF rendering operations */ declare class PDFGenerationError extends PDFGenerationError_base<{ readonly cause?: unknown; readonly message: string; readonly invoiceId?: string; readonly invoiceNumber?: string; }> { } declare const PDFComplianceError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/PDFComplianceError"; } & Readonly<A>; declare class PDFComplianceError extends PDFComplianceError_base<{ readonly cause?: unknown; readonly message: string; readonly complianceIssue: string; }> { } /** * German legal information required for invoice PDFs */ declare const GermanLegalInfoSchema: Schema.Struct<{ companyName: Schema.filter<typeof Schema.String>; companyAddress: Schema.Struct<{ street: Schema.filter<typeof Schema.String>; zip: Schema.filter<typeof Schema.String>; city: Schema.filter<typeof Schema.String>; country: Schema.filter<typeof Schema.String>; }>; phone: Schema.filter<typeof Schema.String>; email: typeof Schema.String; website: Schema.optional<typeof Schema.String>; managingDirector: Schema.filter<typeof Schema.String>; commercialRegister: Schema.filter<typeof Schema.String>; commercialRegisterNumber: Schema.filter<typeof Schema.String>; jurisdiction: Schema.filter<typeof Schema.String>; vatId: Schema.filter<Schema.filter<typeof Schema.String>>; taxNumber: Schema.filter<typeof Schema.String>; bankDetails: Schema.Struct<{ bankName: Schema.filter<typeof Schema.String>; iban: Schema.filter<Schema.filter<typeof Schema.String>>; bic: Schema.filter<Schema.filter<typeof Schema.String>>; }>; }>; type GermanLegalInfo = Schema.Schema.Type<typeof GermanLegalInfoSchema>; /** * PDF rendering options for compliance and formatting */ declare const PDFRenderOptionsSchema: Schema.Struct<{ pdfACompliance: Schema.Literal<["PDF/A-3"]>; embedFonts: typeof Schema.Boolean; colorProfile: typeof Schema.String; legalInfo: Schema.Struct<{ companyName: Schema.filter<typeof Schema.String>; companyAddress: Schema.Struct<{ street: Schema.filter<typeof Schema.String>; zip: Schema.filter<typeof Schema.String>; city: Schema.filter<typeof Schema.String>; country: Schema.filter<typeof Schema.String>; }>; phone: Schema.filter<typeof Schema.String>; email: typeof Schema.String; website: Schema.optional<typeof Schema.String>; managingDirector: Schema.filter<typeof Schema.String>; commercialRegister: Schema.filter<typeof Schema.String>; commercialRegisterNumber: Schema.filter<typeof Schema.String>; jurisdiction: Schema.filter<typeof Schema.String>; vatId: Schema.filter<Schema.filter<typeof Schema.String>>; taxNumber: Schema.filter<typeof Schema.String>; bankDetails: Schema.Struct<{ bankName: Schema.filter<typeof Schema.String>; iban: Schema.filter<Schema.filter<typeof Schema.String>>; bic: Schema.filter<Schema.filter<typeof Schema.String>>; }>; }>; includeXMLAttachment: typeof Schema.Boolean; xmlStandard: Schema.Union<[Schema.Literal<["ZUGfERD"]>, Schema.Literal<["Factur-X"]>]>; language: Schema.Literal<["de"]>; currency: Schema.Literal<["EUR"]>; dateFormat: Schema.Literal<["DD.MM.YYYY"]>; logoBytes: Schema.optional<typeof Schema.Uint8Array>; customFooter: Schema.optional<typeof Schema.String>; }>; type PDFRenderOptions = Schema.Schema.Type<typeof PDFRenderOptionsSchema>; /** * Data structure containing all information needed for PDF rendering */ declare const InvoicePDFDataSchema: Schema.Struct<{ invoice: Schema.filter<Schema.filter<Schema.Struct<{ invoiceId: Schema.filter<Schema.filter<typeof Schema.String>>; orderId: Schema.filter<typeof Schema.String>; invoiceNumber: Schema.filter<typeof Schema.String>; customerSnapshot: Schema.Struct<{ firstName: Schema.filter<typeof Schema.String>; lastName: Schema.filter<typeof Schema.String>; street: Schema.filter<typeof Schema.String>; zip: Schema.filter<typeof Schema.String>; city: Schema.filter<typeof Schema.String>; country: Schema.filter<typeof Schema.String>; email: Schema.filter<Schema.filter<typeof Schema.String>>; phone: Schema.optional<Schema.filter<typeof Schema.String>>; }>; itemsSnapshot: Schema.filter<Schema.Array$<Schema.filter<Schema.Struct<{ unitPrice: typeof MoneySchema; quantity: Schema.filter<Schema.filter<typeof Schema.Number>>; linePrice: typeof MoneySchema; name: Schema.filter<typeof Schema.String>; variant: Schema.optional<Schema.filter<typeof Schema.String>>; productNumber: Schema.optional<Schema.filter<typeof Schema.String>>; }>>>>; financials: Schema.filter<Schema.Struct<{ subtotal: typeof MoneySchema; discount: typeof MoneySchema; taxes: typeof MoneySchema; shippingCost: typeof MoneySchema; grandTotal: typeof MoneySchema; }>>; createdOn: typeof Schema.DateFromSelf; createdBy: Schema.filter<typeof Schema.String>; pdfBytes: Schema.optional<Schema.instanceOf<Uint8Array<ArrayBuffer>>>; }>>>; renderOptions: Schema.Struct<{ pdfACompliance: Schema.Literal<["PDF/A-3"]>; embedFonts: typeof Schema.Boolean; colorProfile: typeof Schema.String; legalInfo: Schema.Struct<{ comp