Show the difference between order acceptance and ERP completion
Give buyers and operators an accurate delivery timeline without exposing integration payloads or implying that commerce acceptance proves ERP completion.
In this guide
A receipt is not an ERP acknowledgment
A buyer sees an order confirmation and assumes the warehouse has received it. Support sees a retrying integration delivery and assumes the order failed. Both interpretations collapse several different milestones into one word: success.
Separate commerce acceptance from external delivery and later fulfillment. The storefront may have a valid accepted order while the ERP connection is temporarily unavailable. Conversely, a transport response can arrive before the external system has completed its own business validation. Status should describe the milestone actually established by evidence.
Define a small public vocabulary
Use states that help the intended audience act. A buyer may need 'Order received', 'Processing', and an actionable support message. An authorized operator may also need queued, attempting, awaiting reconciliation, delivered, and needs attention. Avoid exposing internal exception names as customer-facing states.
Define the source of every milestone and its timestamp. 'Delivered' should mean the agreed provider acknowledgment was obtained, not merely that a worker started. Shipment and invoice milestones belong to their own verified contracts. Do not invent them from a successful create-order response.
Project a safe delivery status
OrderDeliveryStatus.cs takes an already authorized Store/account/order context and a durable delivery record, then returns only the order number, message, and observation time. Unknown enum values fail explicitly. The method performs no transport, replay, or status mutation.
Populate DeliveryRecord from the project-owned ledger after its order identity has been established through the platform order read. Delivered requires the provider acknowledgment defined by that integration. Keep shipment and invoice facts in their own verified contracts instead of inferring them from this delivery state.
Orders/OrderDeliveryStatus.cs csharp
using System;
namespace Gcg.DeveloperExamples.Orders
{
public enum DeliveryState { Queued, Attempting, Reconcile, Delivered, NeedsAttention }
public sealed class DeliveryRecord
{
public int StoreId { get; set; }
public int AccountId { get; set; }
public string OrderNumber { get; set; }
public DeliveryState State { get; set; }
public DateTimeOffset CheckedAt { get; set; }
}
public sealed class PublicDeliveryStatus
{
public string OrderNumber { get; }
public string Message { get; }
public DateTimeOffset CheckedAt { get; }
public PublicDeliveryStatus(string orderNumber, string message, DateTimeOffset checkedAt)
{ OrderNumber = orderNumber; Message = message; CheckedAt = checkedAt; }
}
public static class OrderDeliveryStatus
{
public static PublicDeliveryStatus Project(DeliveryRecord record,
int authorizedStore, int authorizedAccount, string authorizedOrder)
{
if (record == null || authorizedStore < 1 || authorizedAccount < 1 ||
string.IsNullOrWhiteSpace(authorizedOrder) ||
record.StoreId != authorizedStore || record.AccountId != authorizedAccount ||
!string.Equals(record.OrderNumber, authorizedOrder, StringComparison.Ordinal))
throw new UnauthorizedAccessException();
string message;
switch (record.State)
{
case DeliveryState.Delivered: message = "Order processing confirmed."; break;
case DeliveryState.Reconcile: message = "Your order is received. We are confirming processing."; break;
case DeliveryState.NeedsAttention: message = "Your order is received. Our team is reviewing processing."; break;
case DeliveryState.Queued:
case DeliveryState.Attempting: message = "Your order is received and processing."; break;
default: throw new InvalidOperationException("Unknown delivery state.");
}
return new PublicDeliveryStatus(record.OrderNumber, message, record.CheckedAt);
}
}
}
// Call after current order-level authorization. Projection performs no dispatch.
// Delivered requires the provider acknowledgment defined by the integration.
Keep uncertain and failed outcomes separate
A provider timeout after submission may leave an unknown outcome. Calling it failed can encourage a duplicate order. Display a controlled reconciliation state until the adapter can confirm whether the external system accepted the command or an operator resolves it.
Do not automatically promise a retry time unless a scheduled attempt actually exists. If showing an expected next check, label it accordingly and account for worker delays. Keep the status projection consistent with the durable ledger, while acknowledging that the provider's state can be ahead of local observation after a lost response.
Test who can see what
Create fictional orders in two accounts and stores. Verify that each buyer can read only the permitted order status. Attempt direct access using another order number, a guessed delivery ID, and a stale account context. An authenticated session alone is insufficient authorization for every order.
With a mock provider, simulate queued work, a normal acknowledgment, a retryable failure, commit-then-timeout, and a terminal validation problem. Confirm that public messages remain accurate and contain no raw payloads. Verify that repeated polling makes no delivery mutations and that a failed status dependency does not appear as 'order not found'.
- Bound polling frequency and stop it when the page is inactive.
- Authorize operational detail more narrowly than buyer status.
- Keep correlation references opaque and non-sensitive.
- Label mock demonstrations separately from live integration evidence.
Design the operational handoff
When a delivery needs attention, tell the operator what kind of decision is required: repair configuration, correct business data, inspect an uncertain provider outcome, or authorize replay. Link internal tools by a stable reference without making the public endpoint a diagnostic dump.
Useful status reduces confusion because it tells each audience what is known and what happens next. It also protects the integration from accidental duplicate actions. A receipt, a delivery acknowledgment, and a shipment are different events; presenting them honestly makes a complex order lifecycle easier to trust and support.
References and further reading
Independent guidance from GCG. Znode is a trademark of its owner. Examples use fictional data and are not official platform documentation. Suggest a correction.