- tags
- #shop
shop¶
A small online shop, Grindstone Coffee Gear, as a domain model: what it sells, who buys, their orders, and how orders get to them. Its sample data is in shop-samples; what happens when things change (a new cart, an order placed, stock running low…) is in the flow topics, explained in FlowsGuide.
Conventions (d2 class syntax): X* is a list, <>X / <>X* a reference by key to another stored object, and a bare X is containment (a class with no @key is kept inside its owner). @label marks the display field, ? an optional field, @calc(…) a field worked out from the others.
Catalogue¶
$class Variant (
sku: String,
@label option: String,
price: Number,
) @group("Catalogue")
$class Product (
@key id: String,
@label name: String,
description: String,
category: <>Category,
supplier: <>Supplier,
price: Number,
variants: Variant*,
) @group("Catalogue")
$class Category (
@key id: String,
@label name: String,
parent: <>Category?,
) @group("Catalogue")
$class PriceList (
@key id: String,
@label name: String,
discountPct: Number,
) @group("Catalogue")
$class Supplier (
@key id: String,
@label name: String,
email: String,
leadDays: Number,
) @group("Catalogue")
Customers¶
$class Address (
street: String,
city: String,
postalCode: String,
country: String,
) @group("Customers")
$class Customer (
@key id: String,
@label name: String,
email: String,
address: Address,
wishlist: <>Product*,
priceList: <>PriceList?,
) @group("Customers")
$class Review (
@key id: String,
product: <>Product,
customer: <>Customer,
stars: Number,
@label text: String,
) @group("Customers")
Orders¶
$class CartLine (
sku: String,
qty: Number,
unitPrice: Number,
@calc(qty * unitPrice) lineTotal: Number,
) @group("Orders")
$class Cart (
@key id: String,
customer: <>Customer,
status: String,
updated: Date,
lines: CartLine*,
) @group("Orders")
$class OrderLine (
sku: String,
qty: Number,
unitPrice: Number,
@calc(qty * unitPrice) lineTotal: Number,
) @group("Orders")
$class Order (
@key id: String,
customer: <>Customer,
status: String,
placed: Date,
lines: OrderLine*,
@calc(lines map (l => l.qty * l.unitPrice) fold (s = 0.0) (x => s + x)) total: Number,
) @group("Orders")
$class Payment (
@key id: String,
order: <>Order,
amount: Number,
method: String,
status: String,
) @group("Orders")
$class Invoice (
@key number: String,
order: <>Order,
amount: Number,
issued: Date,
) @group("Orders")
$class Refund (
@key id: String,
payment: <>Payment,
amount: Number,
reason: String,
) @group("Orders")
Fulfilment¶
$class Warehouse (
@key id: String,
@label name: String,
city: String,
) @group("Fulfilment")
$class StockLevel (
@key id: String,
sku: String,
warehouse: <>Warehouse,
qty: Number,
reorderAt: Number,
) @group("Fulfilment")
$class Shipment (
@key id: String,
order: <>Order,
carrier: String,
tracking: String,
status: String,
) @group("Fulfilment")
$class ReturnLine (
sku: String,
qty: Number,
) @group("Fulfilment")
$class Return (
@key id: String,
order: <>Order,
status: String,
reason: String,
lines: ReturnLine*,
) @group("Fulfilment")
The shop's outbox¶
Every message the flows send goes through one rule, shop.notify (shop-notify), which keeps it here, so you can see what the shop would have sent and to whom.
$class Message (
@key id: String,
to: String,
@label text: String,
at: Date,
) @group("Outbox")