Initial commit of edr-passenger-api alpha version

This commit is contained in:
Stephanos A
2026-05-13 16:58:49 +03:00
parent 199a3eba11
commit 39ba561d8f
113 changed files with 3602 additions and 1035 deletions

View File

@@ -0,0 +1,15 @@
import { Body, Controller, Get, Param, Post, UseGuards } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
import { SupportService } from './support.service';
import { JwtGuard } from '../../common/jwt.guard';
@ApiTags('Support')
@Controller('support')
export class SupportController {
constructor(private service: SupportService) {}
@Get('faq') @ApiOperation({ summary: 'Get FAQ categories' }) getFaqCategories() { return this.service.getFaqCategories(); }
@Get('faq/:categoryId/articles') @ApiOperation({ summary: 'Get FAQ articles for a category' }) getFaqArticles(@Param('categoryId') id: string) { return this.service.getFaqArticles(id); }
@Post('conversations') @UseGuards(JwtGuard) @ApiBearerAuth('JWT-auth') @ApiOperation({ summary: 'Start a support conversation' }) startConversation(@Body('userId') userId: string) { return this.service.startConversation(userId); }
@Post('conversations/:id/messages') @UseGuards(JwtGuard) @ApiBearerAuth('JWT-auth') @ApiOperation({ summary: 'Send a message in a conversation' }) sendMessage(@Param('id') id: string, @Body() body: { sender: 'USER' | 'BOT' | 'AGENT'; text: string }) { return this.service.sendMessage(id, body.sender, body.text); }
@Get('conversations/:id') @UseGuards(JwtGuard) @ApiBearerAuth('JWT-auth') @ApiOperation({ summary: 'Get conversation with messages' }) getConversation(@Param('id') id: string) { return this.service.getConversation(id); }
}

View File

@@ -0,0 +1,6 @@
import { Module } from '@nestjs/common';
import { SupportController } from './support.controller';
import { SupportService } from './support.service';
@Module({ controllers: [SupportController], providers: [SupportService] })
export class SupportModule {}

View File

@@ -0,0 +1,35 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import { PrismaService } from '../../common/prisma.service';
@Injectable()
export class SupportService {
constructor(private prisma: PrismaService) {}
getFaqCategories() { return this.prisma.faqCategory.findMany({ include: { _count: { select: { articles: true } } } }); }
getFaqArticles(categoryId: string) { return this.prisma.faqArticle.findMany({ where: { categoryId }, orderBy: { rank: 'asc' } }); }
startConversation(userId: string) { return this.prisma.supportConversation.create({ data: { userId } }); }
async sendMessage(conversationId: string, sender: 'USER' | 'BOT' | 'AGENT', text: string) {
const conv = await this.prisma.supportConversation.findUnique({ where: { id: conversationId } });
if (!conv) throw new NotFoundException('Conversation not found');
const message = await this.prisma.supportMessage.create({ data: { conversationId, sender, text } });
if (sender === 'USER') await this.prisma.supportMessage.create({ data: { conversationId, sender: 'BOT', text: this.getBotReply(text) } });
return message;
}
async getConversation(conversationId: string) {
const conv = await this.prisma.supportConversation.findUnique({ where: { id: conversationId }, include: { messages: { orderBy: { createdAt: 'asc' } } } });
if (!conv) throw new NotFoundException('Conversation not found');
return conv;
}
private getBotReply(text: string): string {
const lower = text.toLowerCase();
if (lower.includes('cancel') || lower.includes('refund')) return 'To cancel or refund, go to My Bookings and select the booking. Refunds are processed within 3-5 business days.';
if (lower.includes('miss') || lower.includes('missed')) return 'If you missed your train, please check the Disruptions section for alternative options.';
if (lower.includes('seat')) return 'You can select or change seats during booking. Seat changes after confirmation may incur a fee.';
return 'Thank you for contacting EDR support. An agent will assist you shortly.';
}
}