Order Fulfillment
Scottsdale Mint fulfills orders through a combination of ShipStation (order management) and FedEx (shipping carrier). Physical precious metals require special handling โ signature on delivery, high-value insurance, and discreet packaging.
Fulfillment Flowโ
WooCommerce (wc-processing)
โ
โ ShipStation webhook / API push
โผ
ShipStation
- Creates packing slip
- Assigns to warehouse queue
- Generates FedEx label
- Warehouse packs and ships
โ
โ ShipStation webhook (shipment.shipped)
โผ
WordPress /wp-json/suma/v1/shipstation-webhook
- Stores tracking number on order
- Updates order status to wc-awaiting-shipment โ wc-completed (or awaiting)
- Sends ShippingConfirmation email to customer
โ
โผ
FedEx delivers package โ Customer signs for delivery
ShipStation Integrationโ
Automatic Order Pushโ
Orders automatically appear in ShipStation when they reach wc-processing. ShipStation polls WooCommerce via the WooCommerce ShipStation Gateway plugin or direct API integration.
Products synced:
- Product name and SKU
- Quantity
- Unit price
- Customer note (from checkout)
Order Import Rules (ShipStation settings)โ
ShipStation applies import rules to set:
- Warehouse assignment
- Shipping service (FedEx Overnight, FedEx 2Day, etc.)
- Package type (declare value for insurance)
- Signature confirmation (required for all precious metals shipments)
FedEx Configurationโ
All precious metals orders ship via FedEx:
| Setting | Value |
|---|---|
| Default service | FedEx Overnight (next business day) |
| Signature | Adult signature required |
| Insurance | Declared value = full order amount |
| Packaging | Discreet plain packaging (no "Scottsdale Mint" on exterior) |
FedEx service level available to customer at checkout:
- FedEx Overnight โ standard for most orders
- FedEx 2Day โ lower cost option for lower-value orders
All precious metals shipments require adult signature at delivery. Orders cannot be left without a signature.
ShipStation Webhookโ
When ShipStation ships an order, it calls:
POST /wp-json/suma/v1/shipstation-webhook
Webhook payload:
{
"resource_url": "https://ssapi.shipstation.com/shipments?orderNumber=12345",
"resource_type": "SHIP_NOTIFY",
"order_number": "12345",
"tracking_number": "794658749765",
"carrier": "fedex",
"ship_date": "2024-01-15"
}
Webhook handling:
- Verify webhook secret token
- Fetch full shipment details from ShipStation API (using
resource_url) - Update WooCommerce order:
- Store tracking number in
_tracking_numbermeta - Store carrier in
_tracking_providermeta - Store ship date in
_date_shippedmeta
- Store tracking number in
- Advance order status to
wc-awaiting-shipment(if not alreadywc-completed) - Send ShippingConfirmation email with tracking link
Inventory Managementโ
WooCommerce Inventoryโ
WooCommerce manages product inventory:
- Inventory count decremented when order is placed
- Inventory restored if order is cancelled
The suma-patches plugin includes a modification:
// 0001-Feature-Added-Checkbox-for-ignoring-inventory-limits.patch
This adds an admin checkbox to allow backorders for specific products.
NFusion Inventory Syncโ
When an order is shipped, inventory data is pushed to NFusion to keep the catalog accurate:
- WooCommerce stock โ NFusion catalog availability
- Exported via the NFusion order export endpoint
Backordered Itemsโ
If a product is backordered:
- Admin marks the product to allow backorders
- Customer may still purchase
- Order is held in
wc-processingwith an "Expected Ship Date" meta set by admin - Customer tracking page shows expected ship date
Hold Reasonsโ
Orders that cannot be shipped immediately are put "on hold" for:
| Reason | Status | Required Action |
|---|---|---|
| ACH pending settlement | wc-pending-ach | Wait for iTransact settlement webhook |
| Wire transfer pending | wc-partially-paid | Admin confirm wire received |
| Crypto confirmations | wc-pending-crypto | Wait for blockchain confirmations |
| KYC required | wc-kyc-pending | Compliance team reviews documents |
| Kount review | wc-on-hold | Fraud team manually reviews |
| Inventory shortage | wc-on-hold | Admin resolves inventory/ETA |
Stock Reduction & Restoration Throughout Order Lifecycleโ
Scottsdale Mint's inventory system automatically manages stock levels as orders move through different statuses. This ensures accurate inventory counts while handling edge cases like payment failures and order recovery.
When Stock is Reducedโ
Stock is reduced at checkout for most orders via the ensure_reduce_stock_meta method:
Trigger: Fires on woocommerce_checkout_order_processed hook (priority 20)
Logic:
- Order is created (excludes
crypto-canceled,cancelled,refunded,failed,checkout-draft,atc-order) - System checks if stock was already reduced (
_order_stock_reducedmeta) - If not reduced, calls
wc_reduce_stock_levels($order_id) - Marks order with
_order_stock_reduced = yesmeta - Marks each line item with
_reduced_stock = {quantity}meta - Logs "[Stock] Made sure all items were marked as reduced stock"
Example: Customer orders 10 oz Silver Bar โ WooCommerce inventory decreases by 10 immediately at checkout.
The system uses _order_stock_reduced meta to prevent duplicate reductions. The prevent_duplicate_stock_reduction filter in class-stock.php blocks any attempt to reduce stock again if this meta is already set to yes.
WooCommerce Deposits Integrationโ
For orders with deposits (partial payment), stock reduction timing depends on the Deposits plugin configuration:
Configuration Option: wc_deposits_reduce_stock
depositโ Stock reduced at checkout when deposit is paidfullโ Stock reduced when full payment is completed (not at checkout)
When reduce_stock_on === 'full':
ensure_reduce_stock_metaskips stock reduction at checkout- Deposits plugin handles stock reduction via
payment_complete_reduce_order_stockfilter - Order note: "[Stock] Skipping stock reduction at checkout - Deposits plugin configured to reduce stock on full payment"
Stock Restoration on Order Failureโ
When an order transitions to failed status, stock is automatically restored via handle_order_status_stock_changes:
Trigger: Fires on woocommerce_order_status_changed hook
Logic (via restore_stock_for_failed_order):
- Check if stock was already restored (
_stock_restored_on_failuremeta) to prevent double-restoration - Verify stock was actually reduced by checking
_reduced_stockmeta on line items - Call
wc_increase_stock_levels($order)to restore inventory - Set
_stock_restored_on_failure = yesmeta - Set
_order_stock_reduced = nometa - Delete
_reduced_stockmeta from all line items - Log "[Stock] Stock levels restored due to order failure"
Example:
- Customer orders 5 Gold Eagles โ stock reduced to 95
- Payment fails โ order status changes to
failed - Stock automatically restored to 100
Edge Cases:
- If Deposits plugin manages stock (
reduce_stock_on === 'full'), no restoration occurs - If stock was never reduced, no restoration occurs
Stock Re-Reduction on Order Recoveryโ
When a failed order recovers to a valid status, stock is re-reduced via re_reduce_stock_for_recovered_order:
Valid Recovery Statuses:
pendingprocessingon-holdcompletedpending-achcrypto-pendingpartially-paid
Logic:
- Only executes if
_stock_restored_on_failure = yes(stock was previously restored) - Check if stock is already reduced (
_order_stock_reduced = yes) to prevent double-reduction - Call
wc_reduce_stock_levels($order_id)to re-reduce inventory - Set
_order_stock_reduced = yesmeta - Delete
_stock_restored_on_failuremeta - Re-mark line items with
_reduced_stock = {quantity}meta - Log "[Stock] Stock levels re-reduced after order recovery from failed status"
Example:
- Customer's payment initially fails โ stock restored to 100
- Customer retries payment and succeeds โ order moves to
pending - Stock automatically re-reduced to 95
Order Meta Keys for Stock Trackingโ
| Meta Key | Values | Purpose |
|---|---|---|
_order_stock_reduced | yes / no | Indicates if stock has been reduced for this order |
_stock_restored_on_failure | yes / (absent) | Indicates stock was restored when order failed |
_reduced_stock | {quantity} | Stored on each line item; tracks quantity reduced |
Stock Change Loggingโ
All stock changes are logged via the stock_change_log method in class-stock.php:
Trigger: Fires on woocommerce_product_set_stock and woocommerce_variation_set_stock hooks
Logged Data:
- Product ID
- SKU
- New quantity
- Log type:
activity_product(sub_type:stock_change)
This creates an audit trail for all inventory movements.