Architecture Deployment API

Domain Model

All 14 aggregates and their relationships.

erDiagram
  Vendor ||--o{ SmartVase : "owns"
  Vendor ||--o{ Employee : "employs"
  Vendor {
    VendorId Id
    string Name
    VendorType Type
    string Email
    bool IsActive
  }

  SmartVase ||--o| Bouquet : "currently displays"
  SmartVase {
    VaseId Id
    VendorId VendorId
    string SerialNumber
    Location Location
    VaseStatus Status
    DateTime LastHeartbeat
  }

  Bouquet ||--o{ BouquetFeedback : "receives"
  Bouquet {
    BouquetId Id
    VendorId VendorId
    VaseId VaseId
    string Name
    PriceInfo Price
    BouquetStatus Status
    string QrShortCode
    int FreshnessScore
  }

  Customer ||--o{ Order : "places"
  Customer ||--o{ Favourite : "saves"
  Customer ||--o{ Subscription : "subscribes"
  Customer ||--o{ SavedAddress : "stores"
  Customer ||--o{ DeviceRegistration : "registers"
  Customer ||--o{ Notification : "receives"
  Customer {
    CustomerId Id
    string Name
    ContactInfo ContactInfo
    Address Address
    bool PhoneVerified
  }

  Order ||--|{ OrderLine : "contains"
  Order ||--o{ BouquetFeedback : "generates"
  Order {
    OrderId Id
    CustomerId CustomerId
    VendorId VendorId
    OrderStatus Status
    decimal LinesSubtotal
    DeliveryAddress DeliveryAddress
    DateTime BouquetReservedUntil
  }

  OrderLine {
    OrderLineId Id
    OrderId OrderId
    BouquetId BouquetId
    decimal UnitPrice
  }

  Customer ||--o| Cart : "has"
  Cart ||--|{ CartItem : "contains"
  Cart {
    CartId Id
    CustomerId CustomerId
    VendorId VendorId
    VendorType VendorType
    DateTime CreatedAt
    DateTime UpdatedAt
  }

  CartItem {
    BouquetId BouquetId
    VaseId VaseId
    decimal UnitPrice
    string BouquetName
    DateTime AddedAt
  }

  BouquetFeedback {
    BouquetFeedbackId Id
    OrderId OrderId
    BouquetId BouquetId
    VendorId VendorId
    CustomerId CustomerId
    int Rating
    string Comment
    bool IsAnonymous
  }

  Favourite {
    FavouriteId Id
    CustomerId CustomerId
    BouquetId BouquetId
  }

  Subscription {
    SubscriptionId Id
    CustomerId CustomerId
    VendorId ShopId
    SubscriptionType Type
    bool IsActive
  }

  Notification {
    NotificationId Id
    CustomerId CustomerId
    string Title
    string Body
    bool IsRead
  }

  DeviceRegistration {
    DeviceRegistrationId Id
    CustomerId CustomerId
    string DeviceToken
    DevicePlatform Platform
  }

  SavedAddress {
    SavedAddressId Id
    CustomerId CustomerId
    Address Address
    string Label
  }

  Employee {
    EmployeeId Id
    VendorId VendorId
    string Name
    EmployeeRole Role
    bool IsActive
  }

  User {
    UserId Id
    UserRole Role
    CustomerId CustomerId
    VendorId VendorId
    VendorType VendorType
  }

Aggregate Notes

Aggregate Key Invariants
Vendor Polymorphic — FlowerShop (location + hours) or FreelanceFlorist (privacy radius). VendorId + VendorType scope all child data.
Bouquet Status machine: Available → Sold / Expired. Price changes only when status is Available.
SmartVase One bouquet at a time (CurrentBouquetId). RegistrationStatus: PendingAssignment → Active → Inactive / UnderMaintenance / Decommissioned. ConnectionStatus (Online/Offline/Unstable) tracked separately via heartbeat.
Order Multi-line. Bouquets reserved for 15 min on creation. All lines must belong to the same vendor.
Cart Vendor-scoped: all items must belong to the same vendor. Adding a different vendor returns 409 vendor-mismatch.
User Role determines which of CustomerId / VendorId is set.