Specs › shop · version 1 ·
tags
#shop

shop✎ edit

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✎ edit

$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✎ edit

$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✎ edit

$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✎ edit

$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✎ edit

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")

Declares 21 classes: Variant, Product, Category, PriceList, Supplier, Address, Customer, Review, CartLine, Cart, OrderLine, Order, ….