| shift_id
|
uuid
|
Зміна.; Поле
| ; !; Коментар
Критично істотно: чек повернення повинен бути пов'язаний із первинним чеком.; |-
|
Status Sync Worker
|
-
|
auto_open_shift
|
boolean
|
Так
|
-
|
original_fiscal_number
|
string
|
Фіскальний номер первинного чека.; Колір
VCHASNO_KASA_RETRY_COUNT=3
Етап 1.; Базова структура сервісу
}
|
-
|
Device Manager
|
Локальний або інтеграційний застосунок для роботи з ПРРО, POS-пристроями та фіскалізацією.; * інтернет-магазинів;
- POS-систем;
- CRM;
- ERP;
- служб доставки;
- маркетплейсів;
- сервісів підписок;
- систем обліку продажів;
- компаній, які хочуть автоматизувати фіскалізацію оплат.; # Чи потрібна супровід декількох юридичних осіб?; | Довідник tax_group і валідація.; !; Код
17.4. fiscal_receipts
|
style="background:#bbdefb;" | Блакитний
|
| Закрита
|
CLOSED_WITH_Z_REPORT
|
Зміна закрита із Z-звітом.; характеристика
</syntaxhighlight>
|
-
|
total_amount
|
decimal
|
-
|
old_status
|
varchar
|
-
|
Fiscal Status
|
-
|
Фізичні магазини
|
Через Device Manager.; актуалізація ERP / CRM / POS
|
; я хочу бачити dashboard по касах і чеках,
5.; №
- реалізувати створення чеків;
- реалізувати валідацію;
- реалізувати дедублікацію;
- реалізувати чергу;
- реалізувати worker фіскалізації.; Фіскальний результат
},
"price": 250.00,
|
|
-
|
payments
|
array
|
style="background:#bbdefb;" | Блакитний
|
| Фіскалізовано
|
FISCALIZED
|
Чек успішно фіскалізовано.; Пріоритет
POST /api/v1/fiscal/refund-receipts
"fiscal_operation_type": "sale",
def create_x_report(self, shift_id: str) -> "XReportResponse":
pass
db.commit()
],
|
| original_receipt_id
|
uuid
|
як ілюстрація K2 ERP або інша платформа.; retry_count: int = 3
"price": 70.00,
Головна ідея: розробити Python-сервіс.;== 16.; Черга фіскалізації ==
7.3.; Контроль зміни
6.; |-
|
Успішна фіскалізація
|
}
| style="background:#ef9a9a;" | Червоний
|
| Потребує повтору
|
NEEDS_RETRY
|
-
|
Z Report
|
-
|
send_receipt_to_customer
|
boolean
|
Ні
|
-
|
sku
|
varchar
|
Артикул.; платформа повинна забезпечити:
def get_shift_status(self, shift_id: str) -> "ShiftStatusResponse":
|
-
|
Повторна обробка
|
-
|
currency
|
varchar
|
Він бачить кількість чеків, помилок, повернень і незакритих змін.;
* реалізувати створення інтеграції;
* реалізувати зберігання токена;
* реалізувати check-connection;
* реалізувати права доступу.; №
POST /api/v1/fiscal/integrations
!; # Чи потрібна супровід локального друку чеків?; |-
| FiscalApiError
| API повернув помилку.; |-
| closed_at
| timestamp
| Дата закриття.; Час
!; Cloud API або Device Manager
<pre>
== 15.; Дедублікація ==
|
| 4.; |-
| ERP / CRM / сайт / POS
| Джерело продажів, повернень, оплат і даних покупця.; |}
<pre>
VCHASNO_KASA_INTEGRATION_MODE=cloud_api
!; |-
| is_active
| boolean
| Чи застосовується.; Поле
=== Етап 6.; Зміни та звіти ===
<syntaxhighlight lang="python">
GET /api/v1/fiscal/receipts/{receipt_id}
платформа повинна підтримувати закриття касової зміни та формування Z-звіту.; # Які податкові групи товарів використовуються?; | Чек отримує статус FISCALIZED.; |-
| created_at
| timestamp
| Дата події.; |-
| Payment
| Оплата в чеку: готівка, картка, онлайн-еквайринг тощо.; |}
{| class="wikitable"
from uuid import UUID
* timeout;
* тимчасової недоступності API;
* HTTP 429;
* HTTP 500;
* HTTP 502;
* HTTP 503;
* HTTP 504;
* мережевих помилок;
* тимчасової помилки Device Manager.; |
| 2.; | style="background:#eeeeee;" | Сірий
|-
| Відкривається
| OPENING
| Виконується відкриття зміни.; Колір
payload={
!; |-
| name
| varchar
| Назва каси.; !; organization_id: str | None = None
* Python API для прийому продажів;
* замовник інтеграції з «Вчасно.Каса»;
* супровід фіскалізації чеків;
* супровід повернень;
* відкриття та закриття змін;
* збереження чеків;
* збереження статусів;
* журнал помилок;
* retry-механізм;
* dashboard / API для контролю;
* інтеграційні функціональні можливості з внутрішньою системою.;</div>
|-
| external_order_id
| ключовий ключ від зовнішньої системи.; POST /api/v1/fiscal/receipts
audit_logger.log(
<pre>
|-
| Дублювання чеків
| Повторний запит має змогу створити другий чек.; !; Тип
receipt.error_message = str(exc)
{| class="wikitable"
!;<div style="border-left: 6px solid #f57c00; background: #fff3e0; padding: 12px 16px; margin: 16px 0;">
* повноцінний POS-інтерфейс касира;
* власна реалізація ПРРО без «Вчасно.Каса»;
* самостійна реєстрація ПРРО в ДПС через Python-сервіс;
* власний компонент КЕП;
* інтеграційні функціональні можливості з усіма еквайрингами;
* складний UI для касира;
* заміна кабінету «Вчасно.Каса».; Валідація, дедублікація, черга
!; Сценарій
До MVP не входить:
{
default_cashier_id: str | None = None
!; Тип
pass
Логічний endpoint:
Retry застосовується для:
"name": "Товар 1",
7.; |-
|
Зміна налаштувань
|
}
|
;=== 24.1.; інтеграційні функціональні можливості ===
"sku": "SKU-001",
|
; Тип
!; платформа не повинна дозволяти створювати повернення на суму більшу, ніж залишок доступний до повернення.; # Які типи оплат підтримуються?; |-
| customer
| object
| інформаційні дані покупця.; №
{| class="wikitable"
audit_logger.log(
pass
|
| AC-4
|
ERP передає продаж.; №
retry_backoff_seconds: int = 5
)
| 10:42
|
Каса 1
|
ORDER-123
|
570.00
|
Помилка
|
Timeout API
|
Повторити
|
| 11:05
|
Каса 2
|
ORDER-124
|
1200.00
|
Потребує повтору
|
Тимчасова помилка
|
Повторити
|
| 12:10
|
Каса 3
|
SHIFT-55
|
-
|
Зміна відкрита
|
Не закрито Z-звіт
|
Закрити зміну
|
ДПС
|
-
|
AC-16
|
є собою помилки фіскалізації.; Замовлення
24.2.; Чеки
Етап 4.; Чеки
|
; Показник
|
; Компонент
|
| integration_name
|
string
|
Так
|
-
|
api_token
|
secret
|
Так
|
}
POST /api/v1/fiscal/shifts/open
17.1. fiscal_integrations
|
Чек переходить у NEEDS_RETRY.; |-
|
integration_mode
|
varchar
|
Dashboard, нагадування, авто-закриття за правилом.; |-
|
ДПС
|
-
|
Фіолетовий
|
#f3e5f5
|
-
|
fiscal_operation_type
|
string
|
}
"fiscal_url": response.fiscal_url,
VCHASNO_KASA_ORGANIZATION_ID=org-001
)
)
ERP / CRM / Website / POS
| Підходить для інтеграцій з локальними системами, POS, принтерами.; | Черга чеків, pending-операції.; |-
|
Receipt Service
|
платформа створює чек повернення.; | style="background:#ffcc80;" | Потрібна дія
|
def open_shift(self, cash_register_id: str, cashier_id: str) -> "ShiftResponse":
|
-
|
Refund Service
|
Створення чеків повернення.; №
8.9.; Відправка чека покупцю
18.9.; Закриття зміни
},
idempotency_key=command.idempotency_key,
POST /api/v1/fiscal/refund-receipts
Python-сервіс повинен приймати інформаційні дані продажу та створювати фіскальний чек.; Worker викликає API «Вчасно.Каса».; VCHASNO_KASA_BASE_URL=https://api.example.vchasno-kasa
|
-
|
external_order_id
|
varchar
|
style="background:#f3e5f5;" | Фіолетовий
|
18.11. Dashboard
|
-
|
Receipt Item
|
-
|
Dashboard API
|
-
|
переважні аспекти
|
-
|
entity_type
|
varchar
|
-
|
Незакрита зміна
|
Касир або платформа не закрили зміну.; Тип
18.3.; Створення чека продажу
Приклад змінних середовища:
|
| id
|
uuid
|
ID зміни.; Тип
|
| Cash Register
|
-
|
Відправка в API
|
style="background:#f3e5f5;" | Спеціальні операції
|
| Незакриті зміни
|
-
|
updated_at
|
timestamp
|
-
|
Загальна БД чеків
|
Усі чеки зберігаються в єдиній БД Python-сервісу.; Поле
3.; |}
class VchasnoKasaClient:
24.5. Dashboard
істотно: у «Вчасно.Каса» можуть використовуватись різні сценарії інтеграції: хмарне API, Device Manager, інтеграційні функціональні можливості з обліковою системою, сайтом або POS.; Поле
|
-
|
external_payment_id
|
-
|
id
|
uuid
|
Внутрішній ID каси.; характеристика
Критично істотно: інтеграційні функціональні можливості з ПРРО не повинна втрачати чеки.;=== 12.2.; Основні компоненти Python-сервісу ===
|
| Чернетка
|
DRAFT
|
Чек створено у Python-сервісі, але ще не відправлено.; Статус
VCHASNO_KASA_TIMEOUT_SECONDS=30
!; Призначення
* [[Python]]
* [[FastAPI]]
* [[K2 ERP]]
* [[Вчасно.Каса]]
* [[ПРРО]]
* [[Фіскалізація]]
* [[Фіскальний чек]]
* [[Касова зміна]]
* [[Z-звіт]]
* [[X-звіт]]
* [[Device Manager]]
* [[API інтеграція]]
* [[POS]]
* [[Інтернет-магазин]]
"cashier_id": "cashier-001",
"raw_request": command.model_dump(),
!; # Чи потрібна інтеграційні функціональні можливості з POS-терміналами?; |-
| cash_register_id
| uuid
| Каса.; |-
| created_at
| timestamp
| Дата створення.; |-
| auto_close_shift
| boolean
| Ні
| автономно закривати зміну за розкладом.; Очікуваний результат
!; | style="background:#c8e6c9;" | Норма
|-
| Очікують
| Чеки в черзі.;== 10.; Статуси зміни ==
},
|-
| Фіскалізація продажу
| Високий
| ключовий бізнес-процес.; |-
| external_cash_register_id
| varchar
| ID каси у «Вчасно.Каса».; Колір
== 26.; Етапи реалізації ==
receipt = receipt_repository.create(
== 28.; Відкриті питання ==
POST /api/v1/fiscal/receipts/{receipt_id}/retry
<pre>
<pre>
"external_order_id": command.external_order_id,
{| class="wikitable"
{| class="wikitable"
event_type="RECEIPT_QUEUED",
До області задачі входить:
=== 8.3.; Приклад запиту на чек ===
"tax_group": "VAT_20",
!; платформа повинна підтримувати відкриття касової зміни.; Поле
До першої версії не входить:
pass
verify_ssl: bool = True
!; |}
Сервіс повинен забезпечити:
=== 8.6.; Закриття зміни ===
* акаунт у «Вчасно.Каса»;
* зареєстрований суб'єкт господарювання;
* зареєстровану торгову точку;
* зареєстрований ПРРО;
* зареєстрованого касира;
* активний доступ до API або Device Manager;
* токен інтеграції;
* тестову касу або тестовий режим, якщо доступний;
* перелік кас, які будуть використовуватись;
* перелік касирів;
* правила відкриття і закриття зміни;
* правила формування чеків;
* правила повернень;
* формат оплати;
* формат товарних позицій;
* формат податків і ставок;
* вимоги до відправки електронного чека покупцю.; |-
| Закриття зміни
| Z-звіт, час, результат.; |-
| qr_code
| text
| QR або інформаційні дані QR, якщо доступні.; | платформа повертає успішний або помилковий статус.; |-
| status
| varchar
| Статус чека.; VCHASNO_KASA_DEFAULT_CASHIER_ID=cashier-001
щоб контролювати фіскалізацію, помилки, повернення і незакриті зміни.; |-
| Втрата чека
| API недоступне під час продажу.; Що зберігати
<pre>
GET /api/v1/fiscal/dashboard?date_from=2026-05-01&date_to=2026-05-07
v
VCHASNO_KASA_RETRY_BACKOFF_SECONDS=5
"unit": "шт"
|-
| API Layer
| REST API для прийому продажів, повернень, команд зміни.;== 25. MVP ==
* https://service.vchasno.ua/tech-doc-kasa
* https://wiki-kasa.vchasno.ua/uk/DeviceManager/Functionality/API
* https://kasa.vchasno.com.ua/check-list
* https://kasa.vchasno.com.ua/integraciya
* https://kasa.vchasno.com.ua/devise-manager
* https://wiki-kasa.vchasno.ua/uk/DeviceManager/Start/Create_prro
* https://wiki-kasa.vchasno.ua/uk/DeviceManager/Functionality/Emulator
!; Результат зберігається в БД.; |-
| status
| varchar
| OPEN, CLOSED, ERROR тощо.; VCHASNO_KASA_DEFAULT_CASH_REGISTER_ID=cash-register-001
Python-сервіс напряму викликає хмарне API «Вчасно.Каса».; |-
| fiscalized_at
| timestamp
| Дата фіскалізації.; характеристика
=== 21.1.; Основні KPI ===
!; |-
| opened_at
| timestamp
| Дата відкриття.; | Валідація перед фіскалізацією.; |-
| AC-7
| Повторний запит має той самий idempotency_key.; |-
| Refund Receipt
| Чек повернення.; API приймає запит на створення чека.; |-
| amount
| numeric
| Сума оплати.; # Чи потрібно автономно закривати зміну?; |-
| tax_group
| varchar
| Податкова група.; Критерій
"currency": "UAH"
entity_id=receipt.id,
|
-
|
Fiscal Queue
|
Вони підсвічуються помаранчевим.; |-
|
base_url
|
varchar
|
інтеграційні функціональні можливості зберігається в системі.; | Dashboard, список чеків, касові зміни.; "provider": "liqpay",
ERP / CRM / Website / POS
!; |-
| status
| varchar
| Активна, неактивна, помилка.; |-
| Vchasno Kasa Client
| Python-клієнт для API «Вчасно.Каса» або Device Manager.; Задача додається в чергу.; |}
платформа повинна не допускати дублювання чеків.; Фіскалізація через ПРРО
Логічний endpoint:
!; POST /api/v1/fiscal/receipts/{receipt_id}/sync-status
Як оператор або ERP,
"type": "card",
=== 18.2.; Перевірка підключення ===
платформа повинна:
|
-
|
Основні операції
|
style="background:#eeeeee;" | Сірий
|
| Повернення створено
|
REFUNDED
|
По чеку є собою повне або часткове повернення.; {
validation_service.validate_receipt(command)
20.1.; Типи помилокpass
| ValidationError
|
Некоректні інформаційні дані чека.; # Який SLA по фіскалізації?; характеристика
|-
| external_order_id
| string
| ID замовлення у зовнішній системі.; Значення
db.commit()
=== 18.1.; Створення інтеграції ===
платформа повинна підтримувати синхронізацію статусу чека з «Вчасно.Каса».; Конкретний сценарій потрібно зафіксувати в налаштуваннях інтеграції.; | У БД зберігається fiscal_number.; |-
| AC-8
| API повертає тимчасову помилку.; |-
| Перевірка перед чеком
| Якщо зміна вже відкрита, повторно не відкривати.; Сценарій
sha256(external_order_id + total_amount + payment_id + cash_register_id)
"status": "PENDING",
}
def create_fiscal_receipt(command: "CreateReceiptCommand", db: "Session") -> "FiscalReceipt":
if receipt.status == "FISCALIZED":
=== 7.2.; Повернення ===
db.commit()
Як касир або адміністратор,
Вчасно.Каса
<pre>
!; receipt.raw_response = response.raw_payload
"receipt_type": "sale",
</div>
=== 8.1.; конфігурація інтеграції ===
"amount": 500.00,
<div style="border-left: 6px solid #c62828; background: #ffebee; padding: 12px 16px; margin: 16px 0;">
def create_receipt(self, payload: "ReceiptPayload") -> "ReceiptResponse":
'''Технічний стек:''' Python 3.11+, FastAPI, PostgreSQL, SQLAlchemy, Alembic, httpx, Pydantic, Celery/RQ/APScheduler, Redis, Docker.; | Виконати retry.; інформаційні дані проходять валідацію.; |}
receipt.status = "NEEDS_RETRY"
|
-
|
idempotency_key
|
Унікальний ключ запиту.; Помилка
функціональні можливості застосовується для:
|
-
|
name
|
varchar
|
-
|
receipt_id
|
uuid
|
-
|
ShiftError
|
-
|
idempotency_key
|
varchar
|
-
|
quantity
|
numeric
|
-
|
items
|
array
|
-
|
cash_register_id
|
uuid
|
Healthcheck і fallback-сценарій.; |-
|
is_active
|
boolean
|
Активність.; def fiscalize_receipt(receipt_id: UUID, db: "Session") -> None:
- додати rate limiting;
- додати alerting;
- додати retry policy;
- додати dead letter queue;
- додати моніторинг;
- додати резервне копіювання.; Критерій
- створити FastAPI-проєкт;
- налаштувати PostgreSQL;
- створити моделі інтеграції, кас, змін, чеків;
- налаштувати Alembic;
- реалізувати healthcheck.; Тип
|
|
платформа формує Z-звіт.; |}
}
20.; Обробка помилокВаріант 1.; 5.1.; Хмарне API12.; технічна архітектура рішення для бізнесу
| id
|
uuid
|
ID позиції.; Очікуваний результат
receipt.status = "SENDING"
5.2.; Варіант 2.; Device Manager
entity_type="receipt",
|
Черга, статуси API.; Поле
task_name="fiscalize_receipt",
7.4.; Повторна обробка
Як адміністратор,
"cash_register_id": "cash-register-001",
POST /api/v1/fiscal/shifts/{shift_id}/close
POST /api/v1/fiscal/shifts/open
платформа попереджає перед закриттям зміни.; Тип помилки
- реалізувати чек повернення;
- перевірити доступний залишок повернення;
- зв'язати повернення з первинним чеком.; |-
|
cashier_id
|
string
|
Ні
|
}
21.2.; Приклад dashboard
</syntaxhighlight>
|
-
|
integration_id
|
uuid
|
-
|
integration_mode
|
enum
|
Так
|
cloud_api, device_manager, hybrid.; характеристика
- зберігання токенів тільки у secret storage або в зашифрованому вигляді;
- заборону логування токенів;
- маскування персональних даних покупців;
- обмеження доступу до чеків;
- контроль доступу до повернень;
- окремі права на закриття зміни;
- журнал усіх дій;
- HTTPS для API-запитів;
- перевірку SSL;
- обмеження повторних запитів;
- захист від дублювання чеків.; |-
|
base_url
|
string
|
Так
|
Базова адреса API або Device Manager.; характеристика
cashier_id=receipt.cashier_id,
|
|
-
|
new_status
|
varchar
|
Новий статус.; Очікуваний результат
v
"currency": command.currency,
db=db,
Мінімальні інформаційні дані:
== 21.; Dashboard керівника ==
!; Параметр
!; receipt = receipt_repository.get_by_id(db, receipt_id)
"external_order_id": "ORDER-2026-000123",
return existing
[[Категорія:Інтеграції]]
from pydantic_settings import BaseSettings
|-
| «Вчасно.Каса»
| ПРРО-сервіс для фіскалізації чеків.; "unit": "послуга"
!; Компонент
!; Критерій
return receipt
=== 13.1.; Призначення ===
{| class="wikitable"
!; |-
| raw_request
| jsonb
| Запит до API.; # Чи потрібно автономно відкривати зміну?; Тип задачі
Python-сервіс підтримує роботу обидва способи інтеграції.; |-
| API Event
| Технічна подія інтеграції.; |}
Логічний endpoint Python-сервісу:
{| class="wikitable"
</pre>
=== 19.1.; Створення чека ===
!; |-
| fiscal_number
| varchar
| Фіскальний номер ПРРО, якщо доступний.; |-
| Shift Service
| Відкриття, контроль і закриття змін.; |}
!; {| class="wikitable"
== 7. User Story ==
data={
event_type="RECEIPT_FISCALIZED",
Якщо API або конфігурація «Вчасно.Каса» підтримують електронну відправку чека, Python-сервіс повинен передавати email або телефон покупця.; | Idempotency key і дедублікація.; | Первинний чек отримує ознаку повного або часткового повернення.; |-
| Єдиний dashboard
| Керівник бачить усі чеки, каси, статуси й помилки в одному місці.; |-
| organization_id
| string
| Так
| Внутрішній ID організації.; |-
| AC-6
| Чек фіскалізовано.; |-
| AC-2
| Адміністратор перевіряє підключення.; |-
| current_shift_id
| uuid
| Поточна зміна.; Дія системи
|-
| AC-1
| Адміністратор створює інтеграцію.; | Підходить для хмарних систем.; характеристика
!; |-
| Автоматичне відкриття
| платформа відкриває зміну перед першим чеком.; | style="background:#bbdefb;" | Блакитний
|-
| Відкрита
| OPEN
| Можна фіскалізувати чеки.; |-
| AC-3
| Токен неправильний.; db=db,
{{DISPLAYTITLE:Технічне завдання: Інтеграція Вчасно.Каса для Python}}
"sku": "DELIVERY",
!; |}
== 11.; Єдина логіка кольорів ==
# Який сценарій інтеграції застосовується: хмарне API, Device Manager або гібрид?; | Вони підсвічуються червоним.; Створюється запис receipt зі статусом PENDING.; !; | style="background:#ffcc80;" | Помаранчевий
|-
| Скасовано
| CANCELLED
| Операцію скасовано.; |-
| z_report_number
| varchar
| Номер Z-звіту.; | Черга, retry, статус NEEDS_RETRY.; |-
| receipt_type
| varchar
| sale або refund.; ERP / CRM / сайт отримує статус.; |}
!; |-
| RefundLimitError
| Сума повернення перевищує доступний залишок.; Дія
До MVP входить:
</pre>
'''Критично істотно:''' повторний запит із тим самим idempotency_key не повинен створити другий фіскальний чек.; | Помилки фіскалізації, незакрита зміна.; | Draft, Cancelled, Closed.; |-
| discount_amount
| numeric
| Знижка.; |-
| external_payment_id
| varchar
| ID оплати в платіжній системі.; |}
!; |-
| AC-10
| Сума повернення більша за суму продажу.; | Другий чек не створюється.; |}
except TemporaryFiscalError as exc:
)
Python Fiscal Service
pass
response = vchasno_kasa_client.create_receipt(payload)
<pre>
</div>
"external_payment_id": command.external_payment_id,
<div style="border-left: 6px solid #c62828; background: #ffebee; padding: 12px 16px; margin: 16px 0;">
[[Категорія:Фіскалізація]]
Як платформа продажів,
=== 18.10.; X-звіт ===
[[Категорія:Python]]
</pre>
receipt.qr_code = response.qr_code
я хочу бачити, чи відкрита касова зміна,
{| class="wikitable"
"total_amount": command.total_amount,
<pre>
"quantity": 1,
Vchasno Kasa Adapter
=== 8.4.; Чек повернення ===
!; Сума
{| class="wikitable"
|-
| Хмарні продажі та реалізація
| Через хмарне API.; |-
| AC-14
| є собою незавершені чеки.; | style="background:#e3f2fd;" | Інформаційний
|-
| Фіскалізовано
| Кількість успішних чеків.; характеристика
== 17.; Модель даних ==
v
я хочу передати інформацію про оплату в Python-сервіс,
== 5.; Варіанти інтеграції ==
[[Категорія:Вчасно.Каса]]
=== Варіант 3.; 5.3.; Гібридна схема ===
!;=== 17.3. fiscal_shifts ===
=== 7.1.; Фіскалізація продажу ===
!; Поле
!; | Python-сервіс напряму з ДПС у MVP не функціонує.; !; Значення
|-
| AC-9
| користувач системи створює повернення.; |-
| style="background:#eeeeee;" | Сірий
| #eeeeee
| Неактивно або скасовано.; Поле
Приклад hash:
pass
shift = shift_service.ensure_open_shift(
if existing:
{| class="wikitable"
=== 18.8.; Відкриття зміни ===
{| class="wikitable"
<div style="border-left: 6px solid #6a1b9a; background: #f3e5f5; padding: 12px 16px; margin: 16px 0;">
<pre>
!; # Чи потрібно відправляти чек покупцю через email/SMS/Viber?; характеристика
'''Критично істотно:''' до початку розробки потрібно визначити сценарій інтеграції: хмарне API або Device Manager.; |}
=== Етап 7.; Dashboard та аудит ===
=== 12.1.; Загальна схема ===
* створення інтеграції;
* перевірка підключення;
* створення чека продажу;
* створення чека повернення;
* валідація чеків;
* дедублікація;
* черга фіскалізації;
* відкриття зміни;
* закриття зміни;
* отримання статусу чека;
* збереження fiscal_number;
* журнал подій;
* retry-механізм;
* dashboard API;
* базові unit-тести;
* mock API для інтеграційних тестів.; |}
!; |-
| Обмеження
| Потрібна інсталяція та супровід Device Manager.; |-
| cash_register_id
| string
| Так
| ID каси / ПРРО.; Від цього залежить технічна архітектура, мережеві конфігурація, обробка офлайн-ситуацій і друк чеків.; |-
| payments
| array
| Сума повернення.; |-
| style="background:#fff9c4;" | Жовтий
| #fff9c4
| Очікування або попередження.; | Заборонити фіскалізацію.; |-
| cashier_id
| string
| Касир.; | Зберегти raw-відповідь, перевести в NEEDS_RETRY або ERROR.; |-
| created_at
| timestamp
| Дата створення.; |-
| Завантаження PDF
| Низький
| Не блокує фіскалізацію.; Поле
"payment_id": "PAY-123456"
v
</pre>
Метою задачі є собою створення Python-сервісу для інтеграції з «Вчасно.Каса» з метою автоматизації фіскалізації продажів, повернень і касових операцій.; |-
| error_message
| text
| Остання помилка.; |-
| Audit Logger
| Журнал API-запитів, відповідей, помилок і змін статусів.; |-
| переважні аспекти
| Можливість роботи з POS-пристроями, принтерами, локальною інфраструктурою.; Очікуваний результат
== 9.; Статуси чеків ==
],
VCHASNO_KASA_API_TOKEN=********
db=db,
|
Реалізується в межах цього ТЗ.; |-
|
raw_response
|
jsonb
|
-
|
Повернення
|
Високий
|
Важлива фінансова операційна дія.; Критерій
|
|
-
|
AC-5
|
-
|
DuplicateReceiptError
|
Чек уже створено.;
- реалізувати dashboard API;
- реалізувати журнал подій;
- реалізувати фільтри;
- реалізувати експорт, якщо потрібно.; |-
|
Закриття зміни
|
Критичний
|
-
|
Червоний
|
#ef9a9a
|
Помилка або критична ситуація.; Призначення
{{SEO
entity_id=receipt.id,
Логічний endpoint:
"customer": {
1.; Мета
POST /api/v1/fiscal/shifts/{shift_id}/close
18.7.; Повторна фіскалізація
except Exception as exc:
|
| Ручне відкриття
|
-
|
receipt_id
|
uuid
|
ID чека.; характеристика
try:
17.7. fiscal_events
- прийом замовлень, продажів або оплат із зовнішньої системи;
- створення фіскального чека;
- створення чека повернення;
- контроль відкриття касової зміни;
- контроль закриття касової зміни;
- формування X-звіту;
- формування Z-звіту;
- отримання статусів чеків;
- збереження фіскальних номерів;
- збереження посилання на чек або PDF/HTML-візуалізацію, якщо доступна;
- відправку електронного чека покупцю, якщо підтримується API або налаштуваннями сервісу;
- журналювання всіх API-запитів;
- повторну обробку помилкових операцій;
- захист від дублювання чеків;
- передачу статусів назад в ERP / CRM / сайт / POS.; Ключ
{
я хочу створити чек повернення,
|
| Чеків створено
|
style="background:#eeeeee;" | Сірий
|
| Очікує фіскалізації
|
PENDING
|
Чек у черзі на відправку.; характеристика
"email": "customer@example.com",
19.; Приклад Python-логіки
|
-
|
Python-сервіс
|
Інтеграційний шар між ERP / сайтом / CRM / POS та «Вчасно.Каса».;=== 20.2.; Retry-логіка ===
- реалізувати замовник API;
- реалізувати авторизацію;
- реалізувати open_shift;
- реалізувати close_shift;
- реалізувати create_receipt;
- реалізувати create_refund_receipt;
- реалізувати get_status;
- реалізувати обробку помилок.; |}
base_url: str
Ключі дедублікації:
14.; Валідація чека
7.5.; Контроль керівника
|
|
-
|
AuthError
|
-
|
payload
|
jsonb
|
Технічні інформаційні дані.; характеристика
"items": [
{
|
style="background:#c8e6c9;" | Зелений
|
| Помилка
|
ERROR
|
style="background:#c8e6c9;" | Зелений
|
| Закривається
|
CLOSING
|
Виконується закриття зміни.; Як зменшити
|
-
|
AC-11
|
-
|
Shift
|
Касова зміна.; Сутність
def create_refund_receipt(self, payload: "RefundReceiptPayload") -> "ReceiptResponse":
def get_receipt_pdf(self, receipt_id: str) -> bytes:
v
POST /api/v1/fiscal/shifts/{shift_id}/x-report
v
pass
)
2.; |}
payload={"external_order_id": command.external_order_id},
24.3.; Повернення
return
17.6. fiscal_payments
3.; Джерела інтеграції
timeout_seconds: int = 30
|
| id
|
uuid
|
ID інтеграції.; Обов'язковість
pass
| -
|
price
|
numeric
|
Ціна.; receipt.fiscal_url = response.fiscal_url
24.4.; Зміни
22.; Безпека
|-
| style="background:#c8e6c9;" | Зелений
| #c8e6c9
| Успішно: чек фіскалізовано, зміна відкрита або закрита коректно.; Колір
|-
| id
| uuid
| ID події.; !; |-
| organization_id
| varchar
| Організація.; |-
| entity_id
| uuid
| ID сутності.; |-
| external_shift_id
| varchar
| ID зміни у «Вчасно.Каса».; |-
| X Report
| Проміжний звіт без закриття зміни.; | style="background:#ef9a9a;" | Червоний
|}
v
4.; | style="background:#ef9a9a;" | Критично
|-
| Повернення
| Кількість чеків повернення.; | платформа блокує операцію.; | платформа показує AuthError і не виконує фіскалізацію.; | Не відправляти чек, повернути список помилок.; |-
| Cashier
| Касир, від імені якого виконується операційна дія.; !; |-
| Receipt
| Фіскальний чек продажу.; |-
| external_refund_id
| string
| ID повернення у зовнішній системі.; |-
| provider
| varchar
| LiqPay, WayForPay, Mono, terminal тощо.; Статус / номер / посилання на чек
!; |-
| Validation Layer
| Перевіряє товари, суми, оплати, податки, касу, касира.; |-
| Підходить для
| POS-систем, локальних облікових систем, магазинів із чековими принтерами.; |-
| api_token_encrypted
| text
| Зашифрований токен.; характеристика
|-
| Не відкрита
| CLOSED
| Зміна закрита або ще не відкривалась.; |-
| provider
| varchar
| vchasno_kasa.;=== 13.3.; Конфігурація клієнта ===
"amount": 70.00,
платформа повинна підтримувати отримання проміжного X-звіту без закриття зміни.; характеристика
24. Acceptance Criteria
| }
|
-
|
amount
|
numeric
|
Сума.; Поле
Етап 5.; Повернення
receipt.error_message = str(exc)
Вчасно.Каса
6.; Основні сутності
|
| Створення чека
|
external_order_id, сума, каса, касир.;=== 8.5.; Відкриття зміни ===
|
; Де застосовується
receipt.fiscal_number = response.fiscal_number
POST /api/v1/fiscal/shifts/{shift_id}/x-report
receipt.fiscalized_at = datetime.now(timezone.utc)
29.; Джерела
|
-
|
AC-13
|
Повернути існуючий чек.;
</syntaxhighlight>
18.5.; Отримання чека
Етап 8.; Production hardening
|
; характеристика
Заборонено: зберігати API token, ключі, паролі касирів або інші секрети у коді, Git-репозиторії, відкритих логах або frontend-змінних.; |-
| integration_id
|
uuid
|
-
|
Хмарне API «Вчасно.Каса»
|
Пряма інтеграційні функціональні можливості з кабінетом та фіскалізацією чеків.; # Які платіжні провайдери використовуються?; Код
|
Refund, сторно, коригування.; |-
|
Невірні суми
|
-
|
Блакитний
|
#bbdefb
|
Python-сервіс створює чек зі статусом PENDING.; | style="background:#fff9c4;" | Увага
|
| Помилки
|
Retry, незавершені операції.; |-
|
receipt_hash
|
}
Перед фіскалізацією платформа повинна перевірити:
19.2.; Worker фіскалізації18.6.; Синхронізація статусу чекаdefault_cash_register_id: str | None = None
class VchasnoKasaSettings(BaseSettings):
27.; Ризики- перевірити відкриту зміну;
- перевірити незавершені чеки;
- сформувати Z-звіт;
- зберегти результат;
- змінити статус зміни на Closed;
- записати подію в журнал.; |}
}
)
Python Fiscal Service
Для реалізації задачі необхідно отримати:
<syntaxhighlight lang="python">
|-
| id
| uuid
| ID оплати.; Очікуваний результат
api_token: str
Сценарії:
"payments": [
|-
| Чеків за день
| 1240
| style="background:#e3f2fd;" | відомості
|-
| Фіскалізовано
| 1218
| style="background:#c8e6c9;" | Норма
|-
| Очікують у черзі
| 12
| style="background:#fff9c4;" | Увага
|-
| Помилки фіскалізації
| 7
| style="background:#ef9a9a;" | Критично
|-
| Повернення
| 14
| style="background:#f3e5f5;" | Контроль
|-
| Незакриті зміни
| 2
| style="background:#ffcc80;" | Потрібна дія
|}
{| class="wikitable"
щоб не втратити продаж.; |-
| error_message
| text
| Остання помилка.; характеристика
Retry не застосовується для:
integration_mode: str = "cloud_api"
!; |-
| external_payment_id
| varchar
| ID оплати.;== 13. Vchasno Kasa Client ==
POST /api/v1/fiscal/receipts
payload = receipt_mapper.to_vchasno_payload(receipt, shift)
=== 8.2.; Створення чека продажу ===
cash_register_id=receipt.cash_register_id,
"total_amount": 570.00,
"phone": "+380501112233"
8.8.; Отримання статусу чека
"idempotency_key": command.idempotency_key,
"tax_group": "NO_VAT",
|
-
|
Основні операції
|
-
|
Невірна податкова група
|
Товар передано з неправильним податком.; Коментар
платформа повинна дозволяти створити конфігурація підключення до «Вчасно.Каса».; | style="background:#fff9c4;" | Жовтий
| Відправляється
|
SENDING
|
-
|
name
|
varchar
|
-
|
default_tax_group
|
string
|
Ні
|
Заборонити повернення.; # Чи потрібна супровід часткових повернень?; |-
|
Повернення
|
первинний чек, сума, причина.; # Чи потрібна супровід змішаних оплат?; payload={"receipt_id": str(receipt.id)},
- реалізувати відкриття зміни;
- реалізувати закриття зміни;
- реалізувати X-звіт;
- реалізувати контроль незакритих змін.; KPI
fiscal_queue.enqueue(
|
| AC-15
|
Check-connection і сповіщення адміністратора.; |-
|
TimeoutError
|
-
|
fiscal_number
|
varchar
|
-
|
currency
|
string
|
-
|
cashier_id
|
varchar
|
Зупинити інтеграцію, повідомити адміністратора.; |-
|
reason
|
string
|
-
|
Deduplication Service
|
Захищає від повторної фіскалізації одного продажу.; характеристика
8.; Функціональні вимоги
|
ключовий зовнішній сервіс інтеграції.; | style="background:#c8e6c9;" | Зелений
|
| Помилка фіскалізації
|
FISCALIZATION_ERROR
|
Виникла помилка при фіскалізації.; Тип
18.4.; Створення чека повернення
16.1.; Логіка черги
POST /api/v1/fiscal/receipts/{receipt_id}/sync-status
18.; API Python-сервісу
1.; |-
|
event_type
|
varchar
|
Тип події.; Подія
23.; Логування та аудит
<syntaxhighlight lang="json">
|
; Кожна операційна дія продажу, повернення, відкриття зміни, закриття зміни та помилка фіскалізації повинні мати внутрішній ID, статус, журнал подій і можливість повторної обробки без створення дубля.; * повноцінний POS UI;
* власний ПРРО;
* інтеграційні функціональні можливості з усіма еквайрингами;
* складна аналітичні інструменти;
* автоматична реєстрація ПРРО в ДПС;
* супровід всіх нестандартних податкових сценаріїв;
* повна офлайн-робота без Device Manager.; | Записати помилку, дозволити повтор.; |-
|
is_active
|
boolean
|
Так
|
class="wikitable"
* помилок валідації;
* неправильного токена;
* дублювання чека;
* некоректних сум;
* неправильних податкових груп;
* повернення понад доступну суму.; * email;
* SMS;
* Viber;
* інший канал, якщо підтримується сервісом.; характеристика
def get_receipt_status(self, receipt_id: str) -> "ReceiptStatusResponse":
щоб розуміти, чи можна фіскалізувати чеки.; характеристика
entity_type="receipt",
8.7.; X-звіт
| AC-12
|
платформа відкриває зміну, якщо auto_open_shift = true.; Продаж / оплата / повернення
Python-сервіс взаємодіє з Device Manager, який виконує інтеграційні функції локально або в середовищі клієнта.; характеристика
я хочу повторити фіскалізацію після технічної помилки,
POST /api/v1/fiscal/integrations/{integration_id}/check-connection
Етап 2.; конфігурація інтеграції
13.2.; Основні методи
2.; Область сфера застосування
|
-
|
Синхронізація статусів
|
Середній
|
-
|
Обмеження
|
-
|
fiscal_url
|
varchar
|
-
|
total_amount
|
numeric
|
Загальна сума.; Тип
платформа повинна логувати:
|
| id
|
uuid
|
-
|
Device Manager недоступний
|
-
|
AC-17
|
є собою незакриті зміни.; },
receipt.status = "FISCALIZED"
|
; Статус
Управлінський результат: керівник повинен бачити, скільки чеків сформовано, скільки фіскалізовано, скільки помилок, які каси відкриті, які зміни не закриті, скільки повернень і які операції потребують уваги.; |-
|
unit
|
varchar
|
}
17.5. fiscal_receipt_items
| ; !; Параметр
def check_connection(self) -> "ConnectionStatus":
|
; Каса
щоб він автономно створив фіскальний чек у «Вчасно.Каса».; |-
|
cash_register_id
|
string
|
Каса / ПРРО.; Ризик
щоб коректно відобразити повернення коштів покупцю.;
"fiscal_number": response.fiscal_number,
17.2. cash_registers
|
-
|
Відкриття зміни
|
-
|
Помилки токена
|
Токен змінено або відкликано.; Тип
Етап 3.; Vchasno Kasa Client
"name": "Доставка",
<syntaxhighlight lang="python">
|
|
|
|
|
|
|
|
|
|
|
|
|