REST API для управления промокодами и их активацией с фокусом на целостность данных в PostgreSQL.
- Node.js + TypeScript
- Fastify
- Prisma ORM
- PostgreSQL
- Vitest
- CRUD (реализовано: create, get by id, list) для промокодов
- Активация промокода по email
- Email может активировать конкретный промокод только один раз
- Защита от активации сверх лимита
- Проверка срока действия промокода
Код разделен по модулям:
src/modules/promo- все, что относится к домену промокодов (типы, сервис, репозиторий, роуты, JSON Schema)src/shared- общие зависимости (например, Prisma client)
На уровне БД:
UNIQUE (promo_codes.code)UNIQUE (promo_activations.promo_code_id, promo_activations.email)CHECK (discount_percent BETWEEN 1 AND 100)CHECK (activation_limit > 0)CHECK (activated_count >= 0)
На уровне бизнес-логики:
- Активация выполняется в
prisma.$transaction(...) - Используется
SELECT ... FOR UPDATEдля блокировки строки промокода и защиты от race condition - После успешной записи активации счетчик
activated_countинкрементируется внутри той же транзакции
npm installdocker compose up -dПроверить статус:
docker compose pscp .env.example .envnpm run prisma:migrate
npm run prisma:generatenpm run devdocker compose downnpm testPOST /promo-codes
{
"code": "SPRING15",
"discountPercent": 15,
"activationLimit": 100,
"expiresAt": "2026-12-31T23:59:59.000Z"
}GET /promo-codes/:id
GET /promo-codes?limit=20&offset=0
POST /promo-codes/:code/activate
{
"email": "user@example.com"
}201- создано / активировано200- успешный запрос404- промокод не найден409- лимит исчерпан или email уже активировал код410- промокод истек400- ошибка валидации