Вариант: 21. Система управления арендой автомобилей.
- Назначение: учетные записи клиентов и менеджера автопарка.
- Ключ: строковый UUID в поле
_id, чтобы сохранить совместимость текущего HTTP API. - Основные поля:
_id,login,firstName,lastName,email,phone,driverLicenseNumber,role,createdAtcredentials.salt,credentials.hashprofile.seededAtкак пример поля типаDate
- Индексы:
uniq_loginпоloginidx_users_createdпоcreatedAt, _id
- Назначение: парк автомобилей.
- Основные поля:
_id,vin,brand,model,class,status,pricePerDay,createdAtfeaturesкак массив строкactiveRentalIdдля быстрой проверки занятой машиныmaintenance.lastServiceAtкак пример вложенного объекта сDate
- Индексы:
uniq_vinпоvinidx_cars_status_createdidx_cars_class_created
- Назначение: факты аренды и история их жизненного цикла.
- Основные поля:
_id,userId,carId,startAt,endAt,status,priceTotal,createdAt,closedAt,paymentReferenceuserSnapshotиcarSnapshotstatusHistory[]audit.seededAtкак пример вложенногоDate
- Индексы:
idx_rentals_user_status_createdidx_rentals_car_status_period
- Назначение: outbox для событий аренды.
- Основные поля:
_id,aggregateType,aggregateId,eventType,payload,createdAtmeta.emittedAtкакDate
- Индексы:
idx_outbox_createdidx_outbox_aggregate
- Хранится
referenceчерезuserId. - Дополнительно хранится
embeddedснимокuserSnapshot. - Обоснование:
- пользователь является самостоятельным агрегатом и читается отдельно;
- в истории аренды нужен неизменяемый снимок данных на момент бронирования.
- Хранится
referenceчерезcarId. - Дополнительно хранится
embeddedснимокcarSnapshot. - Обоснование:
- автомобиль меняет статус и может обновляться отдельно;
- история аренды должна сохранять марку, модель, класс и цену на момент оформления.
- Хранится как
embedded array. - Обоснование:
- история статусов принадлежит только одной аренде;
- массив ограничен коротким жизненным циклом аренды;
- обновляется вместе с документом аренды.
- Хранится через отдельную коллекцию
outbox_events. - Обоснование:
- outbox нужен как самостоятельный поток событий;
- удобно считать и читать события глобально;
- текущая архитектура репозитория уже моделирует outbox как отдельное хранилище.
usersиcarsостаются самостоятельными коллекциями, потому что по ним есть отдельные endpoint'ы и независимые сценарии чтения.rentalsденормализована только там, где это уменьшает стоимость чтения истории и не ломает границы агрегатов.- Строковые ISO-8601 timestamp-поля в core-документах сохраняют полную совместимость с текущим API и существующими DTO.
- Для демонстрации типов MongoDB в seed-данных добавлены массивы, вложенные объекты и поля
Date, не влияющие на контракт HTTP API.
loginиvinуникальны на уровне индексов.priceTotal > 0иstatusограничен перечислением через$jsonSchemaдляrentals.- Пересечение активных аренд одного автомобиля контролируется в transaction-backed workflow.
- Перевод статусов машины и аренды выполняется в одной MongoDB транзакции.