Skip to main content

Go Order Tutorial

Build understanding around one draft Order: load its complete item list, change Notebook quantity from 2 to 3, save the Order and line totals together, then read the result in a new process. Follow the recorded native SQLite application and learn why each query, expression and transaction boundary is needed. The version and publication boundaries below apply to this specific example.

The generator/runtime contract repair and pagination observations use the retained workspace: WORKSPACE PASS — RELEASE PENDING. Keep the selected Go workspace/module resolution; a newly published version needs its own qualification.

1. Prepare the example​

You need the Go toolchain, the site checkout, and the retained built golang-app-console workspace from the core Order receipt. Read its build.toolchain, build.runtimeSource, build.runtimePackage and verification.qualification entries for go before selecting dependencies. The commands below assume that recorded workspace and its dependencies already exist; they are not a clean-machine bootstrap or a claim that every published runtime passes. For build/replay preparation use the retained workspace instructions.

Start a new model with the Go Quick Start, then use Order-scoped Assist for its generated Q/E/mutation methods. This page reuses the evaluated Order v1.0 model and the three-order fixture. Do not substitute the isolation/stock fixture: those are separately evaluated model revisions.

The complete application contains imports, helpers, startup and all phase handlers. The excerpts below are function-body excerpts from that application, not standalone files. The source imports the generated lib facade plus the customer_order and order_item expression packages. required, nullable, check and report are application helpers, not new generated APIs. For new models obtain the package paths and method names through Assist.

2. Understand startup and run the first edit​

ServiceRuntimeFromEnv() constructs the native provider and *runtime.UserContext. Check its returned error, then explicitly call EnsureSchema(context) before normal phases. Set ORDER_WORKFLOW_SERVICE_CORE_DATABASE_URL to the absolute database path as well as ORDER_DATABASE.

Module installation registers metadata and behavior. Schema reconciliation is an explicit database operation. Keep startup/admin schema work separate from request execution, and obtain tenant/actor/policy from trusted server context.

From the site root, run this sequence with a new disposable database:

export ORDER_WORKSPACE="$PWD/artifacts/order/2026-10-27/golang/golang-app-console"
export ORDER_FIXTURE="$PWD/static/examples/order/fixture.json"
export ORDER_DATABASE="$(mktemp -d)/orders.sqlite"
export ORDER_WORKFLOW_SERVICE_CORE_DATABASE_URL="$ORDER_DATABASE"
cd "$ORDER_WORKSPACE"
for phase in bootstrap seed draft-graph note-value note-null note-empty note-not-loaded invalid-quantity draft-edit restart-readback; do
../order "$phase"
done

Run seed once on the fresh database; the fixture program is not an import/upsert service. Each phase starts a fresh process against the same absolute database path. The two NotLoaded probes are intentional negative examples; their handler reports the native error and finishes successfully.

Stop and inspectExpected result
bootstrapExplicit schema setup and ORDER_OK phase=bootstrap.
seed and draft-graphThree Orders, six items; ORD-2026-1001 is DRAFT with total 3850 USD cents.
Note phasesValue, SQL NULL, empty text and NotLoaded remain distinct.
invalid-quantity0, -1, 1.5 and 101 rejected before save.
draft-editNotebook quantity 3, Notebook line total 3750, Order total 5100.
restart-readbackThe same totals in a new process; Order and changed item version 2, untouched item version 1.

The handlers print ORDER_CASE JSON and an ORDER_OK completion line. Find the Order by business number and the line by SKU; generated numeric IDs are not portable fixture keys. Compare the returned graph with these expected values before adapting the operation to your own model.

3. Load the full Order before editing​

rows, err := Q.CustomerOrders().WithOrderNumberIs("ORD-2026-1001").
SelectOrderItemListWith(Q.OrderItems().OrderBySkuCodeAsc().OrderByIdAsc().Limit(101)).Limit(2).
Comment("Load full draft and bounded full items").Purpose("Validate and edit one draft order").ExecuteForList(context)

The outer bound of 2 lets the application reject a duplicate business identity. The child bound of 101 is an overflow sentinel for a supported maximum of 100 items. Require exactly one Order, DRAFT status and at most 100 loaded items before continuing. A one-item preview is useful for a list screen, but cannot supply the complete total for an edit. The full source performs these checks after the query; keep them when adapting the excerpt.

comment describes the operation and purpose records the business reason. Both travel with execution through the trusted context. A buyer filter in this v1.0 fixture is a business predicate; it does not authenticate or authorize a buyer. Use the separate buyer/tenant isolation contract when implementing protected access.

4. Validate money and save one atomic edit​

The application validates integral quantity in [1, 100], USD currency, each stored line amount and the complete new Order total. Prices and totals are integer cents. It finds exactly one SKU-NOTEBOOK, computes 3 × 1250 + 3 × 450 = 5100, then changes the selected item and Order together. The following write excerpt assumes those validated, fully loaded variables; it is not a replacement for validation.

The audit reason is Edit draft Order quantity and totals atomically, named EDIT in most examples and editReason/EditReason in Go, Swift and .NET.

selected.UpdateQuantity(int64(quantity))
selected.UpdateLineTotalMinor(int64(quantity) * required(order_item.NewOrderItemExpression(selected).UnitPriceMinor().Eval()))
order.UpdateTotalMinor(total)
fmt.Println("ORDER_GRAPH_ATTEMPT")
_, err = order.AuditAs(editReason).Save(context)
return err

Validate signed bounds before converting them to uint64. Check every returned error. Expressions return (value, present); use the checked required helper for non-null money and the nullable helper for notes. Keep Go’s chain continuation dot at the end of the previous line, as in the excerpt.

A successful audited save returns the persisted typed entity. The core example reads again after mutation, rather than treating a pre-save object as independent evidence of committed state. A rejected stale write requires reloading authoritative state and a business decision before retrying; it is not permission to overwrite the winner or retry every provider error.

5. Use projections, nulls and pages deliberately​

TaskGo API in this exampleResult / responsibility
Execute a bounded queryExecuteForList(context) → result and errorTyped SmartList; preserve native errors and check cardinality.
Read selected moneycustomer_order.NewCustomerOrderExpression(order).TotalMinor().Eval()Loaded integer cents; not a formatting or currency conversion API.
Access selected itemsorder.OrderItemList().Items()Only the relation that was explicitly loaded.
Default a selected SQL NULL noteOrderNote().OrElse(&fallback)Null-only fallback; an empty string stays empty and NotLoaded still reports a missing field.
Save an audited mutationorder.AuditAs(editReason).Save(context)Persisted typed entity; the required transaction includes all changed entities.
Request an exact page totalOffset(uint64(offset)).Limit(uint64(limit)).Count() → page.TotalCount (pointer)Total of the filtered set, independent of page length.

The note accessors in the table are called on the corresponding E expression. required, report, pageRows, load, edit and prepare_edit are application helpers where present; they are not additional generated terminal methods.

Note stateExpected behavior
Selected valueLeave at reception stays that value.
Selected SQL NULLA null-only default produces No note.
Selected empty textRemains the empty string.
Omitted fieldNative NotLoaded diagnostic, including when a null-only default is attempted.

For a read-only list screen, the existing bounded-page handler validates offset >= 0 and 1 <= limit <= 3, sets a stable total/ID order and explicitly selects one item preview per Order. With validated offset, limit and buyer, its native query is:

page, err := Q.CustomerOrders().WithBuyerReferenceIs(buyer).OrderByTotalMinorAsc().OrderByIdAsc().
SelectOrderItemListWith(Q.OrderItems().OrderBySkuCodeAsc().OrderByIdAsc().Limit(1)).Offset(uint64(offset)).Limit(uint64(limit)).Count().
Comment("Read bounded Order pages").Purpose("Compare filtered totals and per-order item previews").ExecuteForList(context)

This query only reads. Do not save its one-item preview as if it were a full Order edit or infer deletion of omitted items. The pagination fixture has eight matching BUYER-EXPORT Orders, whereas the first-edit fixture above has three Orders overall. See the page API decision guide for fixture selection, continuous export, retained-ID jumps and aggregate results.

6. Diagnose a failure before changing code​

For a field error preserve a recovered NotLoaded panic and its path. In cancellation cleanup, database/sql may return native sql.ErrTxDone after auto-rollback; the lifecycle/soak receipt checks actual lock and connection release rather than treating that message alone as a leak.

SymptomFirst action
Workspace or package missingConfirm the retained artifact prerequisite; follow the Quick Start for fresh generation instead of assuming this checkout ships compiled outputs.
Empty Order or duplicate rowConfirm absolute DB path, fixture and business number; preserve the cardinality check.
Wrong total after editCheck complete item loading and integer validation before the audited save.
Missing field errorReload the field/relation explicitly; do not substitute a null default.
Version conflictReload authoritative state and decide whether the requested edit is still valid.
Busy/locked, commit or cancellation failureInspect native provider error and transaction boundary; follow the Go Order troubleshooting table.

Continue with the Order API usage guide, Go advanced data operations, version and qualification table and documentation coverage matrix. The School regression baseline and all prior Order receipts remain unchanged.

Continue with advanced Order writes​

Follow Go Advanced Order Mutations for explicit line deletion, legal state transitions and stale-version recovery. Each recipe explains its starting state, transaction boundary, native errors and independent readback using the existing qualified example. Start a fresh recipe database; do not reuse the quantity-edited database above.

Continue with Order queries​

Use Go Order Queries for continuous export, retained-ID page jumps and provider summaries. The query recipes use separate nine-/ten-order datasets; keep the fixture and context/store lifetime with the operation you are learning.

Continue with buyer and tenant isolation​

Use Go Order Isolation to upgrade the model to v1.1 and build root/buyer scope from an application-owned trusted session.