REST API автосалону. Phase 1 — реляційний ресурс Car (MSSQL). Phase 2 — нереляційний ресурс Customer (Azure Cosmos DB). Phase 3 — зв'язок Purchase між Car і Customer через Azure Blob Storage. Phase 4 — публікація подій create/update у Azure Service Bus і GET-ендпоінт зі статистикою.
- .NET 8, ASP.NET Core Web API
- EF Core 8:
Microsoft.EntityFrameworkCore.SqlServer,Microsoft.EntityFrameworkCore.Cosmos - Microsoft SQL Server 2022, Azure Cosmos DB (NoSQL API)
Azure.Storage.Blobs+ Azurite (Azure Blob Storage emulator)Azure.Messaging.ServiceBus+ Azure Service Bus emulator- AutoMapper
- Swagger
- xUnit, Moq, FluentAssertions (UT)
Microsoft.AspNetCore.Mvc.Testing+EFCore.InMemory(IT) + in-memory fake для Cosmos, Blob і брокера- Docker / docker-compose
| Поле | Тип | Валідація |
|---|---|---|
| Brand | string | Required, 1..50 |
| Model | string | Required, 1..50 |
| Vin | string | Required, regex ^[A-HJ-NPR-Z0-9]{17}$ |
| Year | int | 1900..2100 |
| Price | decimal | 0.01..10 000 000 |
| Mileage | int | 0..2 000 000 |
| AddedAt | DateTime | сервер, UTC |
| Поле | Тип | Валідація |
|---|---|---|
| Id | Guid | сервер генерує (partition key) |
| FullName | string | Required, 2..100 |
| string | Required, email-формат, 5..100 | |
| PhoneNumber | string | Required, regex ^\+?[1-9]\d{6,14}$ |
| BirthDate | DateTime | 1900-01-01..2010-01-01 |
| RegisteredAt | DateTime | сервер, UTC |
Зберігається у Blob: {customerId}/{carId}.json.
| Поле | Тип | Валідація |
|---|---|---|
| CustomerId | Guid | з шляху, має існувати у Cosmos |
| CarId | int | з шляху, має існувати у MSSQL |
| PurchaseDate | DateTime | 2000-01-01..2100-01-01 |
| Price | decimal | 0.01..10 000 000 |
| Notes | string? | до 500 символів |
| CreatedAt | DateTime | сервер, UTC |
api/v1/cars
| Метод | Шлях | Відповідь |
|---|---|---|
| GET | /{id} |
200 / 404 |
| GET | / |
200 |
| POST | / |
201 |
| PUT | /{id} |
200 / 404 |
| DELETE | /{id} |
204 / 404 |
api/v1/customers
| Метод | Шлях | Відповідь |
|---|---|---|
| GET | /{id:guid} |
200 / 404 |
| GET | / |
200 |
| POST | / |
201 |
| PUT | /{id:guid} |
200 / 404 |
| DELETE | /{id:guid} |
204 / 404 |
api/v1/purchases
| Метод | Шлях | Відповідь |
|---|---|---|
| GET | /{customerId:guid}/cars/{carId:int} |
200 / 404 |
| GET | /{customerId:guid}/cars |
200 / 404 |
| POST | /{customerId:guid}/cars/{carId:int} |
201 / 400 / 404 / 409 |
| PUT | /{customerId:guid}/cars/{carId:int} |
200 / 400 / 404 |
| DELETE | /{customerId:guid}/cars/{carId:int} |
204 / 404 |
api/v1/stats (phase 4)
| Метод | Шлях | Відповідь |
|---|---|---|
| GET | / |
200 |
Відповідь — мапа entityType -> { created, updated } за час роботи сервісу. POST/PUT на будь-яку сутність публікують подію у топік entity-events; підписник у API обробляє повідомлення і інкрементує лічильники в пам'яті. Брокер — Azure Service Bus, локально через emulator у docker-compose.yml.
Через Docker Compose (MSSQL + Azurite + Service Bus emulator у контейнерах; Cosmos потребує локального Emulator):
docker compose up --build -dSwagger UI — http://localhost:8080/swagger.
Зупинка:
docker compose down -vЛокально (інфраструктура у контейнерах + Cosmos Emulator + API локально):
docker compose up -d db azurite sqledge servicebus-emulator
# Запустити Azure Cosmos DB Emulator (Windows): з меню Пуск або
# & "$env:ProgramFiles\Azure Cosmos DB Emulator\CosmosDB.Emulator.exe"
dotnet run --project CarSalon.Api/CarSalon.Api.csprojCosmos endpoint за замовчуванням — https://localhost:8081/, у appsettings.Development.json уже прописаний публічний ключ емулятора.
dotnet test CarSalon.slnUT та IT не потребують ні MSSQL, ні Cosmos Emulator, ні Azurite, ні Service Bus: phase 1 використовує EF Core InMemory, phase 2 — in-memory fake-репозиторій для Cosmos, phase 3 — in-memory fake IBlobStorage, phase 4 — in-memory fake IEventPublisher.