Кешування рахунків

Кешування рахунків пидвищує швидкодію в отриманні рахунку для гостя. Expirenza віддає рахунок з "власного кеша", замість того щоб робити запити до POS.

Процес виглядає так:

  1. POS система раз в 5 секунд відправляє інформацію з замовленнями що зараз відкриті в POS на cервер Expirenza:

Короткий перелік всіх замовлень

Повна інфо про замовлення що змінились з моменту останнього оновлення

  1. Сервер може запитати у ПОС детальне інфо про будь яке з замовлень у будь який момент.

Пос система має відправити їх повне інфо з наступним вебхуком ORDERS_CACHE

  1. Про закриті замовлення ПОС система сповіщає сервер окермим вебхуком


Раз на 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

Команда надсилається з сервера 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