Skip to content

Marketplace Order Management

Flow ID: AD-11 Module(s): eshop, webhooks Complexity: High Last Updated: 2026-04-04

Business Context

Three marketplace integrations receive external orders and convert them into internal shop orders: Skroutz SmartCart (webhook-based, real-time), Shopflix (polling-based), and Public Marketplace/Mirakl (polling-based). Each has its own order lifecycle, stock validation, and fulfillment flow. All create "fake carts" and guest customers to generate internal orders.

Entry Points

TypePath / TriggerControllerMethod
WebhookSkroutz new_order / order_updatedecommercen/webhooks/AdvSmartCart.phphandle()
CronShopflix pollingAdvHandleShopflixOrders jobexecuteCommand()
CronPublic marketplace pollingAdvGetPublicMarketplaceAwaitingOrders jobexecuteCommand()
AdminSkroutz ordersecommercen/eshop/controllers/Adv_skroutz_orders_admin.phpindex(), accept(), reject()
AdminShopflix ordersAdv_shopflix_orders_admin.phpindex(), accept(), reject()
AdminPublic ordersAdv_public_orders_admin.phpindex(), accept(), reject()

Architecture Comparison

AspectSkroutzShopflixPublic (Mirakl)
SyncWebhook push (real-time)Polling pull (job)Polling pull (job)
Product lookupshop_product.skroutz_id + size/color attributesproduct_codes.product_code exact matchEAN/product code
RejectionLine-item level with reason codesFull order onlyLine-item level
Express ordersAuto-accept if express=trueN/AN/A
InvoiceSeparate skroutz_invoice_details tableFields in main orderadditional_fields JSON
VouchersVia standard transporter flowJSON array in shopflix_vouchers columnMirakl handles
Auto-cancelVia webhook state changeIf status becomes I (Cancelled) or D (Rejected)Manual only
Provider tagskroutz_smart_cartshopflix_marketplacePUBLIC_MARKETPLACE_PROVIDER

Common Flow Pattern

All three follow the same pattern for order acceptance:

  1. Receive order (webhook or poll) → store in marketplace-specific table
  2. Admin reviews in marketplace order listing
  3. Stock validationgetLiveProductsParsed() checks productAvailabilityStocks >= quantity. Bypassable via DISABLE_PRODUCT_STOCK_CHECK registry.
  4. Accept via API — calls marketplace API to confirm acceptance
  5. Create internal order — builds fake cart, creates guest customer, calls order_model->create_order_admin() with status=PAID
  6. Fire ERP hookinternalApiOrderForErpHook()

Business Rules

RuleDescription
All accepted orders = status PAIDMarketplace orders are pre-paid externally
Stock check bypassableDISABLE_PRODUCT_STOCK_CHECK registry flag
Skroutz auto-cleanupOrders 5+ days old without shop_order_id are auto-deleted
Shopflix auto-cancelIf polling detects status I or D, internal order is auto-canceled
Guest customers created per orderEach marketplace order creates a new guest customer
Skroutz express auto-acceptExpress orders skip manual acceptance

Data Model

TableMarketplacePurpose
skroutz_ordersSkroutzOrder header (code, state, courier, expires_at)
skroutz_line_itemsSkroutzOrder items (shop_uid, quantity, price)
skroutz_invoice_detailsSkroutzInvoice data (company, VAT, DOY)
shopflix_ordersShopflixOrder header (order_id, status, shipment_ids)
shopflix_line_itemsShopflixOrder items (product data, quantity, price)
public_ordersPublicOrder header (order_id, state, total_price)
public_line_itemsPublicOrder items (order_line_id, ean, quantity)

Marketplace Activity Status (Live Production Data)

Based on live production data across deployed clients:

MarketplaceTableApproximate RowsStatusNotes
Skroutz SmartCartskroutz_orders~46,000+ActivePrimary marketplace. Webhook-driven, real-time. Multiple clients active.
Shopflixshopflix_orders0InactiveCode exists, no production usage. Shopflix marketplace was discontinued.
Public/Miraklpublic_orders0InactiveCode exists, no production usage. Requires Mirakl API credentials.
IRISiris_orders0InactivePayment-linked orders (IRIS payment gateway), not a traditional marketplace.
JCCjcc_order_ids0InactivePayment-linked orders (JCC payment gateway, Cyprus), not a traditional marketplace.

Key finding: Skroutz SmartCart is the only actively used marketplace integration. All other marketplace integrations exist in code but have zero production usage. IRIS and JCC are not true marketplaces -- they are payment gateway order ID linking tables.

REST API Endpoints (Marketplace Module)

The modern REST layer exposes read-only endpoints for all marketplace entities at src/Rest/Marketplace/. All endpoints require JWT authentication.

Skroutz Endpoints

MethodPathControllerStatus
GET/rest/marketplace/skroutz/orderSkroutzOrder::index()200 (active data)
GET/rest/marketplace/skroutz/order/itemSkroutzOrder::item()200
GET/rest/marketplace/skroutz/order/{code}SkroutzOrder::show()200
GET/rest/marketplace/skroutz/line-itemSkroutzLineItem::index()200
GET/rest/marketplace/skroutz/line-item/itemSkroutzLineItem::item()200
GET/rest/marketplace/skroutz/line-item/{id}SkroutzLineItem::show()200
GET/rest/marketplace/skroutz/invoice-detailSkroutzInvoiceDetail::index()200
GET/rest/marketplace/skroutz/invoice-detail/itemSkroutzInvoiceDetail::item()200
GET/rest/marketplace/skroutz/invoice-detail/{id}SkroutzInvoiceDetail::show()200

Shopflix Endpoints

MethodPathControllerStatus
GET/rest/marketplace/shopflix/orderShopflixOrder::index()200 (empty result set)
GET/rest/marketplace/shopflix/order/itemShopflixOrder::item()200
GET/rest/marketplace/shopflix/order/{id}ShopflixOrder::show()200
GET/rest/marketplace/shopflix/line-itemShopflixLineItem::index()200 (empty result set)
GET/rest/marketplace/shopflix/line-item/itemShopflixLineItem::item()200
GET/rest/marketplace/shopflix/line-item/{id}ShopflixLineItem::show()200

Public/Mirakl Endpoints

MethodPathControllerStatus
GET/rest/marketplace/public/orderPublicOrder::index()200 (empty result set)
GET/rest/marketplace/public/order/itemPublicOrder::item()200
GET/rest/marketplace/public/order/{id}PublicOrder::show()200
GET/rest/marketplace/public/line-itemPublicLineItem::index()200 (empty result set)
GET/rest/marketplace/public/line-item/itemPublicLineItem::item()200
GET/rest/marketplace/public/line-item/{id}PublicLineItem::show()200

IRIS Endpoints

MethodPathControllerStatus
GET/rest/marketplace/iris/orderIrisOrder::index()200 (empty result set)
GET/rest/marketplace/iris/order/itemIrisOrder::item()200
GET/rest/marketplace/iris/order/{id}IrisOrder::show()200

JCC Endpoints

MethodPathControllerStatus
GET/rest/marketplace/jcc/orderJccOrder::index()200 (empty result set)
GET/rest/marketplace/jcc/order/itemJccOrder::item()200
GET/rest/marketplace/jcc/order/{id}JccOrder::show()200

Note: All write endpoints (POST, PUT, DELETE) are commented out in rest_routes.php for all marketplace entities. Only GET (read) operations are exposed.

IRIS and JCC Detail

IRIS and JCC are not traditional marketplace integrations. They are payment gateway order ID linking tables:

  • iris_orders: Links IRIS payment gateway order IDs (irisOrderId, messageId, initiatingPartyRefId) to shop_order_id. Can also link to gift_card_orders_id for gift card payments.
  • jcc_order_ids: Links JCC (Cyprus) payment gateway order IDs (jcc_order_id) to shop_order_id.

These exist in the REST Marketplace module for API consistency but are functionally payment record linkage, not marketplace order management.

Data Model (Detailed Column Reference)

skroutz_orders Table

ColumnTypeDescription
codeVARCHAR(255) PKSkroutz order code (natural key, not auto-increment)
stateENUMopen, accepted, rejected, cancelled, expired, dispatched, delivered, partially_returned, returned
invoiceTINYINT(1)Invoice requested flag
commentsVARCHAR(255)Customer order comments
courierVARCHAR(255)Assigned courier name
courier_voucherVARCHAR(255)Courier voucher number
courier_tracking_codesVARCHAR(255)Serialized tracking codes array
created_atDATETIMEOrder creation on Skroutz
expires_atDATETIMEAcceptance deadline
dispatch_untilDATETIMEDispatch deadline
number_of_parcelsVARCHAR(500)Comma-separated parcel count options
pickup_locationTEXTJSON pickup location options
pickup_windowTEXTJSON pickup time window options
reject_optionsTEXTJSON rejection reason options
customer_idVARCHAR(50)Skroutz customer ID
first_nameVARCHAR(50)Customer first name
last_nameVARCHAR(50)Customer last name
street_nameVARCHAR(255)Delivery street (null if collection point)
street_numberVARCHAR(10)Delivery street number
zipVARCHAR(10)Postal code
cityVARCHAR(100)City
regionVARCHAR(100)Region
pickup_from_collection_pointTINYINT(1)Collection point delivery flag
collection_point_addressVARCHAR(500)Collection point address
number_of_parcels_selectedINT(11)Admin-selected parcel count
pickup_window_selectedVARCHAR(250)Admin-selected pickup window
pickup_location_selectedVARCHAR(250)Admin-selected pickup location
shop_order_idINT(11) NULLFK to shop_order.id (set after acceptance)
expressTINYINT(1)Express delivery flag (auto-accept trigger)

skroutz_line_items Table

ColumnTypeDescription
idINT(11) PK AILine item ID
skroutz_idVARCHAR(255)Skroutz product ID
shop_uidVARCHAR(255)Shop product UID for matching
product_nameVARCHAR(255)Product display name
quantityINT(11)Ordered quantity
size_label / size_value / size_shop_valueVARCHAR(50)Size attribute data
unit_priceDECIMAL(11,2)Per-unit price
total_priceDECIMAL(11,2)Line total
price_includes_vatTINYINT(1)VAT inclusion flag
eanVARCHAR(255)Product EAN barcode
extra_infoVARCHAR(255)Additional product info
skroutz_order_codeVARCHAR(255)FK to skroutz_orders.code

skroutz_invoice_details Table

ColumnTypeDescription
idINT(11) PK AIRecord ID
companyVARCHAR(100)Company name
professionVARCHAR(100)Profession
vat_numberVARCHAR(9)Tax ID (AFM)
doyVARCHAR(100)Tax office
street_name / street_number / zip / city / regionVARCHARInvoice address
vat_exclusion_requestedTINYINT(1)VAT exemption requested
vat_exl_rep_*VARCHARVAT exclusion representative ID data
skroutz_order_codeVARCHAR(255)FK to skroutz_orders.code

shopflix_orders Table

ColumnTypeDescription
order_idINT(11) PKShopflix order ID (natural key)
order_referenceVARCHAR(255)Shopflix order reference
statusVARCHAR(50)Shopflix status code
payment_methodVARCHAR(50)Payment method
gift_wrapperTINYINT(1)Gift wrap flag
b_firstname / b_lastname / b_address / b_city / b_state / b_zipcode / b_country / b_phoneVARCHARBilling address
timestamp / last_order_changeVARCHAR(30)Order timestamps
voucher_creation_datetimeDATETIMEVoucher creation time
email / phoneVARCHARContact details
total / subtotal / discount / subtotal_discount / display_subtotalDECIMAL(10,2)Price breakdown
shippingVARCHAR(255)Shipping method
shipment_idsVARCHAR(255)Shipment tracking IDs
shopflix_vouchersVARCHAR(255)JSON voucher data
shipping_cost / display_shipping_costDECIMAL(10,2)Shipping costs
shop_order_idVARCHAR(255)FK to shop_order.id (set after acceptance)

shopflix_line_items Table

ColumnTypeDescription
idINT(11) PK AILine item ID
shop_uidINT(11)Shop product UID
shopflix_order_idVARCHAR(255)FK to shopflix_orders.order_id
product_id / product_code / productVARCHAR(255)Product identifiers and name
amountINT(11)Quantity
base_price / original_price / total_priceDECIMAL(10,2)Price data
eanVARCHAR(255)Product EAN
master_product_codeVARCHAR(255)Parent product code
product_status / status_a39VARCHAR(50)Status fields
item_idINT(11)Shopflix item ID
delivery_date / pickup_dateDATELogistics dates
product_urlVARCHAR(255)Product URL

public_orders Table

ColumnTypeDescription
order_idVARCHAR(255) PKPublic/Mirakl order ID (natural key)
stateENUMSame states as Skroutz
invoiceTINYINT(1)Invoice flag
is_tracking_sentTINYINT(1)Tracking sent to marketplace
is_sentTINYINT(1)Order dispatched flag
can_cancelTINYINT(1)Cancellable flag
order_dateDATETIMEOriginal order date
has_invoiceTINYINT(1)Invoice exists flag
shipping_deadline / acceptance_until_dateDATETIMEDeadline timestamps
shipping_price / total_price / commission_priceDECIMAL(10,2)Price data
order_typeVARCHAR(255)Order type classification
customer_id / first_name / last_name / email / region / commentsVARCHARCustomer data
shop_order_idINT(11)FK to shop_order.id (set after acceptance)

public_line_items Table

ColumnTypeDescription
idINT(11) PK AILine item ID
public_order_idVARCHAR(255)FK to public_orders.order_id
order_line_idVARCHAR(255)Mirakl line ID
product_nameVARCHAR(255)Product name
quantityINT(11)Quantity
unit_price / total_priceDECIMAL(11,2)Prices
eanVARCHAR(255)Product EAN

public_transporters_mapping Table

ColumnTypeDescription
transporter_idINT(11) PKInternal transporter FK
codeVARCHAR(255) PKPublic marketplace courier code

Maps Public/Mirakl courier codes to internal transporter IDs for voucher creation.

iris_orders Table

ColumnTypeDescription
idINT(11) PK AIRecord ID
messageIdVARCHAR(35)IRIS message ID
initiatingPartyRefIdVARCHAR(35)Initiating party reference
irisOrderIdVARCHAR(64)IRIS payment order ID
shop_order_idINT(11) NULLFK to shop_order.id
gift_card_orders_idINT(11) NULLFK to gift card orders table

jcc_order_ids Table

ColumnTypeDescription
idINT(11) PK AIRecord ID
jcc_order_idVARCHAR(255)JCC payment order ID
shop_order_idINT(11)FK to shop_order.id

Admin Controller Details

Adv_skroutz_orders_admin.php

The Skroutz admin controller handles order listing, acceptance, and rejection only. It has 4 methods:

MethodDescription
index()Paginated listing with filters (state, courier, pickup location)
resetIndex()Clear session filters
accept($code)Accept order: validate stock, call Skroutz API, create internal order
reject($code)Reject order: per-line-item rejection with reason codes via Skroutz API

Note: Voucher operations for Skroutz orders (create, cancel, print vouchers; manifests) are handled via the main Adv_orders_admin controller, not the Skroutz-specific controller.

Skroutz-specific batch actions (via overridden doBatchActionsSystem()):

  • accept_orders -- Batch accept multiple Skroutz orders
  • reject_orders -- Batch reject multiple Skroutz orders
  • mass_create_vouchers -- Batch voucher generation
  • mass_cancel_vouchers -- Batch voucher cancellation
  • mass_print_vouchers -- Batch voucher printing
  • get_manifest -- Get pickup manifest

Skroutz-specific features:

  • Pickup location selection from accepted orders (getAllSkroutzPickupLocationsFromOrders())
  • Courier filtering from order data (getAllSkroutzCouriersFromOrders())
  • Express order auto-acceptance when express=true
  • Auto-cleanup of orders 5+ days old without shop_order_id

Adv_shopflix_orders_admin.php

MethodDescription
index()Paginated listing
resetIndex()Clear filters
accept($code)Accept order via Shopflix API + create internal order
reject($code)Reject order via Shopflix API
createOrderVouchers($code)Generate vouchers
canceOrderlVouchers($code)Cancel vouchers
printVoucher($voucher)Print voucher
massPrintVouchers($orders)Batch print
massCreateVouchers($orders)Batch create vouchers
massCancelVouchers($orders)Batch cancel vouchers
getManifest($orders)Get manifest
getManifestByDate()Get manifest by date

Adv_public_orders_admin.php

MethodDescription
index()Paginated listing with state filter
processFilters()Filter processing for state/date
resetIndex()Clear filters
accept($orderId)Accept: validate stock, create internal order, call Public API
reject($orderId)Reject via Public/Mirakl API
transformTransportersData()Map internal transporters to Public marketplace codes

Public-specific validation: isValidOrder(), extractProductIds(), getLiveProductsParsed(), checkProductStock() -- validates each line item against live inventory before acceptance.