Skip to main content
Version: v1.0.0(int)

SalesOrders

Sales order header + items + timeline notes + order channels (SO-only org-configurable lookup). FG ledger entries (DEMAND / ALLOCATE / CONSUME) are written by FinishedGoodsInventory via L3. Document attachments live in Documents.

Tables owned​

TablePurpose
org.sales_ordersSO header (number, customer, channel, fulfillment location, costs, MABD, status enum, fulfillment status enum, QBO ID, notes).
org.so_itemsLine items (sku, quantity, unit price).
org.so_timeline_notesAppend-only notes attached to an SO with status-at-time-of-note.
org.order_channelsOrg-configurable channel lookup (e.g., Direct, Distributor) with display color.

Operations​

Writes — Header​

  • createSo(conn, input) → SalesOrder. input: { number, customerId, channelId, fulfillmentLocationId, costs?, mabd?, status, fulfillmentStatus, qboId?, notes? }. Status enums: order_status, fulfillment_status.
  • updateSo(conn, soId, patch) → SalesOrder. Partial update including status transitions.
  • deleteSo(conn, soId) → void. Cascades to items, notes. Documents are detached by L3 (which calls Documents.delete for each).

Writes — Items​

  • addItem(conn, soId, item) → SoItem. item: { skuId, quantity, unitPrice }.
  • updateItem(conn, itemId, patch) → SoItem. Edits quantity / unit price / SKU.
  • removeItem(conn, itemId) → void.

Writes — Timeline notes​

  • addTimelineNote(conn, soId, input) → SoTimelineNote. input: { body, statusAtTime? }. statusAtTime is captured by L3 from the SO's current status if not supplied.
  • deleteTimelineNote(conn, noteId) → void.

Writes — Order channels​

  • createChannel(conn, { name, color? }) → OrderChannel.
  • updateChannel(conn, channelId, patch) → OrderChannel. Rename / recolor.
  • deleteChannel(conn, channelId) → void. L3 enforces "no SO uses it".

Reads — Header​

  • listSos(conn, filters?) → SalesOrder[]. Filters: { status?, fulfillmentStatus?, customerId?, channelId?, fulfillmentLocationId?, dateFrom?, dateTo? }.
  • getSoById(conn, soId) → SalesOrder | null.
  • getSosByIds(conn, soIds) → SalesOrder[].
  • getSoByNumber(conn, number) → SalesOrder | null.

Reads — Items​

  • listItemsBySo(conn, soId) → SoItem[].
  • listItemsBySos(conn, soIds) → Map<soId, SoItem[]>.
  • getItemById(conn, itemId) → SoItem | null.

Reads — Timeline notes​

  • listTimelineNotesBySo(conn, soId) → SoTimelineNote[]. Ordered by created_at desc.

Reads — Order channels​

  • listChannels(conn) → OrderChannel[].
  • getChannelById(conn, channelId) → OrderChannel | null.
  • getChannelsByIds(conn, channelIds) → OrderChannel[]. Batch hydration.
  • isChannelInUse(conn, channelId) → { inUse: boolean, soCount: number }. Gates deletion.

Notes​

  • Document attachments on an SO go through Documents (entity_type = 'sales_order'). L3 composes by calling SalesOrders.getSoById + Documents.listByEntity('sales_order', soId).
  • Computed fulfillment status on the detail view (from the FG ledger) is an L3 derivation. L2 returns the stored enum value only.
  • "Bulk import SOs" is an L3 workflow.