Призначення
Ендпоінт надає довідкову інформацію щодо того, з якої дати (і, за наявності, до якої дати) Організатор може встановити auctionPeriod.startDate для процедури з конкретним sellingMethod.
Ендпоінт обчислює календарні межі згідно правил, описаних у конфігурації.
URL
GET /api/procedures/{sellingMethod}/auctionPeriod
де {sellingMethod} — технічна назва напрямку (наприклад, basicSell-english, legitimatePropertyLease-english тощо)
Приклад: https://procedure.prozorro.sale/api/procedures/legitimatePropertyLease-english/auctionPeriod
Відповідь
Ендпоінт повертає JSON з об’єктом startDate, який містить:
minDate— найраніша допустима дата/час для auctionPeriod.startDatemaxDate— найпізніша допустима дата/час (повертається лише якщо для sellingMethod у конфігу задано validation.max)
Приклад (тільки minDate)
{
"startDate": {
"minDate": "2026-03-04T09:00:00+00:00"
}
}
Приклад (minDate + maxDate)
{
"startDate": {
"minDate": "2026-03-02T09:00:00+00:00",
"maxDate": "2026-03-31T10:00:00+00:00"
}
}
Джерело правил: конфіг specs
Посилання на конфіг: https://procedure.prozorro.sale/api/specs
Розрахунок дат виконується на основі конфігурації конкретного sellingMethod, секція: periods.procedure.auctionPeriod.startDate.validation
Ключові параметри:
Робочий/неробочий день
is_business_day: true означає, що результуюча дата має припадати на робочий день (після застосування diff і direction).
Мінімальна дата (validation.min)
Описує правило, як отримати minDate:
"min": {
"diff": "8 days",
"direction": "forward",
"from": "now",
"time": "11:00"
}
Логіка:
Береться базова точка відліку from (у прикладах це
now— поточна дата/час на момент запиту).Застосовується зміщення diff у напрямку direction:
forward — вперед від базової точки
backward — назад (для цього ендпоінту зазвичай не використовується, але механізм конфігураційно можливий)
Якщо задано is_business_day: true — дата нормалізується/підбирається так, щоб потрапити на робочий день.
Встановлюється час:
якщо
timeвказаний як одна година ("11:00") — використовується цей час;якщо вказано інтервал (
"11:00 - 13:00") — дляminDateвикористовується початок інтервалу (логіка “найраніший можливий час”).
Результат повертається в ISO-8601.
Максимальна дата (validation.max)
Якщо в конфігу присутній блок validation.max, ендпоінт додатково обчислює та повертає maxDate.
Приклад:
"max": {
"diff": "35 days",
"direction": "forward",
"from": "now",
"time": "13:00",
"is_business_day": true
}
Логіка аналогічна min, але:
для maxDate береться “найпізніший допустимий час”.
якщо
time— інтервал, то дляmaxDateвикористовується кінець інтервалу (логіка “найпізніший можливий час”).
Про startDate.time та conditions
У деяких sellingMethod у startDate додатково є:
time: "11:00 - 13:00"— допустиме вікно часу проведення аукціону (впливає на вибір часу в межах доби)conditions[]— правила для автовстановлення або альтернативної логіки (наприклад, коли auto_set: true і case.isPerishable: true)
Практичне використання на майданчиках
Майданчик може використовувати відповідь ендпоінту для:
обмеження вибору дати в UI:
minDateяк мінімально доступна дата,maxDateяк максимально доступна дата (якщо присутня)
валідації введеного значення до відправки в API запиті
відображення підказки Організатору типу:
“Найраніша дата початку аукціону: …”
“Дозволений діапазон: … – …”
Висновок
Ендпоінт повертає розрахунок на момент запиту (прив’язаний до
now).Ендпоінт є допоміжним: фінальна валідність auctionPeriod.startDate все одно перевіряється ЦБД при створенні/оновленні процедури згідно тих самих правил конфігу.
Якщо для sellingMethod не визначено validation.max, то maxDate не повертається.
Change request
Необхідно реалізувати підтримку query-параметрів у GET /api/procedures/{sellingMethod}/auctionPeriod
Мета зміни
Розширити ендпоінт GET /api/procedures/{sellingMethod}/auctionPeriod, щоб він міг обчислювати min/max дати з урахуванням параметрів конкретного кейсу, переданих у query-string (наприклад: isPerishable, value.amount), а не лише базової validation.min/max.
Це потрібно для того, щоб майданчик міг коректно показувати допустимий діапазон дат до створення процедури, але вже з урахуванням бізнес-умов.
Поточна поведінка (as-is)
Ендпоінт повертає startDate.minDate (та опційно startDate.maxDate) на основі periods.procedure.auctionPeriod.startDate.validation.
conditions[] наразі не параметризовані і не залежать від введених даних користувача (бо немає механізму передати ці дані у запит)
Нова поведінка (to-be)
Ендпоінт має приймати query параметри, які будуть використані при визначенні релевантного condition.case та/або правил validation
Базовий приклад:GET /api/procedures/basicSell-english/auctionPeriod?isPerishable=true
Розширений приклад:GET /api/procedures/sanctionedAssets-english/auctionPeriod?value.amount=300000000.00
Примітка
Параметри можуть комбінуватися
Backward compatibility
Якщо query параметри не передані, ендпоінт працює як зараз: повертає межі з startDate.validation.min/max (або тільки min, якщо max відсутній)
Якщо sellingMethod не має conditions[] для auctionPeriod.startDate — query параметри не впливають (результат як зараз)
Правила вибору умов
Загальна логіка
Система завантажує конфіг для {sellingMethod}
Якщо в startDate є масив conditions[], система має:
пройтись по conditions[] у вказаному у відповіді порядку
знайти першу умову, у якої case матчиться із якимось параметром запиту
застосувати її правила розрахунку дат
Якщо жоден case не матчиться — використовується дефолтна логіка з startDate.validation (як зараз)
Якщо матчиться кілька conditions - застосовується перший у масиві (тобто порядок у конфігу = пріоритет).
Це важливо, бо може бути комбінація:
GET /api/procedures/basicSell-english/auctionPeriod?value.amount=300000000.00&isPerishable=true
то в такому випадку застосується правило, яке перше в списку в specs.
Наприклад, конфіг такий:
"active_tendering": {
"periods": {
"procedure": {
"auctionPeriod": {
"startDate": {
"conditions": [
{
"auto_set": true,
"case": {
"isPerishable": true
},
"diff": "2 business days",
"direction": "forward",
"error": "raise",
"from": "now",
"time": "11:00 - 13:00"
},
{
"case": {
"value.amount": { "gt": 250000000 }
},
"validation": {
"min": {
"diff": "30 days",
"direction": "forward",
"error": "raise",
"from": "now",
"time": "11:00",
"is_business_day": true
},
"max": {
"diff": "60 days",
"direction": "forward",
"error": "raise",
"from": "now",
"time": "13:00",
"is_business_day": true
}
}
}
],
"time": "11:00 - 13:00",
"validation": {
"is_business_day": true,
"min": {
"diff": "8 days",
"direction": "forward",
"error": "raise",
"from": "now",
"time": "11:00"
}
}
}
}
}
}
}
Інтерпретація:
isPerishable=trueматчить condition №1value.amount=300000000.00також матчить condition №2 (бо300000000 > 250000000)але оскільки умови перевіряються послідовно, застосовується перший condition, який матчиться.
Отже результат має бути розрахований за condition №1 (isPerishable), а не за “високою ціною”:
minDate = now + 2 business days, час = початок інтервалу11:00maxDateу цьому прикладі не повертається, бо condition №1 не задаєvalidation.max, а визначає лише правило для найранішої дати (як у поточних спеках basicSell).
Робота з case
case — це набір умов над параметрами, переданими у query
Підтримувані типи перевірок:
boolean equality
isPerishable: true→ очікує?isPerishable=truenumeric comparisons для чисел
Наприклад:value.amount > 250000000value.amount >= 250000000value.amount < 250000000value.amount <= 250000000
Розширення формату конфігу
Boolean case (існує і зараз)
"conditions": [
{
"auto_set": true,
"case": {
"isPerishable": true
},
"diff": "2 business days",
"direction": "forward",
"from": "now",
"time": "11:00 - 13:00"
}
]
Numeric case для value.amount
"conditions": [
{
"case": {
"value.amount": {
"gt": 250000000.00 //використовуємо оператори gt/gte/lt/lte
}
},
"validation": {
"min": {
"diff": "30 days",
"direction": "forward",
"from": "now",
"time": "11:00"
},
"max": {
"diff": "60 days",
"direction": "forward",
"from": "now",
"time": "13:00"
}
}
}
]
conditions[] мають мати можливість:
задавати “коротке” правило (diff/from/time) — як у прикладі з isPerishable
АБО
перевизначати validation.min/max локально для цього кейсу
Тобто реалізмція має дозволти робити один із варіантів:
Варіант А: condition має власні поля diff/from/... і повертає тільки minDate (або min+max, якщо є)
Варіант Б: condition містить вкладений validation і повністю замінює дефолтний startDate.validation для обчислення min/max.
"auctionPeriod": {
"startDate": {
"conditions": [
{
"case": { "value.amount": { "gt": 250000000 } },
"validation": {
"min": { "diff": "30 days", "direction": "forward", "from": "now", "time": "11:00" },
"max": { "diff": "60 days", "direction": "forward", "from": "now", "time": "13:00" }
}
},
{
"case": { "value.amount": { "lte": 250000000 } },
"validation": {
"min": { "diff": "20 days", "direction": "forward", "from": "now", "time": "11:00" },
"max": { "diff": "35 days", "direction": "forward", "from": "now", "time": "13:00" }
}
}
],
"time": "11:00 - 13:00",
"validation": {
"is_business_day": true,
"min": {
"diff": "20 days",
"direction": "forward",
"error": "raise",
"from": "now",
"time": "11:00"
}
}
}
}
Формат query параметрів
Boolean
isPerishable=true|false (case-insensitive)
якщо параметр переданий не як boolean → 400 помилка
Числовий value.amount
value.amount— decimalякщо не число → 400 помилка
Відповідь ендпоінта (без змін)
Формат відповіді не змінюється:
{
"startDate": {
"minDate": "...",
"maxDate": "..."
}
}
Помилки / валідації
Некоректні значення в query параметрі - 400 Bad Request
Приклад:
isPerishable = abc
value.amount = not_a_number
Непідтримуваний параметр
Lenient: невідомі параметри ігноруються (щоб не ламати майданчики)
Приклади сценаріїв
Perishable
Запит:
GET /api/procedures/basicSell-english/auctionPeriod?isPerishable=true
Очікування:
якщо в конфігу є condition з case.isPerishable=true, повертається min/max за ним (наприклад +2 business days)
інакше — дефолтний validation.min/max
Поріг стартової ціни
Запит:GET /api/procedures/sanctionedAssets-english/auctionPeriod?value.amount=300000000.65
Очікування:
якщо в конфігу є condition
value.amount gt 250000000, тоді:minDate = now + 30 days
maxDate = now + 60 days (або як задано)
якщо amount менший — інший condition або дефолтні правила