Use this guide to connect Saleculator to an online ordering platform, receive online orders inside POS, print order copies or KOT, and update delivery progress back to the integration platform.
What Saleculator supports #
- The Online Store configuration screen supports WaiterApp, WhatsApp, Deliverect, Yaadro, and WooCommerce.
- Yaadro is linked with a link token and uses
https://menu.yaadro.ae/api/v1unless a different API URL is configured. - WooCommerce is linked with the store URL, consumer key, and consumer secret.
- Online orders are shown in columns: New Orders, Accepted, Prepared, Assigned/Picked Up, and Done.
Before you start #
- Confirm Saleculator can reach the internet from the POS terminal.
- Confirm the local database is working and Saleculator can save tickets.
- Confirm the required print templates exist:
Printer.OrderPreview,Printer.Ticket, and the KOT templates used by the restaurant. - Enable WhatsApp or delivery partner settings only when that site should notify customers or update a remote platform.
Configure the online store #
- Open Administration > Configuration.
- Open the OnlineStore section.
- Select the portal used by the site.
- Enter the portal URL/token/API credentials.
- Save the configuration and reopen the Online Orders screen.
Yaadro setup #
- In Yaadro, create or copy the restaurant link token.
- In Saleculator OnlineStore, select Yaadro.
- Enter the link token.
- Keep the API URL as
https://menu.yaadro.ae/api/v1unless the restaurant uses a different Yaadro server. - Save the configuration.
Typical property values are:
onlinestore.portal=Yaadro
onlinestore.url=https://menu.yaadro.ae/api/v1
onlinestore.token=YOUR_LINK_TOKEN
WooCommerce setup #
- In WooCommerce, create a REST API key with permission to read orders and update order status.
- In Saleculator OnlineStore, select WooCommerce.
- Enter the WooCommerce store URL.
- Enter the consumer key and consumer secret.
- Save the configuration.
onlinestore.portal=WooCommerce
onlinestore.url=https://yourstore.example.com
onlinestore.key=ck_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
onlinestore.secret=cs_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Saleculator stores the WooCommerce secret encrypted in the local configuration after saving from the UI.
Order creation paths #
Saleculator has two different order paths, and the event setup should respect that difference.
| Order path | Where it starts | KOT need | Progress update rule |
|---|---|---|---|
| Online order | Online Orders screen receives an order from Yaadro/WooCommerce/etc. | KOT is usually printed when the order is accepted. | Use online events such as event.orderaccepted, event.orderprepared, and event.orderassigned. |
| Manual standard order | Cashier creates a normal POS bill. | KOT may be needed in restaurants. | No external progress update by default. |
| Manual table order | Cashier/waiter creates an order on a table. | KOT is normally needed. | No external progress update by default. |
| Manual delivery order | Cashier creates a delivery call/order inside Saleculator. | KOT is normally needed. | Sync only with call guards, because this is not an online order object. |
Progress update mapping #
The same KOT action can be used for restaurant operation, but customer notification/platform sync should only run in the scenarios that need it. Use conditions in the event scripts instead of placing an unconditional sync in a shared KOT script.
| Type | Status | Event/place | Code |
|---|---|---|---|
| Online order | Order received | event.orderreceived |
if (order != void && order != null) { sales.printTicket("Printer.OrderPreview"); } return null; |
| Online order | Order accepted / KOT sent | event.orderaccepted |
sales.syncDeliveryPartnerOrderAccepted(); return null; |
| Online order | Order rejected | event.orderrejected |
sales.syncDeliveryPartnerOrderRejected(); return null; |
| Online order | Order prepared / ready | event.orderprepared |
sales.syncDeliveryPartnerOrderPrepared(); return null; |
| Online order | Driver assigned | event.orderassigned |
sales.syncDeliveryPartnerOrderReadyThenAssigned(); return null; |
| Manual delivery order | Order accepted / KOT sent | Script.SendOrder |
if (call != void && call != null) { sales.syncDeliveryPartnerOrderAccepted(); } |
| Manual delivery order | Order prepared / ready | event.close |
if (call != void && call != null) { sales.syncDeliveryPartnerOrderPrepared(); } return null; |
| Manual delivery order | Driver assigned later | event.driverselected |
sales.syncDeliveryPartnerOrderAssigned(); return null; |
| Manual delivery order | Rejected / cancelled | Cancel/reject event used by the site | if (call != void && call != null) { sales.syncDeliveryPartnerOrderRejected(); } return null; |
| Manual table order | KOT sent | Script.SendOrder |
No external sync by default. |
| Manual standard order | KOT sent | Script.SendOrder |
No external sync by default. |
Enable event mappings #
Open Administration > Resources, then open Ticket.Buttons. Add or uncomment only the event lines needed for the site.
<event key="ticket.orderreceived" code="event.orderreceived"/>
<event key="ticket.orderaccepted" code="event.orderaccepted"/>
<event key="ticket.orderrejected" code="event.orderrejected"/>
<event key="ticket.orderprepared" code="event.orderprepared"/>
<event key="ticket.orderassigned" code="event.orderassigned"/>
<event key="ticket.driverselected" code="event.driverselected"/>
If ticket.orderaccepted is already mapped to a custom KOT/send-order script, keep that mapping and put the status sync in that custom script with the correct order or call condition.
Event resource examples #
Order received #
// Resource: event.orderreceived
// Online-only guard. Manual delivery orders have call, not order.
if (order != void && order != null) {
sales.printTicket("Printer.OrderPreview");
}
return null;
The guard is important. Manual delivery orders expose call, not order. Without the guard, a manual delivery print can output raw template text such as $order.getOrderId().
Online accepted / KOT sent #
// Resource: event.orderaccepted
sales.syncDeliveryPartnerOrderAccepted();
return null;
Online rejected #
// Resource: event.orderrejected
sales.syncDeliveryPartnerOrderRejected();
return null;
Online prepared / ready #
// Resource: event.orderprepared
sales.syncDeliveryPartnerOrderPrepared();
return null;
Online assigned #
// Resource: event.orderassigned
// Use this for online delivery orders when assignment should also confirm ready.
sales.syncDeliveryPartnerOrderReadyThenAssigned();
return null;
Manual delivery driver selected #
// Resource: event.driverselected
// Driver selected later from the delivery tracking/order screen.
sales.syncDeliveryPartnerOrderAssigned();
return null;
Manual delivery accepted from KOT send #
// Resource: Script.SendOrder
// Add only if manual delivery KOT send should update the delivery partner platform.
// Keep it conditional because Script.SendOrder is also used by table and standard mode.
if (call != void && call != null) {
sales.syncDeliveryPartnerOrderAccepted();
}
Manual delivery prepared from ticket close #
// Resource: event.close
// Add only if manual delivery billing should update the delivery partner platform.
if (call != void && call != null) {
sales.syncDeliveryPartnerOrderPrepared();
}
return null;
When customers are notified #
Saleculator normally updates the integration platform. The platform then sends the customer notification. Direct Saleculator notification should be used only when the site has Saleculator WhatsApp configuration enabled or a custom HTTP URL configured for notifications.
| Stage | Notify/update? | Reason |
|---|---|---|
| Order received | Optional store print only | The restaurant has not accepted the order yet. |
| Accepted / KOT sent | Yes, when the platform supports accepted/preparing | The restaurant has confirmed the order and kitchen work has started. |
| Prepared / ready | Yes | The order is ready for pickup or driver handoff. |
| Driver assigned | Yes, for delivery orders | The customer/platform can track assignment or dispatch. |
| Rejected/cancelled | Yes | The platform should stop the order and notify the customer. |
Variant printing #
For online orders with variants such as Small, Medium, or Large, the ticket line may have a variant description even when it does not have a product attribute set instance ID. In Printer.OrderPreview, bill templates, and KOT templates, print variants using productAttSetInstDesc.
#foreach ($ticketline in $ticket.getLines())
<line>
<text align="left" length="23">${ticketline.printName()}</text>
<text align="right" length="10">${ticketline.printPriceTax()}</text>
<text align="right" length="5">x${ticketline.printMultiply()}</text>
<text align="right" length="10">${ticketline.printValue()}</text>
</line>
#if ($ticketline.productAttSetInstDesc)
<line>
<text align="left" length="48"> ${ticketline.productAttSetInstDesc}</text>
</line>
#end
#end
Receive and process online orders #
- Open the Online Orders screen in Saleculator.
- Wait for the store connection indicator to show the linked store.
- New remote orders appear under New Orders. Saleculator imports each order as a shared ticket and stores the raw order JSON in the local online-order table.
- Click a new order to preview it.
- Click Accept to move it to Accepted, or Reject to move it to Done as rejected.
- Click an accepted order and click Prepared when preparation is complete.
- Click a prepared delivery order to assign a driver when driver tracking is used.
Troubleshooting #
- No orders appear: verify the selected portal, link token/API keys, internet access, and that the Online Orders screen is open.
- Order appears but does not print on arrival: confirm
ticket.orderreceivedis mapped andevent.orderreceiveduses the online-only guard. - Manual delivery order prints raw
$order...text: remove any unguardedPrinter.OrderPreviewcall from manual delivery events and use the guardedevent.orderreceivedexample above. - KOT does not print or sync on accept: confirm the accepted event mapping points to the correct KOT/send-order script or
event.orderacceptedfor that site. - Variants do not print: update
Printer.OrderPreview, bill, and KOT templates to printproductAttSetInstDesc. - Prepared/bill-made WhatsApp does not send: confirm
ticket.orderpreparedis mapped andevent.orderpreparedcallssales.syncDeliveryPartnerOrderPrepared();. - Assigned WhatsApp does not send: confirm
ticket.orderassignedorticket.driverselectedis mapped and the matching event calls the assigned sync method. - Remote status does not update: check POS internet access, portal credentials, and the delivery partner configuration.