Shumiland/src/app/api/tickets/tariffs/route.ts
Vadym Samoilenko 9b41fa447a
Some checks are pending
CI / Type Check (push) Waiting to run
CI / Lint (push) Waiting to run
CI / Unit Tests (push) Waiting to run
Deploy / Build & Push Image (push) Waiting to run
Deploy / Deploy to VPS (push) Blocked by required conditions
feat: complete backend B1-B7 — Payload CMS, ezy payments, leads, deploy
- B1: Next.js 15 + Payload CMS 3.0 + Postgres 16, ESLint, Prettier, Husky, Vitest
- B2: 9 collections, 6 globals, 12 Page Builder blocks, access control, slugify/revalidate hooks
- B3: ezy.com.ua payments, Binotel HMAC webhook, leads API, Telegram bot, Resend email, rate limiting
- B4: Tariffs collection with ezy API sync (cron + manual), dynamic pricing source-of-truth
- B5: 13 test files covering unit libs and all API routes
- B6: Dockerfile multi-stage, docker-compose.prod.yml, nginx.conf SSL, GitHub Actions CI/CD, health endpoint
- B7: docs/admin-guide-ua.md (marketer guide), docs/deploy.md (VPS instructions), README quickstart

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-09 19:14:54 +01:00

76 lines
2.3 KiB
TypeScript

import { NextResponse } from 'next/server'
import { getPayload } from 'payload'
import config from '@payload-config'
import { getTariffs } from '@/lib/ezy'
import { logger } from '@/lib/logger'
export const dynamic = 'force-dynamic'
export async function GET(): Promise<NextResponse> {
try {
const ezyTariffs = await getTariffs()
const payload = await getPayload({ config })
const { docs: dbTariffs } = await payload.find({
collection: 'tariffs',
where: { visible: { equals: true } },
limit: 100,
overrideAccess: true,
})
const merged = ezyTariffs
.map((t) => {
const dbRecord = dbTariffs.find((d) => d.ezy_id === t.id)
if (!dbRecord) return null
return {
id: t.id,
name: dbRecord.display_name ?? t.name,
price: t.price,
categoryTag: dbRecord.category_tag,
description: dbRecord.description,
image: dbRecord.image,
icon: dbRecord.icon,
sort: dbRecord.sort ?? 0,
}
})
.filter(<T>(v: T | null): v is T => v !== null)
.sort((a, b) => a.sort - b.sort)
return NextResponse.json({ tariffs: merged })
} catch (err) {
logger.error({ err }, 'Failed to get tariffs from ezy — trying DB fallback')
try {
const payload = await getPayload({ config })
const { docs } = await payload.find({
collection: 'tariffs',
where: { visible: { equals: true } },
limit: 100,
overrideAccess: true,
})
if (docs.length === 0) {
return NextResponse.json({ error: 'Tariffs unavailable' }, { status: 503 })
}
const fallback = docs
.map((d) => ({
id: d.ezy_id,
name: d.display_name ?? d.last_synced_name,
price: d.last_synced_price,
categoryTag: d.category_tag,
description: d.description,
image: d.image,
icon: d.icon,
sort: d.sort ?? 0,
stale: true,
}))
.sort((a, b) => a.sort - b.sort)
return NextResponse.json({ tariffs: fallback, warning: 'Prices may be outdated' })
} catch (dbErr) {
logger.error({ dbErr }, 'DB fallback also failed')
return NextResponse.json({ error: 'Service unavailable' }, { status: 503 })
}
}
}