Skip to content

Transactions (Orders)

Overview

Transactions represent all orders placed through any channel. This is where you view, manage, and process orders.

Key Purpose: View and manage all orders from all channels.

Purpose

This page lets you view, filter, and manage all orders across every sales channel, including reviewing order details, resending receipts, exporting data, and tracking payment and fulfillment status.

Key Concepts

  • Transaction: A complete order record stored in MongoDB, containing items, pricing, customer data, and an order channel identifier (Kiosk, POS, Online Ordering, Table Qr Ordering, Uber Eats, Takeaway, Shopify).
  • Order Status: A single status field tracks the combined payment and fulfillment state of an order (Unpaid, Awaiting Capture, Awaiting Invoice, Awaiting Payment, Pending, Complete, Queued, In Progress, Ready, Cancelled). There is no separate payment-status field; all status filtering uses this one enum.
  • Idempotency Key: A unique key per transaction that prevents duplicate order creation; the system checks for an existing transaction with the same key before processing a new one.
  • Stats Aggregation: The stats endpoint aggregates completed transactions for a date range and optional location, returning completed transaction count, total item quantity, total revenue, and currency.
  • Spreadsheet Export: Transactions can be exported to Excel spreadsheets in paginated chunks of 500 records, including columns for order number, date, location, customer, status, total, items, dining option, type, device, receipt number, and channel.

Actions

View Transaction Details

Open any transaction to see the full order breakdown including items, modifiers, pricing, customer information, payment method, and status history.

Resend Receipt

Re-send a receipt for a completed transaction via the ReceiptService; only transactions with a "Complete" status are eligible for receipt resend.

Export Transactions

Download transaction data as a spreadsheet filtered by date range, location, and other criteria; the export processes records in chunks of 500 for efficiency.

Filter and Search Orders

Filter orders by date range, status (via the All / Completed / Unpaid / Stuck tabs), channel, dining option, order type, device, and location, or search by order number, customer name, email, or phone.

View Transaction Statistics

Access aggregated stats showing completed transaction count, total quantity sold, and total revenue for a selected date range and location.

Retry POS Sync

For orders that failed to sync to the POS (shown under the "Stuck" tab), re-dispatch the POS sync job so the order is sent again.

Delete Test Transaction

Delete a transaction that was created in test mode. Only test-mode transactions can be deleted; deleting a live transaction is blocked.

Location

  • Backoffice Route: /transactions
  • Backend Controller: app/Http/Controllers/Api/BackOffice/TransactionController.php
  • Vue Component: src/views/transactions/Transactions.vue

Order Fields

Order Number

PropertyValue
Field IDorder_number
LabelOrder #
TypeString
Auto-generatedYes

Description: Unique identifier for the order.

Format: Sequential number or custom format (e.g., #1234, ORD-2024-001)


Order Status

PropertyValue
Field IDstatus
LabelStatus
TypeSelect
OptionsUnpaid, Awaiting Capture, Awaiting Invoice, Awaiting Payment, Pending, Complete, Queued, In Progress, Ready, Cancelled

Description: Combined payment and fulfillment status of the order (single status field; there is no separate payment-status field).

Statuses:

  • Unpaid: Order placed but not yet paid
  • Awaiting Capture: Payment authorized, awaiting capture
  • Awaiting Invoice: Awaiting an invoice payment
  • Awaiting Payment: Awaiting payment
  • Pending: Order is in but no payment is made/requested (e.g. third-party orders)
  • Complete: Order paid and fulfilled
  • Queued: Order queued for processing
  • In Progress: Order is being processed/prepared
  • Ready: Order ready for pickup/delivery
  • Cancelled: Order cancelled

Order Channel

PropertyValue
Field IDorder_channel
LabelOrder Channel
TypeString

Description: Where the order originated.

Channels (from App\Enums\ChannelOptions):

  • Kiosk - Self-service kiosk
  • POS - Point of sale
  • Online Ordering - Online ordering website
  • Table Qr Ordering - QR table ordering
  • Uber Eats - Uber Eats integration
  • Takeaway - Takeaway
  • Shopify - Shopify integration

Note: the Channel filter dropdown in the Transactions list currently only offers "All", "Online Ordering", and "Kiosk", even though more channel values can appear on records.


Dining Option

PropertyValue
Field IDdining_option
LabelType
TypeSelect
OptionsDelivery, For Here, Pickup, Takeout

Description: How the customer will receive the order. (Note: "Dine In" is deprecated and replaced by "For Here".)


Order Date/Time

PropertyValue
Field IDcreated_at
LabelOrder Time
TypeDateTime

Description: When the order was placed.


Scheduled Time

PropertyValue
Field IDscheduled_time
LabelScheduled For
TypeDateTime

Description: When the order should be ready (pickup) or delivered.


Customer

PropertyValue
Field IDcustomer
LabelCustomer
TypeObject

Description: Customer information.

Fields:

  • name - Customer name
  • email - Email address
  • phone - Phone number
  • customer_id - Account ID (if logged in)

Delivery Address

PropertyValue
Field IDdelivery_address
LabelDelivery Address
TypeObject
Depends Ondining_option = delivery

Description: Address for delivery orders.


Items

PropertyValue
Field IDitems
LabelOrder Items
TypeArray

Description: Items in the order.

Item Structure:

json
{
  "item_id": "item-123",
  "name": "Cheeseburger",
  "quantity": 2,
  "unit_price": 8.95,
  "modifiers": [
    { "name": "Large", "price": 2.00 },
    { "name": "Extra Cheese", "price": 1.50 }
  ],
  "notes": "No pickles",
  "line_total": 24.90
}

Subtotal

PropertyValue
Field IDsubtotal
LabelSubtotal
TypeCurrency

Description: Total of all items before fees and discounts.


Delivery Fee

PropertyValue
Field IDdelivery_fee
LabelDelivery Fee
TypeCurrency

Description: Delivery fee (for delivery orders).


Discount

PropertyValue
Field IDdiscount
LabelDiscount
TypeCurrency

Description: Discount applied (from offers/promo codes).


Tip

PropertyValue
Field IDtip
LabelTip
TypeCurrency

Description: Tip amount (if tips enabled).


Tax

PropertyValue
Field IDtax
LabelTax
TypeCurrency

Description: Total tax amount.


Total

PropertyValue
Field IDtotal
LabelTotal
TypeCurrency

Description: Final order total.

Calculation: Subtotal + Delivery Fee - Discount + Tip + Tax


Payment Method

PropertyValue
Field IDpayment_method
LabelPayment
TypeString

Description: How the order was paid.

Methods:

  • card - Credit/debit card
  • ideal - iDEAL (NL)
  • bancontact - Bancontact (BE)
  • cash - Cash payment
  • apple_pay - Apple Pay
  • google_pay - Google Pay

Notes

PropertyValue
Field IDnotes
LabelOrder Notes
TypeText

Description: Special instructions from customer.


Order Actions

The back-office Transactions feature is read-and-manage only. There are no manual status-progression actions (no Confirm / Mark as Preparing / Mark as Ready / Complete buttons) — order status changes are driven by payment events and the ordering/KDS flow, not by the back office. The TransactionController exposes only: show, dataTable, stats, export, resendReceipt, retrySync, deleteTestTransaction.

Resend Receipt

Re-send a receipt for a transaction (only when its status is "Complete").

Retry POS Sync

Re-dispatch the POS sync job for an order that failed to sync (shown under the "Stuck" tab).

Delete Test Transaction

Delete a transaction that was created in test mode. Live transactions cannot be deleted.

Refund Order (not currently available)

A refund flow exists in the UI but is not wired up: the refund button in OrderDetail.vue is commented out and the store's refundOrder action is a simulated mock with no backend endpoint. Refunds are not processed from the back office today; handle refunds through your payment provider (e.g. the Stripe dashboard).


Business Logic

Order Status

An order's lifecycle is reflected by the single status field. Typical paid orders move toward Complete; unpaid/awaiting-payment orders sit in the Unpaid / Awaiting Payment / Awaiting Capture / Awaiting Invoice / Pending states; fulfillment progresses through QueuedIn ProgressReady; and orders can end in Cancelled. These transitions are driven by payment events and the ordering/KDS flow rather than by manual back-office actions.


Filter Options

  • Date range
  • Status (via the All / Completed / Unpaid / Stuck tabs)
  • Channel
  • Dining option
  • Order type
  • Device
  • Location
  • Order number
  • Customer name
  • Customer email
  • Customer phone

Customer Impact

Order Confirmation

Customer receives:

  • Confirmation email
  • Order number
  • Estimated time
  • Order details

Order Updates

Customer notified when:

  • Order is placed/paid
  • Order ready
  • Order cancelled

Relations

Depends On

  • Locations: Orders belong to locations
  • Menu Items: Items in orders
  • Customers: Order attribution
  • Payments: Payment processing

Affects

  • Inventory: Stock decremented
  • Loyalty: Points earned
  • Reports: Sales data
  • KDS: Orders displayed

Business Rules

  • Only transactions with a status of "Complete" can have their receipt resent; attempting to resend for an incomplete transaction returns a 400 error with "Transaction is incomplete."
  • There are no separate payment-status and order-status fields — a single status enum captures both the payment and fulfillment state.
  • Refunds are not processed from the back office: the refund UI is disabled (button commented out, store action is a mock) and there is no refund endpoint on the TransactionController.
  • There are no manual status-progression actions in the back office (no Confirm / Mark as Preparing / Mark as Ready / Complete). Status changes are driven by payment events and the ordering/KDS flow.
  • Only test-mode transactions can be deleted; deleting a live transaction is blocked with "Only test mode transactions can be deleted".
  • Transaction stats only count orders with status "Complete" and apply date range filtering using MongoDB date queries with timezone-aware parsing via the location's timezone.
  • The spreadsheet export aborts with a 400 error if no transactions match the given filters, rather than producing an empty file.
  • Tip validation enforces mutual exclusivity: a transaction request cannot specify both a tip percentage and a tip amount; providing both throws an InvalidArgumentException.
  • When a customer places an order and no existing customer record matches their email or phone, a new customer and customer-vendor record are created automatically, and any applicable loyalty sign-up bonus is applied.

FAQs

  • "Why can I not resend a receipt for an order?" Receipts can only be resent for transactions with a "Complete" status; if the order is still pending or was cancelled, the resend option is blocked.

  • "How does the export handle large volumes of transactions?" The export processes records in chunks of 500, writing each batch sequentially to the spreadsheet until all matching records are retrieved, preventing memory issues.

  • "What timezone are transaction dates displayed in?" Transaction dates are stored in UTC (MongoDB UTCDateTime) but are displayed and filtered using the location's configured timezone.

  • "Can a transaction belong to multiple locations?" No, each transaction is tied to exactly one location via its location_id; filtering by location returns only that location's transactions.

  • "How are duplicate orders prevented?" Each transaction carries an idempotency key; before creating a new transaction, the system checks for an existing record with the same key and returns the existing order if found.

  • "Which sales channels can I filter transactions by, and what are they called?" Transactions carry an order channel; the recognised values are Online Ordering, Kiosk, POS, Table Qr Ordering, Uber Eats, Takeaway, and Shopify. Note the Channel filter dropdown currently only offers "All", "Online Ordering", and "Kiosk".

  • "What do the status tabs at the top of the Transactions list mean?" Four tabs: All, Completed, Unpaid, and Stuck. Completed shows orders with status Complete, Unpaid shows orders with status Unpaid, and Stuck shows orders whose POS sync failed.

  • "What does the 'Stuck' tab show and how do I fix a stuck order?" The Stuck tab lists transactions that failed to sync to your POS. Each stuck row has a retry icon; clicking it (Retry Sync) clears the failed flag and re-dispatches the POS sync job so the order is sent again.

  • "Why can't I resend a receipt for some orders?" Resend Receipt only works for transactions whose status is Complete. For any other status you get "Transaction is incomplete", so pending, unpaid, or cancelled orders can't have a receipt resent.

  • "What columns are included when I export transactions?" The Excel export includes Order No, Date, Location, Customer, Payment Status, Total, Items, Dining Option, Type, Device, Receipt No, and Channel.

  • "My export downloaded nothing / gave an error — why?" If no transactions match your current filters, the export stops with a "No transactions found" error instead of an empty file. Adjust your date range, location, or filters so at least one order matches, then export again.

  • "What do the four summary cards at the top mean?" Completed Transactions (count of fully paid orders), Total Items (quantity sold), Total Collected (amount collected before fees), and Total Pending (money still awaiting invoice or payment). The Total Pending card only appears if your account accepts invoice payments.

  • "Why doesn't 'Total Pending' change when I change the date range?" The first three figures are scoped to the selected date range, but Total Pending is intentionally not date-scoped — an invoice raised months ago is still outstanding today. It's still limited to the selected location.

  • "Can I filter transactions to a single location?" Yes. If your account has more than one location, a Location filter appears; each transaction belongs to exactly one location. The export and stats respect the same filter.

  • "Which transaction date and timezone are used for filtering?" Date filtering uses the order date, evaluated in your location's configured timezone. Dates are stored in UTC but parsed against the location timezone, so "today" reflects your local trading day.

  • "Can I delete a transaction?" Only test-mode transactions can be deleted; deleting a real (live) transaction is blocked with "Only test mode transactions can be deleted".

Troubleshooting

Problem: Order stuck in an unpaid/pending status

Causes:

  1. Payment not completed
  2. Payment failed
  3. System error

Solutions:

  1. Check the payment in your payment provider (e.g. Stripe)
  2. Contact the customer to retry payment
  3. Note: the back office has no "manually confirm" action — status is updated by the payment flow, not manually

Problem: Order stuck (failed POS sync)

Causes:

  1. POS offline or unreachable
  2. Transient sync error
  3. POS integration misconfiguration

Solutions:

  1. Open the "Stuck" tab, which lists orders whose POS sync failed
  2. Click the retry icon (Retry Sync) on the row to re-dispatch the POS sync job
  3. If it keeps failing, check the POS connection and integration settings

Problem: Order not appearing on KDS

Causes:

  1. KDS not connected
  2. Channel filter on KDS
  3. Order status not yet eligible for KDS

Solutions:

  1. Check KDS connection
  2. Review KDS channel settings
  3. Confirm the order has reached a status that routes it to the KDS

Problem: Customer didn't receive an order email

Causes:

  1. Wrong email address
  2. Email in spam
  3. Email service issue

Solutions:

  1. Verify the email address on the order
  2. Ask the customer to check spam
  3. For receipts on completed orders, use Resend Receipt from the order detail (there is no separate "resend confirmation" action)

Problem: Need to refund an order

Note: Refunds are not processed from the back office today — the refund UI is disabled and there is no refund endpoint.

Solutions:

  1. Process the refund directly in your payment provider (e.g. the Stripe dashboard)
  2. For cash payments, handle the refund at the point of sale
  3. Contact your payment provider if the refund fails

Examples

Online Order (Delivery)

json
{
  "order_number": "1234",
  "status": "Complete",
  "order_channel": "Online Ordering",
  "dining_option": "Delivery",
  "created_at": "2024-01-15T12:30:00Z",
  "scheduled_time": "2024-01-15T13:15:00Z",
  "customer": {
    "name": "Jan de Vries",
    "email": "jan@example.com",
    "phone": "+31612345678"
  },
  "delivery_address": {
    "address_line_1": "Kalverstraat 123",
    "city": "Amsterdam",
    "postal_code": "1012 AB"
  },
  "items": [
    {
      "name": "Margherita Pizza",
      "quantity": 1,
      "unit_price": 12.50,
      "modifiers": [
        { "name": "Large", "price": 3.00 }
      ],
      "line_total": 15.50
    },
    {
      "name": "Garlic Bread",
      "quantity": 1,
      "unit_price": 4.50,
      "line_total": 4.50
    }
  ],
  "subtotal": 20.00,
  "delivery_fee": 3.50,
  "discount": 0,
  "tip": 2.00,
  "tax": 1.89,
  "total": 27.39,
  "payment_method": "ideal"
}

Kiosk Order (For Here)

json
{
  "order_number": "42",
  "status": "In Progress",
  "order_channel": "Kiosk",
  "dining_option": "For Here",
  "created_at": "2024-01-15T12:45:00Z",
  "items": [
    {
      "name": "Cheeseburger",
      "quantity": 2,
      "unit_price": 8.95,
      "modifiers": [
        { "name": "Extra Cheese", "price": 1.50 }
      ],
      "line_total": 20.90
    },
    {
      "name": "French Fries",
      "quantity": 2,
      "unit_price": 3.50,
      "line_total": 7.00
    },
    {
      "name": "Cola",
      "quantity": 2,
      "unit_price": 2.50,
      "line_total": 5.00
    }
  ],
  "subtotal": 32.90,
  "tip": 5.00,
  "tax": 2.81,
  "total": 40.71,
  "payment_method": "card"
}

Order Summary View

Order #1234 - Jan de Vries
Status: Complete
Channel: Online Ordering
Type: Delivery

Items:
  1x Margherita Pizza (Large)     €15.50
  1x Garlic Bread                  €4.50
                          ─────────────
  Subtotal                        €20.00
  Delivery Fee                     €3.50
  Tip                              €2.00
  Tax                              €1.89
                          ─────────────
  Total                           €27.39

Payment: iDEAL ✓ Paid

Delivery: Kalverstraat 123, Amsterdam
Scheduled: 13:15