Синхронний підпроект: openprocurement

Стек: Pyramid + pymongo + schematics. Основний продакшн API із повною функціональністю.

Коренева директорія: src/openprocurement/

Інфраструктурний пакет api/

Містить увесь базовий рівень, від якого успадковуються всі доменні пакети.

Файл / директорія

Призначення

app.py

Ініціалізація Pyramid-додатку; підключення всіх includeme

database.py

MongodbStore, BaseCollection, atomic_transaction; логіка фіду (list()), save_data(), watermark

context.py

Thread-local контекст запиту (get_request, set_request_now, get_db_session)

auth.py

Автентифікація брокерів і сервісних токенів

constants.py / constants_env.py

Бізнес-константи та константи з env-змінних (FEED_WATERMARK_SECONDS тощо)

utils.py

Спільні утиліти: context_unpack, raise_operation_error, json_view, update_logging_context

validation.py

Декоратори валідації запитів

middlewares.py

WSGI-middleware (таймінги, логування)

views/base.py

BaseResource, MongodbResourceListing; парсинг та формування offset; логіка пагінації фіду

procedure/models/

Базові schematics-моделі: Address, Document, Organization, Period, Value тощо

procedure/state/base.py

BaseState: хуки on_post / on_patch / always; status_up

procedure/serializers/

Базові серіалізатори відповідей

procedure/views/

(порожньо на рівні api; конкретні views — в доменних пакетах)

migrations/

Базова інфраструктура міграцій (base.py, rename.py)

tests/

Базові утиліти для тестів: base.py, mock.py, utils.py

Глобальні pytest-фікстури: src/openprocurement/conftest.py

Доменні пакети

Кожен домен — окремий пакет: tender/, contracting/, framework/, planning/, relocation/, historical/.

Всередині кожного домену:

  • core/ — спільна логіка для всіх типів процедур домену

  • Конкретні типи процедур (belowthreshold/, open/, contract/ тощо)

Структура всередині кожного типу процедури:

<domain>/<type>/
├── procedure/
│   ├── models/       # schematics-моделі об'єктів (Contract, Agreement тощо; у tender/ — лише в core/)
│   ├── state/        # бізнес-логіка переходів станів
│   ├── views/        # Pyramid-в'юхи (GET, POST, PATCH)
│   └── serializers/  # серіалізатори відповідей
├── migrations/       # міграції даних у MongoDB (нумеровані, 0001_…)
└── tests/            # інтеграційні тести

У домені tender/ усі моделі, request-валідатори та утиліти процедур зібрані в tender/core/procedure/ (models/, validation.py, utils.py); пакет типу процедури містить лише state/, views/, serializers/, constants.py і тести.

Правила розміщення коду

  • Бізнес-логіка → procedure/state/; state-класи не роблять запити до БД напряму

  • Запити до БД → лише з procedure/views/ (через request.registry.mongodb.<collection>)

  • Валідація вхідних даних → procedure/models/ (schematics) і validation.py

  • Спільні schematics-моделі тендерного домену → tender/core/procedure/models/; відмінності між типами процедур, що зводяться до обмежень (обов’язковість поля, ліміти, допустимі значення), реалізуються атрибутами й validate_*-методами state-класів (items_delivery_required, required_multilingual_fields, features_max_weight, patch_status_choices тощо), а не окремими моделями. Окремі моделі з префіксом (ESCO*, CFA* …) допускаються лише для структурних відмінностей (інші типи чи набір полів)

  • Реєстр процедур → tender/core/procedure/registry.py: PROCEDURE_MODELS зіставляє procurementMethodType з core-моделями процедури (ProcedureModels: tender/bid/award/lot/agreement для POST, PATCH і збереженого об’єкта); state-класи отримують моделі через get_procedure_models

  • Request-валідатори й утиліти конкретних процедур тендерного домену → tender/core/procedure/validation.py і tender/core/procedure/utils.py з префіксом процедури в назві (validate_bt_*, validate_cfa_*, validate_cd2_*, validate_limited_* …), а не окремі validation.py / utils.py у пакеті процедури

  • Серіалізація відповіді → procedure/serializers/

  • Зміна схеми / даних у БД → migrations/ (не в коді ініціалізації)

  • Спільні утиліти домену → <domain>/core/

  • Глобальні константи з часовою прив’язкою → constants_env.py (читаються з env або constants.ini)