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. |