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.