# Order

> E-commerce order with line items, shipping/billing addresses, status tracking, and totals.

- Name: `order`
- Categories: ecommerce
- Depends on: `@open-types/address`, `@open-types/cart-item`
- Detail page: https://open-types.dev/types/order

## Install

```bash
# Types only
npx shadcn add @open-types/order

# Types + Zod v4 validators
npx shadcn add @open-types/order-zod

# Types + real-world examples
npx shadcn add @open-types/order-examples
```

## Types

```typescript
import type { Address } from "./address";
import type { CartItem } from "./cart-item";
import type { CurrencyCode } from "./product";

export type OrderStatus =
  | "pending"
  | "confirmed"
  | "processing"
  | "shipped"
  | "delivered"
  | "cancelled"
  | "refunded";

export interface Order {
  id: string;
  items: CartItem[];
  shippingAddress: Address;
  billingAddress?: Address;
  subtotal: number;
  tax: number;
  shippingCost?: number;
  discount?: number;
  total: number;
  currency?: CurrencyCode;
  status?: OrderStatus;
  notes?: string;
  createdAt: string;
  updatedAt: string;
}

export type OrderCreate = Omit<Order, "id" | "createdAt" | "updatedAt">;
```

## Zod validator

```typescript
import * as z from "zod";
import type { Order, OrderCreate, OrderStatus } from "../types/order";
import { addressSchema } from "./address";
import { cartItemSchema } from "./cart-item";
import { currencyCodeSchema } from "./product";

export const orderStatusSchema = z.enum([
  "pending",
  "confirmed",
  "processing",
  "shipped",
  "delivered",
  "cancelled",
  "refunded",
]);

export const orderSchema = z.object({
  id: z.uuid({ error: "Invalid order ID" }),
  items: z
    .array(cartItemSchema)
    .min(1, { error: "Order must have at least one item" }),
  shippingAddress: addressSchema,
  billingAddress: addressSchema.optional(),
  subtotal: z
    .number()
    .min(0, { error: "Subtotal cannot be negative" })
    .multipleOf(0.01),
  tax: z
    .number()
    .min(0, { error: "Tax cannot be negative" })
    .multipleOf(0.01),
  shippingCost: z
    .number()
    .min(0, { error: "Shipping cost cannot be negative" })
    .multipleOf(0.01)
    .default(0),
  discount: z
    .number()
    .min(0, { error: "Discount cannot be negative" })
    .multipleOf(0.01)
    .default(0),
  total: z
    .number()
    .min(0, { error: "Total cannot be negative" })
    .multipleOf(0.01),
  currency: currencyCodeSchema,
  status: orderStatusSchema.default("pending"),
  notes: z.string().max(1000, { error: "Notes must be at most 1000 characters" }).optional(),
  createdAt: z.iso.datetime({ error: "Invalid datetime" }),
  updatedAt: z.iso.datetime({ error: "Invalid datetime" }),
}) satisfies z.ZodType<Order>;

export const orderCreateSchema = orderSchema.omit({
  id: true,
  createdAt: true,
  updatedAt: true,
});

export type { Order, OrderCreate, OrderStatus } from "../types/order";
```

## Examples

```typescript
// Source: hand-crafted
import type {
  OrderStatus,
  Order,
  OrderCreate,
} from "../types/order";
import { cartItemExamples } from "./cart-item.examples";
import { addressExamples } from "./address.examples";

export const orderStatusExamples = {
  pending: "pending",
  confirmed: "confirmed",
  processing: "processing",
  shipped: "shipped",
  delivered: "delivered",
  cancelled: "cancelled",
  refunded: "refunded",
} as const satisfies Record<string, OrderStatus>;

const placed = {
  id: "aaaaaaaa-1111-4111-8111-111111111111",
  items: [cartItemExamples.basic, cartItemExamples.withVariant],
  shippingAddress: addressExamples.minimal,
  billingAddress: addressExamples.full,
  subtotal: 131.98,
  tax: 11.55,
  shippingCost: 5.99,
  discount: 0,
  total: 149.52,
  currency: "USD",
  status: "confirmed",
  notes: "Ring doorbell on arrival.",
  createdAt: "2026-05-16T18:30:00.000Z",
  updatedAt: "2026-05-16T18:32:15.000Z",
} as const satisfies Order;

export const orderExamples = {
  placed,
  shipped: {
    ...placed,
    id: "bbbbbbbb-2222-4222-8222-222222222222",
    status: "shipped",
    updatedAt: "2026-05-17T10:00:00.000Z",
  } satisfies Order,
  delivered: {
    ...placed,
    id: "cccccccc-3333-4333-8333-333333333333",
    status: "delivered",
    updatedAt: "2026-05-19T16:42:00.000Z",
  } satisfies Order,
  cancelled: {
    ...placed,
    id: "dddddddd-4444-4444-8444-444444444444",
    status: "cancelled",
    updatedAt: "2026-05-16T18:45:00.000Z",
  } satisfies Order,
  refunded: {
    ...placed,
    id: "eeeeeeee-5555-4555-8555-555555555555",
    status: "refunded",
    updatedAt: "2026-05-20T09:00:00.000Z",
  } satisfies Order,
  minimal: {
    id: "ffffffff-6666-4666-8666-666666666666",
    items: [cartItemExamples.basic],
    shippingAddress: addressExamples.minimal,
    subtotal: 59.98,
    tax: 5.25,
    total: 65.23,
    createdAt: "2026-05-16T18:30:00.000Z",
    updatedAt: "2026-05-16T18:30:00.000Z",
  } satisfies Order,
  digitalOnly: {
    ...placed,
    id: "99999999-7777-4777-8777-777777777777",
    items: [cartItemExamples.digital],
    subtotal: 19.99,
    tax: 1.75,
    shippingCost: 0,
    total: 21.74,
    notes: undefined,
  } satisfies Order,
} as const;

export const orderCreateExamples = {
  basic: {
    items: [cartItemExamples.basic],
    shippingAddress: addressExamples.minimal,
    subtotal: 59.98,
    tax: 5.25,
    total: 65.23,
    status: "pending",
  } satisfies OrderCreate,
} as const;
```
