Кешування рахунків
Кешування рахунків пидвищує швидкодію в отриманні рахунку для гостя. Expirenza віддає рахунок з "власного кеша", замість того щоб робити запити до POS.
Процес виглядає так:
POS система раз в 5 секунд відправляє інформацію з замовленнями що зараз відкриті в POS на cервер Expirenza:
Короткий перелік всіх замовлень
Повна інфо про замовлення що змінились з моменту останнього оновлення
Сервер може запитати у ПОС детальне інфо про будь яке з замовлень у будь який момент.
Пос система має відправити їх повне інфо з наступним вебхуком ORDERS_CACHE
Про закриті замовлення ПОС система сповіщає сервер окермим вебхуком
Раз на 5 секунд необхідно відправляти інформацію про всі замовлення в стані New (нове) або Bill (надруковано пречек). Якщо сервер не отримує вебхук протягом 15 секунд - вважає замовлення неактуальними. Віддавати треба замовлення що є на столі, так і пусті замовлення, а також ті що змінились з моменту останнього оновлення.
Потребує реалізації linkedTo
та positionId
у getBill.
Після необхідно додати в versionInfo в implementedFeature
відповідний об'єкт реалізованого функціоналу - BILL_V2 та ORDERS_CACHE.
Payload example /callback/webhook
{
"webhookType": "ORDERS_CACHE",
"eventTime":"timestamp UTC"
"actualOrders": [
{
"orderId": "079D89A0-5BEF-4BCC-A279-2566D5FBAEAA",
"revision": 2
},
{
"orderId": "A9D1D59E-DBE5-423F-82C8-95C14FEA97BD",
"revision": 2
}
],
"changedOrders": [
{
"orderInfo": {
"billId": "A9D1D59E-DBE5-423F-82C8-95C14FEA97BD",
"orderNumber": "11.3",
"totalSum": 77.40, //загальна сумма до сплати
"rawSum": 86.00, // сумма до сплати без урахування знижки
"paidSum": 0, //сплачена сумма
"discountSum": 8.60, // сумма знижки
"waiter": "TEST",
"waiterId": "1000004",
"tables": [
11
],
"discounts": {
"list": [
{
"id": "1002291",
"name": "Скидка 10% на чек",
"sum": 8.60,
//нижче будь які інші поля з інформацією про знижку
"code": 6
}
]
},
"guests": [
{
"name": "Гість 1",
"id": "8436f6ff-6665-44de-a863-8be3352cb7d2", //ід гостя
"additionalInfo": {
"system": "syrve",
"comment": "some guest comment"
},
"dishes": [
{
"positionId": "4",
"name": "Combo salatov",
"count": 1.000,
"sum": 0.00,
"categoryId": -1,
"category": "Блюдо без категории",
"orderNumber": "11.3",
"type": "combo",
"dishId": "1002281",
"rawSum": 0.00,
"price": 86.00 //ціна за 1
},
{
"positionId": "7",
"name": "Томатный холодный суп",
"count": 1.000, //загальна кількість дочірніх страв з урахуванням кількості батьківської страви
"positionCount": 1.000, //кількість дочірніх страв в рамках 1 позиції (null для тих у кого linkedTo - null)
"sum": 27.00,
"categoryId": -1,
"category": "Блюдо без категории",
"orderNumber": "11.3",
"type": "dish", //dish/modifier/combo
"dishId": "1002099",
"rawSum": 30.00, //сумма дочірніх страв без урахування знижок та з урахуванням кількості батьківських страв
"positionRawSum": 30.00, //сума дочірніх страв без урахування знижок для 1 батьківської страви
"linkedTo": "4", //positionId страви до якої цю страву
"price": 30.00 //результуюча ціна за 1
},
{
"positionId": "13",
"name": "Salat iz anacond",
"count": 1.000000,
"positionCount": 1.000,
"sum": 50.40,
"categoryId": -1,
"category": "Блюдо без категории",
"orderNumber": "11.3",
"type": "dish",
"dishId": "1001946",
"rawSum": 56.00000,
"positionRawSum": 56.00,
"linkedTo": "4",
"price": 56.00
},
{
"positionId": "16",
"name": "Персиковый",
"count": 1.000000,
"positionCount": 1.000,
"sum": 0.00,
"categoryId": -1,
"category": "Блюдо без категории",
"orderNumber": "11.3",
"type": "modifier",
"dishId": "1001759",
"rawSum": 0.00,
"positionRawSum": 0,
"linkedTo": "13",
"price": 12.00,
"additionalInfo": {
"system": "syrve",
"comment": "string",
"status": "added",
"productGroupExternalId": "for modifiers only"//ид группы модификаторов
}
}
]
}
],
"state": "New",//New/Bill/Closed/Deleted
"isDelivery": false,
"splitAvailable": true,
"version": 2, //version = revision
"payments": [
{
"sum": 0,
"paymentTypeName": "string",
"paymentTypeKind": "Card",//Card/Cash і тд
"additionalInfo": {
"system": "syrve",
"isPrepay": true,
"isExternal": true,
"status": "new",
"externalId": "string",
"typeId": "string"
}
}
],
"orderType": "Common", // Common - обычные/DeliveryByClient - самовывоз/DeliveryByCourier
"additionalInfo": {
"system": "posName",
"tablesDetails": [
{
"externalId": "string",
"name": "string",
"fullName": "string",
"number": 21,
"seatingCapacity": 0,
"description": "string",
"isActive": true
}
],
"waiterDetails": {
"externalId": "string",
"name": "string",
"phone": "string",
"pinCode": "string"
}
},
"tableId": "1000051",
"created": "2024.09.30 13:47:57",
"banquetOrder": false
},
"tables": [ //столи на яких розміщено замовлення
11
]
}
]
}
Роз'яснення і деталі.
Вебхук має 2 додаткових поля:
”eventTime
” - дата формування івенту в UTC таймзоні
"actualOrders
" - поточні активні замовлення в системі
"orderId
" - id замовлення
"revision
" - long версія замовлення, інкрементальне значення, дає зрозуміти системі поточну “версію замовлення”. Значення має збільшуватись при кожній зміні замовлення. Обмежень на крок або значення немає. Якщо в ПОС відсутне поняття версії, то можна віддавати у якості значення дату останньої зміни замовлення в мілісекундах
"changedOrders
" - Список замовлень що змінились з моменту останньої відправки вебхука
"orderInfo
" - оновленний стан про замовлення
Команда ordersCacheUpdate
ordersCacheUpdate
Команда надсилається з сервера Expirenza в вебсокет, сервер надсилає перелік замовлень по яким треба обов'язково передати розгорнуту інформацію в при наступному виклику /calback/webhook (Той що ORDERS_CACHE
).
Відповідати на команду не потрібно.
Команда використовується для синхронізації з інтеграцією у випадку якщо сервер не отримав один або декілька вебхуків і ревізія замовлень які присилає інтеграція відрізняється від тих що є на сервері, сервер “просить” надіслати замовлення по яким є втрачені зміни ще раз.
Сервер надсилатиме повідомлення в такому форматі:
{
"operation":"ordersCacheUpdate",
"rID":"7e70fb9f257e459d8fc8dd609b7d23fc",
"orders":["14392","14386","14396","14400"]
}
Вебхук фінального статусу замовлення
Структура самого замовлення не відрізняється від ORDERS_CACHE
, відрізняється лише назва деяких полів.
Необхідно відправляти при отриманні фінального статуса по рахунку (Closed/Deleted) Якщо сервер не відповів 200, необхідно повторити відправку через деякий час ~1-5 хвилин.
Payload example /callback/webhook
{
"webhookType": "BILL_CLOSED",
"eventTime": "2024-09-30T15:29:04.9036828Z",
"orderId": "492fa768-2fb0-4b30-9f5a-db9c17db3fff",
"tableNumber": 1,
"closeTime": "2024.09.30 18:28:59",
"openTime": "2024.09.30 18:27:46",
"orderNumber": 133264,
"resultSum": 140.00,
"orderStatus": "Closed",
"totalSum": 140.00,
"waiterId": "0ab41df0-f4ae-4fbe-959f-ecaba7c85c85",
"waiter": "Максимейко Наталія",
"discounts": {
"list": [
{
"id": "1002291",
"name": "Скидка 10% на чек",
"sum": 8.60,
//нижче будь які інші поля з інформацією про знижку
"code": 6
}
]
},
"guests": [
{
"name": "Гість 0",
"id": "91ed5c34-85b2-4c54-a001-0f9e040d0004",
"dishes": [
{
"taxCategoryId": null,
"taxCategory": null,
"positionId": "127aaa1a-7fce-4ddc-95af-7af102eecc08",
"name": "Макаронс ",
"count": 1.0,
"sum": 70.00,
"price": 70.00,
"categoryId": "2e2e28fc-bbfd-ee15-018f-9687de9ed540",
"category": "Десерти Кебчук",
"orderNumber": 133264,
"type": "dish",
"dishId": "68591915-9a42-4fe8-84fa-a10a9fbbd6a2",
"linkedTo": null,
"rawSum": 70.00,
"additionalInfo": {
"system": "syrve",
"course": 1,
"comment": null,
"status": "Served",
"productGroupExternalId": null
}
},
{
"taxCategoryId": null,
"taxCategory": null,
"positionId": "5a9d658b-df19-4d38-96b1-41862d51db1d",
"name": "Лате",
"count": 1.0,
"sum": 10.00,
"price": 10.00,
"categoryId": "2e2e28fc-bbfd-ee15-018f-9687de9ed18d",
"category": "Бар ",
"orderNumber": 133264,
"type": "dish",
"dishId": "99295f7e-255d-46cf-ba76-2c340e1ba990",
"linkedTo": null,
"rawSum": 10.00,
"additionalInfo": {
"system": "syrve",
"course": 1,
"comment": null,
"status": "Served",
"productGroupExternalId": null
}
},
{
"taxCategoryId": null,
"taxCategory": null,
"positionId": "b059c0bb-e500-4c81-920c-62a83bfb7abc",
"name": "- Молоко",
"count": 1.0,
"sum": 50.00,
"price": 50.0000,
"categoryId": "2e2e28fc-bbfd-ee15-018f-9687de9ed18d",
"category": "Бар ",
"orderNumber": 133264,
"type": "modifier",
"dishId": "6b98a6de-f14f-4d9d-99a4-4feacc99bbec",
"linkedTo": "5a9d658b-df19-4d38-96b1-41862d51db1d",
"rawSum": 50.00,
"additionalInfo": {
"system": "syrve",
"course": null,
"comment": null,
"status": null,
"productGroupExternalId": "7d81b3a9-5339-4a10-be56-8f1a034ebe57"
}
},
{
"taxCategoryId": "42fe1bf4-fcd8-4f0b-9261-ee2952a2dd68",
"taxCategory": "Без НДС (0%)",
"positionId": "1bc7fafd-2bc3-401f-a8bc-2917aced1987",
"name": "- з собою 350 К",
"count": 1.0,
"sum": 0.00,
"price": 0.0000,
"categoryId": "-1",
"category": "Блюдо без категории",
"orderNumber": 133264,
"type": "modifier",
"dishId": "8e657ffc-0343-4429-a7cd-6f1463a919ce",
"linkedTo": "5a9d658b-df19-4d38-96b1-41862d51db1d",
"rawSum": 0.00,
"additionalInfo": {
"system": "syrve",
"course": null,
"comment": null,
"status": null,
"productGroupExternalId": "8fae65e1-27da-4d51-9f4a-e5fe47391e8b"
}
},
{
"taxCategoryId": null,
"taxCategory": null,
"positionId": "eccd76a0-1148-4d8c-b442-5b367cea38c0",
"name": "Солона карамель 25г ",
"count": 1.0,
"sum": 10.00,
"price": 10.00,
"categoryId": "2e2e28fc-bbfd-ee15-018f-9687de9ed18d",
"category": "Бар ",
"orderNumber": 133264,
"type": "dish",
"dishId": "ee7f8427-65e5-4ba3-aeb0-a9979e5f8552",
"linkedTo": null,
"rawSum": 10.00,
"additionalInfo": {
"system": "syrve",
"course": 1,
"comment": null,
"status": "Served",
"productGroupExternalId": null
}
}
]
}
],
"isBanquetOrder": false,
"isDelivery": false,
"bonusSum": 0.0,
"splitAvailable": false,
"rewardAvailable": true,
"billTime": "2024.09.30 18:28:59",
"paidSum": 140.00,
"discountSum": 0.0,
"tableId": "e6ad6ef3-bbdb-41c4-8fd3-dd0691142074",
"pricingTime": null,
"version": 1865768,
"payments": [
{
"paymentTypeName": "Готівка",
"sum": 140.00,
"paymentTypeKind": "Cash",
"additionalInfo": {
"system": "syrve",
"externalId": "5b28a833-ba81-41d9-83a2-2cef3189d882",
"status": "Processed",
"typeId": "09322f46-578a-d210-add7-eec222a08871",
"isPrepay": false,
"isExternal": false
}
}
],
"additionalInfo": {
"system": "syrve",
"tablesDetails": [
{
"externalId": "e6ad6ef3-bbdb-41c4-8fd3-dd0691142074",
"name": "",
"fullName": null,
"number": 1,
"seatingCapacity": 0,
"description": null,
"isActive": true
}
],
"waiterDetails": [
{
"externalId": "0ab41df0-f4ae-4fbe-959f-ecaba7c85c85",
"name": "Максимейко Наталія",
"phone": "+380997716858",
"pinCode": "АК00-00043"
}
]
},
"orderType": "Common"
}
Last updated