fix: reviews — correct pending/archive logic, rejected_at field, stats, reply email
- Migration 085: add rejected_at to reviews - pending = !isPublic && !reply && !rejectedAt - archived = isPublic || reply || rejectedAt - Stats: avgRating/NPS from all reviews; 'В архиве' = archived count - sendReply: no longer sets isPublic=true on negative reviews - reject: sets rejected_at=NOW() (distinct from pending) - restore: clears rejected_at (now actually works) - Badge 'Отклонён' for rejected reviews, opacity-60 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2
backend/migrations/085_reviews_rejected.sql
Normal file
2
backend/migrations/085_reviews_rejected.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
-- Migration 085 — add rejected_at to reviews for explicit rejected state
|
||||
ALTER TABLE reviews ADD COLUMN IF NOT EXISTS rejected_at TIMESTAMPTZ;
|
||||
@@ -37,7 +37,7 @@ const reviewsRoutes: FastifyPluginAsync = async (fastify) => {
|
||||
|
||||
const { rows } = await db.query(
|
||||
`SELECT r.id, r.booking_id, r.guest_id, r.guest_name, r.source,
|
||||
r.rating, r.text, r.reply, r.replied_at, r.is_public,
|
||||
r.rating, r.text, r.reply, r.replied_at, r.is_public, r.rejected_at,
|
||||
r.created_at, r.updated_at,
|
||||
b.room_id,
|
||||
rm.number AS room_number,
|
||||
@@ -54,7 +54,7 @@ const reviewsRoutes: FastifyPluginAsync = async (fastify) => {
|
||||
)
|
||||
|
||||
// ── PATCH /api/hotels/:slug/reviews/:id ───────────────────────────────────
|
||||
fastify.patch<SlugIdParam & { Body: { reply?: string; isPublic?: boolean } }>(
|
||||
fastify.patch<SlugIdParam & { Body: { reply?: string; isPublic?: boolean; rejected?: boolean } }>(
|
||||
'/api/hotels/:slug/reviews/:id',
|
||||
{ onRequest: [fastify.authenticate] },
|
||||
async (request, reply) => {
|
||||
@@ -65,7 +65,7 @@ const reviewsRoutes: FastifyPluginAsync = async (fastify) => {
|
||||
const hotelId = await getHotelId(slug)
|
||||
if (!hotelId) return reply.code(404).send({ error: 'Hotel not found' })
|
||||
|
||||
const { reply: replyText, isPublic } = request.body
|
||||
const { reply: replyText, isPublic, rejected } = request.body
|
||||
const updates: string[] = []
|
||||
const vals: unknown[] = [id, hotelId]
|
||||
|
||||
@@ -77,6 +77,9 @@ const reviewsRoutes: FastifyPluginAsync = async (fastify) => {
|
||||
vals.push(isPublic)
|
||||
updates.push(`is_public = $${vals.length}`)
|
||||
}
|
||||
if (rejected === true) updates.push(`rejected_at = NOW()`)
|
||||
if (rejected === false) updates.push(`rejected_at = NULL`)
|
||||
|
||||
if (updates.length === 0) return reply.code(400).send({ error: 'Nothing to update' })
|
||||
|
||||
const { rows } = await db.query(
|
||||
|
||||
Reference in New Issue
Block a user