Appearance
Admin Order Management
Flow ID: AD-03 Module(s): eshop Complexity: Very High Last Updated: 2026-04-08
Business Context
Order management covers the full order lifecycle: viewing, status transitions, voucher generation for shipping providers, shipment closure, invoice generation, and order editing (which is actually clone + cancel). The status state machine governs stock adjustments, payment reconciliation, and loyalty point handling.
Entry Points
| Type | Path / Trigger | Controller | Method |
|---|---|---|---|
| Admin | Order listing | ecommercen/eshop/controllers/Adv_orders_admin.php | index() |
| Admin | Order detail | same | view($id) |
| Admin | Edit order | same | edit($id) |
| Admin | Batch cancel | same | setBatchCanceled() |
| Admin | Create voucher | same | setPendingWithVoucher() |
| Admin | Close shipments | same | close_pending_jobs() |
Order Status State Machine
| Status | Meaning | Next |
|---|---|---|
| PENDING | Awaiting payment/acceptance | → PENDING_ACCEPTED, CANCELED |
| PENDING_ACCEPTED | Accepted, payment received (COD) | → PENDING_ACCEPTED_VOUCHER, CANCELED |
| PENDING_ACCEPTED_VOUCHER | Voucher created, awaiting shipment | → SENT / PAID_SENT, CANCELED |
| PAID | Payment received (prepaid) | → SENT / PAID_SENT |
| SENT | COD orders shipped | → INVOICED |
| PAID_SENT | Prepaid orders shipped | → INVOICED |
| INVOICED | Completed | (terminal) |
| CANCELED | Canceled | (terminal) |
| RETURN | Returned | (terminal) |
SENT vs PAID_SENT determined by payment method: COD (delivery/byphone) → SENT; prepaid (card, paypal, etc.) → PAID_SENT.
Stock Management
| Transition | Stock Effect | ignoreStock |
|---|---|---|
| Order creation (PENDING) | Deducted (-qty) | false |
| Any → CANCELED | Returned (+qty) | false |
| PENDING_ACCEPTED_VOUCHER → SENT/PAID_SENT | No change | true |
| Edit (clone + cancel) | Cancel returns stock, new order deducts | — |
Stock is adjusted via returnOrderStock() (+qty per basket item to product_codes.stock) and removeOrderStock() (-qty).
Voucher Lifecycle
- Create:
setPendingWithVoucher()→ calls transporter API (ACS, Geniki, DHL, etc.) → savesgtcode+gtjobcode→ status = PENDING_ACCEPTED_VOUCHER - Close:
close_pending_jobs()→ calls transporter pickup/closure API → status = SENT or PAID_SENT (stock NOT adjusted) - Cancel:
cancelVoucher()→ calls transporter cancel API → clearsgtcode/gtjobcode→ reverts to PENDING_ACCEPTED or PAID
Supported transporters: ACS, Geniki (v1/v2), DHL, ELTA, Speedex, Center, EasyMail, FIS, BoxNow, DailyCourier, Taxydema (v1/v2), Skroutz, ASAP.
Order Editing
edit() (line 1051-1189) is actually clone + cancel:
- Cancel original order (returns stock, rolls back points/coupons)
- Create new order with modified items/prices/addresses
- Clone order notes, send new confirmation email
- Configurable:
keepProductPriceForEdit— retain old or use current prices
Cancellation Restrictions
Cannot cancel if:
- Already CANCELED
- Payway is bank card provider (eurobank, alpha, ethniki, piraeus, apcopay) — refund not automated
- PayByBank PAID orders — payment already settled
- Status = PENDING with non-PayByBank card payment
Business Rules
- Stock deducted at creation, returned at cancel -- Never double-adjusted during voucher lifecycle. Stock adjustments happen via
returnOrderStock()(+qty) andremoveOrderStock()(-qty) onproduct_codes.stock. (ecommercen/eshop/controllers/Adv_orders_admin.php) - Loyalty points rolled back on cancel -- Both spent points (returned to customer) and earned points (removed) are reversed. (
ecommercen/eshop/controllers/Adv_orders_admin.php, cancel flow) - Edit = clone + cancel -- Original order canceled, new order created. Configurable via
keepProductPriceForEditwhether to retain old or use current prices. (ecommercen/eshop/controllers/Adv_orders_admin.php,edit()line 1051-1189) - Voucher status blocks cancel -- Must cancel voucher before canceling order. Voucher cancellation calls transporter API and clears
gtcode/gtjobcode. (ecommercen/eshop/controllers/Adv_orders_admin.php,cancelVoucher()) - Invoice uses order barcode -- Generated via
BarcodeGeneratorPNG. (ecommercen/eshop/controllers/Adv_orders_admin.php) - Batch cancel validates each order -- Per-order validation before canceling, respects payment method and status restrictions. (
ecommercen/eshop/controllers/Adv_orders_admin.php,setBatchCanceled()) - Payment method determines SENT vs PAID_SENT -- COD/byphone orders transition to SENT; prepaid (card, paypal, etc.) transition to PAID_SENT. (
ecommercen/eshop/controllers/Adv_orders_admin.php,close_pending_jobs()) - Cancel blocked for card payments -- Cannot cancel orders with bank card payment methods (eurobank, alpha, ethniki, piraeus, apcopay) since refunds are not automated. (
ecommercen/eshop/controllers/Adv_orders_admin.php, cancellation restrictions) - Order status emails on transition -- Status changes trigger automated email and SMS notifications via the SY-24 Email Dispatch system. The email templates used (
order_created,order_update,order_on_store,notify_admin) are catalogued in AD-53 Email Template Viewer. - Coupon usage rolled back on cancel -- If order used a coupon, the coupon usage count is decremented. (
ecommercen/eshop/controllers/Adv_orders_admin.php, cancel flow) - Gift stock rolled back on cancel -- Gift product stock is returned when an order containing gift items is canceled. See AD-09 Gift Rules.
Order Lifecycle Hooks
The order system fires HTTP webhook notifications on key lifecycle transitions using OrderForErpHookFireTrait and OrderCancelHookFireTrait (Guzzle HTTP with Bearer token authentication).
Configuration: application/config/api.php under internalApi.apiOrderWebHooks:
erpReady-- URL for order-ready webhookcancel-- URL for order-cancel webhookreturn-- URL for order-return webhook
| Hook Method | Trigger Point | HTTP Call | Description |
|---|---|---|---|
afterOrderSuccessHooks | Order success | internalApiOrderForErpHook($orderId) | HTTP GET to configured ERP webhook URL -- notifies ERP that order is ready |
afterOrderCancelHooks | Order cancellation (controller) | internalApiOrderCancelHook($orderId) | HTTP GET to cancel webhook URL -- notifies ERP of cancellation |
afterCancelOrderHooks | Order cancellation (model-level) | internalApiOrderCancelHook($orderId) | Same cancel notification fired from model layer |
| (orphaned) | Never fired | internalApiOrderReturnHook($orderId) | Exists in code but is not called from any trigger point -- dead code |
Note:
internalApiOrderReturnHookis implemented but orphaned -- no code path currently invokes it. If return webhook notifications are needed, a trigger must be wired into the return status transition.
Data Model
shop_order Table (Primary)
| Column | Type | Description |
|---|---|---|
id | INT(11) PK AI | Internal order ID |
cancel_id | INT(11) | ID of canceled predecessor (for edit/clone). Default 0. |
store_id | INT(11) NULL | Pickup store ID (NULL for delivery orders) |
transport_id | INT(11) NULL | Transporter FK (NULL for store pickup) |
order_serial | VARCHAR(255) | Human-readable serial number (generated via createSerial()) |
webignore | INT(1) | 0 = online order, 1 = phone/admin order |
total_qty | INT(11) | Total item quantity in basket |
gen_tax_service | VARCHAR(2) | Tax service code (default AM) |
order_currency | VARCHAR(3) | ISO currency code |
currency_rate | DECIMAL(11,4) | Exchange rate at order time |
currency_id | INT(11) | Currency FK |
pricing_* | VARCHAR | Billing address fields: name, surname, address, city, region, postal, county, country, phone, mobile |
shipping_* | VARCHAR | Shipping address fields: same set as billing |
afm | VARCHAR(30) | Tax ID (VAT number) for invoices |
doy | VARCHAR(100) | Tax office for invoices |
profession | VARCHAR(255) | Profession (invoice) |
company | VARCHAR(255) | Company name (invoice) |
company_address | VARCHAR(255) | Company address (invoice) |
payway | VARCHAR(255) | Payment method slug (e.g., delivery, paypal, stripe, eurobank, paybybank) |
viva_payway | VARCHAR(255) | Viva Wallet sub-payway code |
paymerch | VARCHAR(25) | receipt or invoice |
customer_id | INT(11) | Customer FK |
customer_comments | TEXT | Customer notes |
admin_comments | TEXT | Admin notes |
courier_comments | TEXT | Courier delivery notes |
total | DECIMAL(11,2) | Subtotal without VAT |
total_vat | DECIMAL(11,2) | Grand total with VAT + transport + delivery - reward + gift packaging |
transportation_cost | DECIMAL(11,2) | Shipping cost |
delivery_cost | DECIMAL(11,2) | COD fee |
status | VARCHAR(30) | Order status (see state machine above) |
gtcode | VARCHAR(30) | Transporter voucher code |
gtjobcode | VARCHAR(255) | Transporter job/tracking code |
gtstatus | VARCHAR(255) | Voucher status from transporter API |
gtflag | TINYINT(1) | Voucher processing flag |
gtdatetime | DATETIME | Voucher creation timestamp |
gtcount | INT(3) | Voucher request attempt counter |
notes | MEDIUMTEXT | Legacy order notes |
charge_to | TINYINT(1) | Charge recipient flag |
entry_date | VARCHAR(30) | UNIX timestamp string of order creation |
entry_datetime | DATETIME | Order creation datetime |
canceled_date | DATETIME NULL | Cancellation timestamp |
ip_address | VARCHAR(45) | Client IP at order time |
user_agent | TEXT | Browser user agent |
admin_order_check | INT(1) | 1 = admin has viewed this order |
is_email_sent | TINYINT(1) | Status email sent flag |
is_paid | TINYINT(1) | Payment confirmed by gateway (0=unknown, 1=paid) |
paid | TINYINT(1) | Admin-toggled paid flag (differs from is_paid) |
is_visible | TINYINT(1) | Customer-facing visibility |
invoised_date_time | DATETIME NULL | Invoice generation timestamp |
printed_date_time | DATETIME NULL | Print timestamp |
sent_date_time | DATETIME NULL | Shipment closure timestamp |
sms_status | TINYINT(1) NULL | null=no SMS, 1=requested, 2=sent success, 3=sent fail, 4=pending callback |
coupon_id | INT(11) NULL | Applied coupon FK |
coupon_value | DECIMAL(11,2) | Coupon discount amount |
points_spend | INT(11) | Loyalty points redeemed |
points_reward | DECIMAL(11,2) | Cash value of points reward |
points_added | TINYINT(1) | 0=product points not added to customer, 1=added |
skroutz_referer | TINYINT(1) NULL | Referrer tracking code |
delivery_warning | TINYINT(1) | Delivery delay warning flag |
delivery_warning_msg_status | TINYINT(1) | 0=not sent, 1=sent, 2=admin opted out |
meta_data | VARCHAR(255) | Serialized extra data |
remind | TINYINT(1) | Reminder flag |
remind_at | DATETIME NULL | Reminder scheduled time |
pbb_payment_code | VARCHAR(255) | PayByBank payment reference |
tran_ticket | VARCHAR(32) | Viva Wallet transaction ticket |
provider | VARCHAR(50) | Marketplace provider tag (skroutz_smart_cart, shopflix_marketplace, etc.) |
invoice_pdf | VARCHAR(255) | Uploaded invoice PDF filename |
gift_packaging | TINYINT(1) | Gift wrapping enabled |
gift_packaging_message | TEXT | Gift wrapping message |
gift_packaging_cost | DECIMAL(11,2) | Gift wrapping cost |
json_invoice | LONGTEXT | JSON invoice data (e-invoicing) |
Indexes (22 indexes for query optimization):
order_serial-- unique order lookupstatus,entry_datetime,status_entry_datetime-- listing and filteringcustomer_id,customer_id_status_is_visible-- customer order historycancel_id-- edit chain lookupgtcode_gtflag_gtcount-- voucher processing queriespaid,sms_status,coupon_id,skroutz_referer-- filteringstore_id,store_payway_customer,store_customer-- store-based queriestransport_id-- transporter filteringdelivery_warning_msg-- composite for delivery delay jobremind_remind_at-- reminder jobpoints_added-- loyalty points jobstatus_invoised_date_time-- invoice reporting
shop_order_basket Table
| Column | Type | Description |
|---|---|---|
id | INT(11) PK AI | Basket item ID |
order_id | INT(11) | FK to shop_order.id |
product_code_id | INT(11) | FK to product_codes.id (SKU) |
product_vat | DECIMAL(11,2) | VAT percentage at time of order |
price | DECIMAL(11,2) | Unit price (VAT-inclusive) |
item_points | INT(11) NULL | Loyalty points per unit |
qty | INT(11) | Quantity ordered |
subtotal | DECIMAL(11,2) | Line total (price * qty) |
discount_string | VARCHAR(10) | Discount label (e.g., 10%) |
discount_price | DECIMAL(11,2) | Discounted unit price |
original_price | DECIMAL(11,2) | Pre-discount unit price |
gift_id | INT(11) NULL | Gift rule FK (non-NULL = gift item) |
track_type | TINYINT(1) | 0=normal, smart/AI recommendation types |
added_at | INT(11) NULL | UNIX timestamp when added to cart |
track_id | VARCHAR(255) NULL | Recommendation tracking ID |
options | TEXT NULL | Serialized product options (bundles, variations) |
Supporting Tables
| Table | Purpose |
|---|---|
shop_order_dhl_vouchers | DHL-specific voucher data: dispatch confirmation, tracking number, product code |
shop_order_smart_point | Smart point/locker delivery data: transporter_id, shop_id, json_data |
shop_order_tags | Order tag definitions (id, tag name, active flag) |
shop_order_tags_lp | Order-to-tag linking table (order_id, tag_id) |
shop_order_basket_options_applied_bundles | Bundle application records for basket items |
Complete Batch Operations Reference
The batch actions system in doBatchActions() dispatches through three method chains: doBatchActionsGeniki() for per-transporter operations, doBatchActionsSystem() for system operations, and doBatchActionsClient() for client-repo overrides.
Per-Transporter Batch Actions (dynamic, one per active transporter)
| Action Key | Method | Description |
|---|---|---|
set_pending_with_voucher_{transporterId} | setPendingWithVoucher() | Create vouchers via transporter API for selected orders |
cancel_jobs_{transporterId} | cancelVoucher() | Cancel vouchers via transporter API for selected orders |
print_vouchers_pdf_{transporterId} | printVouchersPdf() | Print voucher PDFs for selected orders |
System Batch Actions
| Action Key | Method | Description |
|---|---|---|
set_status_canceled | setBatchCanceled() | Cancel selected orders with per-order validation, stock return, points rollback |
set_paid | setPaid() | Mark selected orders as paid |
set_unpaid | unsetPaid() | Unmark selected orders as paid |
print_selected | printSelected() | Print invoices for selected orders (HTML or PDF via DomPDF) |
print_selected_xls | exportXls() | Export selected orders to Excel (XLSX via PhpSpreadsheet) |
print_selected_products_xls | exportProductsXls() | Export product breakdown from selected orders to Excel |
addPoints | addPointsSelected() | Add earned loyalty points to customers for selected orders |
removePoints | removePointsSelected() | Remove earned loyalty points from customers for selected orders |
markInformDelayOrder | markInformDelayOrderSelected() | Mark delivery delay notification sent |
unMarkInformDelayOrder | unMarkInformDelayOrderSelected() | Clear delivery delay notification flag |
set_order_tags | batch_action() | Assign tags to selected orders (redirect to tag selection UI) |
unset_order_tags | batch_action() | Remove tags from selected orders (redirect to tag selection UI) |
Client Extension Point
doBatchActionsClient() is an empty hook method that client repos can override to add custom batch actions (e.g., ERP sync, custom exports).
Close Shipments (Transporter Integration)
The close_pending_jobs($transporterId) method implements the shipment closure flow for 15 supported transporter providers:
| Provider Class | Closure Method | API Integration |
|---|---|---|
ACS | closePendingJobsAcs() | ACS issuePickupList() API -- remote pickup request |
GT (Geniki v1) | closePendingJobsGeniki() | Geniki closeOpenJobs() API -- remote closure |
GTV2 (Geniki v2) | closePendingJobsGenikiV2() | GenikiV2 closeOpenJobs() API -- remote closure |
DHL | closePendingJobsDhl() | DHL API -- remote closure with dispatch confirmation |
ELTA | closePendingJobsLocally() | Local status update only (no remote API) |
SPEEDEX | closePendingJobsLocally() | Local status update only |
CENTER | closePendingJobsLocally() | Local status update only |
EASYMAIL | closePendingJobsLocally() | Local status update only |
FIS | closePendingJobsLocally() | Local status update only |
BOXNOW | closePendingJobsLocally() | Local status update only |
DAILYCOURIER | closePendingJobsLocally() | Local status update only |
TAXYDEMA | closePendingJobsLocally() | Local status update only |
SKROUTZ | closePendingJobsLocally() | Local status update only |
ASAP | closePendingJobsLocally() | Local status update only |
TAXYDEMAV2 | closePendingJobsLocally() | Local status update only |
Closure flow:
- Fetch all orders with status
PENDING_ACCEPTED_VOUCHERfor the transporter - Call transporter API (for ACS/Geniki/DHL) or update locally
- For each successfully closed order: set status to
SENT(COD) orPAID_SENT(prepaid) viaorderGetSentStatusForPayWayVoucher() - Send shipment email via
adv_mailer->order_has_been_updated() - Set
is_email_sent = true
Invoice Generation
The invoice($orderSerial) method generates printable invoices:
- Loads full order data via
getRecordForInvoice() - Generates barcode image using
BarcodeGeneratorPNG(Code 128 format) - Optionally includes Geniki voucher barcode if GT provider is configured
- Supports batch printing via
printSelected()which can output HTML or PDF (DomPDF, A4 format)
Export Capabilities
| Export | Method | Format | Content |
|---|---|---|---|
| Order XLS | exportXls() | XLSX (PhpSpreadsheet) | Customer ID, address, phone, postal, weight, COD amount, courier notes |
| Products XLS | exportProductsXls() | XLSX | Product ID, name, quantity, order count |
| Orders CSV | exportOrders() | CSV (semicolon, UTF-8 BOM) | 28 columns: order ID/serial, billing/shipping addresses, payway, totals, status |
| Searched Orders CSV | exportSearchedOrders() | CSV (semicolon, UTF-8 BOM) | Product-level: product code, shelf code, barcodes, VAT, price, qty, vendor, order serial |
Order Repeat (Without Cancellation)
The repeat($orderId) method creates a new order from an existing order without canceling the original:
- Pre-fills form with original order's customer/address/products data
- Creates new order with fresh
entry_datetimebut preservesentry_dateandskroutz_referer - Supports SmartPoint (locker) delivery selection
- Fires ERP hooks and sends confirmation email/SMS for the new order
- Does NOT cancel the original order (unlike
edit()which does clone+cancel)
Admin Order Creation (POS / Phone)
Manual order creation via Adv_orders_admin::add() — including the fake cart mechanism, 5 AJAX product-search endpoints, POS-specific field defaults (webignore=1, status=PENDING_ACCEPTED, order_currency=EUR, unconditional stock decrement), and customer 3-tier resolution — is documented in AD-54 POS / Phone Orders.
SMS Provider Integration
Status notification SMS is sent via multiple provider integrations (sendSmsForOrder() helper):
| Provider | SMS Status Mapping |
|---|---|
plivo | 2 (sent) or 3 (fail) |
routeeViber | Viber first, fallback to SMS; status from provider |
routee | 2 (delivered), 4 (pending), 3 (fail) |
bulker | 4 (pending) or 3 (fail) |
yuboto_omni | 4 (pending) or 3 (fail) |
omni_messaging | 4 (pending) or 3 (fail) |
yuboto | Direct status from provider |
ERP Integration (Farmakon)
The postErpOrdersJob() method queues a FarmakonPostOrders job for ERP synchronization. This is available when FARMAKON.IS_ENABLED registry flag is set. The job processes orders with status PENDING_ACCEPTED or PAID via getOrdersForFarmakon().
REST API Endpoints
All REST endpoints require JWT authentication. Routes support an optional (\w{2})/ language prefix (e.g., /el/rest/...). POST is used for both create and update operations (not PUT).
Order (8 operations)
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /rest/order/order | JWT | List orders (paginated, filterable) |
| GET | /rest/order/order/item | JWT | Get order field metadata (schema introspection) |
| GET | /rest/order/order/{id} | JWT | Get single order by ID |
| POST | /rest/order/order | JWT | Create new order |
| POST | /rest/order/order/{id} | JWT | Update existing order |
| DELETE | /rest/order/order/{id} | JWT | Delete order |
| POST | /rest/order/order/{id}/cancel | JWT | Cancel order (triggers stock return, points rollback) |
| GET | /rest/order/order/{id}/tracking | JWT | Get order tracking information |
Note (6 operations)
Notes are polymorphic -- the entity_type field supports customer, product, and order scoping. Stored in shop_notes table.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /rest/order/note | JWT | List notes (paginated, filterable by entity_type) |
| GET | /rest/order/note/item | JWT | Get note field metadata |
| GET | /rest/order/note/{id} | JWT | Get single note by ID |
| POST | /rest/order/note | JWT | Create new note |
| POST | /rest/order/note/{id} | JWT | Update existing note |
| DELETE | /rest/order/note/{id} | JWT | Delete note |
Vat (6 operations)
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /rest/order/vat | JWT | List VAT rates (paginated, filterable) |
| GET | /rest/order/vat/item | JWT | Get VAT rate field metadata |
| GET | /rest/order/vat/{id} | JWT | Get single VAT rate by ID |
| POST | /rest/order/vat | JWT | Create new VAT rate |
| POST | /rest/order/vat/{id} | JWT | Update existing VAT rate |
| DELETE | /rest/order/vat/{id} | JWT | Delete VAT rate |
For the canonical
shop_product_vatsschema, delete-guard gap in the modern REST layer, validator gaps, and all related security issues, see AD-50 VAT Management.
Basket (3 operations -- read-only)
Write routes exist in code but are commented out in route config. Basket items are managed through the order lifecycle, not directly via REST.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /rest/order/basket | JWT | List order basket items (paginated, filterable) |
| GET | /rest/order/basket/item | JWT | Get basket item field metadata |
| GET | /rest/order/basket/{id} | JWT | Get single basket item by ID |
DhlVoucher (3 operations -- read-only)
Write routes exist in code but are commented out in route config. DHL vouchers are created through the transporter integration flow, not directly via REST.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /rest/order/dhl-voucher | JWT | List DHL vouchers (paginated, filterable) |
| GET | /rest/order/dhl-voucher/item | JWT | Get DHL voucher field metadata |
| GET | /rest/order/dhl-voucher/{id} | JWT | Get single DHL voucher by ID |
SmartPoint (3 operations -- read-only)
Write routes exist in code but are commented out in route config. Smart point/locker delivery records are managed through the order creation flow, not directly via REST.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /rest/order/smart-point | JWT | List smart point delivery records (paginated, filterable) |
| GET | /rest/order/smart-point/item | JWT | Get smart point field metadata |
| GET | /rest/order/smart-point/{id} | JWT | Get single smart point record by ID |
Route config: application/config/rest_routes.php -- read routes at lines 700-794, write routes at lines 1320-1346. Controllers: src/Rest/Order/Controllers/ -- Order, Note, Vat, Basket, DhlVoucher, SmartPoint.
Known Issues & Security Gaps
- No known issues at this time.
Related Flows
Customer Flows
- CF-05 Cart Management -- cart contents become order basket items
- CF-06 Order Preview -- checkout flow that creates orders
- CF-07 Order Confirmation -- order confirmation page and email
- CF-08 Payment Processing -- payment creates orders in PENDING status
- CF-09 Payment Webhooks -- async payment status updates
- CF-13 Coupons -- coupon usage tracked in orders, rolled back on cancel
- CF-14 Gift Rules -- gift items added to order basket
- CF-32 Loyalty Points -- points earned/spent per order
Admin Flows
- AD-04 Customer Management -- customer linked to orders
- AD-06 Transporter Management -- transporter configuration and voucher lifecycle
- AD-08 Coupon Management -- coupon usage tracking and rollback
- AD-09 Gift Rules -- gift stock decremented on order creation, rolled back on cancel
- AD-10 Reporting -- order-based sales reports
- AD-11 Marketplace Orders -- marketplace orders accepted into internal order flow
- AD-15 Attributes & Tags -- order tag assignment (order tags section)
- AD-23 Gift Cards -- gift card orders in unified order timeline
- AD-34 Voucher Generation -- bulk voucher generation workflow
- AD-33 Multi-Carrier Tracking -- tracking URL resolution for shipped orders
- AD-51 Shelf Codes -- shelf code labels surface on order detail, packing slip, build summary, and in the searched-orders CSV export
- AD-54 POS / Phone Orders -- manual order creation from admin panel
Integration Flows
- IN-09 Transporter Integrations -- voucher API calls to courier providers
- IN-20 Order Webhooks -- external webhook notifications on order events
System Flows
- SY-02 Order Email Notifications -- status change triggers emails
- SY-03 Incomplete Order Cancellation -- automated cancellation of unpaid orders
- SY-10 Loyalty Points Jobs -- points awarded on delivery
- SY-15 Delivery Delay -- delivery delay notifications
- SY-24 Email Dispatch -- email sending infrastructure for order notifications
- SY-27 Deferred Tasks -- deferred processing for order-related background tasks
Wiki Guides: Job Manager Guide | DHL Guide | Stripe Guide