Skip to main content

stateset_core/traits/
mod.rs

1//! Repository traits for data access abstraction.
2//!
3//! This module defines the interface for data persistence. Implementations
4//! can be SQLite, PostgreSQL, in-memory, etc.
5//!
6//! # Generic Repository
7//!
8//! The [`Repository`] trait provides a generic CRUD interface using associated
9//! types. Domain-specific traits (e.g. [`OrderRepository`]) extend it with
10//! entity-specific operations.
11//!
12//! # Auto-impl
13//!
14//! Key traits use [`auto_impl`](https://docs.rs/auto_impl) so that `&T`,
15//! `Box<T>`, and `Arc<T>` automatically implement the trait when `T` does.
16
17pub mod repository;
18
19pub use repository::{Repository, Transactional};
20
21use crate::errors::{BatchResult, Result};
22use crate::models::{
23    A2APurchase, A2APurchaseFilter, AddCartItem, AddCarton, AddCartonItem, AddLotCertificate,
24    AddShipmentEvent, AddWishlistItem, AddWorkOrderMaterial, AddressType, AdjustInventory,
25    AdjustLocationInventory, AdjustLot, AdjustPoints, AdjustStoreCredit, AgentCard,
26    AgentCardFilter, AgentFeedback, AgentFeedbackFilter, AgentFeedbackResponse, AgentIdentity,
27    AgentIdentityFilter, AgentMetadataEntry, AgentValidationRequest, AgentValidationResponse,
28    AgentValidationStatus, AgentWalletProofType, AllocateBackorder, AnalyticsQuery, ApAgingSummary,
29    ApplyCreditMemo, ApplyPaymentToInvoices, ApplyPromotionsRequest, ApplyPromotionsResult,
30    ArAgingFilter, ArAgingSummary, ArPaymentApplication, AutoPostingConfig, Backorder,
31    BackorderAllocation, BackorderFilter, BackorderFulfillment, BackorderSummary, BalanceSheet,
32    Bill, BillFilter, BillItem, BillOfMaterials, BillPayment, BillPaymentFilter, BillingCycle,
33    BillingCycleFilter, BillingCycleStatus, BomComponent, BomFilter, CancelSubscription, Cart,
34    CartAddress, CartFilter, CartItem, Carton, CartonItem, ChangeSerialStatus, CheckoutResult,
35    ClaimResolution, CollectionActivity, CollectionActivityFilter, CollectionStatus, CompletePick,
36    CompletePutAway, CompleteShip, ConsumeLot, ConversionResult, ConvertCurrency, CostAdjustment,
37    CostAdjustmentFilter, CostLayer, CostLayerFilter, CostMethod, CostRollup, CostTransaction,
38    CostTransactionFilter, CostTransactionType, CostVariance, CostVarianceFilter, CouponCode,
39    CouponFilter, CreateA2APurchase, CreateA2AQuote, CreateAgentCard, CreateAgentFeedback,
40    CreateAgentFeedbackResponse, CreateAgentIdentity, CreateAgentValidationRequest,
41    CreateAgentValidationResponse, CreateAutoPostingConfig, CreateBackorder, CreateBill,
42    CreateBillItem, CreateBillPayment, CreateBillingCycle, CreateBom, CreateBomComponent,
43    CreateCart, CreateCollectionActivity, CreateCostAdjustment, CreateCostLayer, CreateCouponCode,
44    CreateCreditAccount, CreateCreditMemo, CreateCustomObject, CreateCustomObjectType,
45    CreateCustomer, CreateCustomerAddress, CreateCycleCount, CreateDefectCode,
46    CreateFraudAssessment, CreateFraudRule, CreateGiftCard, CreateGlAccount, CreateGlPeriod,
47    CreateInspection, CreateInventoryItem, CreateInvoice, CreateInvoiceItem, CreateJournalEntry,
48    CreateLocation, CreateLot, CreateLoyaltyProgram, CreateNonConformance, CreateOrder,
49    CreateOrderItem, CreatePackTask, CreatePayment, CreatePaymentMethod, CreatePaymentRun,
50    CreatePickTask, CreateProduct, CreateProductVariant, CreatePromotion, CreatePurchaseOrder,
51    CreatePurchaseOrderItem, CreatePutAway, CreateQualityHold, CreateReceipt, CreateRefund,
52    CreateReturn, CreateReview, CreateReward, CreateSearchConfig, CreateSegment,
53    CreateSerialNumber, CreateSerialNumbersBulk, CreateShipTask, CreateShipment,
54    CreateShipmentItem, CreateShippingZone, CreateStoreCredit, CreateSubscription,
55    CreateSubscriptionPlan, CreateSupplier, CreateTaxExemption, CreateTaxJurisdiction,
56    CreateTaxRate, CreateWarehouse, CreateWarranty, CreateWarrantyClaim, CreateWave,
57    CreateWishlist, CreateWorkOrder, CreateWorkOrderTask, CreateWriteOff, CreateX402PaymentIntent,
58    CreateZone, CreateZoneShippingMethod, CreditAccount, CreditAccountFilter, CreditAgingBucket,
59    CreditApplication, CreditApplicationFilter, CreditCheckResult, CreditHold, CreditHoldFilter,
60    CreditMemo, CreditMemoFilter, CreditTransaction, CreditTransactionFilter, Currency,
61    CustomObject, CustomObjectFilter, CustomObjectType, CustomObjectTypeFilter, Customer,
62    CustomerAddress, CustomerArAging, CustomerArSummary, CustomerCreditSummary, CustomerFilter,
63    CustomerMetrics, CustomerStatement, CycleCount, CycleCountFilter, DefectCode, DemandForecast,
64    DunningLetterType, EmbeddingMetadata, EmbeddingStats, EnrollCustomer, EntityType, ExchangeRate,
65    ExchangeRateFilter, FeedbackSummary, FraudAssessment, FraudAssessmentFilter, FraudDecision,
66    FraudRule, FraudRuleFilter, FulfillBackorder, FulfillmentMetrics, GenerateStatementRequest,
67    GiftCard, GiftCardFilter, GiftCardTransaction, GlAccount, GlAccountFilter, GlPeriod,
68    GlPeriodFilter, IncomeStatement, Inspection, InspectionFilter, InspectionItem,
69    InventoryBalance, InventoryFilter, InventoryHealth, InventoryItem, InventoryMovement,
70    InventoryReservation, InventoryTransaction, InventoryValuation, Invoice, InvoiceFilter,
71    InvoiceItem, IssueCostLayers, ItemCost, ItemCostFilter, JournalEntry, JournalEntryFilter,
72    JournalEntryLine, Location, LocationFilter, LocationInventory, LocationInventoryFilter,
73    LocationMovement, Lot, LotCertificate, LotFilter, LotLocation, LotTransaction, LowStockItem,
74    LoyaltyAccount, LoyaltyAccountFilter, LoyaltyProgram, LoyaltyTransaction, MergeLots,
75    MoveInventory, MoveSerial, MovementFilter, NonConformance, NonConformanceFilter, Order,
76    OrderFilter, OrderItem, OrderStatusBreakdown, PackTask, PackTaskFilter, PauseSubscription,
77    Payment, PaymentAllocation, PaymentFilter, PaymentMethod, PaymentRun, PaymentRunFilter,
78    PickTask, PickTaskFilter, PlaceCreditHold, Product, ProductFilter, ProductPerformance,
79    ProductTaxCategory, ProductVariant, Promotion, PromotionFilter, PromotionUsage, PurchaseOrder,
80    PurchaseOrderFilter, PurchaseOrderItem, PurchaseStatus, PutAway, PutAwayFilter, QualityHold,
81    QualityHoldFilter, QuoteStatus, Receipt, ReceiptFilter, ReceiptItem, ReceiveItems,
82    ReceivePurchaseOrderItems, RecordCostVariance, RecordCreditTransaction, RecordCycleCountLine,
83    RecordInspectionResult, RecordInvoicePayment, Refund, ReleaseCreditHold, ReleaseQualityHold,
84    ReserveInventory, ReserveLot, ReserveSerialNumber, Return, ReturnFilter, ReturnMetrics,
85    RevaluationResult, RevenueByPeriod, RevenueForecast, Review, ReviewCreditApplication,
86    ReviewFilter, ReviewSummary, Reward, RewardFilter, SalesSummary, SearchConfig,
87    SearchConfigFilter, Segment, SegmentFilter, SegmentMembership, SerialFilter, SerialHistory,
88    SerialHistoryFilter, SerialLookupResult, SerialNumber, SerialReservation, SerialValidation,
89    SetCartPayment, SetCartShipping, SetCartX402Payment, SetExchangeRate, SetItemCost, ShipTask,
90    ShipTaskFilter, Shipment, ShipmentEvent, ShipmentFilter, ShipmentItem, ShippingRate,
91    ShippingZone, ShippingZoneFilter, SignX402PaymentIntent, SkillQuote, SkillQuoteFilter,
92    SkipBillingCycle, SkuBackorderSummary, SkuCostSummary, SplitLot, StockLevel, StoreCredit,
93    StoreCreditFilter, StoreCreditTransaction, StoreCurrencySettings, SubmitCreditApplication,
94    Subscription, SubscriptionEvent, SubscriptionEventType, SubscriptionFilter, SubscriptionPlan,
95    SubscriptionPlanFilter, Supplier, SupplierApSummary, SupplierFilter, TaxAddress,
96    TaxCalculationRequest, TaxCalculationResult, TaxExemption, TaxJurisdiction,
97    TaxJurisdictionFilter, TaxRate, TaxRateFilter, TaxSettings, TimeGranularity, TopCustomer,
98    TopProduct, TraceabilityResult, TransferLot, TransferSerialOwnership, TrialBalance, TrustLevel,
99    UpdateAgentCard, UpdateAgentIdentity, UpdateBackorder, UpdateBill, UpdateBom, UpdateCart,
100    UpdateCartItem, UpdateCreditAccount, UpdateCustomObject, UpdateCustomObjectType,
101    UpdateCustomer, UpdateFraudRule, UpdateGiftCard, UpdateGlAccount, UpdateInspection,
102    UpdateInvoice, UpdateLocation, UpdateLot, UpdateNonConformance, UpdateOrder, UpdatePayment,
103    UpdateProduct, UpdatePromotion, UpdatePurchaseOrder, UpdateReceipt, UpdateReturn, UpdateReview,
104    UpdateSearchConfig, UpdateSegment, UpdateSerialNumber, UpdateShipment, UpdateShippingZone,
105    UpdateSubscription, UpdateSubscriptionPlan, UpdateSupplier, UpdateWarehouse, UpdateWarranty,
106    UpdateWarrantyClaim, UpdateWishlist, UpdateWorkOrder, UpdateWorkOrderTask, UpdateZone,
107    ValidationSummary, VectorSearchResult, Warehouse, WarehouseFilter, Warranty, WarrantyClaim,
108    WarrantyClaimFilter, WarrantyFilter, Wave, WaveFilter, Wishlist, WishlistFilter, WishlistItem,
109    WorkOrder, WorkOrderFilter, WorkOrderMaterial, WorkOrderTask, WriteOff, WriteOffFilter,
110    X402Asset, X402CheckoutResult, X402CreditAccount, X402CreditAdjustment, X402CreditTransaction,
111    X402CreditTransactionFilter, X402Network, X402PaymentIntent, X402PaymentIntentFilter, Zone,
112    ZoneShippingMethod, ZoneShippingMethodFilter, ZoneShippingRate, ZoneShippingRateRequest,
113};
114// Newly-added B2B / ERP-ops entities (channels, companies, transfer orders,
115// units of measure, production batches).
116use crate::models::{
117    ActivityLogEntry, ActivityLogFilter, ApplyPrepayment, ApplyVendorCredit, BulkSupplierSkuItem,
118    CaptureStockSnapshot, CaptureTopologySnapshot, CreateEdiDocument, CreateInboundShipment,
119    CreateIntegrationFieldMapping, CreateIntegrationMapping, CreatePaymentObligation,
120    CreatePrepayment, CreatePriceLevel, CreatePriceSchedule, CreatePrintStation, CreateSupplierSku,
121    CreateVendorCredit, CreateVendorReturn, EdiAggregateSummary, EdiDocument, EdiDocumentFilter,
122    EdiStatus, EnqueuePrintJob, InboundShipment, InboundShipmentFilter, IngestOrder,
123    IntegrationFieldMapping, IntegrationFieldMappingFilter, IntegrationMapping,
124    IntegrationMappingFilter, MapPurgatoryLine, MappingLookup, PairStationResult,
125    PaymentObligation, PaymentObligationDashboard, PaymentObligationFilter,
126    PaymentObligationStatus, Prepayment, PrepaymentApplication, PrepaymentFilter, PriceLevel,
127    PriceLevelEntry, PriceLevelFilter, PriceSchedule, PriceScheduleEntry, PriceScheduleFilter,
128    PrintJob, PrintJobFilter, PrintStation, PurgatoryFilter, PurgatoryOrder, RecordActivity,
129    StockSnapshot, StockSnapshotFilter, SupplierSku, SupplierSkuFilter, TopologySnapshot,
130    TopologySnapshotFilter, UpdateIntegrationFieldMapping, UpdateIntegrationMapping,
131    UpdatePriceLevel, UpdatePriceSchedule, UpdateSupplierSku, VendorCredit,
132    VendorCreditApplication, VendorCreditFilter, VendorReturn, VendorReturnFilter,
133};
134use crate::models::{
135    Channel, ChannelFilter, ChannelProductMapping, ChannelProductSyncItem, Company, CompanyFilter,
136    CompanyPriceOverride, CompanyShippingAddress, Contact, CreateChannel, CreateCompany,
137    CreateContact, CreateProductionBatch, CreateTransferOrder, CreateUnitClass,
138    CreateUnitConversionRule, CreateUnitOfMeasure, ProductionBatch, ProductionBatchFilter,
139    TransferOrder, TransferOrderFilter, UnitClass, UnitConversionRule, UnitOfMeasure,
140    UnitOfMeasureFilter, UpdateChannel, UpdateCompany, UpdateProductionBatch,
141};
142use chrono::{DateTime, Utc};
143use stateset_primitives::{
144    ActivityLogId, ChannelId, CompanyId, ContactId, EdiDocumentId, InboundShipmentId,
145    InboundShipmentItemId, IntegrationFieldMappingId, IntegrationMappingId, PaymentObligationId,
146    PrepaymentApplicationId, PrepaymentId, PriceLevelId, PriceScheduleId, PrintJobId,
147    PrintStationId, ProductionBatchId, PurgatoryLineItemId, PurgatoryOrderId, StockSnapshotId,
148    SupplierSkuId, TopologySnapshotId, TransferOrderId, TransferOrderItemId, UnitClassId,
149    UnitConversionRuleId, UnitOfMeasureId, VendorCreditApplicationId, VendorCreditId,
150    VendorReturnId,
151};
152use stateset_primitives::{
153    CartId, CreditId, CustomerId, FraudRuleId, FulfillmentId, GiftCardId, InvoiceId,
154    LoyaltyAccountId, LoyaltyProgramId, OrderId, OrderItemId, PaymentId, ProductId, PromotionId,
155    PurchaseOrderId, ReturnId, ReviewId, RewardId, SearchConfigId, SegmentId, ShipmentId,
156    ShippingMethodId, ShippingZoneId, StoreCreditId, SubscriptionId, WarrantyId, WishlistId,
157};
158use uuid::Uuid;
159
160/// Order repository trait.
161#[auto_impl::auto_impl(&, Box, Arc)]
162pub trait OrderRepository: Send + Sync {
163    /// Create a new order
164    fn create(&self, input: CreateOrder) -> Result<Order>;
165
166    /// Get order by ID
167    fn get(&self, id: OrderId) -> Result<Option<Order>>;
168
169    /// Get order by order number
170    fn get_by_number(&self, order_number: &str) -> Result<Option<Order>>;
171
172    /// Update an order
173    fn update(&self, id: OrderId, input: UpdateOrder) -> Result<Order>;
174
175    /// List orders with filter
176    fn list(&self, filter: OrderFilter) -> Result<Vec<Order>>;
177
178    /// Delete an order
179    fn delete(&self, id: OrderId) -> Result<()>;
180
181    /// Add item to order
182    fn add_item(&self, order_id: OrderId, item: CreateOrderItem) -> Result<OrderItem>;
183
184    /// Remove item from order
185    fn remove_item(&self, order_id: OrderId, item_id: OrderItemId) -> Result<()>;
186
187    /// Count orders matching filter
188    fn count(&self, filter: OrderFilter) -> Result<u64>;
189
190    // === Batch Operations ===
191
192    /// Create multiple orders - partial success allowed
193    fn create_batch(&self, inputs: Vec<CreateOrder>) -> Result<BatchResult<Order>>;
194
195    /// Create multiple orders - atomic (all-or-nothing)
196    fn create_batch_atomic(&self, inputs: Vec<CreateOrder>) -> Result<Vec<Order>>;
197
198    /// Update multiple orders - partial success allowed
199    fn update_batch(&self, updates: Vec<(OrderId, UpdateOrder)>) -> Result<BatchResult<Order>>;
200
201    /// Update multiple orders - atomic (all-or-nothing)
202    fn update_batch_atomic(&self, updates: Vec<(OrderId, UpdateOrder)>) -> Result<Vec<Order>>;
203
204    /// Delete multiple orders - partial success allowed
205    fn delete_batch(&self, ids: Vec<OrderId>) -> Result<BatchResult<OrderId>>;
206
207    /// Delete multiple orders - atomic (all-or-nothing)
208    fn delete_batch_atomic(&self, ids: Vec<OrderId>) -> Result<()>;
209
210    /// Get multiple orders by ID
211    fn get_batch(&self, ids: Vec<OrderId>) -> Result<Vec<Order>>;
212}
213
214/// Inventory repository trait.
215#[auto_impl::auto_impl(&, Box, Arc)]
216pub trait InventoryRepository: Send + Sync {
217    /// Create a new inventory item
218    fn create_item(&self, input: CreateInventoryItem) -> Result<InventoryItem>;
219
220    /// Get inventory item by ID
221    fn get_item(&self, id: i64) -> Result<Option<InventoryItem>>;
222
223    /// Get inventory item by SKU
224    fn get_item_by_sku(&self, sku: &str) -> Result<Option<InventoryItem>>;
225
226    /// Get stock level for SKU (aggregated across locations)
227    fn get_stock(&self, sku: &str) -> Result<Option<StockLevel>>;
228
229    /// Get balance at specific location
230    fn get_balance(&self, item_id: i64, location_id: i32) -> Result<Option<InventoryBalance>>;
231
232    /// Adjust inventory quantity
233    fn adjust(&self, input: AdjustInventory) -> Result<InventoryTransaction>;
234
235    /// Reserve inventory
236    fn reserve(&self, input: ReserveInventory) -> Result<InventoryReservation>;
237
238    /// Get a reservation by ID
239    fn get_reservation(&self, reservation_id: Uuid) -> Result<Option<InventoryReservation>>;
240
241    /// Release reservation
242    fn release_reservation(&self, reservation_id: Uuid) -> Result<()>;
243
244    /// Confirm reservation (convert to allocation)
245    fn confirm_reservation(&self, reservation_id: Uuid) -> Result<()>;
246
247    /// List reservations by reference (e.g., order id)
248    fn list_reservations_by_reference(
249        &self,
250        reference_type: &str,
251        reference_id: &str,
252    ) -> Result<Vec<InventoryReservation>>;
253
254    /// List inventory items with filter
255    fn list(&self, filter: InventoryFilter) -> Result<Vec<InventoryItem>>;
256
257    /// Get items below reorder point
258    fn get_reorder_needed(&self) -> Result<Vec<StockLevel>>;
259
260    /// Record transaction
261    fn record_transaction(&self, transaction: InventoryTransaction)
262    -> Result<InventoryTransaction>;
263
264    /// Get transaction history
265    fn get_transactions(&self, item_id: i64, limit: u32) -> Result<Vec<InventoryTransaction>>;
266
267    // === Batch Operations ===
268
269    /// Create multiple inventory items - partial success allowed
270    fn create_item_batch(
271        &self,
272        inputs: Vec<CreateInventoryItem>,
273    ) -> Result<BatchResult<InventoryItem>>;
274
275    /// Create multiple inventory items - atomic (all-or-nothing)
276    fn create_item_batch_atomic(
277        &self,
278        inputs: Vec<CreateInventoryItem>,
279    ) -> Result<Vec<InventoryItem>>;
280
281    /// Adjust multiple inventory quantities - partial success allowed
282    fn adjust_batch(
283        &self,
284        adjustments: Vec<AdjustInventory>,
285    ) -> Result<BatchResult<InventoryTransaction>>;
286
287    /// Adjust multiple inventory quantities - atomic (all-or-nothing)
288    fn adjust_batch_atomic(
289        &self,
290        adjustments: Vec<AdjustInventory>,
291    ) -> Result<Vec<InventoryTransaction>>;
292
293    /// Get multiple inventory items by ID
294    fn get_item_batch(&self, ids: Vec<i64>) -> Result<Vec<InventoryItem>>;
295
296    /// Get stock levels for multiple SKUs
297    fn get_stock_batch(&self, skus: Vec<String>) -> Result<Vec<StockLevel>>;
298}
299
300/// Customer repository trait.
301#[auto_impl::auto_impl(&, Box, Arc)]
302pub trait CustomerRepository: Send + Sync {
303    /// Create a new customer
304    fn create(&self, input: CreateCustomer) -> Result<Customer>;
305
306    /// Get customer by ID
307    fn get(&self, id: CustomerId) -> Result<Option<Customer>>;
308
309    /// Get customer by email
310    fn get_by_email(&self, email: &str) -> Result<Option<Customer>>;
311
312    /// Update a customer
313    fn update(&self, id: CustomerId, input: UpdateCustomer) -> Result<Customer>;
314
315    /// List customers with filter
316    fn list(&self, filter: CustomerFilter) -> Result<Vec<Customer>>;
317
318    /// Delete a customer (soft delete)
319    fn delete(&self, id: CustomerId) -> Result<()>;
320
321    /// Add address for customer
322    fn add_address(&self, input: CreateCustomerAddress) -> Result<CustomerAddress>;
323
324    /// Get customer addresses
325    fn get_addresses(&self, customer_id: CustomerId) -> Result<Vec<CustomerAddress>>;
326
327    /// Update address
328    fn update_address(
329        &self,
330        address_id: Uuid,
331        input: CreateCustomerAddress,
332    ) -> Result<CustomerAddress>;
333
334    /// Delete address
335    fn delete_address(&self, address_id: Uuid) -> Result<()>;
336
337    /// Set default address
338    fn set_default_address(
339        &self,
340        customer_id: CustomerId,
341        address_id: Uuid,
342        address_type: AddressType,
343    ) -> Result<()>;
344
345    /// Count customers matching filter
346    fn count(&self, filter: CustomerFilter) -> Result<u64>;
347
348    // === Batch Operations ===
349
350    /// Create multiple customers - partial success allowed
351    fn create_batch(&self, inputs: Vec<CreateCustomer>) -> Result<BatchResult<Customer>>;
352
353    /// Create multiple customers - atomic (all-or-nothing)
354    fn create_batch_atomic(&self, inputs: Vec<CreateCustomer>) -> Result<Vec<Customer>>;
355
356    /// Update multiple customers - partial success allowed
357    fn update_batch(
358        &self,
359        updates: Vec<(CustomerId, UpdateCustomer)>,
360    ) -> Result<BatchResult<Customer>>;
361
362    /// Update multiple customers - atomic (all-or-nothing)
363    fn update_batch_atomic(
364        &self,
365        updates: Vec<(CustomerId, UpdateCustomer)>,
366    ) -> Result<Vec<Customer>>;
367
368    /// Delete multiple customers - partial success allowed
369    fn delete_batch(&self, ids: Vec<CustomerId>) -> Result<BatchResult<CustomerId>>;
370
371    /// Delete multiple customers - atomic (all-or-nothing)
372    fn delete_batch_atomic(&self, ids: Vec<CustomerId>) -> Result<()>;
373
374    /// Get multiple customers by ID
375    fn get_batch(&self, ids: Vec<CustomerId>) -> Result<Vec<Customer>>;
376}
377
378/// Product repository trait.
379#[auto_impl::auto_impl(&, Box, Arc)]
380pub trait ProductRepository: Send + Sync {
381    /// Create a new product
382    fn create(&self, input: CreateProduct) -> Result<Product>;
383
384    /// Get product by ID
385    fn get(&self, id: ProductId) -> Result<Option<Product>>;
386
387    /// Get product by slug
388    fn get_by_slug(&self, slug: &str) -> Result<Option<Product>>;
389
390    /// Update a product
391    fn update(&self, id: ProductId, input: UpdateProduct) -> Result<Product>;
392
393    /// List products with filter
394    fn list(&self, filter: ProductFilter) -> Result<Vec<Product>>;
395
396    /// Delete a product (archive)
397    fn delete(&self, id: ProductId) -> Result<()>;
398
399    /// Add variant to product
400    fn add_variant(
401        &self,
402        product_id: ProductId,
403        variant: CreateProductVariant,
404    ) -> Result<ProductVariant>;
405
406    /// Get variant by ID
407    fn get_variant(&self, id: Uuid) -> Result<Option<ProductVariant>>;
408
409    /// Get variant by SKU
410    fn get_variant_by_sku(&self, sku: &str) -> Result<Option<ProductVariant>>;
411
412    /// Update variant
413    fn update_variant(&self, id: Uuid, variant: CreateProductVariant) -> Result<ProductVariant>;
414
415    /// Delete variant
416    fn delete_variant(&self, id: Uuid) -> Result<()>;
417
418    /// Get all variants for product
419    fn get_variants(&self, product_id: ProductId) -> Result<Vec<ProductVariant>>;
420
421    /// Count products matching filter
422    fn count(&self, filter: ProductFilter) -> Result<u64>;
423
424    // === Batch Operations ===
425
426    /// Create multiple products - partial success allowed
427    fn create_batch(&self, inputs: Vec<CreateProduct>) -> Result<BatchResult<Product>>;
428
429    /// Create multiple products - atomic (all-or-nothing)
430    fn create_batch_atomic(&self, inputs: Vec<CreateProduct>) -> Result<Vec<Product>>;
431
432    /// Update multiple products - partial success allowed
433    fn update_batch(
434        &self,
435        updates: Vec<(ProductId, UpdateProduct)>,
436    ) -> Result<BatchResult<Product>>;
437
438    /// Update multiple products - atomic (all-or-nothing)
439    fn update_batch_atomic(&self, updates: Vec<(ProductId, UpdateProduct)>)
440    -> Result<Vec<Product>>;
441
442    /// Delete multiple products - partial success allowed
443    fn delete_batch(&self, ids: Vec<ProductId>) -> Result<BatchResult<ProductId>>;
444
445    /// Delete multiple products - atomic (all-or-nothing)
446    fn delete_batch_atomic(&self, ids: Vec<ProductId>) -> Result<()>;
447
448    /// Get multiple products by ID
449    fn get_batch(&self, ids: Vec<ProductId>) -> Result<Vec<Product>>;
450}
451
452/// Return repository trait.
453#[auto_impl::auto_impl(&, Box, Arc)]
454pub trait ReturnRepository: Send + Sync {
455    /// Create a new return
456    fn create(&self, input: CreateReturn) -> Result<Return>;
457
458    /// Get return by ID
459    fn get(&self, id: ReturnId) -> Result<Option<Return>>;
460
461    /// Update a return
462    fn update(&self, id: ReturnId, input: UpdateReturn) -> Result<Return>;
463
464    /// List returns with filter
465    fn list(&self, filter: ReturnFilter) -> Result<Vec<Return>>;
466
467    /// Approve a return
468    fn approve(&self, id: ReturnId) -> Result<Return>;
469
470    /// Reject a return
471    fn reject(&self, id: ReturnId, reason: &str) -> Result<Return>;
472
473    /// Complete a return
474    fn complete(&self, id: ReturnId) -> Result<Return>;
475
476    /// Cancel a return
477    fn cancel(&self, id: ReturnId) -> Result<Return>;
478
479    /// Count returns matching filter
480    fn count(&self, filter: ReturnFilter) -> Result<u64>;
481
482    // === Batch Operations ===
483
484    /// Create multiple returns - partial success allowed
485    fn create_batch(&self, inputs: Vec<CreateReturn>) -> Result<BatchResult<Return>>;
486
487    /// Create multiple returns - atomic (all-or-nothing)
488    fn create_batch_atomic(&self, inputs: Vec<CreateReturn>) -> Result<Vec<Return>>;
489
490    /// Update multiple returns - partial success allowed
491    fn update_batch(&self, updates: Vec<(ReturnId, UpdateReturn)>) -> Result<BatchResult<Return>>;
492
493    /// Update multiple returns - atomic (all-or-nothing)
494    fn update_batch_atomic(&self, updates: Vec<(ReturnId, UpdateReturn)>) -> Result<Vec<Return>>;
495
496    /// Delete multiple returns - partial success allowed
497    fn delete_batch(&self, ids: Vec<ReturnId>) -> Result<BatchResult<Uuid>>;
498
499    /// Delete multiple returns - atomic (all-or-nothing)
500    fn delete_batch_atomic(&self, ids: Vec<ReturnId>) -> Result<()>;
501
502    /// Get multiple returns by ID
503    fn get_batch(&self, ids: Vec<ReturnId>) -> Result<Vec<Return>>;
504}
505
506/// Event handler trait for domain events
507#[auto_impl::auto_impl(&, Box, Arc)]
508pub trait EventHandler: Send + Sync {
509    /// Handle a commerce event
510    fn handle(&self, event: &crate::events::CommerceEvent) -> Result<()>;
511}
512
513/// Bill of Materials repository trait
514#[auto_impl::auto_impl(&, Box, Arc)]
515pub trait BomRepository: Send + Sync {
516    /// Create a new BOM
517    fn create(&self, input: CreateBom) -> Result<BillOfMaterials>;
518
519    /// Get BOM by ID
520    fn get(&self, id: Uuid) -> Result<Option<BillOfMaterials>>;
521
522    /// Get BOM by BOM number
523    fn get_by_number(&self, bom_number: &str) -> Result<Option<BillOfMaterials>>;
524
525    /// Update a BOM
526    fn update(&self, id: Uuid, input: UpdateBom) -> Result<BillOfMaterials>;
527
528    /// List BOMs with filter
529    fn list(&self, filter: BomFilter) -> Result<Vec<BillOfMaterials>>;
530
531    /// Delete a BOM (marks as obsolete)
532    fn delete(&self, id: Uuid) -> Result<()>;
533
534    /// Add component to BOM
535    fn add_component(&self, bom_id: Uuid, component: CreateBomComponent) -> Result<BomComponent>;
536
537    /// Update a BOM component
538    fn update_component(
539        &self,
540        component_id: Uuid,
541        component: CreateBomComponent,
542    ) -> Result<BomComponent>;
543
544    /// Remove component from BOM
545    fn remove_component(&self, component_id: Uuid) -> Result<()>;
546
547    /// Get all components for a BOM
548    fn get_components(&self, bom_id: Uuid) -> Result<Vec<BomComponent>>;
549
550    /// Activate a BOM (make it ready for production use)
551    fn activate(&self, id: Uuid) -> Result<BillOfMaterials>;
552
553    /// Count BOMs matching filter
554    fn count(&self, filter: BomFilter) -> Result<u64>;
555
556    // === Batch Operations ===
557
558    /// Create multiple BOMs - partial success allowed
559    fn create_batch(&self, inputs: Vec<CreateBom>) -> Result<BatchResult<BillOfMaterials>>;
560
561    /// Create multiple BOMs - atomic (all-or-nothing)
562    fn create_batch_atomic(&self, inputs: Vec<CreateBom>) -> Result<Vec<BillOfMaterials>>;
563
564    /// Update multiple BOMs - partial success allowed
565    fn update_batch(&self, updates: Vec<(Uuid, UpdateBom)>)
566    -> Result<BatchResult<BillOfMaterials>>;
567
568    /// Update multiple BOMs - atomic (all-or-nothing)
569    fn update_batch_atomic(&self, updates: Vec<(Uuid, UpdateBom)>) -> Result<Vec<BillOfMaterials>>;
570
571    /// Delete multiple BOMs - partial success allowed
572    fn delete_batch(&self, ids: Vec<Uuid>) -> Result<BatchResult<Uuid>>;
573
574    /// Delete multiple BOMs - atomic (all-or-nothing)
575    fn delete_batch_atomic(&self, ids: Vec<Uuid>) -> Result<()>;
576
577    /// Get multiple BOMs by ID
578    fn get_batch(&self, ids: Vec<Uuid>) -> Result<Vec<BillOfMaterials>>;
579}
580
581/// Work Order repository trait
582#[auto_impl::auto_impl(&, Box, Arc)]
583pub trait WorkOrderRepository: Send + Sync {
584    /// Create a new work order
585    fn create(&self, input: CreateWorkOrder) -> Result<WorkOrder>;
586
587    /// Get work order by ID
588    fn get(&self, id: Uuid) -> Result<Option<WorkOrder>>;
589
590    /// Get work order by work order number
591    fn get_by_number(&self, work_order_number: &str) -> Result<Option<WorkOrder>>;
592
593    /// Update a work order
594    fn update(&self, id: Uuid, input: UpdateWorkOrder) -> Result<WorkOrder>;
595
596    /// List work orders with filter
597    fn list(&self, filter: WorkOrderFilter) -> Result<Vec<WorkOrder>>;
598
599    /// Delete a work order (cancels if not started)
600    fn delete(&self, id: Uuid) -> Result<()>;
601
602    /// Start a work order (transitions from planned to `in_progress`)
603    fn start(&self, id: Uuid) -> Result<WorkOrder>;
604
605    /// Complete a work order
606    fn complete(&self, id: Uuid, quantity_completed: rust_decimal::Decimal) -> Result<WorkOrder>;
607
608    /// Put work order on hold
609    fn hold(&self, id: Uuid) -> Result<WorkOrder>;
610
611    /// Resume a held work order
612    fn resume(&self, id: Uuid) -> Result<WorkOrder>;
613
614    /// Cancel a work order
615    fn cancel(&self, id: Uuid) -> Result<WorkOrder>;
616
617    // Task operations
618    /// Add task to work order
619    fn add_task(&self, work_order_id: Uuid, task: CreateWorkOrderTask) -> Result<WorkOrderTask>;
620
621    /// Update a task
622    fn update_task(&self, task_id: Uuid, task: UpdateWorkOrderTask) -> Result<WorkOrderTask>;
623
624    /// Remove task from work order
625    fn remove_task(&self, task_id: Uuid) -> Result<()>;
626
627    /// Get tasks for work order
628    fn get_tasks(&self, work_order_id: Uuid) -> Result<Vec<WorkOrderTask>>;
629
630    /// Start a task
631    fn start_task(&self, task_id: Uuid) -> Result<WorkOrderTask>;
632
633    /// Complete a task
634    fn complete_task(
635        &self,
636        task_id: Uuid,
637        actual_hours: Option<rust_decimal::Decimal>,
638    ) -> Result<WorkOrderTask>;
639
640    // Material operations
641    /// Add material to work order
642    fn add_material(
643        &self,
644        work_order_id: Uuid,
645        material: AddWorkOrderMaterial,
646    ) -> Result<WorkOrderMaterial>;
647
648    /// Consume material
649    fn consume_material(
650        &self,
651        material_id: Uuid,
652        quantity: rust_decimal::Decimal,
653    ) -> Result<WorkOrderMaterial>;
654
655    /// Get materials for work order
656    fn get_materials(&self, work_order_id: Uuid) -> Result<Vec<WorkOrderMaterial>>;
657
658    /// Count work orders matching filter
659    fn count(&self, filter: WorkOrderFilter) -> Result<u64>;
660
661    // === Batch Operations ===
662
663    /// Create multiple work orders - partial success allowed
664    fn create_batch(&self, inputs: Vec<CreateWorkOrder>) -> Result<BatchResult<WorkOrder>>;
665
666    /// Create multiple work orders - atomic (all-or-nothing)
667    fn create_batch_atomic(&self, inputs: Vec<CreateWorkOrder>) -> Result<Vec<WorkOrder>>;
668
669    /// Update multiple work orders - partial success allowed
670    fn update_batch(&self, updates: Vec<(Uuid, UpdateWorkOrder)>)
671    -> Result<BatchResult<WorkOrder>>;
672
673    /// Update multiple work orders - atomic (all-or-nothing)
674    fn update_batch_atomic(&self, updates: Vec<(Uuid, UpdateWorkOrder)>) -> Result<Vec<WorkOrder>>;
675
676    /// Delete multiple work orders - partial success allowed
677    fn delete_batch(&self, ids: Vec<Uuid>) -> Result<BatchResult<Uuid>>;
678
679    /// Delete multiple work orders - atomic (all-or-nothing)
680    fn delete_batch_atomic(&self, ids: Vec<Uuid>) -> Result<()>;
681
682    /// Get multiple work orders by ID
683    fn get_batch(&self, ids: Vec<Uuid>) -> Result<Vec<WorkOrder>>;
684}
685
686/// Shipment repository trait
687#[auto_impl::auto_impl(&, Box, Arc)]
688pub trait ShipmentRepository: Send + Sync {
689    /// Create a new shipment
690    fn create(&self, input: CreateShipment) -> Result<Shipment>;
691
692    /// Get shipment by ID
693    fn get(&self, id: ShipmentId) -> Result<Option<Shipment>>;
694
695    /// Get shipment by shipment number
696    fn get_by_number(&self, shipment_number: &str) -> Result<Option<Shipment>>;
697
698    /// Get shipment by tracking number
699    fn get_by_tracking(&self, tracking_number: &str) -> Result<Option<Shipment>>;
700
701    /// Update a shipment
702    fn update(&self, id: ShipmentId, input: UpdateShipment) -> Result<Shipment>;
703
704    /// List shipments with filter
705    fn list(&self, filter: ShipmentFilter) -> Result<Vec<Shipment>>;
706
707    /// Get shipments for an order
708    fn for_order(&self, order_id: OrderId) -> Result<Vec<Shipment>>;
709
710    /// Delete a shipment (cancel if not shipped)
711    fn delete(&self, id: ShipmentId) -> Result<()>;
712
713    // Status transitions
714    /// Mark shipment as processing
715    fn mark_processing(&self, id: ShipmentId) -> Result<Shipment>;
716
717    /// Mark shipment as ready to ship
718    fn mark_ready(&self, id: ShipmentId) -> Result<Shipment>;
719
720    /// Mark shipment as shipped with tracking number
721    fn ship(&self, id: ShipmentId, tracking_number: Option<String>) -> Result<Shipment>;
722
723    /// Mark shipment as in transit
724    fn mark_in_transit(&self, id: ShipmentId) -> Result<Shipment>;
725
726    /// Mark shipment as out for delivery
727    fn mark_out_for_delivery(&self, id: ShipmentId) -> Result<Shipment>;
728
729    /// Mark shipment as delivered
730    fn mark_delivered(&self, id: ShipmentId) -> Result<Shipment>;
731
732    /// Mark shipment as failed delivery
733    fn mark_failed(&self, id: ShipmentId) -> Result<Shipment>;
734
735    /// Put shipment on hold
736    fn hold(&self, id: ShipmentId) -> Result<Shipment>;
737
738    /// Cancel shipment
739    fn cancel(&self, id: ShipmentId) -> Result<Shipment>;
740
741    // Item operations
742    /// Add item to shipment
743    fn add_item(&self, shipment_id: ShipmentId, item: CreateShipmentItem) -> Result<ShipmentItem>;
744
745    /// Remove item from shipment
746    fn remove_item(&self, item_id: Uuid) -> Result<()>;
747
748    /// Get items in shipment
749    fn get_items(&self, shipment_id: ShipmentId) -> Result<Vec<ShipmentItem>>;
750
751    // Event/tracking operations
752    /// Add tracking event
753    fn add_event(&self, shipment_id: ShipmentId, event: AddShipmentEvent) -> Result<ShipmentEvent>;
754
755    /// Get tracking events for shipment
756    fn get_events(&self, shipment_id: ShipmentId) -> Result<Vec<ShipmentEvent>>;
757
758    /// Count shipments matching filter
759    fn count(&self, filter: ShipmentFilter) -> Result<u64>;
760
761    // === Batch Operations ===
762
763    /// Create multiple shipments - partial success allowed
764    fn create_batch(&self, inputs: Vec<CreateShipment>) -> Result<BatchResult<Shipment>>;
765
766    /// Create multiple shipments - atomic (all-or-nothing)
767    fn create_batch_atomic(&self, inputs: Vec<CreateShipment>) -> Result<Vec<Shipment>>;
768
769    /// Update multiple shipments - partial success allowed
770    fn update_batch(
771        &self,
772        updates: Vec<(ShipmentId, UpdateShipment)>,
773    ) -> Result<BatchResult<Shipment>>;
774
775    /// Update multiple shipments - atomic (all-or-nothing)
776    fn update_batch_atomic(
777        &self,
778        updates: Vec<(ShipmentId, UpdateShipment)>,
779    ) -> Result<Vec<Shipment>>;
780
781    /// Delete multiple shipments - partial success allowed
782    fn delete_batch(&self, ids: Vec<ShipmentId>) -> Result<BatchResult<Uuid>>;
783
784    /// Delete multiple shipments - atomic (all-or-nothing)
785    fn delete_batch_atomic(&self, ids: Vec<ShipmentId>) -> Result<()>;
786
787    /// Get multiple shipments by ID
788    fn get_batch(&self, ids: Vec<ShipmentId>) -> Result<Vec<Shipment>>;
789}
790
791/// Payment repository trait
792#[auto_impl::auto_impl(&, Box, Arc)]
793pub trait PaymentRepository: Send + Sync {
794    /// Create a new payment
795    fn create(&self, input: CreatePayment) -> Result<Payment>;
796
797    /// Get payment by ID
798    fn get(&self, id: PaymentId) -> Result<Option<Payment>>;
799
800    /// Get payment by payment number
801    fn get_by_number(&self, payment_number: &str) -> Result<Option<Payment>>;
802
803    /// Get payment by external ID (e.g., Stripe payment intent)
804    fn get_by_external_id(&self, external_id: &str) -> Result<Option<Payment>>;
805
806    /// Update a payment
807    fn update(&self, id: PaymentId, input: UpdatePayment) -> Result<Payment>;
808
809    /// List payments with filter
810    fn list(&self, filter: PaymentFilter) -> Result<Vec<Payment>>;
811
812    /// Get payments for an order
813    fn for_order(&self, order_id: OrderId) -> Result<Vec<Payment>>;
814
815    /// Get payments for an invoice
816    fn for_invoice(&self, invoice_id: InvoiceId) -> Result<Vec<Payment>>;
817
818    // Status transitions
819    /// Mark payment as processing
820    fn mark_processing(&self, id: PaymentId) -> Result<Payment>;
821
822    /// Mark payment as completed (paid)
823    fn mark_completed(&self, id: PaymentId) -> Result<Payment>;
824
825    /// Mark payment as failed
826    fn mark_failed(&self, id: PaymentId, reason: &str, code: Option<&str>) -> Result<Payment>;
827
828    /// Cancel payment
829    fn cancel(&self, id: PaymentId) -> Result<Payment>;
830
831    // Refund operations
832    /// Create a refund for a payment
833    fn create_refund(&self, input: CreateRefund) -> Result<Refund>;
834
835    /// Get refund by ID
836    fn get_refund(&self, id: Uuid) -> Result<Option<Refund>>;
837
838    /// Get refunds for a payment
839    fn get_refunds(&self, payment_id: PaymentId) -> Result<Vec<Refund>>;
840
841    /// Process refund (mark as completed)
842    fn complete_refund(&self, id: Uuid) -> Result<Refund>;
843
844    /// Fail refund
845    fn fail_refund(&self, id: Uuid, reason: &str) -> Result<Refund>;
846
847    // Payment method operations
848    /// Create a payment method for a customer
849    fn create_payment_method(&self, input: CreatePaymentMethod) -> Result<PaymentMethod>;
850
851    /// Get payment methods for a customer
852    fn get_payment_methods(&self, customer_id: CustomerId) -> Result<Vec<PaymentMethod>>;
853
854    /// Delete a payment method
855    fn delete_payment_method(&self, id: Uuid) -> Result<()>;
856
857    /// Set default payment method
858    fn set_default_payment_method(&self, customer_id: CustomerId, method_id: Uuid) -> Result<()>;
859
860    /// Count payments matching filter
861    fn count(&self, filter: PaymentFilter) -> Result<u64>;
862
863    // === Batch Operations ===
864
865    /// Create multiple payments - partial success allowed
866    fn create_batch(&self, inputs: Vec<CreatePayment>) -> Result<BatchResult<Payment>>;
867
868    /// Create multiple payments - atomic (all-or-nothing)
869    fn create_batch_atomic(&self, inputs: Vec<CreatePayment>) -> Result<Vec<Payment>>;
870
871    /// Update multiple payments - partial success allowed
872    fn update_batch(
873        &self,
874        updates: Vec<(PaymentId, UpdatePayment)>,
875    ) -> Result<BatchResult<Payment>>;
876
877    /// Update multiple payments - atomic (all-or-nothing)
878    fn update_batch_atomic(&self, updates: Vec<(PaymentId, UpdatePayment)>)
879    -> Result<Vec<Payment>>;
880
881    /// Delete multiple payments - partial success allowed
882    fn delete_batch(&self, ids: Vec<PaymentId>) -> Result<BatchResult<Uuid>>;
883
884    /// Delete multiple payments - atomic (all-or-nothing)
885    fn delete_batch_atomic(&self, ids: Vec<PaymentId>) -> Result<()>;
886
887    /// Get multiple payments by ID
888    fn get_batch(&self, ids: Vec<PaymentId>) -> Result<Vec<Payment>>;
889}
890
891/// Warranty repository trait
892#[auto_impl::auto_impl(&, Box, Arc)]
893pub trait WarrantyRepository: Send + Sync {
894    /// Create a new warranty
895    fn create(&self, input: CreateWarranty) -> Result<Warranty>;
896
897    /// Get warranty by ID
898    fn get(&self, id: WarrantyId) -> Result<Option<Warranty>>;
899
900    /// Get warranty by warranty number
901    fn get_by_number(&self, warranty_number: &str) -> Result<Option<Warranty>>;
902
903    /// Get warranty by serial number
904    fn get_by_serial(&self, serial_number: &str) -> Result<Option<Warranty>>;
905
906    /// Update a warranty
907    fn update(&self, id: WarrantyId, input: UpdateWarranty) -> Result<Warranty>;
908
909    /// List warranties with filter
910    fn list(&self, filter: WarrantyFilter) -> Result<Vec<Warranty>>;
911
912    /// Get warranties for a customer
913    fn for_customer(&self, customer_id: CustomerId) -> Result<Vec<Warranty>>;
914
915    /// Get warranties for an order
916    fn for_order(&self, order_id: OrderId) -> Result<Vec<Warranty>>;
917
918    // Status transitions
919    /// Void a warranty
920    fn void(&self, id: WarrantyId) -> Result<Warranty>;
921
922    /// Expire a warranty
923    fn expire(&self, id: WarrantyId) -> Result<Warranty>;
924
925    /// Transfer warranty to new owner
926    fn transfer(&self, id: WarrantyId, new_customer_id: CustomerId) -> Result<Warranty>;
927
928    // Claim operations
929    /// Create a warranty claim
930    fn create_claim(&self, input: CreateWarrantyClaim) -> Result<WarrantyClaim>;
931
932    /// Get claim by ID
933    fn get_claim(&self, id: Uuid) -> Result<Option<WarrantyClaim>>;
934
935    /// Get claim by claim number
936    fn get_claim_by_number(&self, claim_number: &str) -> Result<Option<WarrantyClaim>>;
937
938    /// Update a claim
939    fn update_claim(&self, id: Uuid, input: UpdateWarrantyClaim) -> Result<WarrantyClaim>;
940
941    /// List claims with filter
942    fn list_claims(&self, filter: WarrantyClaimFilter) -> Result<Vec<WarrantyClaim>>;
943
944    /// Get claims for a warranty
945    fn get_claims(&self, warranty_id: WarrantyId) -> Result<Vec<WarrantyClaim>>;
946
947    // Claim status transitions
948    /// Approve a claim
949    fn approve_claim(&self, id: Uuid) -> Result<WarrantyClaim>;
950
951    /// Deny a claim
952    fn deny_claim(&self, id: Uuid, reason: &str) -> Result<WarrantyClaim>;
953
954    /// Complete a claim
955    fn complete_claim(&self, id: Uuid, resolution: ClaimResolution) -> Result<WarrantyClaim>;
956
957    /// Cancel a claim
958    fn cancel_claim(&self, id: Uuid) -> Result<WarrantyClaim>;
959
960    /// Count warranties matching filter
961    fn count(&self, filter: WarrantyFilter) -> Result<u64>;
962
963    /// Count claims matching filter
964    fn count_claims(&self, filter: WarrantyClaimFilter) -> Result<u64>;
965
966    // === Batch Operations ===
967
968    /// Create multiple warranties - partial success allowed
969    fn create_batch(&self, inputs: Vec<CreateWarranty>) -> Result<BatchResult<Warranty>>;
970
971    /// Create multiple warranties - atomic (all-or-nothing)
972    fn create_batch_atomic(&self, inputs: Vec<CreateWarranty>) -> Result<Vec<Warranty>>;
973
974    /// Update multiple warranties - partial success allowed
975    fn update_batch(
976        &self,
977        updates: Vec<(WarrantyId, UpdateWarranty)>,
978    ) -> Result<BatchResult<Warranty>>;
979
980    /// Update multiple warranties - atomic (all-or-nothing)
981    fn update_batch_atomic(
982        &self,
983        updates: Vec<(WarrantyId, UpdateWarranty)>,
984    ) -> Result<Vec<Warranty>>;
985
986    /// Delete multiple warranties - partial success allowed
987    fn delete_batch(&self, ids: Vec<WarrantyId>) -> Result<BatchResult<Uuid>>;
988
989    /// Delete multiple warranties - atomic (all-or-nothing)
990    fn delete_batch_atomic(&self, ids: Vec<WarrantyId>) -> Result<()>;
991
992    /// Get multiple warranties by ID
993    fn get_batch(&self, ids: Vec<WarrantyId>) -> Result<Vec<Warranty>>;
994}
995
996/// Purchase Order repository trait
997#[auto_impl::auto_impl(&, Box, Arc)]
998pub trait PurchaseOrderRepository: Send + Sync {
999    // Supplier operations
1000    /// Create a new supplier
1001    fn create_supplier(&self, input: CreateSupplier) -> Result<Supplier>;
1002
1003    /// Get supplier by ID
1004    fn get_supplier(&self, id: Uuid) -> Result<Option<Supplier>>;
1005
1006    /// Get supplier by code
1007    fn get_supplier_by_code(&self, code: &str) -> Result<Option<Supplier>>;
1008
1009    /// Update a supplier
1010    fn update_supplier(&self, id: Uuid, input: UpdateSupplier) -> Result<Supplier>;
1011
1012    /// List suppliers with filter
1013    fn list_suppliers(&self, filter: SupplierFilter) -> Result<Vec<Supplier>>;
1014
1015    /// Delete supplier (deactivate)
1016    fn delete_supplier(&self, id: Uuid) -> Result<()>;
1017
1018    // Purchase Order operations
1019    /// Create a new purchase order
1020    fn create(&self, input: CreatePurchaseOrder) -> Result<PurchaseOrder>;
1021
1022    /// Get purchase order by ID
1023    fn get(&self, id: PurchaseOrderId) -> Result<Option<PurchaseOrder>>;
1024
1025    /// Get purchase order by PO number
1026    fn get_by_number(&self, po_number: &str) -> Result<Option<PurchaseOrder>>;
1027
1028    /// Update a purchase order
1029    fn update(&self, id: PurchaseOrderId, input: UpdatePurchaseOrder) -> Result<PurchaseOrder>;
1030
1031    /// List purchase orders with filter
1032    fn list(&self, filter: PurchaseOrderFilter) -> Result<Vec<PurchaseOrder>>;
1033
1034    /// Get purchase orders for a supplier
1035    fn for_supplier(&self, supplier_id: Uuid) -> Result<Vec<PurchaseOrder>>;
1036
1037    /// Delete a purchase order (only if draft)
1038    fn delete(&self, id: PurchaseOrderId) -> Result<()>;
1039
1040    // Status transitions
1041    /// Submit for approval
1042    fn submit_for_approval(&self, id: PurchaseOrderId) -> Result<PurchaseOrder>;
1043
1044    /// Approve purchase order
1045    fn approve(&self, id: PurchaseOrderId, approved_by: &str) -> Result<PurchaseOrder>;
1046
1047    /// Send to supplier
1048    fn send(&self, id: PurchaseOrderId) -> Result<PurchaseOrder>;
1049
1050    /// Mark as acknowledged by supplier
1051    fn acknowledge(
1052        &self,
1053        id: PurchaseOrderId,
1054        supplier_reference: Option<&str>,
1055    ) -> Result<PurchaseOrder>;
1056
1057    /// Put on hold
1058    fn hold(&self, id: PurchaseOrderId) -> Result<PurchaseOrder>;
1059
1060    /// Cancel purchase order
1061    fn cancel(&self, id: PurchaseOrderId) -> Result<PurchaseOrder>;
1062
1063    /// Receive items on a purchase order
1064    fn receive(
1065        &self,
1066        id: PurchaseOrderId,
1067        items: ReceivePurchaseOrderItems,
1068    ) -> Result<PurchaseOrder>;
1069
1070    /// Complete/close purchase order
1071    fn complete(&self, id: PurchaseOrderId) -> Result<PurchaseOrder>;
1072
1073    // Item operations
1074    /// Add item to purchase order
1075    fn add_item(
1076        &self,
1077        po_id: PurchaseOrderId,
1078        item: CreatePurchaseOrderItem,
1079    ) -> Result<PurchaseOrderItem>;
1080
1081    /// Update a PO item
1082    fn update_item(
1083        &self,
1084        item_id: Uuid,
1085        item: CreatePurchaseOrderItem,
1086    ) -> Result<PurchaseOrderItem>;
1087
1088    /// Remove item from purchase order
1089    fn remove_item(&self, item_id: Uuid) -> Result<()>;
1090
1091    /// Get items for purchase order
1092    fn get_items(&self, po_id: PurchaseOrderId) -> Result<Vec<PurchaseOrderItem>>;
1093
1094    /// Count purchase orders matching filter
1095    fn count(&self, filter: PurchaseOrderFilter) -> Result<u64>;
1096
1097    /// Count suppliers matching filter
1098    fn count_suppliers(&self, filter: SupplierFilter) -> Result<u64>;
1099
1100    // === Batch Operations ===
1101
1102    /// Create multiple purchase orders - partial success allowed
1103    fn create_batch(&self, inputs: Vec<CreatePurchaseOrder>) -> Result<BatchResult<PurchaseOrder>>;
1104
1105    /// Create multiple purchase orders - atomic (all-or-nothing)
1106    fn create_batch_atomic(&self, inputs: Vec<CreatePurchaseOrder>) -> Result<Vec<PurchaseOrder>>;
1107
1108    /// Update multiple purchase orders - partial success allowed
1109    fn update_batch(
1110        &self,
1111        updates: Vec<(PurchaseOrderId, UpdatePurchaseOrder)>,
1112    ) -> Result<BatchResult<PurchaseOrder>>;
1113
1114    /// Update multiple purchase orders - atomic (all-or-nothing)
1115    fn update_batch_atomic(
1116        &self,
1117        updates: Vec<(PurchaseOrderId, UpdatePurchaseOrder)>,
1118    ) -> Result<Vec<PurchaseOrder>>;
1119
1120    /// Delete multiple purchase orders - partial success allowed
1121    fn delete_batch(&self, ids: Vec<PurchaseOrderId>) -> Result<BatchResult<PurchaseOrderId>>;
1122
1123    /// Delete multiple purchase orders - atomic (all-or-nothing)
1124    fn delete_batch_atomic(&self, ids: Vec<PurchaseOrderId>) -> Result<()>;
1125
1126    /// Get multiple purchase orders by ID
1127    fn get_batch(&self, ids: Vec<PurchaseOrderId>) -> Result<Vec<PurchaseOrder>>;
1128}
1129
1130/// Invoice repository trait
1131#[auto_impl::auto_impl(&, Box, Arc)]
1132pub trait InvoiceRepository: Send + Sync {
1133    /// Create a new invoice
1134    fn create(&self, input: CreateInvoice) -> Result<Invoice>;
1135
1136    /// Get invoice by ID
1137    fn get(&self, id: InvoiceId) -> Result<Option<Invoice>>;
1138
1139    /// Get invoice by invoice number
1140    fn get_by_number(&self, invoice_number: &str) -> Result<Option<Invoice>>;
1141
1142    /// Update an invoice
1143    fn update(&self, id: InvoiceId, input: UpdateInvoice) -> Result<Invoice>;
1144
1145    /// List invoices with filter
1146    fn list(&self, filter: InvoiceFilter) -> Result<Vec<Invoice>>;
1147
1148    /// Get invoices for a customer
1149    fn for_customer(&self, customer_id: CustomerId) -> Result<Vec<Invoice>>;
1150
1151    /// Get invoices for an order
1152    fn for_order(&self, order_id: OrderId) -> Result<Vec<Invoice>>;
1153
1154    /// Delete an invoice (only if draft)
1155    fn delete(&self, id: InvoiceId) -> Result<()>;
1156
1157    // Status transitions
1158    /// Send invoice to customer
1159    fn send(&self, id: InvoiceId) -> Result<Invoice>;
1160
1161    /// Mark invoice as viewed
1162    fn mark_viewed(&self, id: InvoiceId) -> Result<Invoice>;
1163
1164    /// Record a payment on the invoice
1165    fn record_payment(&self, id: InvoiceId, payment: RecordInvoicePayment) -> Result<Invoice>;
1166
1167    /// Void an invoice
1168    fn void(&self, id: InvoiceId) -> Result<Invoice>;
1169
1170    /// Write off an invoice as uncollectible
1171    fn write_off(&self, id: InvoiceId) -> Result<Invoice>;
1172
1173    /// Mark invoice as disputed
1174    fn dispute(&self, id: InvoiceId) -> Result<Invoice>;
1175
1176    // Item operations
1177    /// Add item to invoice
1178    fn add_item(&self, invoice_id: InvoiceId, item: CreateInvoiceItem) -> Result<InvoiceItem>;
1179
1180    /// Update an invoice item
1181    fn update_item(&self, item_id: Uuid, item: CreateInvoiceItem) -> Result<InvoiceItem>;
1182
1183    /// Remove item from invoice
1184    fn remove_item(&self, item_id: Uuid) -> Result<()>;
1185
1186    /// Get items for invoice
1187    fn get_items(&self, invoice_id: InvoiceId) -> Result<Vec<InvoiceItem>>;
1188
1189    /// Recalculate invoice totals
1190    fn recalculate(&self, id: InvoiceId) -> Result<Invoice>;
1191
1192    /// Get overdue invoices
1193    fn get_overdue(&self) -> Result<Vec<Invoice>>;
1194
1195    /// Count invoices matching filter
1196    fn count(&self, filter: InvoiceFilter) -> Result<u64>;
1197
1198    // === Batch Operations ===
1199
1200    /// Create multiple invoices - partial success allowed
1201    fn create_batch(&self, inputs: Vec<CreateInvoice>) -> Result<BatchResult<Invoice>>;
1202
1203    /// Create multiple invoices - atomic (all-or-nothing)
1204    fn create_batch_atomic(&self, inputs: Vec<CreateInvoice>) -> Result<Vec<Invoice>>;
1205
1206    /// Update multiple invoices - partial success allowed
1207    fn update_batch(
1208        &self,
1209        updates: Vec<(InvoiceId, UpdateInvoice)>,
1210    ) -> Result<BatchResult<Invoice>>;
1211
1212    /// Update multiple invoices - atomic (all-or-nothing)
1213    fn update_batch_atomic(&self, updates: Vec<(InvoiceId, UpdateInvoice)>)
1214    -> Result<Vec<Invoice>>;
1215
1216    /// Delete multiple invoices - partial success allowed
1217    fn delete_batch(&self, ids: Vec<InvoiceId>) -> Result<BatchResult<Uuid>>;
1218
1219    /// Delete multiple invoices - atomic (all-or-nothing)
1220    fn delete_batch_atomic(&self, ids: Vec<InvoiceId>) -> Result<()>;
1221
1222    /// Get multiple invoices by ID
1223    fn get_batch(&self, ids: Vec<InvoiceId>) -> Result<Vec<Invoice>>;
1224}
1225
1226/// Cart/Checkout repository trait
1227#[auto_impl::auto_impl(&, Box, Arc)]
1228pub trait CartRepository: Send + Sync {
1229    /// Create a new cart/checkout session
1230    fn create(&self, input: CreateCart) -> Result<Cart>;
1231
1232    /// Get cart by ID
1233    fn get(&self, id: CartId) -> Result<Option<Cart>>;
1234
1235    /// Get cart by cart number
1236    fn get_by_number(&self, cart_number: &str) -> Result<Option<Cart>>;
1237
1238    /// Update a cart
1239    fn update(&self, id: CartId, input: UpdateCart) -> Result<Cart>;
1240
1241    /// List carts with filter
1242    fn list(&self, filter: CartFilter) -> Result<Vec<Cart>>;
1243
1244    /// Get carts for a customer
1245    fn for_customer(&self, customer_id: CustomerId) -> Result<Vec<Cart>>;
1246
1247    /// Delete a cart (or mark as cancelled)
1248    fn delete(&self, id: CartId) -> Result<()>;
1249
1250    // Item operations
1251    /// Add item to cart
1252    fn add_item(&self, cart_id: CartId, item: AddCartItem) -> Result<CartItem>;
1253
1254    /// Update a cart item (quantity, etc)
1255    fn update_item(&self, item_id: Uuid, input: UpdateCartItem) -> Result<CartItem>;
1256
1257    /// Remove item from cart
1258    fn remove_item(&self, item_id: Uuid) -> Result<()>;
1259
1260    /// Get items for a cart
1261    fn get_items(&self, cart_id: CartId) -> Result<Vec<CartItem>>;
1262
1263    /// Clear all items from cart
1264    fn clear_items(&self, cart_id: CartId) -> Result<()>;
1265
1266    // Address operations
1267    /// Set shipping address
1268    fn set_shipping_address(&self, id: CartId, address: CartAddress) -> Result<Cart>;
1269
1270    /// Set billing address
1271    fn set_billing_address(&self, id: CartId, address: CartAddress) -> Result<Cart>;
1272
1273    // Shipping operations
1274    /// Set shipping method
1275    fn set_shipping(&self, id: CartId, shipping: SetCartShipping) -> Result<Cart>;
1276
1277    /// Get available shipping rates for cart
1278    fn get_shipping_rates(&self, id: CartId) -> Result<Vec<ShippingRate>>;
1279
1280    // Payment operations
1281    /// Set payment method/token
1282    fn set_payment(&self, id: CartId, payment: SetCartPayment) -> Result<Cart>;
1283
1284    /// Set x402 payment method (stablecoin)
1285    fn set_x402_payment(&self, id: CartId, payment: SetCartX402Payment) -> Result<Cart>;
1286
1287    /// Complete checkout with x402 payment
1288    /// Returns `PaymentRequired` if no intent exists, `IntentCreated` if awaiting signature,
1289    /// `AwaitingSettlement` if signed but not settled, or Completed if settled
1290    fn complete_with_x402(&self, id: CartId, payee_address: &str) -> Result<X402CheckoutResult>;
1291
1292    // Discount operations
1293    /// Apply coupon/discount code
1294    fn apply_discount(&self, id: CartId, coupon_code: &str) -> Result<Cart>;
1295
1296    /// Remove discount
1297    fn remove_discount(&self, id: CartId) -> Result<Cart>;
1298
1299    // Status transitions
1300    /// Mark cart as ready for payment (validates all requirements met)
1301    fn mark_ready_for_payment(&self, id: CartId) -> Result<Cart>;
1302
1303    /// Begin checkout/payment process
1304    fn begin_checkout(&self, id: CartId) -> Result<Cart>;
1305
1306    /// Complete checkout (creates order, returns checkout result).
1307    ///
1308    /// The minted order is `Confirmed` with payment left `Pending`; record the
1309    /// payment through the payments API (or use
1310    /// [`complete_settled_externally`](Self::complete_settled_externally) when
1311    /// settlement genuinely happened out of band).
1312    fn complete(&self, id: CartId) -> Result<CheckoutResult>;
1313
1314    /// Complete checkout for a cart whose payment was settled outside the
1315    /// engine (ACP, external PSP). Explicitly opts in to minting an order that
1316    /// is `Confirmed` + `Paid` with no engine-side payment record.
1317    fn complete_settled_externally(&self, id: CartId) -> Result<CheckoutResult>;
1318
1319    /// Cancel a cart
1320    fn cancel(&self, id: CartId) -> Result<Cart>;
1321
1322    /// Mark cart as abandoned
1323    fn abandon(&self, id: CartId) -> Result<Cart>;
1324
1325    /// Expire a cart
1326    fn expire(&self, id: CartId) -> Result<Cart>;
1327
1328    // Inventory operations
1329    /// Reserve inventory for cart items
1330    fn reserve_inventory(&self, id: CartId) -> Result<Cart>;
1331
1332    /// Release inventory reservations
1333    fn release_inventory(&self, id: CartId) -> Result<Cart>;
1334
1335    // Totals
1336    /// Recalculate cart totals
1337    fn recalculate(&self, id: CartId) -> Result<Cart>;
1338
1339    /// Set tax amount
1340    fn set_tax(&self, id: CartId, tax_amount: rust_decimal::Decimal) -> Result<Cart>;
1341
1342    // Queries
1343    /// Get abandoned carts (for recovery campaigns)
1344    fn get_abandoned(&self) -> Result<Vec<Cart>>;
1345
1346    /// Get expired carts
1347    fn get_expired(&self) -> Result<Vec<Cart>>;
1348
1349    /// Count carts matching filter
1350    fn count(&self, filter: CartFilter) -> Result<u64>;
1351
1352    // === Batch Operations ===
1353
1354    /// Create multiple carts - partial success allowed
1355    fn create_batch(&self, inputs: Vec<CreateCart>) -> Result<BatchResult<Cart>>;
1356
1357    /// Create multiple carts - atomic (all-or-nothing)
1358    fn create_batch_atomic(&self, inputs: Vec<CreateCart>) -> Result<Vec<Cart>>;
1359
1360    /// Update multiple carts - partial success allowed
1361    fn update_batch(&self, updates: Vec<(CartId, UpdateCart)>) -> Result<BatchResult<Cart>>;
1362
1363    /// Update multiple carts - atomic (all-or-nothing)
1364    fn update_batch_atomic(&self, updates: Vec<(CartId, UpdateCart)>) -> Result<Vec<Cart>>;
1365
1366    /// Delete multiple carts - partial success allowed
1367    fn delete_batch(&self, ids: Vec<CartId>) -> Result<BatchResult<CartId>>;
1368
1369    /// Delete multiple carts - atomic (all-or-nothing)
1370    fn delete_batch_atomic(&self, ids: Vec<CartId>) -> Result<()>;
1371
1372    /// Get multiple carts by ID
1373    fn get_batch(&self, ids: Vec<CartId>) -> Result<Vec<Cart>>;
1374}
1375
1376/// Analytics repository trait
1377#[auto_impl::auto_impl(&, Box, Arc)]
1378pub trait AnalyticsRepository: Send + Sync {
1379    // Sales analytics
1380    /// Get sales summary for a time period
1381    fn get_sales_summary(&self, query: AnalyticsQuery) -> Result<SalesSummary>;
1382
1383    /// Get revenue broken down by time periods
1384    fn get_revenue_by_period(&self, query: AnalyticsQuery) -> Result<Vec<RevenueByPeriod>>;
1385
1386    /// Get top selling products
1387    fn get_top_products(&self, query: AnalyticsQuery) -> Result<Vec<TopProduct>>;
1388
1389    /// Get product performance with period comparison
1390    fn get_product_performance(&self, query: AnalyticsQuery) -> Result<Vec<ProductPerformance>>;
1391
1392    // Customer analytics
1393    /// Get customer metrics
1394    fn get_customer_metrics(&self, query: AnalyticsQuery) -> Result<CustomerMetrics>;
1395
1396    /// Get top customers by spend
1397    fn get_top_customers(&self, query: AnalyticsQuery) -> Result<Vec<TopCustomer>>;
1398
1399    // Inventory analytics
1400    /// Get inventory health summary
1401    fn get_inventory_health(&self) -> Result<InventoryHealth>;
1402
1403    /// Get low stock items
1404    fn get_low_stock_items(
1405        &self,
1406        threshold: Option<rust_decimal::Decimal>,
1407    ) -> Result<Vec<LowStockItem>>;
1408
1409    /// Get inventory movement summary
1410    fn get_inventory_movement(&self, query: AnalyticsQuery) -> Result<Vec<InventoryMovement>>;
1411
1412    // Order analytics
1413    /// Get order status breakdown
1414    fn get_order_status_breakdown(&self, query: AnalyticsQuery) -> Result<OrderStatusBreakdown>;
1415
1416    /// Get fulfillment metrics
1417    fn get_fulfillment_metrics(&self, query: AnalyticsQuery) -> Result<FulfillmentMetrics>;
1418
1419    // Return analytics
1420    /// Get return metrics
1421    fn get_return_metrics(&self, query: AnalyticsQuery) -> Result<ReturnMetrics>;
1422
1423    // Forecasting
1424    /// Get demand forecast for SKUs
1425    fn get_demand_forecast(
1426        &self,
1427        skus: Option<Vec<String>>,
1428        days_ahead: u32,
1429    ) -> Result<Vec<DemandForecast>>;
1430
1431    /// Get revenue forecast
1432    fn get_revenue_forecast(
1433        &self,
1434        periods_ahead: u32,
1435        granularity: TimeGranularity,
1436    ) -> Result<Vec<RevenueForecast>>;
1437
1438    // === Batch Operations ===
1439
1440    /// Get multiple sales summaries for different queries
1441    fn get_sales_summary_batch(&self, queries: Vec<AnalyticsQuery>) -> Result<Vec<SalesSummary>>;
1442}
1443
1444/// Currency and exchange rate repository trait
1445#[auto_impl::auto_impl(&, Box, Arc)]
1446pub trait CurrencyRepository: Send + Sync {
1447    /// Get current exchange rate between two currencies
1448    fn get_rate(&self, from: Currency, to: Currency) -> Result<Option<ExchangeRate>>;
1449
1450    /// Get all exchange rates for a base currency
1451    fn get_rates_for(&self, base: Currency) -> Result<Vec<ExchangeRate>>;
1452
1453    /// List all exchange rates with optional filter
1454    fn list_rates(&self, filter: ExchangeRateFilter) -> Result<Vec<ExchangeRate>>;
1455
1456    /// Set an exchange rate
1457    fn set_rate(&self, input: SetExchangeRate) -> Result<ExchangeRate>;
1458
1459    /// Set multiple exchange rates at once
1460    fn set_rates(&self, rates: Vec<SetExchangeRate>) -> Result<Vec<ExchangeRate>>;
1461
1462    /// Delete an exchange rate
1463    fn delete_rate(&self, id: Uuid) -> Result<()>;
1464
1465    /// Convert money between currencies
1466    fn convert(&self, input: ConvertCurrency) -> Result<ConversionResult>;
1467
1468    /// Get store currency settings
1469    fn get_settings(&self) -> Result<StoreCurrencySettings>;
1470
1471    /// Update store currency settings
1472    fn update_settings(&self, settings: StoreCurrencySettings) -> Result<StoreCurrencySettings>;
1473
1474    // === Batch Operations ===
1475
1476    /// Set multiple exchange rates - atomic (all-or-nothing)
1477    /// Note: `set_rates` already exists as a partial-success batch operation
1478    fn set_rates_atomic(&self, rates: Vec<SetExchangeRate>) -> Result<Vec<ExchangeRate>>;
1479
1480    /// Delete multiple exchange rates - partial success allowed
1481    fn delete_rates_batch(&self, ids: Vec<Uuid>) -> Result<BatchResult<Uuid>>;
1482
1483    /// Delete multiple exchange rates - atomic (all-or-nothing)
1484    fn delete_rates_atomic(&self, ids: Vec<Uuid>) -> Result<()>;
1485
1486    /// Get multiple exchange rates by currency pairs
1487    fn get_rates_batch(&self, pairs: Vec<(Currency, Currency)>) -> Result<Vec<ExchangeRate>>;
1488}
1489
1490/// Tax repository trait
1491#[auto_impl::auto_impl(&, Box, Arc)]
1492pub trait TaxRepository: Send + Sync {
1493    /// Create a tax jurisdiction
1494    fn create_jurisdiction(&self, input: CreateTaxJurisdiction) -> Result<TaxJurisdiction>;
1495    /// Get a tax jurisdiction by ID
1496    fn get_jurisdiction(&self, id: Uuid) -> Result<Option<TaxJurisdiction>>;
1497    /// Get a tax jurisdiction by code
1498    fn get_jurisdiction_by_code(&self, code: &str) -> Result<Option<TaxJurisdiction>>;
1499    /// List tax jurisdictions matching a filter
1500    fn list_jurisdictions(&self, filter: TaxJurisdictionFilter) -> Result<Vec<TaxJurisdiction>>;
1501
1502    /// Create a tax rate
1503    fn create_rate(&self, input: CreateTaxRate) -> Result<TaxRate>;
1504    /// Get a tax rate by ID
1505    fn get_rate(&self, id: Uuid) -> Result<Option<TaxRate>>;
1506    /// List tax rates matching a filter
1507    fn list_rates(&self, filter: TaxRateFilter) -> Result<Vec<TaxRate>>;
1508    /// Get applicable tax rates for an address and category on a date
1509    fn get_rates_for_address(
1510        &self,
1511        address: &TaxAddress,
1512        category: ProductTaxCategory,
1513        date: chrono::NaiveDate,
1514    ) -> Result<Vec<TaxRate>>;
1515
1516    /// Create a tax exemption
1517    fn create_exemption(&self, input: CreateTaxExemption) -> Result<TaxExemption>;
1518    /// Get a tax exemption by ID
1519    fn get_exemption(&self, id: Uuid) -> Result<Option<TaxExemption>>;
1520    /// Get all exemptions for a customer
1521    fn get_customer_exemptions(&self, customer_id: Uuid) -> Result<Vec<TaxExemption>>;
1522
1523    /// Get tax settings
1524    fn get_settings(&self) -> Result<TaxSettings>;
1525    /// Update tax settings
1526    fn update_settings(&self, settings: TaxSettings) -> Result<TaxSettings>;
1527
1528    /// Calculate tax for a request
1529    fn calculate_tax(&self, request: TaxCalculationRequest) -> Result<TaxCalculationResult>;
1530    /// Persist a tax calculation for audit/reporting
1531    fn save_calculation(
1532        &self,
1533        result: &TaxCalculationResult,
1534        order_id: Option<Uuid>,
1535        cart_id: Option<Uuid>,
1536        customer_id: Option<Uuid>,
1537        address: &TaxAddress,
1538        currency: &str,
1539    ) -> Result<()>;
1540}
1541
1542/// Promotions repository trait
1543#[auto_impl::auto_impl(&, Box, Arc)]
1544pub trait PromotionRepository: Send + Sync {
1545    /// Create a promotion
1546    fn create(&self, input: CreatePromotion) -> Result<Promotion>;
1547    /// Get a promotion by ID
1548    fn get(&self, id: PromotionId) -> Result<Option<Promotion>>;
1549    /// Get a promotion by code
1550    fn get_by_code(&self, code: &str) -> Result<Option<Promotion>>;
1551    /// List promotions matching a filter
1552    fn list(&self, filter: PromotionFilter) -> Result<Vec<Promotion>>;
1553    /// Update a promotion
1554    fn update(&self, id: PromotionId, input: UpdatePromotion) -> Result<Promotion>;
1555    /// Delete a promotion
1556    fn delete(&self, id: PromotionId) -> Result<()>;
1557    /// Activate a promotion
1558    fn activate(&self, id: PromotionId) -> Result<Promotion>;
1559    /// Deactivate a promotion
1560    fn deactivate(&self, id: PromotionId) -> Result<Promotion>;
1561
1562    /// Create a coupon code
1563    fn create_coupon(&self, input: CreateCouponCode) -> Result<CouponCode>;
1564    /// Get a coupon by ID
1565    fn get_coupon(&self, id: Uuid) -> Result<Option<CouponCode>>;
1566    /// Get a coupon by code
1567    fn get_coupon_by_code(&self, code: &str) -> Result<Option<CouponCode>>;
1568    /// List coupons matching a filter
1569    fn list_coupons(&self, filter: CouponFilter) -> Result<Vec<CouponCode>>;
1570
1571    /// Apply promotions to a cart or order snapshot
1572    fn apply_promotions(&self, request: ApplyPromotionsRequest) -> Result<ApplyPromotionsResult>;
1573    /// Record a promotion usage event
1574    #[allow(clippy::too_many_arguments)]
1575    fn record_usage(
1576        &self,
1577        promotion_id: PromotionId,
1578        coupon_id: Option<Uuid>,
1579        customer_id: Option<CustomerId>,
1580        order_id: Option<OrderId>,
1581        cart_id: Option<CartId>,
1582        discount_amount: rust_decimal::Decimal,
1583        currency: &str,
1584    ) -> Result<PromotionUsage>;
1585}
1586
1587/// Subscriptions repository trait
1588#[auto_impl::auto_impl(&, Box, Arc)]
1589pub trait SubscriptionRepository: Send + Sync {
1590    /// Create a subscription plan
1591    fn create_plan(&self, input: CreateSubscriptionPlan) -> Result<SubscriptionPlan>;
1592    /// Get a subscription plan by ID
1593    fn get_plan(&self, id: Uuid) -> Result<Option<SubscriptionPlan>>;
1594    /// Get a subscription plan by code
1595    fn get_plan_by_code(&self, code: &str) -> Result<Option<SubscriptionPlan>>;
1596    /// List subscription plans matching a filter
1597    fn list_plans(&self, filter: SubscriptionPlanFilter) -> Result<Vec<SubscriptionPlan>>;
1598    /// Update a subscription plan
1599    fn update_plan(&self, id: Uuid, input: UpdateSubscriptionPlan) -> Result<SubscriptionPlan>;
1600    /// Activate a subscription plan
1601    fn activate_plan(&self, id: Uuid) -> Result<SubscriptionPlan>;
1602    /// Archive a subscription plan
1603    fn archive_plan(&self, id: Uuid) -> Result<SubscriptionPlan>;
1604
1605    /// Create a subscription
1606    fn create_subscription(&self, input: CreateSubscription) -> Result<Subscription>;
1607    /// Get a subscription by ID
1608    fn get_subscription(&self, id: SubscriptionId) -> Result<Option<Subscription>>;
1609    /// Get a subscription by number
1610    fn get_subscription_by_number(&self, number: &str) -> Result<Option<Subscription>>;
1611    /// List subscriptions matching a filter
1612    fn list_subscriptions(&self, filter: SubscriptionFilter) -> Result<Vec<Subscription>>;
1613    /// Update a subscription
1614    fn update_subscription(
1615        &self,
1616        id: SubscriptionId,
1617        input: UpdateSubscription,
1618    ) -> Result<Subscription>;
1619    /// Cancel a subscription
1620    fn cancel_subscription(
1621        &self,
1622        id: SubscriptionId,
1623        input: CancelSubscription,
1624    ) -> Result<Subscription>;
1625    /// Pause a subscription
1626    fn pause_subscription(
1627        &self,
1628        id: SubscriptionId,
1629        input: PauseSubscription,
1630    ) -> Result<Subscription>;
1631    /// Resume a paused subscription
1632    fn resume_subscription(&self, id: SubscriptionId) -> Result<Subscription>;
1633
1634    /// Create a billing cycle
1635    fn create_billing_cycle(&self, input: CreateBillingCycle) -> Result<BillingCycle>;
1636    /// Get a billing cycle by ID
1637    fn get_billing_cycle(&self, id: Uuid) -> Result<Option<BillingCycle>>;
1638    /// List billing cycles matching a filter
1639    fn list_billing_cycles(&self, filter: BillingCycleFilter) -> Result<Vec<BillingCycle>>;
1640    /// Update the status of a billing cycle
1641    fn update_billing_cycle_status(
1642        &self,
1643        id: Uuid,
1644        status: BillingCycleStatus,
1645    ) -> Result<BillingCycle>;
1646    /// Skip a billing cycle
1647    fn skip_billing_cycle(
1648        &self,
1649        id: SubscriptionId,
1650        input: SkipBillingCycle,
1651    ) -> Result<Subscription>;
1652
1653    /// Record a subscription event
1654    fn record_event(
1655        &self,
1656        subscription_id: SubscriptionId,
1657        event_type: SubscriptionEventType,
1658        notes: Option<String>,
1659    ) -> Result<SubscriptionEvent>;
1660    /// Get all events for a subscription
1661    fn get_subscription_events(
1662        &self,
1663        subscription_id: SubscriptionId,
1664    ) -> Result<Vec<SubscriptionEvent>>;
1665}
1666
1667// The `Transactional` trait is defined in `repository.rs` and re-exported
1668// from this module via `pub use repository::Transactional;`.
1669
1670// ============================================================================
1671// Quality Control Repository
1672// ============================================================================
1673
1674/// Quality Control repository trait
1675#[auto_impl::auto_impl(&, Box, Arc)]
1676pub trait QualityRepository: Send + Sync {
1677    // Inspection operations
1678    /// Create a new inspection
1679    fn create_inspection(&self, input: CreateInspection) -> Result<Inspection>;
1680
1681    /// Get inspection by ID
1682    fn get_inspection(&self, id: Uuid) -> Result<Option<Inspection>>;
1683
1684    /// Get inspection by number
1685    fn get_inspection_by_number(&self, number: &str) -> Result<Option<Inspection>>;
1686
1687    /// Update an inspection
1688    fn update_inspection(&self, id: Uuid, input: UpdateInspection) -> Result<Inspection>;
1689
1690    /// List inspections with filter
1691    fn list_inspections(&self, filter: InspectionFilter) -> Result<Vec<Inspection>>;
1692
1693    /// Delete an inspection
1694    fn delete_inspection(&self, id: Uuid) -> Result<()>;
1695
1696    /// Start an inspection
1697    fn start_inspection(&self, id: Uuid) -> Result<Inspection>;
1698
1699    /// Complete an inspection
1700    fn complete_inspection(&self, id: Uuid) -> Result<Inspection>;
1701
1702    /// Record inspection result for an item
1703    fn record_inspection_result(&self, input: RecordInspectionResult) -> Result<InspectionItem>;
1704
1705    /// Get inspection items
1706    fn get_inspection_items(&self, inspection_id: Uuid) -> Result<Vec<InspectionItem>>;
1707
1708    /// Count inspections
1709    fn count_inspections(&self, filter: InspectionFilter) -> Result<u64>;
1710
1711    // NCR operations
1712    /// Create a non-conformance report
1713    fn create_ncr(&self, input: CreateNonConformance) -> Result<NonConformance>;
1714
1715    /// Get NCR by ID
1716    fn get_ncr(&self, id: Uuid) -> Result<Option<NonConformance>>;
1717
1718    /// Get NCR by number
1719    fn get_ncr_by_number(&self, number: &str) -> Result<Option<NonConformance>>;
1720
1721    /// Update an NCR
1722    fn update_ncr(&self, id: Uuid, input: UpdateNonConformance) -> Result<NonConformance>;
1723
1724    /// List NCRs with filter
1725    fn list_ncrs(&self, filter: NonConformanceFilter) -> Result<Vec<NonConformance>>;
1726
1727    /// Close an NCR
1728    fn close_ncr(&self, id: Uuid) -> Result<NonConformance>;
1729
1730    /// Cancel an NCR
1731    fn cancel_ncr(&self, id: Uuid) -> Result<NonConformance>;
1732
1733    /// Count NCRs
1734    fn count_ncrs(&self, filter: NonConformanceFilter) -> Result<u64>;
1735
1736    // Quality hold operations
1737    /// Create a quality hold
1738    fn create_hold(&self, input: CreateQualityHold) -> Result<QualityHold>;
1739
1740    /// Get hold by ID
1741    fn get_hold(&self, id: Uuid) -> Result<Option<QualityHold>>;
1742
1743    /// List holds with filter
1744    fn list_holds(&self, filter: QualityHoldFilter) -> Result<Vec<QualityHold>>;
1745
1746    /// Release a hold
1747    fn release_hold(&self, id: Uuid, input: ReleaseQualityHold) -> Result<QualityHold>;
1748
1749    /// Get active holds for SKU
1750    fn get_active_holds_for_sku(&self, sku: &str) -> Result<Vec<QualityHold>>;
1751
1752    /// Get active holds for lot
1753    fn get_active_holds_for_lot(&self, lot_number: &str) -> Result<Vec<QualityHold>>;
1754
1755    /// Count active holds
1756    fn count_active_holds(&self) -> Result<u64>;
1757
1758    // Defect code operations
1759    /// Create a defect code
1760    fn create_defect_code(&self, input: CreateDefectCode) -> Result<DefectCode>;
1761
1762    /// Get defect code by code
1763    fn get_defect_code(&self, code: &str) -> Result<Option<DefectCode>>;
1764
1765    /// List defect codes
1766    fn list_defect_codes(&self, category: Option<&str>) -> Result<Vec<DefectCode>>;
1767
1768    /// Deactivate a defect code
1769    fn deactivate_defect_code(&self, id: Uuid) -> Result<()>;
1770}
1771
1772// ============================================================================
1773// Lot Repository
1774// ============================================================================
1775
1776/// Lot/Batch tracking repository trait
1777#[auto_impl::auto_impl(&, Box, Arc)]
1778pub trait LotRepository: Send + Sync {
1779    /// Create a new lot
1780    fn create(&self, input: CreateLot) -> Result<Lot>;
1781
1782    /// Get lot by ID
1783    fn get(&self, id: Uuid) -> Result<Option<Lot>>;
1784
1785    /// Get lot by lot number
1786    fn get_by_number(&self, lot_number: &str) -> Result<Option<Lot>>;
1787
1788    /// Update a lot
1789    fn update(&self, id: Uuid, input: UpdateLot) -> Result<Lot>;
1790
1791    /// List lots with filter
1792    fn list(&self, filter: LotFilter) -> Result<Vec<Lot>>;
1793
1794    /// Delete a lot (only if no transactions)
1795    fn delete(&self, id: Uuid) -> Result<()>;
1796
1797    /// Adjust lot quantity
1798    fn adjust(&self, input: AdjustLot) -> Result<LotTransaction>;
1799
1800    /// Consume from a lot
1801    fn consume(&self, input: ConsumeLot) -> Result<LotTransaction>;
1802
1803    /// Reserve quantity from a lot
1804    fn reserve(&self, input: ReserveLot) -> Result<Uuid>;
1805
1806    /// Release a reservation
1807    fn release_reservation(&self, reservation_id: Uuid) -> Result<()>;
1808
1809    /// Confirm a reservation (convert to consumption)
1810    fn confirm_reservation(&self, reservation_id: Uuid) -> Result<LotTransaction>;
1811
1812    /// Transfer lot between locations
1813    fn transfer(&self, input: TransferLot) -> Result<LotTransaction>;
1814
1815    /// Split a lot into two
1816    fn split(&self, input: SplitLot) -> Result<Lot>;
1817
1818    /// Merge multiple lots into one
1819    fn merge(&self, input: MergeLots) -> Result<Lot>;
1820
1821    /// Quarantine a lot
1822    fn quarantine(&self, id: Uuid, reason: &str) -> Result<Lot>;
1823
1824    /// Release from quarantine
1825    fn release_quarantine(&self, id: Uuid) -> Result<Lot>;
1826
1827    /// Get lot transactions
1828    fn get_transactions(&self, lot_id: Uuid, limit: u32) -> Result<Vec<LotTransaction>>;
1829
1830    /// Get lot quantity at a location (None if no location record exists)
1831    fn get_quantity_at_location(
1832        &self,
1833        lot_id: Uuid,
1834        location_id: i32,
1835    ) -> Result<Option<rust_decimal::Decimal>>;
1836
1837    /// Get all locations for a lot
1838    fn get_lot_locations(&self, lot_id: Uuid) -> Result<Vec<LotLocation>>;
1839
1840    // Certificate operations
1841    /// Add certificate to lot
1842    fn add_certificate(&self, input: AddLotCertificate) -> Result<LotCertificate>;
1843
1844    /// Get certificates for lot
1845    fn get_certificates(&self, lot_id: Uuid) -> Result<Vec<LotCertificate>>;
1846
1847    /// Delete certificate
1848    fn delete_certificate(&self, certificate_id: Uuid) -> Result<()>;
1849
1850    // Queries
1851    /// Get expiring lots
1852    fn get_expiring_lots(&self, days: i32) -> Result<Vec<Lot>>;
1853
1854    /// Get expired lots
1855    fn get_expired_lots(&self) -> Result<Vec<Lot>>;
1856
1857    /// Get lots with available quantity for SKU
1858    fn get_available_lots_for_sku(&self, sku: &str) -> Result<Vec<Lot>>;
1859
1860    /// Trace lot (upstream and downstream)
1861    fn trace(&self, lot_id: Uuid) -> Result<TraceabilityResult>;
1862
1863    /// Count lots
1864    fn count(&self, filter: LotFilter) -> Result<u64>;
1865
1866    // Batch operations
1867    /// Create multiple lots
1868    fn create_batch(&self, inputs: Vec<CreateLot>) -> Result<BatchResult<Lot>>;
1869
1870    /// Get multiple lots by ID
1871    fn get_batch(&self, ids: Vec<Uuid>) -> Result<Vec<Lot>>;
1872}
1873
1874// ============================================================================
1875// Serial Number Repository
1876// ============================================================================
1877
1878/// Serial number management repository trait
1879#[auto_impl::auto_impl(&, Box, Arc)]
1880pub trait SerialRepository: Send + Sync {
1881    /// Create a serial number
1882    fn create(&self, input: CreateSerialNumber) -> Result<SerialNumber>;
1883
1884    /// Create multiple serial numbers in bulk
1885    fn create_bulk(&self, input: CreateSerialNumbersBulk) -> Result<Vec<SerialNumber>>;
1886
1887    /// Get serial by ID
1888    fn get(&self, id: Uuid) -> Result<Option<SerialNumber>>;
1889
1890    /// Get serial by serial number string
1891    fn get_by_serial(&self, serial: &str) -> Result<Option<SerialNumber>>;
1892
1893    /// Update a serial number
1894    fn update(&self, id: Uuid, input: UpdateSerialNumber) -> Result<SerialNumber>;
1895
1896    /// List serials with filter
1897    fn list(&self, filter: SerialFilter) -> Result<Vec<SerialNumber>>;
1898
1899    /// Delete a serial (only if never used)
1900    fn delete(&self, id: Uuid) -> Result<()>;
1901
1902    /// Change serial status with history tracking
1903    fn change_status(&self, input: ChangeSerialStatus) -> Result<SerialNumber>;
1904
1905    /// Reserve a serial
1906    fn reserve(&self, input: ReserveSerialNumber) -> Result<SerialReservation>;
1907
1908    /// Release reservation
1909    fn release_reservation(&self, reservation_id: Uuid) -> Result<()>;
1910
1911    /// Confirm reservation
1912    fn confirm_reservation(&self, reservation_id: Uuid) -> Result<()>;
1913
1914    /// Move serial to new location
1915    fn move_serial(&self, input: MoveSerial) -> Result<SerialNumber>;
1916
1917    /// Transfer ownership
1918    fn transfer_ownership(&self, input: TransferSerialOwnership) -> Result<SerialNumber>;
1919
1920    /// Mark as sold
1921    fn mark_sold(
1922        &self,
1923        id: Uuid,
1924        customer_id: Uuid,
1925        order_id: Option<Uuid>,
1926    ) -> Result<SerialNumber>;
1927
1928    /// Mark as shipped
1929    fn mark_shipped(&self, id: Uuid, shipment_id: Uuid) -> Result<SerialNumber>;
1930
1931    /// Mark as returned
1932    fn mark_returned(&self, id: Uuid, return_id: Uuid) -> Result<SerialNumber>;
1933
1934    /// Activate serial (e.g., for warranty)
1935    fn activate(&self, id: Uuid) -> Result<SerialNumber>;
1936
1937    /// Quarantine serial
1938    fn quarantine(&self, id: Uuid, reason: &str) -> Result<SerialNumber>;
1939
1940    /// Release from quarantine
1941    fn release_quarantine(&self, id: Uuid) -> Result<SerialNumber>;
1942
1943    /// Scrap serial
1944    fn scrap(&self, id: Uuid, reason: &str) -> Result<SerialNumber>;
1945
1946    // History operations
1947    /// Get serial history
1948    fn get_history(
1949        &self,
1950        serial_id: Uuid,
1951        filter: SerialHistoryFilter,
1952    ) -> Result<Vec<SerialHistory>>;
1953
1954    /// Get full serial lookup with related data
1955    fn lookup(&self, serial: &str) -> Result<Option<SerialLookupResult>>;
1956
1957    /// Validate serial number
1958    fn validate(&self, serial: &str) -> Result<SerialValidation>;
1959
1960    // Queries
1961    /// Get available serials for SKU
1962    fn get_available_for_sku(&self, sku: &str, limit: u32) -> Result<Vec<SerialNumber>>;
1963
1964    /// Get serials for lot
1965    fn get_for_lot(&self, lot_id: Uuid) -> Result<Vec<SerialNumber>>;
1966
1967    /// Get serials for customer
1968    fn get_for_customer(&self, customer_id: Uuid) -> Result<Vec<SerialNumber>>;
1969
1970    /// Count serials
1971    fn count(&self, filter: SerialFilter) -> Result<u64>;
1972
1973    // Batch operations
1974    /// Create multiple serials
1975    fn create_batch(&self, inputs: Vec<CreateSerialNumber>) -> Result<BatchResult<SerialNumber>>;
1976
1977    /// Get multiple serials by ID
1978    fn get_batch(&self, ids: Vec<Uuid>) -> Result<Vec<SerialNumber>>;
1979
1980    /// Get multiple serials by serial string
1981    fn get_batch_by_serial(&self, serials: Vec<String>) -> Result<Vec<SerialNumber>>;
1982}
1983
1984// ============================================================================
1985// Warehouse Repository
1986// ============================================================================
1987
1988/// Warehouse management repository trait
1989#[auto_impl::auto_impl(&, Box, Arc)]
1990pub trait WarehouseRepository: Send + Sync {
1991    // Warehouse operations
1992    /// Create a new warehouse
1993    fn create_warehouse(&self, input: CreateWarehouse) -> Result<Warehouse>;
1994
1995    /// Get warehouse by ID
1996    fn get_warehouse(&self, id: i32) -> Result<Option<Warehouse>>;
1997
1998    /// Get warehouse by code
1999    fn get_warehouse_by_code(&self, code: &str) -> Result<Option<Warehouse>>;
2000
2001    /// Update a warehouse
2002    fn update_warehouse(&self, id: i32, input: UpdateWarehouse) -> Result<Warehouse>;
2003
2004    /// List warehouses with filter
2005    fn list_warehouses(&self, filter: WarehouseFilter) -> Result<Vec<Warehouse>>;
2006
2007    /// Delete a warehouse (only if empty)
2008    fn delete_warehouse(&self, id: i32) -> Result<()>;
2009
2010    /// Count warehouses
2011    fn count_warehouses(&self, filter: WarehouseFilter) -> Result<u64>;
2012
2013    // Zone operations
2014    /// Create a zone
2015    fn create_zone(&self, input: CreateZone) -> Result<Zone>;
2016
2017    /// Get zone by ID
2018    fn get_zone(&self, id: i32) -> Result<Option<Zone>>;
2019
2020    /// Get zones for warehouse
2021    fn get_zones(&self, warehouse_id: i32) -> Result<Vec<Zone>>;
2022
2023    /// Update a zone
2024    fn update_zone(&self, id: i32, input: UpdateZone) -> Result<Zone>;
2025
2026    /// Delete a zone
2027    fn delete_zone(&self, id: i32) -> Result<()>;
2028
2029    // Location operations
2030    /// Create a location
2031    fn create_location(&self, input: CreateLocation) -> Result<Location>;
2032
2033    /// Get location by ID
2034    fn get_location(&self, id: i32) -> Result<Option<Location>>;
2035
2036    /// Get location by code
2037    fn get_location_by_code(&self, warehouse_id: i32, code: &str) -> Result<Option<Location>>;
2038
2039    /// Update a location
2040    fn update_location(&self, id: i32, input: UpdateLocation) -> Result<Location>;
2041
2042    /// List locations with filter
2043    fn list_locations(&self, filter: LocationFilter) -> Result<Vec<Location>>;
2044
2045    /// Delete a location (only if empty)
2046    fn delete_location(&self, id: i32) -> Result<()>;
2047
2048    /// Count locations
2049    fn count_locations(&self, filter: LocationFilter) -> Result<u64>;
2050
2051    /// Get locations for warehouse
2052    fn get_locations_for_warehouse(&self, warehouse_id: i32) -> Result<Vec<Location>>;
2053
2054    /// Get pickable locations for SKU
2055    fn get_pickable_locations(&self, warehouse_id: i32, sku: &str) -> Result<Vec<Location>>;
2056
2057    /// Get receivable locations
2058    fn get_receivable_locations(&self, warehouse_id: i32) -> Result<Vec<Location>>;
2059
2060    // Location inventory operations
2061    /// Get inventory at location
2062    fn get_location_inventory(&self, location_id: i32) -> Result<Vec<LocationInventory>>;
2063
2064    /// Get inventory for SKU across locations
2065    fn get_inventory_for_sku(&self, warehouse_id: i32, sku: &str)
2066    -> Result<Vec<LocationInventory>>;
2067
2068    /// Adjust inventory at location
2069    fn adjust_inventory(&self, input: AdjustLocationInventory) -> Result<LocationInventory>;
2070
2071    /// Move inventory between locations
2072    fn move_inventory(&self, input: MoveInventory) -> Result<LocationMovement>;
2073
2074    /// Get location inventory by filter
2075    fn list_location_inventory(
2076        &self,
2077        filter: LocationInventoryFilter,
2078    ) -> Result<Vec<LocationInventory>>;
2079
2080    // Movement operations
2081    /// Get inventory movements
2082    fn get_movements(&self, filter: MovementFilter) -> Result<Vec<LocationMovement>>;
2083
2084    /// Count movements
2085    fn count_movements(&self, filter: MovementFilter) -> Result<u64>;
2086
2087    // Batch operations
2088    /// Create multiple locations
2089    fn create_locations_batch(&self, inputs: Vec<CreateLocation>) -> Result<BatchResult<Location>>;
2090
2091    /// Get multiple locations by ID
2092    fn get_locations_batch(&self, ids: Vec<i32>) -> Result<Vec<Location>>;
2093
2094    // Cycle count operations
2095    /// Create a cycle count (draft) with its expected lines
2096    fn create_cycle_count(&self, input: CreateCycleCount) -> Result<CycleCount>;
2097
2098    /// Get a cycle count (with lines) by ID
2099    fn get_cycle_count(&self, id: Uuid) -> Result<Option<CycleCount>>;
2100
2101    /// List cycle counts (with lines) matching the filter
2102    fn list_cycle_counts(&self, filter: CycleCountFilter) -> Result<Vec<CycleCount>>;
2103
2104    /// Start a draft cycle count (draft → `in_progress`)
2105    fn start_cycle_count(&self, id: Uuid) -> Result<CycleCount>;
2106
2107    /// Record physical counts against an in-progress cycle count
2108    fn record_cycle_counts(
2109        &self,
2110        id: Uuid,
2111        counts: Vec<RecordCycleCountLine>,
2112    ) -> Result<CycleCount>;
2113
2114    /// Complete an in-progress cycle count: computes variances and applies
2115    /// inventory adjustments (recorded as `cycle_count` movements)
2116    fn complete_cycle_count(&self, id: Uuid) -> Result<CycleCount>;
2117
2118    /// Cancel a draft or in-progress cycle count
2119    fn cancel_cycle_count(&self, id: Uuid) -> Result<CycleCount>;
2120}
2121
2122// ============================================================================
2123// Receiving Repository
2124// ============================================================================
2125
2126/// Receiving/Goods receipt repository trait
2127#[auto_impl::auto_impl(&, Box, Arc)]
2128pub trait ReceivingRepository: Send + Sync {
2129    // Receipt operations
2130    /// Create a new receipt
2131    fn create_receipt(&self, input: CreateReceipt) -> Result<Receipt>;
2132
2133    /// Get receipt by ID
2134    fn get_receipt(&self, id: Uuid) -> Result<Option<Receipt>>;
2135
2136    /// Get receipt by receipt number
2137    fn get_receipt_by_number(&self, number: &str) -> Result<Option<Receipt>>;
2138
2139    /// Update a receipt
2140    fn update_receipt(&self, id: Uuid, input: UpdateReceipt) -> Result<Receipt>;
2141
2142    /// List receipts with filter
2143    fn list_receipts(&self, filter: ReceiptFilter) -> Result<Vec<Receipt>>;
2144
2145    /// Delete a receipt (only if not started)
2146    fn delete_receipt(&self, id: Uuid) -> Result<()>;
2147
2148    /// Start receiving (transition to `in_progress`)
2149    fn start_receiving(&self, id: Uuid) -> Result<Receipt>;
2150
2151    /// Receive items on a receipt
2152    fn receive_items(&self, input: ReceiveItems) -> Result<Receipt>;
2153
2154    /// Complete receiving (all items received)
2155    fn complete_receiving(&self, id: Uuid) -> Result<Receipt>;
2156
2157    /// Cancel a receipt
2158    fn cancel_receipt(&self, id: Uuid) -> Result<Receipt>;
2159
2160    /// Get receipt items
2161    fn get_receipt_items(&self, receipt_id: Uuid) -> Result<Vec<ReceiptItem>>;
2162
2163    /// Count receipts
2164    fn count_receipts(&self, filter: ReceiptFilter) -> Result<u64>;
2165
2166    // Put-away operations
2167    /// Create a put-away task
2168    fn create_put_away(&self, input: CreatePutAway) -> Result<PutAway>;
2169
2170    /// Get put-away by ID
2171    fn get_put_away(&self, id: Uuid) -> Result<Option<PutAway>>;
2172
2173    /// List put-aways with filter
2174    fn list_put_aways(&self, filter: PutAwayFilter) -> Result<Vec<PutAway>>;
2175
2176    /// Assign put-away to user
2177    fn assign_put_away(&self, id: Uuid, assigned_to: &str) -> Result<PutAway>;
2178
2179    /// Start put-away
2180    fn start_put_away(&self, id: Uuid) -> Result<PutAway>;
2181
2182    /// Complete put-away
2183    fn complete_put_away(&self, input: CompletePutAway) -> Result<PutAway>;
2184
2185    /// Cancel put-away
2186    fn cancel_put_away(&self, id: Uuid) -> Result<PutAway>;
2187
2188    /// Get pending put-aways for receipt
2189    fn get_pending_put_aways(&self, receipt_id: Uuid) -> Result<Vec<PutAway>>;
2190
2191    /// Count put-aways
2192    fn count_put_aways(&self, filter: PutAwayFilter) -> Result<u64>;
2193
2194    // Integration with PO
2195    /// Create receipt from purchase order
2196    fn create_receipt_from_po(&self, po_id: Uuid, warehouse_id: i32) -> Result<Receipt>;
2197
2198    // Batch operations
2199    /// Create multiple receipts
2200    fn create_receipts_batch(&self, inputs: Vec<CreateReceipt>) -> Result<BatchResult<Receipt>>;
2201
2202    /// Get multiple receipts by ID
2203    fn get_receipts_batch(&self, ids: Vec<Uuid>) -> Result<Vec<Receipt>>;
2204}
2205
2206// ============================================================================
2207// Fulfillment Repository
2208// ============================================================================
2209
2210/// Fulfillment (pick/pack/ship) repository trait
2211#[auto_impl::auto_impl(&, Box, Arc)]
2212pub trait FulfillmentRepository: Send + Sync {
2213    // Wave operations
2214    /// Create a wave from orders
2215    fn create_wave(&self, input: CreateWave) -> Result<Wave>;
2216
2217    /// Get wave by ID
2218    fn get_wave(&self, id: FulfillmentId) -> Result<Option<Wave>>;
2219
2220    /// Get wave by number
2221    fn get_wave_by_number(&self, number: &str) -> Result<Option<Wave>>;
2222
2223    /// List waves with filter
2224    fn list_waves(&self, filter: WaveFilter) -> Result<Vec<Wave>>;
2225
2226    /// Release wave for picking
2227    fn release_wave(&self, id: FulfillmentId) -> Result<Wave>;
2228
2229    /// Complete a wave
2230    fn complete_wave(&self, id: FulfillmentId) -> Result<Wave>;
2231
2232    /// Cancel a wave
2233    fn cancel_wave(&self, id: FulfillmentId) -> Result<Wave>;
2234
2235    /// Get orders in a wave
2236    fn get_wave_orders(&self, wave_id: FulfillmentId) -> Result<Vec<OrderId>>;
2237
2238    /// Count waves
2239    fn count_waves(&self, filter: WaveFilter) -> Result<u64>;
2240
2241    // Pick operations
2242    /// Create a pick task
2243    fn create_pick(&self, input: CreatePickTask) -> Result<PickTask>;
2244
2245    /// Get pick task by ID
2246    fn get_pick(&self, id: Uuid) -> Result<Option<PickTask>>;
2247
2248    /// List pick tasks with filter
2249    fn list_picks(&self, filter: PickTaskFilter) -> Result<Vec<PickTask>>;
2250
2251    /// Assign pick to user
2252    fn assign_pick(&self, id: Uuid, assigned_to: &str) -> Result<PickTask>;
2253
2254    /// Start a pick
2255    fn start_pick(&self, id: Uuid) -> Result<PickTask>;
2256
2257    /// Complete a pick
2258    fn complete_pick(&self, input: CompletePick) -> Result<PickTask>;
2259
2260    /// Report short pick
2261    fn report_short(
2262        &self,
2263        id: Uuid,
2264        short_qty: rust_decimal::Decimal,
2265        reason: &str,
2266    ) -> Result<PickTask>;
2267
2268    /// Cancel a pick
2269    fn cancel_pick(&self, id: Uuid) -> Result<PickTask>;
2270
2271    /// Get picks for order
2272    fn get_picks_for_order(&self, order_id: OrderId) -> Result<Vec<PickTask>>;
2273
2274    /// Get picks for wave
2275    fn get_picks_for_wave(&self, wave_id: FulfillmentId) -> Result<Vec<PickTask>>;
2276
2277    /// Count picks
2278    fn count_picks(&self, filter: PickTaskFilter) -> Result<u64>;
2279
2280    // Pack operations
2281    /// Create a pack task
2282    fn create_pack(&self, input: CreatePackTask) -> Result<PackTask>;
2283
2284    /// Get pack task by ID
2285    fn get_pack(&self, id: Uuid) -> Result<Option<PackTask>>;
2286
2287    /// List pack tasks with filter
2288    fn list_packs(&self, filter: PackTaskFilter) -> Result<Vec<PackTask>>;
2289
2290    /// Assign pack to user
2291    fn assign_pack(&self, id: Uuid, assigned_to: &str) -> Result<PackTask>;
2292
2293    /// Start packing
2294    fn start_pack(&self, id: Uuid) -> Result<PackTask>;
2295
2296    /// Complete packing
2297    fn complete_pack(&self, id: Uuid) -> Result<PackTask>;
2298
2299    /// Add carton to pack task
2300    fn add_carton(&self, input: AddCarton) -> Result<Carton>;
2301
2302    /// Add item to carton
2303    fn add_carton_item(&self, input: AddCartonItem) -> Result<CartonItem>;
2304
2305    /// Get cartons for pack task
2306    fn get_cartons(&self, pack_task_id: Uuid) -> Result<Vec<Carton>>;
2307
2308    /// Get items in carton
2309    fn get_carton_items(&self, carton_id: Uuid) -> Result<Vec<CartonItem>>;
2310
2311    /// Mark carton label printed
2312    fn mark_label_printed(&self, carton_id: Uuid) -> Result<Carton>;
2313
2314    /// Cancel pack task
2315    fn cancel_pack(&self, id: Uuid) -> Result<PackTask>;
2316
2317    /// Count packs
2318    fn count_packs(&self, filter: PackTaskFilter) -> Result<u64>;
2319
2320    // Ship operations
2321    /// Create a ship task
2322    fn create_ship(&self, input: CreateShipTask) -> Result<ShipTask>;
2323
2324    /// Get ship task by ID
2325    fn get_ship(&self, id: Uuid) -> Result<Option<ShipTask>>;
2326
2327    /// List ship tasks with filter
2328    fn list_ships(&self, filter: ShipTaskFilter) -> Result<Vec<ShipTask>>;
2329
2330    /// Assign ship to user
2331    fn assign_ship(&self, id: Uuid, assigned_to: &str) -> Result<ShipTask>;
2332
2333    /// Print shipping label
2334    fn print_label(&self, id: Uuid, label_url: &str) -> Result<ShipTask>;
2335
2336    /// Complete shipping
2337    fn complete_ship(&self, input: CompleteShip) -> Result<ShipTask>;
2338
2339    /// Cancel ship task
2340    fn cancel_ship(&self, id: Uuid) -> Result<ShipTask>;
2341
2342    /// Count ships
2343    fn count_ships(&self, filter: ShipTaskFilter) -> Result<u64>;
2344
2345    // Workflow helpers
2346    /// Create picks for an order
2347    fn create_picks_for_order(&self, order_id: OrderId, warehouse_id: i32)
2348    -> Result<Vec<PickTask>>;
2349
2350    /// Check if order is ready to pack
2351    fn is_order_ready_to_pack(&self, order_id: OrderId) -> Result<bool>;
2352
2353    /// Check if order is ready to ship
2354    fn is_order_ready_to_ship(&self, order_id: OrderId) -> Result<bool>;
2355
2356    // Batch operations
2357    /// Create multiple waves
2358    fn create_waves_batch(&self, inputs: Vec<CreateWave>) -> Result<BatchResult<Wave>>;
2359
2360    /// Get multiple picks by ID
2361    fn get_picks_batch(&self, ids: Vec<Uuid>) -> Result<Vec<PickTask>>;
2362}
2363
2364// ============================================================================
2365// Accounts Payable Repository
2366// ============================================================================
2367
2368/// Accounts Payable repository trait
2369#[auto_impl::auto_impl(&, Box, Arc)]
2370pub trait AccountsPayableRepository: Send + Sync {
2371    // Bill operations
2372    /// Create a new bill
2373    fn create_bill(&self, input: CreateBill) -> Result<Bill>;
2374
2375    /// Get bill by ID
2376    fn get_bill(&self, id: Uuid) -> Result<Option<Bill>>;
2377
2378    /// Get bill by number
2379    fn get_bill_by_number(&self, number: &str) -> Result<Option<Bill>>;
2380
2381    /// Update a bill
2382    fn update_bill(&self, id: Uuid, input: UpdateBill) -> Result<Bill>;
2383
2384    /// List bills with filter
2385    fn list_bills(&self, filter: BillFilter) -> Result<Vec<Bill>>;
2386
2387    /// Delete a bill (only if draft)
2388    fn delete_bill(&self, id: Uuid) -> Result<()>;
2389
2390    /// Approve a bill
2391    fn approve_bill(&self, id: Uuid) -> Result<Bill>;
2392
2393    /// Cancel a bill
2394    fn cancel_bill(&self, id: Uuid) -> Result<Bill>;
2395
2396    /// Mark bill as disputed
2397    fn dispute_bill(&self, id: Uuid) -> Result<Bill>;
2398
2399    /// Get bill items
2400    fn get_bill_items(&self, bill_id: Uuid) -> Result<Vec<BillItem>>;
2401
2402    /// Add item to bill
2403    fn add_bill_item(&self, bill_id: Uuid, item: CreateBillItem) -> Result<BillItem>;
2404
2405    /// Remove item from bill
2406    fn remove_bill_item(&self, item_id: Uuid) -> Result<()>;
2407
2408    /// Count bills
2409    fn count_bills(&self, filter: BillFilter) -> Result<u64>;
2410
2411    /// Get overdue bills
2412    fn get_overdue_bills(&self) -> Result<Vec<Bill>>;
2413
2414    /// Get bills due soon (within days)
2415    fn get_bills_due_soon(&self, days: i32) -> Result<Vec<Bill>>;
2416
2417    // Payment operations
2418    /// Create a payment
2419    fn create_payment(&self, input: CreateBillPayment) -> Result<BillPayment>;
2420
2421    /// Get payment by ID
2422    fn get_payment(&self, id: Uuid) -> Result<Option<BillPayment>>;
2423
2424    /// Get payment by number
2425    fn get_payment_by_number(&self, number: &str) -> Result<Option<BillPayment>>;
2426
2427    /// List payments with filter
2428    fn list_payments(&self, filter: BillPaymentFilter) -> Result<Vec<BillPayment>>;
2429
2430    /// Void a payment
2431    fn void_payment(&self, id: Uuid) -> Result<BillPayment>;
2432
2433    /// Mark payment as cleared
2434    fn clear_payment(&self, id: Uuid) -> Result<BillPayment>;
2435
2436    /// Get payment allocations
2437    fn get_payment_allocations(&self, payment_id: Uuid) -> Result<Vec<PaymentAllocation>>;
2438
2439    /// Get payments for bill
2440    fn get_payments_for_bill(&self, bill_id: Uuid) -> Result<Vec<BillPayment>>;
2441
2442    /// Count payments
2443    fn count_payments(&self, filter: BillPaymentFilter) -> Result<u64>;
2444
2445    // Payment run operations
2446    /// Create a payment run
2447    fn create_payment_run(&self, input: CreatePaymentRun) -> Result<PaymentRun>;
2448
2449    /// Get payment run by ID
2450    fn get_payment_run(&self, id: Uuid) -> Result<Option<PaymentRun>>;
2451
2452    /// List payment runs with filter
2453    fn list_payment_runs(&self, filter: PaymentRunFilter) -> Result<Vec<PaymentRun>>;
2454
2455    /// Approve payment run
2456    fn approve_payment_run(&self, id: Uuid, approved_by: &str) -> Result<PaymentRun>;
2457
2458    /// Process payment run
2459    fn process_payment_run(&self, id: Uuid) -> Result<PaymentRun>;
2460
2461    /// Cancel payment run
2462    fn cancel_payment_run(&self, id: Uuid) -> Result<PaymentRun>;
2463
2464    /// Get bills in payment run
2465    fn get_payment_run_bills(&self, run_id: Uuid) -> Result<Vec<Bill>>;
2466
2467    // Analytics
2468    /// Get AP aging summary
2469    fn get_aging_summary(&self) -> Result<ApAgingSummary>;
2470
2471    /// Get AP summary by supplier (None if supplier is not found)
2472    fn get_supplier_summary(&self, supplier_id: Uuid) -> Result<Option<SupplierApSummary>>;
2473
2474    /// Get total AP outstanding
2475    fn get_total_outstanding(&self) -> Result<rust_decimal::Decimal>;
2476
2477    // Batch operations
2478    /// Create multiple bills
2479    fn create_bills_batch(&self, inputs: Vec<CreateBill>) -> Result<BatchResult<Bill>>;
2480
2481    /// Get multiple bills by ID
2482    fn get_bills_batch(&self, ids: Vec<Uuid>) -> Result<Vec<Bill>>;
2483}
2484
2485/// Cost Accounting repository trait
2486#[auto_impl::auto_impl(&, Box, Arc)]
2487pub trait CostAccountingRepository: Send + Sync {
2488    // Item cost operations
2489    /// Get item cost by SKU
2490    fn get_item_cost(&self, sku: &str) -> Result<Option<ItemCost>>;
2491
2492    /// Set/update item cost
2493    fn set_item_cost(&self, input: SetItemCost) -> Result<ItemCost>;
2494
2495    /// List item costs
2496    fn list_item_costs(&self, filter: ItemCostFilter) -> Result<Vec<ItemCost>>;
2497
2498    /// Update average cost (called when receiving inventory)
2499    fn update_average_cost(
2500        &self,
2501        sku: &str,
2502        quantity: rust_decimal::Decimal,
2503        unit_cost: rust_decimal::Decimal,
2504    ) -> Result<ItemCost>;
2505
2506    /// Update last cost
2507    fn update_last_cost(&self, sku: &str, unit_cost: rust_decimal::Decimal) -> Result<ItemCost>;
2508
2509    // Cost layer operations (for FIFO/LIFO)
2510    /// Create a cost layer
2511    fn create_cost_layer(&self, input: CreateCostLayer) -> Result<CostLayer>;
2512
2513    /// Get cost layer by ID
2514    fn get_cost_layer(&self, id: Uuid) -> Result<Option<CostLayer>>;
2515
2516    /// List cost layers
2517    fn list_cost_layers(&self, filter: CostLayerFilter) -> Result<Vec<CostLayer>>;
2518
2519    /// Issue from cost layers (FIFO)
2520    fn issue_fifo(&self, input: IssueCostLayers) -> Result<Vec<CostTransaction>>;
2521
2522    /// Issue from cost layers (LIFO)
2523    fn issue_lifo(&self, input: IssueCostLayers) -> Result<Vec<CostTransaction>>;
2524
2525    /// Get remaining quantity in layers for SKU
2526    fn get_layers_remaining(&self, sku: &str) -> Result<rust_decimal::Decimal>;
2527
2528    // Cost transaction operations
2529    /// Record a cost transaction
2530    #[allow(clippy::too_many_arguments)]
2531    fn record_cost_transaction(
2532        &self,
2533        sku: &str,
2534        transaction_type: CostTransactionType,
2535        quantity: rust_decimal::Decimal,
2536        unit_cost: rust_decimal::Decimal,
2537        layer_id: Option<Uuid>,
2538        reference_type: Option<&str>,
2539        reference_id: Option<Uuid>,
2540        notes: Option<&str>,
2541    ) -> Result<CostTransaction>;
2542
2543    /// List cost transactions
2544    fn list_cost_transactions(&self, filter: CostTransactionFilter)
2545    -> Result<Vec<CostTransaction>>;
2546
2547    // Cost variance operations
2548    /// Record a cost variance
2549    fn record_variance(&self, input: RecordCostVariance) -> Result<CostVariance>;
2550
2551    /// List cost variances
2552    fn list_variances(&self, filter: CostVarianceFilter) -> Result<Vec<CostVariance>>;
2553
2554    /// Get variance summary for period
2555    fn get_variance_summary(
2556        &self,
2557        from: DateTime<Utc>,
2558        to: DateTime<Utc>,
2559    ) -> Result<rust_decimal::Decimal>;
2560
2561    // Cost adjustment operations
2562    /// Create a cost adjustment
2563    fn create_adjustment(&self, input: CreateCostAdjustment) -> Result<CostAdjustment>;
2564
2565    /// Get adjustment by ID
2566    fn get_adjustment(&self, id: Uuid) -> Result<Option<CostAdjustment>>;
2567
2568    /// List adjustments
2569    fn list_adjustments(&self, filter: CostAdjustmentFilter) -> Result<Vec<CostAdjustment>>;
2570
2571    /// Approve adjustment
2572    fn approve_adjustment(&self, id: Uuid, approved_by: &str) -> Result<CostAdjustment>;
2573
2574    /// Apply adjustment (update item cost)
2575    fn apply_adjustment(&self, id: Uuid) -> Result<CostAdjustment>;
2576
2577    /// Reject adjustment
2578    fn reject_adjustment(&self, id: Uuid) -> Result<CostAdjustment>;
2579
2580    // Rollup operations
2581    /// Calculate cost rollup for manufactured item
2582    fn calculate_rollup(&self, sku: &str, bom_id: Option<Uuid>) -> Result<CostRollup>;
2583
2584    /// Get latest rollup for SKU
2585    fn get_rollup(&self, sku: &str) -> Result<Option<CostRollup>>;
2586
2587    // Valuation operations
2588    /// Get inventory valuation
2589    fn get_inventory_valuation(&self, cost_method: CostMethod) -> Result<InventoryValuation>;
2590
2591    /// Get SKU cost summary
2592    fn get_sku_cost_summary(&self, sku: &str) -> Result<Option<SkuCostSummary>>;
2593
2594    /// Get total inventory value
2595    fn get_total_inventory_value(&self) -> Result<rust_decimal::Decimal>;
2596}
2597
2598/// Credit Management repository trait
2599#[auto_impl::auto_impl(&, Box, Arc)]
2600pub trait CreditRepository: Send + Sync {
2601    // Credit account operations
2602    /// Create a credit account for a customer
2603    fn create_credit_account(&self, input: CreateCreditAccount) -> Result<CreditAccount>;
2604
2605    /// Get credit account by ID
2606    fn get_credit_account(&self, id: CreditId) -> Result<Option<CreditAccount>>;
2607
2608    /// Get credit account by customer ID
2609    fn get_credit_account_by_customer(
2610        &self,
2611        customer_id: CustomerId,
2612    ) -> Result<Option<CreditAccount>>;
2613
2614    /// Update credit account
2615    fn update_credit_account(
2616        &self,
2617        id: CreditId,
2618        input: UpdateCreditAccount,
2619    ) -> Result<CreditAccount>;
2620
2621    /// List credit accounts
2622    fn list_credit_accounts(&self, filter: CreditAccountFilter) -> Result<Vec<CreditAccount>>;
2623
2624    /// Adjust credit limit
2625    fn adjust_credit_limit(
2626        &self,
2627        customer_id: CustomerId,
2628        new_limit: rust_decimal::Decimal,
2629        reason: &str,
2630    ) -> Result<CreditAccount>;
2631
2632    /// Suspend credit account
2633    fn suspend_credit_account(
2634        &self,
2635        customer_id: CustomerId,
2636        reason: &str,
2637    ) -> Result<CreditAccount>;
2638
2639    /// Reactivate credit account
2640    fn reactivate_credit_account(&self, customer_id: CustomerId) -> Result<CreditAccount>;
2641
2642    // Credit check operations
2643    /// Check credit for an order
2644    fn check_credit(
2645        &self,
2646        customer_id: CustomerId,
2647        order_amount: rust_decimal::Decimal,
2648    ) -> Result<CreditCheckResult>;
2649
2650    /// Reserve credit for an order
2651    fn reserve_credit(
2652        &self,
2653        customer_id: CustomerId,
2654        order_id: OrderId,
2655        amount: rust_decimal::Decimal,
2656    ) -> Result<CreditAccount>;
2657
2658    /// Release credit reservation
2659    fn release_credit_reservation(
2660        &self,
2661        customer_id: CustomerId,
2662        order_id: OrderId,
2663    ) -> Result<CreditAccount>;
2664
2665    /// Charge credit (convert reservation to balance)
2666    fn charge_credit(
2667        &self,
2668        customer_id: CustomerId,
2669        order_id: OrderId,
2670        amount: rust_decimal::Decimal,
2671    ) -> Result<CreditAccount>;
2672
2673    // Credit hold operations
2674    /// Place a credit hold
2675    fn place_hold(&self, input: PlaceCreditHold) -> Result<CreditHold>;
2676
2677    /// Get credit hold by ID
2678    fn get_hold(&self, id: Uuid) -> Result<Option<CreditHold>>;
2679
2680    /// List credit holds
2681    fn list_holds(&self, filter: CreditHoldFilter) -> Result<Vec<CreditHold>>;
2682
2683    /// Release a credit hold
2684    fn release_hold(&self, input: ReleaseCreditHold) -> Result<CreditHold>;
2685
2686    /// Get active holds for customer
2687    fn get_active_holds(&self, customer_id: CustomerId) -> Result<Vec<CreditHold>>;
2688
2689    /// Get active holds for order
2690    fn get_holds_for_order(&self, order_id: OrderId) -> Result<Vec<CreditHold>>;
2691
2692    // Credit application operations
2693    /// Submit a credit application
2694    fn submit_application(&self, input: SubmitCreditApplication) -> Result<CreditApplication>;
2695
2696    /// Get credit application by ID
2697    fn get_application(&self, id: Uuid) -> Result<Option<CreditApplication>>;
2698
2699    /// List credit applications
2700    fn list_applications(&self, filter: CreditApplicationFilter) -> Result<Vec<CreditApplication>>;
2701
2702    /// Review credit application
2703    fn review_application(&self, input: ReviewCreditApplication) -> Result<CreditApplication>;
2704
2705    /// Withdraw credit application
2706    fn withdraw_application(&self, id: Uuid) -> Result<CreditApplication>;
2707
2708    // Transaction operations
2709    /// Record a credit transaction
2710    fn record_transaction(&self, input: RecordCreditTransaction) -> Result<CreditTransaction>;
2711
2712    /// List credit transactions
2713    fn list_transactions(&self, filter: CreditTransactionFilter) -> Result<Vec<CreditTransaction>>;
2714
2715    /// Apply payment to balance
2716    fn apply_payment(
2717        &self,
2718        customer_id: CustomerId,
2719        amount: rust_decimal::Decimal,
2720        reference_id: Option<Uuid>,
2721    ) -> Result<CreditAccount>;
2722
2723    // Analytics
2724    /// Get customer credit summary
2725    fn get_customer_summary(
2726        &self,
2727        customer_id: CustomerId,
2728    ) -> Result<Option<CustomerCreditSummary>>;
2729
2730    /// Get credit aging buckets
2731    fn get_aging_report(&self) -> Result<Vec<(CustomerId, CreditAgingBucket)>>;
2732
2733    /// Get customers over credit limit
2734    fn get_over_limit_customers(&self) -> Result<Vec<CreditAccount>>;
2735}
2736
2737/// Backorder repository trait
2738#[auto_impl::auto_impl(&, Box, Arc)]
2739pub trait BackorderRepository: Send + Sync {
2740    // Backorder operations
2741    /// Create a backorder
2742    fn create_backorder(&self, input: CreateBackorder) -> Result<Backorder>;
2743
2744    /// Get backorder by ID
2745    fn get_backorder(&self, id: Uuid) -> Result<Option<Backorder>>;
2746
2747    /// Get backorder by number
2748    fn get_backorder_by_number(&self, number: &str) -> Result<Option<Backorder>>;
2749
2750    /// Update backorder
2751    fn update_backorder(&self, id: Uuid, input: UpdateBackorder) -> Result<Backorder>;
2752
2753    /// List backorders
2754    fn list_backorders(&self, filter: BackorderFilter) -> Result<Vec<Backorder>>;
2755
2756    /// Cancel backorder
2757    fn cancel_backorder(&self, id: Uuid) -> Result<Backorder>;
2758
2759    /// Get backorders for order
2760    fn get_backorders_for_order(&self, order_id: Uuid) -> Result<Vec<Backorder>>;
2761
2762    /// Get backorders for customer
2763    fn get_backorders_for_customer(&self, customer_id: Uuid) -> Result<Vec<Backorder>>;
2764
2765    /// Get backorders for SKU
2766    fn get_backorders_for_sku(&self, sku: &str) -> Result<Vec<Backorder>>;
2767
2768    // Fulfillment operations
2769    /// Fulfill backorder (partial or full)
2770    fn fulfill_backorder(&self, input: FulfillBackorder) -> Result<Backorder>;
2771
2772    /// Get fulfillment history for backorder
2773    fn get_fulfillment_history(&self, backorder_id: Uuid) -> Result<Vec<BackorderFulfillment>>;
2774
2775    // Allocation operations
2776    /// Allocate inventory to backorder
2777    fn allocate_backorder(&self, input: AllocateBackorder) -> Result<BackorderAllocation>;
2778
2779    /// Get allocations for backorder
2780    fn get_allocations(&self, backorder_id: Uuid) -> Result<Vec<BackorderAllocation>>;
2781
2782    /// Release allocation
2783    fn release_allocation(&self, allocation_id: Uuid) -> Result<BackorderAllocation>;
2784
2785    /// Confirm allocation
2786    fn confirm_allocation(&self, allocation_id: Uuid) -> Result<BackorderAllocation>;
2787
2788    /// Expire old allocations
2789    fn expire_allocations(&self) -> Result<u32>;
2790
2791    // Auto-allocation
2792    /// Auto-allocate available inventory to pending backorders
2793    fn auto_allocate_inventory(&self, sku: &str) -> Result<Vec<BackorderAllocation>>;
2794
2795    // Analytics
2796    /// Get backorder summary
2797    fn get_summary(&self) -> Result<BackorderSummary>;
2798
2799    /// Get SKU backorder summary
2800    fn get_sku_summary(&self, sku: &str) -> Result<Option<SkuBackorderSummary>>;
2801
2802    /// Get overdue backorders
2803    fn get_overdue_backorders(&self) -> Result<Vec<Backorder>>;
2804
2805    /// Count pending backorders
2806    fn count_pending(&self) -> Result<u64>;
2807}
2808
2809// ============================================================================
2810// Accounts Receivable Repository
2811// ============================================================================
2812
2813/// Accounts Receivable repository trait
2814#[auto_impl::auto_impl(&, Box, Arc)]
2815pub trait AccountsReceivableRepository: Send + Sync {
2816    // Aging reports
2817    /// Get AR aging summary across all customers
2818    fn get_aging_summary(&self) -> Result<ArAgingSummary>;
2819
2820    /// Get aging by customer (None if customer is not found)
2821    fn get_customer_aging(&self, customer_id: Uuid) -> Result<Option<CustomerArAging>>;
2822
2823    /// Get all customers with aging (AR aging report)
2824    fn get_aging_report(&self, filter: ArAgingFilter) -> Result<Vec<CustomerArAging>>;
2825
2826    // Collection management
2827    /// Log collection activity
2828    fn log_collection_activity(
2829        &self,
2830        input: CreateCollectionActivity,
2831    ) -> Result<CollectionActivity>;
2832
2833    /// Get collection activities
2834    fn list_collection_activities(
2835        &self,
2836        filter: CollectionActivityFilter,
2837    ) -> Result<Vec<CollectionActivity>>;
2838
2839    /// Update invoice collection status
2840    fn update_collection_status(
2841        &self,
2842        invoice_id: InvoiceId,
2843        status: CollectionStatus,
2844    ) -> Result<()>;
2845
2846    /// Get invoices due for dunning (based on aging)
2847    fn get_invoices_due_for_dunning(&self) -> Result<Vec<Invoice>>;
2848
2849    /// Send dunning letter (records activity, updates status)
2850    fn send_dunning_letter(
2851        &self,
2852        invoice_id: InvoiceId,
2853        letter_type: DunningLetterType,
2854        sent_by: Option<&str>,
2855    ) -> Result<CollectionActivity>;
2856
2857    // Write-offs
2858    /// Create a write-off
2859    fn create_write_off(&self, input: CreateWriteOff) -> Result<WriteOff>;
2860
2861    /// Get write-off by ID
2862    fn get_write_off(&self, id: Uuid) -> Result<Option<WriteOff>>;
2863
2864    /// List write-offs
2865    fn list_write_offs(&self, filter: WriteOffFilter) -> Result<Vec<WriteOff>>;
2866
2867    /// Reverse a write-off
2868    fn reverse_write_off(&self, id: Uuid) -> Result<WriteOff>;
2869
2870    // Credit memos
2871    /// Create a credit memo
2872    fn create_credit_memo(&self, input: CreateCreditMemo) -> Result<CreditMemo>;
2873
2874    /// Get credit memo by ID
2875    fn get_credit_memo(&self, id: Uuid) -> Result<Option<CreditMemo>>;
2876
2877    /// Get credit memo by number
2878    fn get_credit_memo_by_number(&self, number: &str) -> Result<Option<CreditMemo>>;
2879
2880    /// List credit memos
2881    fn list_credit_memos(&self, filter: CreditMemoFilter) -> Result<Vec<CreditMemo>>;
2882
2883    /// Apply credit memo to invoice
2884    fn apply_credit_memo(&self, input: ApplyCreditMemo) -> Result<CreditMemo>;
2885
2886    /// Void credit memo
2887    fn void_credit_memo(&self, id: Uuid) -> Result<CreditMemo>;
2888
2889    /// Get unapplied credit memos for customer
2890    fn get_unapplied_credits(&self, customer_id: Uuid) -> Result<Vec<CreditMemo>>;
2891
2892    // Payment application
2893    /// Apply payment to invoices
2894    fn apply_payment_to_invoices(
2895        &self,
2896        input: ApplyPaymentToInvoices,
2897    ) -> Result<Vec<ArPaymentApplication>>;
2898
2899    /// Get payment applications
2900    fn get_payment_applications(&self, payment_id: Uuid) -> Result<Vec<ArPaymentApplication>>;
2901
2902    /// Unapply payment from invoice
2903    fn unapply_payment(&self, application_id: Uuid) -> Result<()>;
2904
2905    // Customer summaries and statements
2906    /// Get customer AR summary (None if customer is not found)
2907    fn get_customer_summary(&self, customer_id: Uuid) -> Result<Option<CustomerArSummary>>;
2908
2909    /// Generate customer statement
2910    fn generate_statement(&self, request: GenerateStatementRequest) -> Result<CustomerStatement>;
2911
2912    // Analytics
2913    /// Get total AR outstanding
2914    fn get_total_outstanding(&self) -> Result<rust_decimal::Decimal>;
2915
2916    /// Get Days Sales Outstanding (DSO)
2917    fn get_dso(&self, days: i32) -> Result<rust_decimal::Decimal>;
2918
2919    /// Get average days to pay by customer
2920    fn get_average_days_to_pay(&self, customer_id: Uuid) -> Result<Option<i32>>;
2921
2922    // Batch operations
2923    fn get_customers_batch(&self, ids: Vec<Uuid>) -> Result<Vec<CustomerArSummary>>;
2924}
2925
2926// ============================================================================
2927// General Ledger Repository
2928// ============================================================================
2929
2930use chrono::NaiveDate;
2931
2932/// General Ledger repository trait
2933#[auto_impl::auto_impl(&, Box, Arc)]
2934pub trait GeneralLedgerRepository: Send + Sync {
2935    // Chart of Accounts
2936    /// Create a GL account
2937    fn create_account(&self, input: CreateGlAccount) -> Result<GlAccount>;
2938
2939    /// Get account by ID
2940    fn get_account(&self, id: Uuid) -> Result<Option<GlAccount>>;
2941
2942    /// Get account by account number
2943    fn get_account_by_number(&self, account_number: &str) -> Result<Option<GlAccount>>;
2944
2945    /// Update account
2946    fn update_account(&self, id: Uuid, input: UpdateGlAccount) -> Result<GlAccount>;
2947
2948    /// List accounts (Chart of Accounts)
2949    fn list_accounts(&self, filter: GlAccountFilter) -> Result<Vec<GlAccount>>;
2950
2951    /// Get account hierarchy (parent-child)
2952    fn get_account_hierarchy(&self) -> Result<Vec<GlAccount>>;
2953
2954    /// Delete account (only if no transactions)
2955    fn delete_account(&self, id: Uuid) -> Result<()>;
2956
2957    /// Initialize default Chart of Accounts
2958    fn initialize_chart_of_accounts(&self) -> Result<Vec<GlAccount>>;
2959
2960    // GL Periods
2961    /// Create a GL period
2962    fn create_period(&self, input: CreateGlPeriod) -> Result<GlPeriod>;
2963
2964    /// Get period by ID
2965    fn get_period(&self, id: Uuid) -> Result<Option<GlPeriod>>;
2966
2967    /// Get current open period
2968    fn get_current_period(&self) -> Result<Option<GlPeriod>>;
2969
2970    /// Get period for a date
2971    fn get_period_for_date(&self, date: NaiveDate) -> Result<Option<GlPeriod>>;
2972
2973    /// List periods
2974    fn list_periods(&self, filter: GlPeriodFilter) -> Result<Vec<GlPeriod>>;
2975
2976    /// Open a period
2977    fn open_period(&self, id: Uuid) -> Result<GlPeriod>;
2978
2979    /// Close a period
2980    fn close_period(&self, id: Uuid, closed_by: &str) -> Result<GlPeriod>;
2981
2982    /// Lock a period (prevents any changes)
2983    fn lock_period(&self, id: Uuid, locked_by: &str) -> Result<GlPeriod>;
2984
2985    /// Reopen a closed period (not locked)
2986    fn reopen_period(&self, id: Uuid) -> Result<GlPeriod>;
2987
2988    // Journal Entries
2989    /// Create a journal entry
2990    fn create_journal_entry(&self, input: CreateJournalEntry) -> Result<JournalEntry>;
2991
2992    /// Get journal entry by ID
2993    fn get_journal_entry(&self, id: Uuid) -> Result<Option<JournalEntry>>;
2994
2995    /// Get journal entry by number
2996    fn get_journal_entry_by_number(&self, number: &str) -> Result<Option<JournalEntry>>;
2997
2998    /// List journal entries
2999    fn list_journal_entries(&self, filter: JournalEntryFilter) -> Result<Vec<JournalEntry>>;
3000
3001    /// Post a journal entry (update account balances)
3002    fn post_journal_entry(&self, id: Uuid, posted_by: &str) -> Result<JournalEntry>;
3003
3004    /// Void a journal entry
3005    fn void_journal_entry(&self, id: Uuid) -> Result<JournalEntry>;
3006
3007    /// Reverse a journal entry (creates reversing entry)
3008    fn reverse_journal_entry(&self, id: Uuid, reversal_date: NaiveDate) -> Result<JournalEntry>;
3009
3010    /// Get journal entry lines
3011    fn get_journal_entry_lines(&self, journal_entry_id: Uuid) -> Result<Vec<JournalEntryLine>>;
3012
3013    // Auto-posting
3014    /// Get active auto-posting config
3015    fn get_auto_posting_config(&self) -> Result<Option<AutoPostingConfig>>;
3016
3017    /// Create/update auto-posting config
3018    fn set_auto_posting_config(&self, input: CreateAutoPostingConfig) -> Result<AutoPostingConfig>;
3019
3020    /// Auto-post invoice creation (DR AR / CR Revenue)
3021    fn auto_post_invoice(&self, invoice_id: InvoiceId) -> Result<JournalEntry>;
3022
3023    /// Auto-post payment received (DR Cash / CR AR)
3024    fn auto_post_payment_received(&self, payment_id: Uuid) -> Result<JournalEntry>;
3025
3026    /// Auto-post bill creation (DR Expense / CR AP)
3027    fn auto_post_bill(&self, bill_id: Uuid) -> Result<JournalEntry>;
3028
3029    /// Auto-post bill payment (DR AP / CR Cash)
3030    fn auto_post_bill_payment(&self, payment_id: Uuid) -> Result<JournalEntry>;
3031
3032    /// Auto-post inventory cost transaction (DR/CR Inventory/COGS)
3033    fn auto_post_inventory_cost(&self, cost_transaction_id: Uuid) -> Result<JournalEntry>;
3034
3035    /// Auto-post write-off (DR Bad Debt / CR AR)
3036    fn auto_post_write_off(&self, write_off_id: Uuid) -> Result<JournalEntry>;
3037
3038    // Financial Reports
3039    /// Generate trial balance
3040    fn get_trial_balance(&self, as_of_date: NaiveDate) -> Result<TrialBalance>;
3041
3042    /// Generate balance sheet
3043    fn get_balance_sheet(&self, as_of_date: NaiveDate) -> Result<BalanceSheet>;
3044
3045    /// Generate income statement
3046    fn get_income_statement(
3047        &self,
3048        start_date: NaiveDate,
3049        end_date: NaiveDate,
3050    ) -> Result<IncomeStatement>;
3051
3052    /// Get account balance (None if account is not found)
3053    fn get_account_balance(
3054        &self,
3055        account_id: Uuid,
3056        as_of_date: Option<NaiveDate>,
3057    ) -> Result<Option<rust_decimal::Decimal>>;
3058
3059    /// Get account transaction history
3060    fn get_account_transactions(
3061        &self,
3062        account_id: Uuid,
3063        filter: JournalEntryFilter,
3064    ) -> Result<Vec<JournalEntryLine>>;
3065
3066    // Period close process
3067    /// Run period close (creates closing entries)
3068    fn run_period_close(&self, period_id: Uuid, closed_by: &str) -> Result<JournalEntry>;
3069
3070    // FX revaluation
3071    /// Revalue foreign-currency account balances at the as-of exchange rate,
3072    /// posting the net unrealized gain/loss as a balanced adjusting entry.
3073    ///
3074    /// `base_currency` defaults to the store's configured base currency.
3075    fn revalue(
3076        &self,
3077        as_of_date: NaiveDate,
3078        base_currency: Option<Currency>,
3079    ) -> Result<RevaluationResult>;
3080
3081    // Batch operations
3082    fn create_accounts_batch(&self, inputs: Vec<CreateGlAccount>)
3083    -> Result<BatchResult<GlAccount>>;
3084    fn get_accounts_batch(&self, ids: Vec<Uuid>) -> Result<Vec<GlAccount>>;
3085}
3086
3087// ============================================================================
3088// Vector Search Repository
3089// ============================================================================
3090
3091/// Vector search repository trait for semantic similarity search
3092#[auto_impl::auto_impl(&, Box, Arc)]
3093pub trait VectorRepository: Send + Sync {
3094    /// Store embedding for an entity
3095    fn store_embedding(
3096        &self,
3097        entity_type: EntityType,
3098        entity_id: &str,
3099        embedding: &[f32],
3100        text_hash: &str,
3101        model: &str,
3102    ) -> Result<()>;
3103
3104    /// Search similar products by embedding vector
3105    fn search_products(
3106        &self,
3107        embedding: &[f32],
3108        limit: usize,
3109    ) -> Result<Vec<VectorSearchResult<Product>>>;
3110
3111    /// Search similar customers by embedding vector
3112    fn search_customers(
3113        &self,
3114        embedding: &[f32],
3115        limit: usize,
3116    ) -> Result<Vec<VectorSearchResult<Customer>>>;
3117
3118    /// Search similar orders by embedding vector
3119    fn search_orders(
3120        &self,
3121        embedding: &[f32],
3122        limit: usize,
3123    ) -> Result<Vec<VectorSearchResult<Order>>>;
3124
3125    /// Search similar inventory items by embedding vector
3126    fn search_inventory(
3127        &self,
3128        embedding: &[f32],
3129        limit: usize,
3130    ) -> Result<Vec<VectorSearchResult<InventoryItem>>>;
3131
3132    /// Delete embedding for an entity
3133    fn delete_embedding(&self, entity_type: EntityType, entity_id: &str) -> Result<()>;
3134
3135    /// Check if entity has an embedding stored
3136    fn has_embedding(&self, entity_type: EntityType, entity_id: &str) -> Result<bool>;
3137
3138    /// Get embedding metadata for an entity
3139    fn get_embedding_metadata(
3140        &self,
3141        entity_type: EntityType,
3142        entity_id: &str,
3143    ) -> Result<Option<EmbeddingMetadata>>;
3144
3145    /// Get embedding statistics
3146    fn get_stats(&self) -> Result<EmbeddingStats>;
3147
3148    /// Delete all embeddings for an entity type
3149    fn clear_embeddings(&self, entity_type: EntityType) -> Result<u64>;
3150}
3151
3152// ============================================================================
3153// X402 Payment Intent Repository
3154// ============================================================================
3155
3156/// X402 Payment Intent repository trait for off-chain payment signing
3157#[auto_impl::auto_impl(&, Box, Arc)]
3158pub trait X402PaymentIntentRepository: Send + Sync {
3159    /// Create a new x402 payment intent
3160    fn create(&self, input: CreateX402PaymentIntent) -> Result<X402PaymentIntent>;
3161
3162    /// Get payment intent by ID
3163    fn get(&self, id: Uuid) -> Result<Option<X402PaymentIntent>>;
3164
3165    /// Get payment intent by idempotency key
3166    fn get_by_idempotency_key(&self, key: &str) -> Result<Option<X402PaymentIntent>>;
3167
3168    /// Sign a payment intent (records signature and public key)
3169    fn sign(&self, id: Uuid, input: SignX402PaymentIntent) -> Result<X402PaymentIntent>;
3170
3171    /// Mark intent as sequenced (submitted to sequencer)
3172    fn mark_sequenced(
3173        &self,
3174        id: Uuid,
3175        sequence_number: u64,
3176        batch_id: Uuid,
3177    ) -> Result<X402PaymentIntent>;
3178
3179    /// Mark intent as settled (confirmed on-chain)
3180    fn mark_settled(&self, id: Uuid, tx_hash: &str, block_number: u64)
3181    -> Result<X402PaymentIntent>;
3182
3183    /// Mark intent as failed
3184    fn mark_failed(&self, id: Uuid, reason: &str) -> Result<X402PaymentIntent>;
3185
3186    /// Mark intent as expired
3187    fn mark_expired(&self, id: Uuid) -> Result<X402PaymentIntent>;
3188
3189    /// Cancel a payment intent (only if not yet sequenced)
3190    fn cancel(&self, id: Uuid) -> Result<X402PaymentIntent>;
3191
3192    /// Get payment intents for a cart
3193    fn for_cart(&self, cart_id: Uuid) -> Result<Vec<X402PaymentIntent>>;
3194
3195    /// Get payment intents for an order
3196    fn for_order(&self, order_id: Uuid) -> Result<Vec<X402PaymentIntent>>;
3197
3198    /// Get the next nonce for a payer address
3199    fn get_next_nonce(&self, payer_address: &str) -> Result<u64>;
3200
3201    /// List payment intents with filter
3202    fn list(&self, filter: X402PaymentIntentFilter) -> Result<Vec<X402PaymentIntent>>;
3203
3204    /// Count payment intents matching filter
3205    fn count(&self, filter: X402PaymentIntentFilter) -> Result<u64>;
3206
3207    /// Expire all intents that have passed their `valid_until` timestamp
3208    fn expire_stale_intents(&self) -> Result<u64>;
3209
3210    // === Batch Operations ===
3211
3212    /// Create multiple payment intents - partial success allowed
3213    fn create_batch(
3214        &self,
3215        inputs: Vec<CreateX402PaymentIntent>,
3216    ) -> Result<BatchResult<X402PaymentIntent>>;
3217
3218    /// Create multiple payment intents - atomic (all-or-nothing)
3219    fn create_batch_atomic(
3220        &self,
3221        inputs: Vec<CreateX402PaymentIntent>,
3222    ) -> Result<Vec<X402PaymentIntent>>;
3223
3224    /// Get multiple payment intents by ID
3225    fn get_batch(&self, ids: Vec<Uuid>) -> Result<Vec<X402PaymentIntent>>;
3226}
3227
3228// ============================================================================
3229// X402 Credit Repository (Metered Billing)
3230// ============================================================================
3231
3232/// X402 credit ledger repository for prepaid balances and metered usage.
3233#[auto_impl::auto_impl(&, Box, Arc)]
3234pub trait X402CreditRepository: Send + Sync {
3235    /// Get a credit account for payer/asset/network
3236    fn get_account(
3237        &self,
3238        payer_address: &str,
3239        asset: X402Asset,
3240        network: X402Network,
3241    ) -> Result<Option<X402CreditAccount>>;
3242
3243    /// Get or create a credit account (balance default = 0)
3244    fn get_or_create_account(
3245        &self,
3246        payer_address: &str,
3247        asset: X402Asset,
3248        network: X402Network,
3249    ) -> Result<X402CreditAccount>;
3250
3251    /// Get current balance for payer/asset/network
3252    fn get_balance(
3253        &self,
3254        payer_address: &str,
3255        asset: X402Asset,
3256        network: X402Network,
3257    ) -> Result<u64>;
3258
3259    /// Apply a credit or debit adjustment
3260    fn adjust_balance(&self, input: X402CreditAdjustment) -> Result<X402CreditTransaction>;
3261
3262    /// List credit transactions with optional filter
3263    fn list_transactions(
3264        &self,
3265        filter: X402CreditTransactionFilter,
3266    ) -> Result<Vec<X402CreditTransaction>>;
3267}
3268
3269// ============================================================================
3270// Agent Card Repository
3271// ============================================================================
3272
3273/// Agent Card repository trait for AI agent identity and capabilities
3274#[auto_impl::auto_impl(&, Box, Arc)]
3275pub trait AgentCardRepository: Send + Sync {
3276    /// Create a new agent card
3277    fn create(&self, input: CreateAgentCard) -> Result<AgentCard>;
3278
3279    /// Get agent card by ID
3280    fn get(&self, id: Uuid) -> Result<Option<AgentCard>>;
3281
3282    /// Get agent card by wallet address
3283    fn get_by_wallet(&self, wallet_address: &str) -> Result<Option<AgentCard>>;
3284
3285    /// Update an agent card
3286    fn update(&self, id: Uuid, input: UpdateAgentCard) -> Result<AgentCard>;
3287
3288    /// Delete an agent card
3289    fn delete(&self, id: Uuid) -> Result<()>;
3290
3291    /// List agent cards with filter
3292    fn list(&self, filter: AgentCardFilter) -> Result<Vec<AgentCard>>;
3293
3294    /// Count agent cards matching filter
3295    fn count(&self, filter: AgentCardFilter) -> Result<u64>;
3296
3297    /// Verify an agent card (set trust level and verification info)
3298    fn verify(&self, id: Uuid, trust_level: TrustLevel, method: &str) -> Result<AgentCard>;
3299
3300    /// Suspend an agent card
3301    fn suspend(&self, id: Uuid, reason: &str) -> Result<AgentCard>;
3302
3303    /// Reactivate a suspended agent card
3304    fn reactivate(&self, id: Uuid) -> Result<AgentCard>;
3305
3306    /// Discover agents with specific capabilities
3307    fn discover(&self, filter: AgentCardFilter) -> Result<Vec<AgentCard>>;
3308
3309    // === Batch Operations ===
3310
3311    /// Create multiple agent cards - partial success allowed
3312    fn create_batch(&self, inputs: Vec<CreateAgentCard>) -> Result<BatchResult<AgentCard>>;
3313
3314    /// Create multiple agent cards - atomic (all-or-nothing)
3315    fn create_batch_atomic(&self, inputs: Vec<CreateAgentCard>) -> Result<Vec<AgentCard>>;
3316
3317    /// Get multiple agent cards by ID
3318    fn get_batch(&self, ids: Vec<Uuid>) -> Result<Vec<AgentCard>>;
3319}
3320
3321// ============================================================================
3322// ERC-8004 Agent Identity Repository
3323// ============================================================================
3324
3325/// Agent identity registry repository (ERC-8004)
3326#[auto_impl::auto_impl(&, Box, Arc)]
3327pub trait AgentIdentityRepository: Send + Sync {
3328    /// Register a new agent identity
3329    fn register(&self, input: CreateAgentIdentity) -> Result<AgentIdentity>;
3330
3331    /// Get identity by agent registry and agent ID
3332    fn get(&self, agent_registry: &str, agent_id: &str) -> Result<Option<AgentIdentity>>;
3333
3334    /// Get identity by agent wallet address
3335    fn get_by_wallet(&self, agent_wallet: &str) -> Result<Option<AgentIdentity>>;
3336
3337    /// Update agent identity
3338    fn update(
3339        &self,
3340        agent_registry: &str,
3341        agent_id: &str,
3342        input: UpdateAgentIdentity,
3343    ) -> Result<AgentIdentity>;
3344
3345    /// Set or update agent wallet with proof metadata
3346    #[allow(clippy::too_many_arguments)]
3347    fn set_agent_wallet(
3348        &self,
3349        agent_registry: &str,
3350        agent_id: &str,
3351        agent_wallet: &str,
3352        proof_type: Option<AgentWalletProofType>,
3353        proof: Option<&str>,
3354        proof_chain_id: Option<u64>,
3355        proof_deadline: Option<DateTime<Utc>>,
3356    ) -> Result<AgentIdentity>;
3357
3358    /// Clear agent wallet
3359    fn clear_agent_wallet(&self, agent_registry: &str, agent_id: &str) -> Result<AgentIdentity>;
3360
3361    /// List identities with optional filtering
3362    fn list(&self, filter: AgentIdentityFilter) -> Result<Vec<AgentIdentity>>;
3363
3364    /// Count identities matching filter
3365    fn count(&self, filter: AgentIdentityFilter) -> Result<u64>;
3366
3367    /// Set identity metadata entry
3368    fn set_metadata(
3369        &self,
3370        agent_registry: &str,
3371        agent_id: &str,
3372        entry: AgentMetadataEntry,
3373    ) -> Result<()>;
3374
3375    /// Get identity metadata entry
3376    fn get_metadata(
3377        &self,
3378        agent_registry: &str,
3379        agent_id: &str,
3380        metadata_key: &str,
3381    ) -> Result<Option<Vec<u8>>>;
3382
3383    /// Delete identity metadata entry
3384    fn delete_metadata(
3385        &self,
3386        agent_registry: &str,
3387        agent_id: &str,
3388        metadata_key: &str,
3389    ) -> Result<()>;
3390}
3391
3392// ============================================================================
3393// ERC-8004 Reputation Registry
3394// ============================================================================
3395
3396/// Reputation feedback registry repository (ERC-8004)
3397#[auto_impl::auto_impl(&, Box, Arc)]
3398pub trait AgentReputationRepository: Send + Sync {
3399    /// Submit feedback for an agent
3400    fn give_feedback(&self, input: CreateAgentFeedback) -> Result<AgentFeedback>;
3401
3402    /// Revoke previously submitted feedback
3403    fn revoke_feedback(
3404        &self,
3405        agent_registry: &str,
3406        agent_id: &str,
3407        client_address: &str,
3408        feedback_index: u64,
3409    ) -> Result<AgentFeedback>;
3410
3411    /// Read a specific feedback entry
3412    fn read_feedback(
3413        &self,
3414        agent_registry: &str,
3415        agent_id: &str,
3416        client_address: &str,
3417        feedback_index: u64,
3418    ) -> Result<Option<AgentFeedback>>;
3419
3420    /// Read feedback entries with filters
3421    fn read_all_feedback(&self, filter: AgentFeedbackFilter) -> Result<Vec<AgentFeedback>>;
3422
3423    /// Get feedback summary for an agent (filtered by client addresses + tags)
3424    fn get_summary(
3425        &self,
3426        agent_registry: &str,
3427        agent_id: &str,
3428        client_addresses: Vec<String>,
3429        tag1: Option<String>,
3430        tag2: Option<String>,
3431    ) -> Result<FeedbackSummary>;
3432
3433    /// Append a response to a feedback entry
3434    fn append_response(&self, input: CreateAgentFeedbackResponse) -> Result<AgentFeedbackResponse>;
3435
3436    /// Count responses for a feedback entry
3437    fn get_response_count(
3438        &self,
3439        agent_registry: &str,
3440        agent_id: &str,
3441        client_address: &str,
3442        feedback_index: u64,
3443        responders: Option<Vec<String>>,
3444    ) -> Result<u64>;
3445
3446    /// List client addresses that have provided feedback
3447    fn get_clients(&self, agent_registry: &str, agent_id: &str) -> Result<Vec<String>>;
3448
3449    /// Get last feedback index for a client/agent pair
3450    fn get_last_index(
3451        &self,
3452        agent_registry: &str,
3453        agent_id: &str,
3454        client_address: &str,
3455    ) -> Result<u64>;
3456}
3457
3458// ============================================================================
3459// ERC-8004 Validation Registry
3460// ============================================================================
3461
3462/// Validation registry repository (ERC-8004)
3463#[auto_impl::auto_impl(&, Box, Arc)]
3464pub trait AgentValidationRepository: Send + Sync {
3465    /// Submit a validation request
3466    fn request_validation(
3467        &self,
3468        input: CreateAgentValidationRequest,
3469    ) -> Result<AgentValidationRequest>;
3470
3471    /// Record a validation response for a request hash
3472    fn respond_validation(
3473        &self,
3474        request_hash: &str,
3475        input: CreateAgentValidationResponse,
3476    ) -> Result<AgentValidationResponse>;
3477
3478    /// Get latest validation status for a request hash
3479    fn get_validation_status(&self, request_hash: &str) -> Result<Option<AgentValidationStatus>>;
3480
3481    /// Get validation summary for an agent
3482    fn get_summary(
3483        &self,
3484        agent_registry: &str,
3485        agent_id: &str,
3486        validator_addresses: Option<Vec<String>>,
3487        tag: Option<String>,
3488    ) -> Result<ValidationSummary>;
3489
3490    /// Get all request hashes for an agent
3491    fn get_agent_validations(&self, agent_registry: &str, agent_id: &str) -> Result<Vec<String>>;
3492
3493    /// Get all request hashes for a validator
3494    fn get_validator_requests(&self, validator_address: &str) -> Result<Vec<String>>;
3495}
3496
3497// ============================================================================
3498// A2A Commerce Repository
3499// ============================================================================
3500
3501/// A2A (Agent-to-Agent) Commerce repository trait
3502#[auto_impl::auto_impl(&, Box, Arc)]
3503pub trait A2ACommerceRepository: Send + Sync {
3504    // Quote operations
3505    /// Create a new quote
3506    fn create_quote(&self, input: CreateA2AQuote) -> Result<SkillQuote>;
3507
3508    /// Get quote by ID
3509    fn get_quote(&self, id: Uuid) -> Result<Option<SkillQuote>>;
3510
3511    /// Get quote by quote number
3512    fn get_quote_by_number(&self, quote_number: &str) -> Result<Option<SkillQuote>>;
3513
3514    /// Update quote status
3515    fn update_quote_status(&self, id: Uuid, status: QuoteStatus) -> Result<SkillQuote>;
3516
3517    /// List quotes with filter
3518    fn list_quotes(&self, filter: SkillQuoteFilter) -> Result<Vec<SkillQuote>>;
3519
3520    /// Count quotes matching filter
3521    fn count_quotes(&self, filter: SkillQuoteFilter) -> Result<u64>;
3522
3523    // Purchase operations
3524    /// Create a new purchase
3525    fn create_purchase(&self, input: CreateA2APurchase) -> Result<A2APurchase>;
3526
3527    /// Get purchase by ID
3528    fn get_purchase(&self, id: Uuid) -> Result<Option<A2APurchase>>;
3529
3530    /// Get purchase by purchase number
3531    fn get_purchase_by_number(&self, purchase_number: &str) -> Result<Option<A2APurchase>>;
3532
3533    /// Update purchase status
3534    fn update_purchase_status(&self, id: Uuid, status: PurchaseStatus) -> Result<A2APurchase>;
3535
3536    /// Link purchase to order
3537    fn link_purchase_to_order(&self, purchase_id: Uuid, order_id: Uuid) -> Result<A2APurchase>;
3538
3539    /// Confirm delivery
3540    fn confirm_delivery(
3541        &self,
3542        purchase_id: Uuid,
3543        signature: &str,
3544        rating: Option<u8>,
3545        feedback: Option<&str>,
3546    ) -> Result<A2APurchase>;
3547
3548    /// List purchases with filter
3549    fn list_purchases(&self, filter: A2APurchaseFilter) -> Result<Vec<A2APurchase>>;
3550
3551    /// Count purchases matching filter
3552    fn count_purchases(&self, filter: A2APurchaseFilter) -> Result<u64>;
3553}
3554
3555// ============================================================================
3556// Custom Objects Repository
3557// ============================================================================
3558
3559/// Custom Objects repository trait (custom states / metaobjects).
3560///
3561/// Provides a schema-driven custom data system:
3562/// - Define types (schemas) with typed fields
3563/// - Create records (instances) that validate against the schema
3564#[auto_impl::auto_impl(&, Box, Arc)]
3565pub trait CustomObjectRepository: Send + Sync {
3566    // ------------------------------------------------------------------------
3567    // Type (schema) operations
3568    // ------------------------------------------------------------------------
3569
3570    fn create_type(&self, input: CreateCustomObjectType) -> Result<CustomObjectType>;
3571
3572    fn get_type(&self, id: Uuid) -> Result<Option<CustomObjectType>>;
3573
3574    fn get_type_by_handle(&self, handle: &str) -> Result<Option<CustomObjectType>>;
3575
3576    fn update_type(&self, id: Uuid, input: UpdateCustomObjectType) -> Result<CustomObjectType>;
3577
3578    fn list_types(&self, filter: CustomObjectTypeFilter) -> Result<Vec<CustomObjectType>>;
3579
3580    fn delete_type(&self, id: Uuid) -> Result<()>;
3581
3582    // ------------------------------------------------------------------------
3583    // Record operations
3584    // ------------------------------------------------------------------------
3585
3586    fn create_object(&self, input: CreateCustomObject) -> Result<CustomObject>;
3587
3588    fn get_object(&self, id: Uuid) -> Result<Option<CustomObject>>;
3589
3590    fn get_object_by_handle(
3591        &self,
3592        type_handle: &str,
3593        object_handle: &str,
3594    ) -> Result<Option<CustomObject>>;
3595
3596    fn update_object(&self, id: Uuid, input: UpdateCustomObject) -> Result<CustomObject>;
3597
3598    fn list_objects(&self, filter: CustomObjectFilter) -> Result<Vec<CustomObject>>;
3599
3600    fn delete_object(&self, id: Uuid) -> Result<()>;
3601}
3602
3603// ============================================================================
3604// New Domain Repository Traits
3605// ============================================================================
3606
3607/// Gift card repository trait.
3608#[auto_impl::auto_impl(&, Box, Arc)]
3609pub trait GiftCardRepository: Send + Sync {
3610    /// Create a new gift card
3611    fn create(&self, input: CreateGiftCard) -> Result<GiftCard>;
3612
3613    /// Get gift card by ID
3614    fn get(&self, id: GiftCardId) -> Result<Option<GiftCard>>;
3615
3616    /// Get gift card by code
3617    fn get_by_code(&self, code: &str) -> Result<Option<GiftCard>>;
3618
3619    /// Update a gift card
3620    fn update(&self, id: GiftCardId, input: UpdateGiftCard) -> Result<GiftCard>;
3621
3622    /// List gift cards with filter
3623    fn list(&self, filter: GiftCardFilter) -> Result<Vec<GiftCard>>;
3624
3625    /// Charge (debit) a gift card
3626    fn charge(
3627        &self,
3628        id: GiftCardId,
3629        amount: rust_decimal::Decimal,
3630        reference_id: Option<String>,
3631    ) -> Result<GiftCardTransaction>;
3632
3633    /// Refund (credit) to a gift card
3634    fn refund(
3635        &self,
3636        id: GiftCardId,
3637        amount: rust_decimal::Decimal,
3638        reference_id: Option<String>,
3639    ) -> Result<GiftCardTransaction>;
3640
3641    /// Disable a gift card
3642    fn disable(&self, id: GiftCardId) -> Result<GiftCard>;
3643
3644    /// Get transaction history for a gift card
3645    fn get_transactions(&self, gift_card_id: GiftCardId) -> Result<Vec<GiftCardTransaction>>;
3646}
3647
3648/// Store credit repository trait.
3649#[auto_impl::auto_impl(&, Box, Arc)]
3650pub trait StoreCreditRepository: Send + Sync {
3651    /// Create a new store credit
3652    fn create(&self, input: CreateStoreCredit) -> Result<StoreCredit>;
3653
3654    /// Get store credit by ID
3655    fn get(&self, id: StoreCreditId) -> Result<Option<StoreCredit>>;
3656
3657    /// List store credits with filter
3658    fn list(&self, filter: StoreCreditFilter) -> Result<Vec<StoreCredit>>;
3659
3660    /// Adjust store credit balance
3661    fn adjust(&self, id: StoreCreditId, input: AdjustStoreCredit) -> Result<StoreCredit>;
3662
3663    /// Apply store credit to an order (debit)
3664    fn apply(
3665        &self,
3666        id: StoreCreditId,
3667        amount: rust_decimal::Decimal,
3668        reference_id: Option<String>,
3669    ) -> Result<StoreCreditTransaction>;
3670
3671    /// Get transaction history for a store credit
3672    fn get_transactions(
3673        &self,
3674        store_credit_id: StoreCreditId,
3675    ) -> Result<Vec<StoreCreditTransaction>>;
3676}
3677
3678/// Customer segment repository trait.
3679#[auto_impl::auto_impl(&, Box, Arc)]
3680pub trait SegmentRepository: Send + Sync {
3681    /// Create a new segment
3682    fn create(&self, input: CreateSegment) -> Result<Segment>;
3683
3684    /// Get segment by ID
3685    fn get(&self, id: SegmentId) -> Result<Option<Segment>>;
3686
3687    /// Update a segment
3688    fn update(&self, id: SegmentId, input: UpdateSegment) -> Result<Segment>;
3689
3690    /// List segments with filter
3691    fn list(&self, filter: SegmentFilter) -> Result<Vec<Segment>>;
3692
3693    /// Delete a segment
3694    fn delete(&self, id: SegmentId) -> Result<()>;
3695
3696    /// Add a customer to a static segment
3697    fn add_member(
3698        &self,
3699        segment_id: SegmentId,
3700        customer_id: CustomerId,
3701    ) -> Result<SegmentMembership>;
3702
3703    /// Remove a customer from a static segment
3704    fn remove_member(&self, segment_id: SegmentId, customer_id: CustomerId) -> Result<()>;
3705
3706    /// List members of a segment
3707    fn list_members(
3708        &self,
3709        segment_id: SegmentId,
3710        limit: Option<u32>,
3711        offset: Option<u32>,
3712    ) -> Result<Vec<SegmentMembership>>;
3713
3714    /// Check if a customer is a member of a segment
3715    fn is_member(&self, segment_id: SegmentId, customer_id: CustomerId) -> Result<bool>;
3716
3717    /// Count members in a segment
3718    fn count_members(&self, segment_id: SegmentId) -> Result<u64>;
3719}
3720
3721/// Shipping zone repository trait.
3722#[auto_impl::auto_impl(&, Box, Arc)]
3723pub trait ShippingZoneRepository: Send + Sync {
3724    /// Create a new shipping zone
3725    fn create(&self, input: CreateShippingZone) -> Result<ShippingZone>;
3726
3727    /// Get shipping zone by ID
3728    fn get(&self, id: ShippingZoneId) -> Result<Option<ShippingZone>>;
3729
3730    /// Update a shipping zone
3731    fn update(&self, id: ShippingZoneId, input: UpdateShippingZone) -> Result<ShippingZone>;
3732
3733    /// List shipping zones with filter
3734    fn list(&self, filter: ShippingZoneFilter) -> Result<Vec<ShippingZone>>;
3735
3736    /// Delete a shipping zone
3737    fn delete(&self, id: ShippingZoneId) -> Result<()>;
3738
3739    /// Find zones matching a destination
3740    fn find_matching_zones(
3741        &self,
3742        country: &str,
3743        region: Option<&str>,
3744        postal_code: Option<&str>,
3745    ) -> Result<Vec<ShippingZone>>;
3746}
3747
3748/// Zone shipping method repository trait.
3749#[auto_impl::auto_impl(&, Box, Arc)]
3750pub trait ZoneShippingMethodRepository: Send + Sync {
3751    /// Create a shipping method in a zone
3752    fn create(&self, input: CreateZoneShippingMethod) -> Result<ZoneShippingMethod>;
3753
3754    /// Get shipping method by ID
3755    fn get(&self, id: ShippingMethodId) -> Result<Option<ZoneShippingMethod>>;
3756
3757    /// List shipping methods with filter
3758    fn list(&self, filter: ZoneShippingMethodFilter) -> Result<Vec<ZoneShippingMethod>>;
3759
3760    /// Delete a shipping method
3761    fn delete(&self, id: ShippingMethodId) -> Result<()>;
3762
3763    /// Calculate rates for a destination
3764    fn calculate_rates(&self, request: ZoneShippingRateRequest) -> Result<Vec<ZoneShippingRate>>;
3765}
3766
3767/// Product review repository trait.
3768#[auto_impl::auto_impl(&, Box, Arc)]
3769pub trait ReviewRepository: Send + Sync {
3770    /// Create a new review
3771    fn create(&self, input: CreateReview) -> Result<Review>;
3772
3773    /// Get review by ID
3774    fn get(&self, id: ReviewId) -> Result<Option<Review>>;
3775
3776    /// Update a review
3777    fn update(&self, id: ReviewId, input: UpdateReview) -> Result<Review>;
3778
3779    /// List reviews with filter
3780    fn list(&self, filter: ReviewFilter) -> Result<Vec<Review>>;
3781
3782    /// Delete a review
3783    fn delete(&self, id: ReviewId) -> Result<()>;
3784
3785    /// Get aggregate review summary for a product
3786    fn get_summary(&self, product_id: ProductId) -> Result<ReviewSummary>;
3787
3788    /// Increment the helpful count
3789    fn mark_helpful(&self, id: ReviewId) -> Result<()>;
3790
3791    /// Increment the reported count
3792    fn mark_reported(&self, id: ReviewId) -> Result<()>;
3793}
3794
3795/// Wishlist repository trait.
3796#[auto_impl::auto_impl(&, Box, Arc)]
3797pub trait WishlistRepository: Send + Sync {
3798    /// Create a new wishlist
3799    fn create(&self, input: CreateWishlist) -> Result<Wishlist>;
3800
3801    /// Get wishlist by ID
3802    fn get(&self, id: WishlistId) -> Result<Option<Wishlist>>;
3803
3804    /// Update wishlist metadata
3805    fn update(&self, id: WishlistId, input: UpdateWishlist) -> Result<Wishlist>;
3806
3807    /// List wishlists with filter
3808    fn list(&self, filter: WishlistFilter) -> Result<Vec<Wishlist>>;
3809
3810    /// Delete a wishlist
3811    fn delete(&self, id: WishlistId) -> Result<()>;
3812
3813    /// Add an item to a wishlist
3814    fn add_item(&self, wishlist_id: WishlistId, item: AddWishlistItem) -> Result<WishlistItem>;
3815
3816    /// Remove an item from a wishlist
3817    fn remove_item(&self, wishlist_id: WishlistId, product_id: ProductId) -> Result<()>;
3818}
3819
3820/// Loyalty program repository trait.
3821#[auto_impl::auto_impl(&, Box, Arc)]
3822pub trait LoyaltyProgramRepository: Send + Sync {
3823    /// Create a new loyalty program
3824    fn create(&self, input: CreateLoyaltyProgram) -> Result<LoyaltyProgram>;
3825
3826    /// Get loyalty program by ID
3827    fn get(&self, id: LoyaltyProgramId) -> Result<Option<LoyaltyProgram>>;
3828
3829    /// List all loyalty programs
3830    fn list(&self) -> Result<Vec<LoyaltyProgram>>;
3831
3832    /// Enroll a customer in a program
3833    fn enroll(&self, input: EnrollCustomer) -> Result<LoyaltyAccount>;
3834
3835    /// Get a loyalty account
3836    fn get_account(&self, id: LoyaltyAccountId) -> Result<Option<LoyaltyAccount>>;
3837
3838    /// Get loyalty account by customer and program
3839    fn get_account_by_customer(
3840        &self,
3841        customer_id: CustomerId,
3842        program_id: LoyaltyProgramId,
3843    ) -> Result<Option<LoyaltyAccount>>;
3844
3845    /// List loyalty accounts with filter
3846    fn list_accounts(&self, filter: LoyaltyAccountFilter) -> Result<Vec<LoyaltyAccount>>;
3847
3848    /// Adjust points on an account (earn, redeem, etc.)
3849    fn adjust_points(&self, input: AdjustPoints) -> Result<LoyaltyTransaction>;
3850
3851    /// Get transaction history for an account
3852    fn get_transactions(
3853        &self,
3854        account_id: LoyaltyAccountId,
3855        limit: Option<u32>,
3856    ) -> Result<Vec<LoyaltyTransaction>>;
3857}
3858
3859/// Reward catalog repository trait.
3860#[auto_impl::auto_impl(&, Box, Arc)]
3861pub trait RewardRepository: Send + Sync {
3862    /// Create a new reward
3863    fn create(&self, input: CreateReward) -> Result<Reward>;
3864
3865    /// Get reward by ID
3866    fn get(&self, id: RewardId) -> Result<Option<Reward>>;
3867
3868    /// List rewards with filter
3869    fn list(&self, filter: RewardFilter) -> Result<Vec<Reward>>;
3870
3871    /// Delete a reward
3872    fn delete(&self, id: RewardId) -> Result<()>;
3873}
3874
3875/// Fraud detection repository trait.
3876#[auto_impl::auto_impl(&, Box, Arc)]
3877pub trait FraudRepository: Send + Sync {
3878    /// Create a fraud assessment for an order
3879    fn create_assessment(&self, input: CreateFraudAssessment) -> Result<FraudAssessment>;
3880
3881    /// Get fraud assessment for an order
3882    fn get_assessment(&self, order_id: OrderId) -> Result<Option<FraudAssessment>>;
3883
3884    /// List fraud assessments with filter
3885    fn list_assessments(&self, filter: FraudAssessmentFilter) -> Result<Vec<FraudAssessment>>;
3886
3887    /// Update assessment after manual review
3888    fn review_assessment(
3889        &self,
3890        order_id: OrderId,
3891        decision: FraudDecision,
3892        reviewer: String,
3893        notes: Option<String>,
3894    ) -> Result<FraudAssessment>;
3895
3896    /// Create a fraud rule
3897    fn create_rule(&self, input: CreateFraudRule) -> Result<FraudRule>;
3898
3899    /// Get a fraud rule by ID
3900    fn get_rule(&self, id: FraudRuleId) -> Result<Option<FraudRule>>;
3901
3902    /// Update a fraud rule
3903    fn update_rule(&self, id: FraudRuleId, input: UpdateFraudRule) -> Result<FraudRule>;
3904
3905    /// List fraud rules with filter
3906    fn list_rules(&self, filter: FraudRuleFilter) -> Result<Vec<FraudRule>>;
3907
3908    /// Delete a fraud rule
3909    fn delete_rule(&self, id: FraudRuleId) -> Result<()>;
3910
3911    /// Get all enabled rules
3912    fn get_active_rules(&self) -> Result<Vec<FraudRule>>;
3913}
3914
3915/// Search configuration repository trait.
3916#[auto_impl::auto_impl(&, Box, Arc)]
3917pub trait SearchConfigRepository: Send + Sync {
3918    /// Create a search configuration
3919    fn create(&self, input: CreateSearchConfig) -> Result<SearchConfig>;
3920
3921    /// Get search configuration by ID
3922    fn get(&self, id: SearchConfigId) -> Result<Option<SearchConfig>>;
3923
3924    /// Update a search configuration
3925    fn update(&self, id: SearchConfigId, input: UpdateSearchConfig) -> Result<SearchConfig>;
3926
3927    /// List search configurations with filter
3928    fn list(&self, filter: SearchConfigFilter) -> Result<Vec<SearchConfig>>;
3929
3930    /// Delete a search configuration
3931    fn delete(&self, id: SearchConfigId) -> Result<()>;
3932
3933    /// Get the currently active search configuration
3934    fn get_active(&self) -> Result<Option<SearchConfig>>;
3935
3936    /// Set a configuration as active (deactivating any current one)
3937    fn set_active(&self, id: SearchConfigId) -> Result<SearchConfig>;
3938}
3939
3940/// Sales / fulfillment channel repository trait.
3941#[auto_impl::auto_impl(&, Box, Arc)]
3942pub trait ChannelRepository: Send + Sync {
3943    /// Create a new channel.
3944    fn create(&self, input: CreateChannel) -> Result<Channel>;
3945
3946    /// Get a channel by ID.
3947    fn get(&self, id: ChannelId) -> Result<Option<Channel>>;
3948
3949    /// Update a channel (PATCH/merge semantics).
3950    fn update(&self, id: ChannelId, input: UpdateChannel) -> Result<Channel>;
3951
3952    /// List channels with filter.
3953    fn list(&self, filter: ChannelFilter) -> Result<Vec<Channel>>;
3954
3955    /// Soft-delete a channel. Errors if the channel is API-locked.
3956    fn delete(&self, id: ChannelId) -> Result<()>;
3957
3958    /// Set the channel's lock state, blocking/allowing external mutations.
3959    fn set_lock(&self, id: ChannelId, locked: bool) -> Result<Channel>;
3960
3961    /// Bulk upsert/delete channel SKU mappings. Returns the affected count.
3962    fn sync_products(&self, id: ChannelId, items: Vec<ChannelProductSyncItem>) -> Result<u64>;
3963
3964    /// List a channel's SKU mappings.
3965    fn list_product_mappings(&self, id: ChannelId) -> Result<Vec<ChannelProductMapping>>;
3966}
3967
3968/// B2B company (account) repository trait.
3969#[auto_impl::auto_impl(&, Box, Arc)]
3970pub trait CompanyRepository: Send + Sync {
3971    /// Create a new company.
3972    fn create(&self, input: CreateCompany) -> Result<Company>;
3973
3974    /// Get a company by ID.
3975    fn get(&self, id: CompanyId) -> Result<Option<Company>>;
3976
3977    /// Update a company (partial).
3978    fn update(&self, id: CompanyId, input: UpdateCompany) -> Result<Company>;
3979
3980    /// List companies with filter.
3981    fn list(&self, filter: CompanyFilter) -> Result<Vec<Company>>;
3982
3983    /// Delete a company by ID.
3984    fn delete(&self, id: CompanyId) -> Result<()>;
3985
3986    /// List the company's shipping addresses.
3987    fn list_addresses(&self, id: CompanyId) -> Result<Vec<CompanyShippingAddress>>;
3988
3989    /// List the company's product price overrides.
3990    fn list_price_overrides(&self, id: CompanyId) -> Result<Vec<CompanyPriceOverride>>;
3991
3992    /// Create a contact, linking it to one or more companies.
3993    fn create_contact(&self, input: CreateContact) -> Result<Contact>;
3994
3995    /// Get a contact by ID.
3996    fn get_contact(&self, id: ContactId) -> Result<Option<Contact>>;
3997
3998    /// List contacts for a company.
3999    fn list_contacts(&self, company_id: CompanyId) -> Result<Vec<Contact>>;
4000}
4001
4002/// Transfer order repository trait.
4003#[auto_impl::auto_impl(&, Box, Arc)]
4004pub trait TransferOrderRepository: Send + Sync {
4005    /// Create a new transfer order.
4006    fn create(&self, input: CreateTransferOrder) -> Result<TransferOrder>;
4007
4008    /// Get a transfer order by ID (with line items).
4009    fn get(&self, id: TransferOrderId) -> Result<Option<TransferOrder>>;
4010
4011    /// List transfer orders with filter.
4012    fn list(&self, filter: TransferOrderFilter) -> Result<Vec<TransferOrder>>;
4013
4014    /// Mark a transfer order as shipped from the source.
4015    fn ship(&self, id: TransferOrderId) -> Result<TransferOrder>;
4016
4017    /// Receive quantities at the destination for a single line.
4018    fn receive_line(
4019        &self,
4020        id: TransferOrderId,
4021        item_id: TransferOrderItemId,
4022        quantity: rust_decimal::Decimal,
4023    ) -> Result<TransferOrder>;
4024
4025    /// Cancel a transfer order.
4026    fn cancel(&self, id: TransferOrderId) -> Result<TransferOrder>;
4027}
4028
4029/// Units of measure / unit class / conversion rule repository trait.
4030#[auto_impl::auto_impl(&, Box, Arc)]
4031pub trait UnitOfMeasureRepository: Send + Sync {
4032    /// Create a unit class.
4033    fn create_class(&self, input: CreateUnitClass) -> Result<UnitClass>;
4034
4035    /// List unit classes.
4036    fn list_classes(&self) -> Result<Vec<UnitClass>>;
4037
4038    /// Delete a unit class (fails if still referenced).
4039    fn delete_class(&self, id: UnitClassId) -> Result<()>;
4040
4041    /// Create a unit of measure under a class.
4042    fn create_uom(&self, input: CreateUnitOfMeasure) -> Result<UnitOfMeasure>;
4043
4044    /// List units of measure, optionally scoped to a class.
4045    ///
4046    /// A server-side pagination policy applies when the filter has no limit.
4047    fn list_uoms(&self, filter: UnitOfMeasureFilter) -> Result<Vec<UnitOfMeasure>>;
4048
4049    /// Mark a UOM as the base unit for its class.
4050    fn set_base_uom(&self, id: UnitOfMeasureId) -> Result<UnitOfMeasure>;
4051
4052    /// Delete a unit of measure (fails if still referenced).
4053    fn delete_uom(&self, id: UnitOfMeasureId) -> Result<()>;
4054
4055    /// Create a conversion rule.
4056    fn create_rule(&self, input: CreateUnitConversionRule) -> Result<UnitConversionRule>;
4057
4058    /// List conversion rules.
4059    fn list_rules(&self) -> Result<Vec<UnitConversionRule>>;
4060
4061    /// Delete a conversion rule.
4062    fn delete_rule(&self, id: UnitConversionRuleId) -> Result<()>;
4063}
4064
4065/// Production batch repository trait.
4066#[auto_impl::auto_impl(&, Box, Arc)]
4067pub trait ProductionBatchRepository: Send + Sync {
4068    /// Create a new production batch.
4069    fn create(&self, input: CreateProductionBatch) -> Result<ProductionBatch>;
4070
4071    /// Get a production batch by ID.
4072    fn get(&self, id: ProductionBatchId) -> Result<Option<ProductionBatch>>;
4073
4074    /// Update a production batch (partial).
4075    fn update(
4076        &self,
4077        id: ProductionBatchId,
4078        input: UpdateProductionBatch,
4079    ) -> Result<ProductionBatch>;
4080
4081    /// List production batches with filter.
4082    fn list(&self, filter: ProductionBatchFilter) -> Result<Vec<ProductionBatch>>;
4083
4084    /// Delete a production batch.
4085    fn delete(&self, id: ProductionBatchId) -> Result<()>;
4086
4087    /// Link work orders to a batch. Returns the updated batch.
4088    fn add_work_orders(
4089        &self,
4090        id: ProductionBatchId,
4091        work_order_ids: Vec<uuid::Uuid>,
4092    ) -> Result<ProductionBatch>;
4093
4094    /// Remove a work order from a batch. Returns the updated batch.
4095    fn remove_work_order(
4096        &self,
4097        id: ProductionBatchId,
4098        work_order_id: uuid::Uuid,
4099    ) -> Result<ProductionBatch>;
4100}
4101
4102/// Supplier SKU repository trait.
4103#[auto_impl::auto_impl(&, Box, Arc)]
4104pub trait SupplierSkuRepository: Send + Sync {
4105    /// Create a new supplier SKU.
4106    fn create(&self, input: CreateSupplierSku) -> Result<SupplierSku>;
4107
4108    /// Get a supplier SKU by ID.
4109    fn get(&self, id: SupplierSkuId) -> Result<Option<SupplierSku>>;
4110
4111    /// Update a supplier SKU (partial).
4112    fn update(&self, id: SupplierSkuId, input: UpdateSupplierSku) -> Result<SupplierSku>;
4113
4114    /// List supplier SKUs with filter.
4115    fn list(&self, filter: SupplierSkuFilter) -> Result<Vec<SupplierSku>>;
4116
4117    /// Delete a supplier SKU.
4118    fn delete(&self, id: SupplierSkuId) -> Result<()>;
4119
4120    /// Bulk upsert supplier SKUs for a single supplier, keyed by internal
4121    /// product. Returns the number of rows affected.
4122    fn bulk_upsert(&self, supplier_id: uuid::Uuid, items: Vec<BulkSupplierSkuItem>) -> Result<u64>;
4123}
4124
4125/// Vendor return (return-to-supplier) repository trait.
4126#[auto_impl::auto_impl(&, Box, Arc)]
4127pub trait VendorReturnRepository: Send + Sync {
4128    /// Create a new vendor return.
4129    fn create(&self, input: CreateVendorReturn) -> Result<VendorReturn>;
4130
4131    /// Get a vendor return by ID (with line items).
4132    fn get(&self, id: VendorReturnId) -> Result<Option<VendorReturn>>;
4133
4134    /// List vendor returns with filter.
4135    fn list(&self, filter: VendorReturnFilter) -> Result<Vec<VendorReturn>>;
4136
4137    /// Submit a draft vendor return to the supplier.
4138    fn submit(&self, id: VendorReturnId) -> Result<VendorReturn>;
4139
4140    /// Process a vendor return: mark processed and optionally generate a credit.
4141    fn process(&self, id: VendorReturnId, generate_credit: bool) -> Result<VendorReturn>;
4142
4143    /// Cancel a vendor return.
4144    fn cancel(&self, id: VendorReturnId) -> Result<VendorReturn>;
4145}
4146
4147/// Vendor credit repository trait.
4148#[auto_impl::auto_impl(&, Box, Arc)]
4149pub trait VendorCreditRepository: Send + Sync {
4150    /// Create a new vendor credit.
4151    fn create(&self, input: CreateVendorCredit) -> Result<VendorCredit>;
4152
4153    /// Get a vendor credit by ID.
4154    fn get(&self, id: VendorCreditId) -> Result<Option<VendorCredit>>;
4155
4156    /// List vendor credits with filter.
4157    fn list(&self, filter: VendorCreditFilter) -> Result<Vec<VendorCredit>>;
4158
4159    /// Apply a vendor credit against a bill or payment obligation. Decrements
4160    /// the remaining balance and records an application.
4161    fn apply(&self, id: VendorCreditId, input: ApplyVendorCredit) -> Result<VendorCredit>;
4162
4163    /// List applications for a vendor credit.
4164    fn list_applications(&self, id: VendorCreditId) -> Result<Vec<VendorCreditApplication>>;
4165
4166    /// Reverse a previously-recorded application, restoring the balance.
4167    fn reverse_application(
4168        &self,
4169        id: VendorCreditId,
4170        application_id: VendorCreditApplicationId,
4171    ) -> Result<VendorCredit>;
4172
4173    /// Cancel a vendor credit (only when it has no active applications).
4174    fn cancel(&self, id: VendorCreditId) -> Result<VendorCredit>;
4175}
4176
4177/// Payment obligation repository trait.
4178#[auto_impl::auto_impl(&, Box, Arc)]
4179pub trait PaymentObligationRepository: Send + Sync {
4180    /// Create a new payment obligation.
4181    fn create(&self, input: CreatePaymentObligation) -> Result<PaymentObligation>;
4182
4183    /// Get a payment obligation by ID.
4184    fn get(&self, id: PaymentObligationId) -> Result<Option<PaymentObligation>>;
4185
4186    /// List payment obligations with filter.
4187    fn list(&self, filter: PaymentObligationFilter) -> Result<Vec<PaymentObligation>>;
4188
4189    /// Record a payment against an obligation, advancing its status.
4190    fn record_payment(
4191        &self,
4192        id: PaymentObligationId,
4193        amount: rust_decimal::Decimal,
4194    ) -> Result<PaymentObligation>;
4195
4196    /// Set the obligation status explicitly (e.g. schedule or cancel).
4197    fn set_status(
4198        &self,
4199        id: PaymentObligationId,
4200        status: PaymentObligationStatus,
4201    ) -> Result<PaymentObligation>;
4202
4203    /// Link an AP bill to an obligation (idempotent).
4204    fn link_bill(&self, id: PaymentObligationId, bill_id: uuid::Uuid) -> Result<PaymentObligation>;
4205
4206    /// Aggregate dashboard summary as of the given date.
4207    fn dashboard(&self, today: chrono::NaiveDate) -> Result<PaymentObligationDashboard>;
4208}
4209
4210/// Price level (B2B pricing tier) repository trait.
4211#[auto_impl::auto_impl(&, Box, Arc)]
4212pub trait PriceLevelRepository: Send + Sync {
4213    /// Create a new price level.
4214    fn create(&self, input: CreatePriceLevel) -> Result<PriceLevel>;
4215
4216    /// Get a price level by ID.
4217    fn get(&self, id: PriceLevelId) -> Result<Option<PriceLevel>>;
4218
4219    /// Update a price level (partial).
4220    fn update(&self, id: PriceLevelId, input: UpdatePriceLevel) -> Result<PriceLevel>;
4221
4222    /// List price levels with filter.
4223    fn list(&self, filter: PriceLevelFilter) -> Result<Vec<PriceLevel>>;
4224
4225    /// Delete a price level (and its entries).
4226    fn delete(&self, id: PriceLevelId) -> Result<()>;
4227
4228    /// Upsert a per-product fixed price entry within a level.
4229    fn set_entry(
4230        &self,
4231        id: PriceLevelId,
4232        product_id: ProductId,
4233        price: rust_decimal::Decimal,
4234    ) -> Result<PriceLevelEntry>;
4235
4236    /// Remove a per-product entry from a level.
4237    fn delete_entry(&self, id: PriceLevelId, product_id: ProductId) -> Result<()>;
4238
4239    /// List the per-product entries for a level.
4240    fn list_entries(&self, id: PriceLevelId) -> Result<Vec<PriceLevelEntry>>;
4241}
4242
4243/// Prepayment repository trait.
4244#[auto_impl::auto_impl(&, Box, Arc)]
4245pub trait PrepaymentRepository: Send + Sync {
4246    /// Create a new prepayment.
4247    fn create(&self, input: CreatePrepayment) -> Result<Prepayment>;
4248
4249    /// Get a prepayment by ID.
4250    fn get(&self, id: PrepaymentId) -> Result<Option<Prepayment>>;
4251
4252    /// List prepayments with filter.
4253    fn list(&self, filter: PrepaymentFilter) -> Result<Vec<Prepayment>>;
4254
4255    /// Apply a prepayment against a bill or payment obligation, drawing down
4256    /// the remaining balance and recording an application.
4257    fn apply(&self, id: PrepaymentId, input: ApplyPrepayment) -> Result<Prepayment>;
4258
4259    /// List applications for a prepayment.
4260    fn list_applications(&self, id: PrepaymentId) -> Result<Vec<PrepaymentApplication>>;
4261
4262    /// Reverse a previously-recorded application, restoring the balance.
4263    fn reverse_application(
4264        &self,
4265        id: PrepaymentId,
4266        application_id: PrepaymentApplicationId,
4267    ) -> Result<Prepayment>;
4268
4269    /// Refund the remaining balance, closing the prepayment.
4270    fn refund(&self, id: PrepaymentId) -> Result<Prepayment>;
4271}
4272
4273/// Price schedule (time-bounded pricing) repository trait.
4274#[auto_impl::auto_impl(&, Box, Arc)]
4275pub trait PriceScheduleRepository: Send + Sync {
4276    /// Create a new price schedule.
4277    fn create(&self, input: CreatePriceSchedule) -> Result<PriceSchedule>;
4278
4279    /// Get a price schedule by ID.
4280    fn get(&self, id: PriceScheduleId) -> Result<Option<PriceSchedule>>;
4281
4282    /// Update a price schedule (partial).
4283    fn update(&self, id: PriceScheduleId, input: UpdatePriceSchedule) -> Result<PriceSchedule>;
4284
4285    /// List price schedules with filter.
4286    fn list(&self, filter: PriceScheduleFilter) -> Result<Vec<PriceSchedule>>;
4287
4288    /// Delete a price schedule (and its entries).
4289    fn delete(&self, id: PriceScheduleId) -> Result<()>;
4290
4291    /// Upsert a per-product scheduled price.
4292    fn set_entry(
4293        &self,
4294        id: PriceScheduleId,
4295        product_id: ProductId,
4296        price: rust_decimal::Decimal,
4297    ) -> Result<PriceScheduleEntry>;
4298
4299    /// Remove a per-product entry.
4300    fn delete_entry(&self, id: PriceScheduleId, product_id: ProductId) -> Result<()>;
4301
4302    /// List per-product entries for a schedule.
4303    fn list_entries(&self, id: PriceScheduleId) -> Result<Vec<PriceScheduleEntry>>;
4304
4305    /// Resolve the effective scheduled price for a product at an instant,
4306    /// scanning active schedules (highest priority then latest start wins).
4307    fn resolve_price(
4308        &self,
4309        product_id: ProductId,
4310        at: chrono::DateTime<chrono::Utc>,
4311    ) -> Result<Option<rust_decimal::Decimal>>;
4312}
4313
4314/// Activity log (append-only subject history) repository trait.
4315#[auto_impl::auto_impl(&, Box, Arc)]
4316pub trait ActivityLogRepository: Send + Sync {
4317    /// Record a new activity log entry.
4318    fn record(&self, input: RecordActivity) -> Result<ActivityLogEntry>;
4319
4320    /// Get an entry by ID.
4321    fn get(&self, id: ActivityLogId) -> Result<Option<ActivityLogEntry>>;
4322
4323    /// List entries with filter (most recent first).
4324    fn list(&self, filter: ActivityLogFilter) -> Result<Vec<ActivityLogEntry>>;
4325
4326    /// List the full (unpaginated) history for a single subject, most recent
4327    /// first. Used for timelines and AI-over-history summaries.
4328    fn history_for_subject(
4329        &self,
4330        subject_type: &str,
4331        subject_id: uuid::Uuid,
4332    ) -> Result<Vec<ActivityLogEntry>>;
4333}
4334
4335/// Integration mapping repository trait.
4336#[auto_impl::auto_impl(&, Box, Arc)]
4337pub trait IntegrationMappingRepository: Send + Sync {
4338    /// Create a new integration mapping.
4339    fn create(&self, input: CreateIntegrationMapping) -> Result<IntegrationMapping>;
4340
4341    /// Get a mapping by ID.
4342    fn get(&self, id: IntegrationMappingId) -> Result<Option<IntegrationMapping>>;
4343
4344    /// Update a mapping (partial).
4345    fn update(
4346        &self,
4347        id: IntegrationMappingId,
4348        input: UpdateIntegrationMapping,
4349    ) -> Result<IntegrationMapping>;
4350
4351    /// List mappings with filter.
4352    fn list(&self, filter: IntegrationMappingFilter) -> Result<Vec<IntegrationMapping>>;
4353
4354    /// Delete a mapping.
4355    fn delete(&self, id: IntegrationMappingId) -> Result<()>;
4356
4357    /// Bulk upsert mappings. Returns the number of rows affected.
4358    fn bulk_upsert(&self, items: Vec<CreateIntegrationMapping>) -> Result<u64>;
4359
4360    /// Resolve the internal value for an external value, or `None` if unmapped
4361    /// (or the mapping is inactive).
4362    fn resolve(&self, lookup: &MappingLookup) -> Result<Option<String>>;
4363}
4364
4365/// Inbound shipment (ASN) repository trait.
4366#[auto_impl::auto_impl(&, Box, Arc)]
4367pub trait InboundShipmentRepository: Send + Sync {
4368    /// Create a new inbound shipment.
4369    fn create(&self, input: CreateInboundShipment) -> Result<InboundShipment>;
4370
4371    /// Get an inbound shipment by ID (with line items).
4372    fn get(&self, id: InboundShipmentId) -> Result<Option<InboundShipment>>;
4373
4374    /// List inbound shipments with filter.
4375    fn list(&self, filter: InboundShipmentFilter) -> Result<Vec<InboundShipment>>;
4376
4377    /// Mark a shipment as in transit.
4378    fn mark_in_transit(&self, id: InboundShipmentId) -> Result<InboundShipment>;
4379
4380    /// Mark a shipment as arrived at the warehouse.
4381    fn mark_arrived(&self, id: InboundShipmentId) -> Result<InboundShipment>;
4382
4383    /// Receive a quantity against a single line, advancing the shipment status.
4384    fn receive_line(
4385        &self,
4386        id: InboundShipmentId,
4387        item_id: InboundShipmentItemId,
4388        quantity: rust_decimal::Decimal,
4389    ) -> Result<InboundShipment>;
4390
4391    /// Cancel an inbound shipment.
4392    fn cancel(&self, id: InboundShipmentId) -> Result<InboundShipment>;
4393}
4394
4395/// Purgatory (order ingestion staging) repository trait.
4396#[auto_impl::auto_impl(&, Box, Arc)]
4397pub trait PurgatoryRepository: Send + Sync {
4398    /// Ingest an order into purgatory (non-posted).
4399    fn ingest(&self, input: IngestOrder) -> Result<PurgatoryOrder>;
4400
4401    /// Get a purgatory order by ID (with line items).
4402    fn get(&self, id: PurgatoryOrderId) -> Result<Option<PurgatoryOrder>>;
4403
4404    /// List purgatory orders with filter (defaults to non-posted).
4405    fn list(&self, filter: PurgatoryFilter) -> Result<Vec<PurgatoryOrder>>;
4406
4407    /// Map a line to a product and/or toggle its ignore / non-physical flags.
4408    fn map_line(
4409        &self,
4410        id: PurgatoryOrderId,
4411        line_id: PurgatoryLineItemId,
4412        input: MapPurgatoryLine,
4413    ) -> Result<PurgatoryOrder>;
4414
4415    /// Post the order, committing it out of purgatory. Errors if any line is
4416    /// still unresolved.
4417    fn post(&self, id: PurgatoryOrderId) -> Result<PurgatoryOrder>;
4418
4419    /// Delete a purgatory order.
4420    fn delete(&self, id: PurgatoryOrderId) -> Result<()>;
4421}
4422
4423/// Print station / print job repository trait.
4424#[auto_impl::auto_impl(&, Box, Arc)]
4425pub trait PrintStationRepository: Send + Sync {
4426    /// Pair a new print station, returning the station and its one-time token.
4427    fn pair(&self, input: CreatePrintStation) -> Result<PairStationResult>;
4428
4429    /// List paired stations (most recently paired first).
4430    fn list_stations(&self) -> Result<Vec<PrintStation>>;
4431
4432    /// Get a station by ID.
4433    fn get_station(&self, id: PrintStationId) -> Result<Option<PrintStation>>;
4434
4435    /// Revoke a station's token.
4436    fn revoke_station(&self, id: PrintStationId) -> Result<PrintStation>;
4437
4438    /// Enqueue a print job to a station. Errors if the station is revoked.
4439    fn enqueue_job(&self, station_id: PrintStationId, input: EnqueuePrintJob) -> Result<PrintJob>;
4440
4441    /// Pick up the next queued job for a station (agent long-poll), marking it
4442    /// picked up and updating the station's last-seen time. Returns `None` when
4443    /// the queue is empty.
4444    fn next_job(&self, station_id: PrintStationId) -> Result<Option<PrintJob>>;
4445
4446    /// Mark a job printed (`success = true`) or failed.
4447    fn complete_job(&self, job_id: PrintJobId, success: bool) -> Result<PrintJob>;
4448
4449    /// List jobs for a station.
4450    fn list_jobs(
4451        &self,
4452        station_id: PrintStationId,
4453        filter: PrintJobFilter,
4454    ) -> Result<Vec<PrintJob>>;
4455}
4456
4457/// EDI document repository trait.
4458#[auto_impl::auto_impl(&, Box, Arc)]
4459pub trait EdiDocumentRepository: Send + Sync {
4460    /// Create / ingest an EDI document.
4461    fn create(&self, input: CreateEdiDocument) -> Result<EdiDocument>;
4462
4463    /// Get a document by ID.
4464    fn get(&self, id: EdiDocumentId) -> Result<Option<EdiDocument>>;
4465
4466    /// List documents with filter.
4467    fn list(&self, filter: EdiDocumentFilter) -> Result<Vec<EdiDocument>>;
4468
4469    /// Update a document's status, optionally recording an error message.
4470    fn set_status(
4471        &self,
4472        id: EdiDocumentId,
4473        status: EdiStatus,
4474        error_message: Option<String>,
4475    ) -> Result<EdiDocument>;
4476
4477    /// Aggregate summary (counts by status and type) across all documents.
4478    fn summary(&self) -> Result<EdiAggregateSummary>;
4479}
4480
4481/// Integration field-mapping repository trait.
4482#[auto_impl::auto_impl(&, Box, Arc)]
4483pub trait IntegrationFieldMappingRepository: Send + Sync {
4484    /// Create a new field mapping.
4485    fn create(&self, input: CreateIntegrationFieldMapping) -> Result<IntegrationFieldMapping>;
4486
4487    /// Get a field mapping by ID.
4488    fn get(&self, id: IntegrationFieldMappingId) -> Result<Option<IntegrationFieldMapping>>;
4489
4490    /// Update a field mapping (partial).
4491    fn update(
4492        &self,
4493        id: IntegrationFieldMappingId,
4494        input: UpdateIntegrationFieldMapping,
4495    ) -> Result<IntegrationFieldMapping>;
4496
4497    /// List field mappings with filter.
4498    fn list(&self, filter: IntegrationFieldMappingFilter) -> Result<Vec<IntegrationFieldMapping>>;
4499
4500    /// Delete a field mapping.
4501    fn delete(&self, id: IntegrationFieldMappingId) -> Result<()>;
4502
4503    /// Bulk create field mappings. Returns the number created.
4504    fn bulk_create(&self, items: Vec<CreateIntegrationFieldMapping>) -> Result<u64>;
4505
4506    /// Bulk delete field mappings by ID. Returns the number deleted.
4507    fn bulk_delete(&self, ids: Vec<IntegrationFieldMappingId>) -> Result<u64>;
4508
4509    /// List the distinct mapping groups for an integration account.
4510    fn distinct_groups(&self, integration_account: &str) -> Result<Vec<String>>;
4511}
4512
4513/// Customer operational topology snapshot repository trait.
4514#[auto_impl::auto_impl(&, Box, Arc)]
4515pub trait TopologySnapshotRepository: Send + Sync {
4516    /// Capture a new snapshot (health is derived from the metrics).
4517    fn capture(&self, input: CaptureTopologySnapshot) -> Result<TopologySnapshot>;
4518
4519    /// Get a snapshot by ID.
4520    fn get(&self, id: TopologySnapshotId) -> Result<Option<TopologySnapshot>>;
4521
4522    /// Get the most recent snapshot, if any.
4523    fn latest(&self) -> Result<Option<TopologySnapshot>>;
4524
4525    /// List snapshots (most recent first).
4526    fn list(&self, filter: TopologySnapshotFilter) -> Result<Vec<TopologySnapshot>>;
4527
4528    /// Delete a snapshot.
4529    fn delete(&self, id: TopologySnapshotId) -> Result<()>;
4530}
4531
4532/// Stock snapshot repository trait.
4533#[auto_impl::auto_impl(&, Box, Arc)]
4534pub trait StockSnapshotRepository: Send + Sync {
4535    /// Capture a new stock snapshot (totals are computed from the lines).
4536    fn capture(&self, input: CaptureStockSnapshot) -> Result<StockSnapshot>;
4537
4538    /// Get a snapshot by ID (with lines).
4539    fn get(&self, id: StockSnapshotId) -> Result<Option<StockSnapshot>>;
4540
4541    /// Get the most recent snapshot, if any.
4542    fn latest(&self) -> Result<Option<StockSnapshot>>;
4543
4544    /// List snapshots (header-level, most recent first).
4545    fn list(&self, filter: StockSnapshotFilter) -> Result<Vec<StockSnapshot>>;
4546
4547    /// Delete a snapshot.
4548    fn delete(&self, id: StockSnapshotId) -> Result<()>;
4549}
4550
4551use crate::models::{
4552    CreateFixedAsset, CreateRevenueContract, DepreciationSchedule, FixedAsset, FixedAssetFilter,
4553    PerformanceObligation, RevenueContract, RevenueContractFilter, RevenueSchedule,
4554    UpdateFixedAsset, UpdateRevenueContract,
4555};
4556
4557/// Fixed asset register repository trait.
4558#[auto_impl::auto_impl(&, Box, Arc)]
4559pub trait FixedAssetRepository: Send + Sync {
4560    /// Create a new fixed asset (draft, or in-service when an in-service date is supplied).
4561    fn create(&self, input: CreateFixedAsset) -> Result<FixedAsset>;
4562
4563    /// Get a fixed asset by ID.
4564    fn get(&self, id: uuid::Uuid) -> Result<Option<FixedAsset>>;
4565
4566    /// List fixed assets with filter.
4567    fn list(&self, filter: FixedAssetFilter) -> Result<Vec<FixedAsset>>;
4568
4569    /// Update a fixed asset (partial). Terminal assets cannot be updated.
4570    fn update(&self, id: uuid::Uuid, input: UpdateFixedAsset) -> Result<FixedAsset>;
4571
4572    /// Place a draft asset in service on the given date.
4573    fn place_in_service(&self, id: uuid::Uuid, date: chrono::NaiveDate) -> Result<FixedAsset>;
4574
4575    /// Dispose of an asset for the given proceeds, recording gain/loss.
4576    fn dispose(
4577        &self,
4578        id: uuid::Uuid,
4579        date: chrono::NaiveDate,
4580        proceeds: rust_decimal::Decimal,
4581        notes: Option<String>,
4582    ) -> Result<FixedAsset>;
4583
4584    /// Write off an asset (disposal with zero proceeds).
4585    fn write_off(
4586        &self,
4587        id: uuid::Uuid,
4588        date: chrono::NaiveDate,
4589        notes: Option<String>,
4590    ) -> Result<FixedAsset>;
4591
4592    /// Generate and persist the depreciation schedule for an asset,
4593    /// replacing any previously scheduled (unposted) entries.
4594    fn generate_schedule(&self, id: uuid::Uuid) -> Result<DepreciationSchedule>;
4595
4596    /// Get the persisted depreciation schedule for an asset, if generated.
4597    fn get_schedule(&self, id: uuid::Uuid) -> Result<Option<DepreciationSchedule>>;
4598
4599    /// Post the next `periods` scheduled depreciation entries, advancing
4600    /// accumulated depreciation (and status when fully depreciated).
4601    fn post_depreciation(&self, id: uuid::Uuid, periods: u32) -> Result<FixedAsset>;
4602}
4603
4604/// Revenue recognition (ASC 606) repository trait.
4605#[auto_impl::auto_impl(&, Box, Arc)]
4606pub trait RevenueRecognitionRepository: Send + Sync {
4607    /// Create a new revenue contract with its performance obligations.
4608    fn create_contract(&self, input: CreateRevenueContract) -> Result<RevenueContract>;
4609
4610    /// Get a revenue contract by ID (with obligations).
4611    fn get_contract(&self, id: uuid::Uuid) -> Result<Option<RevenueContract>>;
4612
4613    /// List revenue contracts with filter.
4614    fn list_contracts(&self, filter: RevenueContractFilter) -> Result<Vec<RevenueContract>>;
4615
4616    /// Update a revenue contract (partial); status changes are transition-guarded.
4617    fn update_contract(
4618        &self,
4619        id: uuid::Uuid,
4620        input: UpdateRevenueContract,
4621    ) -> Result<RevenueContract>;
4622
4623    /// List the performance obligations under a contract.
4624    fn list_obligations(&self, contract_id: uuid::Uuid) -> Result<Vec<PerformanceObligation>>;
4625
4626    /// Generate and persist the recognition schedule for an obligation,
4627    /// replacing any previously deferred (unrecognized) entries.
4628    fn generate_schedule(&self, obligation_id: uuid::Uuid) -> Result<RevenueSchedule>;
4629
4630    /// Get the persisted recognition schedule for an obligation, if generated.
4631    fn get_schedule(&self, obligation_id: uuid::Uuid) -> Result<Option<RevenueSchedule>>;
4632
4633    /// Recognize all deferred entries with a period start on or before
4634    /// `through`, advancing the obligation's recognized amount (and the
4635    /// contract status when fully recognized).
4636    fn recognize_period(
4637        &self,
4638        obligation_id: uuid::Uuid,
4639        through: chrono::NaiveDate,
4640    ) -> Result<RevenueSchedule>;
4641}