Merge pull request #611 from Tria-plc/alpha

Alpha
This commit is contained in:
Stephanos A.
2026-07-11 00:56:45 +03:00
committed by GitHub
17 changed files with 79 additions and 29 deletions

View File

@@ -3,6 +3,7 @@ import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
import { AgentsService } from './agents.service';
import { CreateAgentDto, CreateAgentBookingDto, OpenShiftDto, CloseShiftDto } from './agents.dto';
import { JwtGuard as IamJwtGuard } from '@tria-plc/api-common/modules/auth/services/jwt.guard';
import { PassengerAdmin } from '../../common/passenger-guards';
@ApiTags('Agents')
@Controller('agents')
@@ -36,6 +37,8 @@ export class AgentsController {
}
@Delete(':id')
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'Delete agent profile' })
deleteAgent(@Param('id') id: string) {
return this.service.deleteAgent(id);

View File

@@ -7,6 +7,7 @@ import { GuestBookingService } from './guest-booking.service';
import { CreateBookingDto, ModifyBookingDto, CancelBookingDto } from './bookings.dto';
import { CreateGuestBookingDto, GetSavedPassengersDto } from './guest-booking.dto';
import { JwtGuard } from '../../common/jwt.guard';
import { PassengerAdmin } from '../../common/passenger-guards';
@ApiTags('Booking')
@Controller('bookings')
@@ -466,7 +467,8 @@ export class BookingsController {
}
@Delete(':id')
@SetMetadata('isPublic', true)
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({
description: 'Permanently deletes a booking record'
})

View File

@@ -1,5 +1,5 @@
import { Controller, Get, Post, Patch, Delete, Body, Param, HttpCode } from '@nestjs/common';
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
import { Body, Controller, Delete, Get, HttpCode, Param, Patch, Post, UseGuards } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
import { CurrenciesService } from './currencies.service';
import { CreateCurrencyDto, UpdateCurrencyDto } from './currencies.dto';
import { PassengerAdmin, PassengerStaff } from '../../common/passenger-guards';
@@ -31,7 +31,7 @@ export class CurrenciesController {
}
@Delete(':id')
@PassengerStaff(PASSENGER_PERMS.currencies.manage)
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
deleteCurrency(@Param('id') id: string) {
return this.currenciesService.deleteCurrency(id);

View File

@@ -8,6 +8,7 @@ import {
InitiateExcessPaymentDto,
} from './excess-baggage.dto';
import { JwtGuard as IamJwtGuard } from '@tria-plc/api-common/modules/auth/services/jwt.guard';
import { PassengerAdmin } from '../../common/passenger-guards';
class UpsertBaggageAllowanceDto {
@IsString() seatClassId: string;
@@ -70,6 +71,8 @@ export class ExcessBaggageAgentController {
}
@Delete('allowances/:id')
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'Delete baggage allowance rule' })
deleteAllowance(@Param('id') id: string) {
return this.service.deleteAllowance(id);
@@ -94,6 +97,8 @@ export class ExcessBaggageAgentController {
}
@Delete(':id')
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'Delete excess baggage charge (admin only)' })
deleteCharge(@Param('id') id: string) {
return this.service.deleteCharge(id);

View File

@@ -1,9 +1,10 @@
import { Body, Controller, Delete, Get, Param, Patch, Put, Post } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiParam, ApiProperty, ApiResponse } from '@nestjs/swagger';
import { ApiTags, ApiOperation, ApiParam, ApiProperty, ApiResponse, ApiBearerAuth } from '@nestjs/swagger';
import { CurrencyService } from '../currency/currency.service';
import { UpsertExchangeRateDto } from './currency.dto';
import { IsNumber, IsPositive, IsOptional, IsString } from 'class-validator';
import { Type } from 'class-transformer';
import { PassengerAdmin } from '../../common/passenger-guards';
class UpdateExchangeRateDto {
@ApiProperty({ example: 3.5 }) @Type(() => Number) @IsNumber() @IsPositive() rate: number;
@@ -38,6 +39,8 @@ export class CurrencyController {
}
@Delete(':id')
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'Delete an exchange rate record by ID' })
@ApiParam({ name: 'id', description: 'CurrencyExchangeRate UUID' })
@ApiResponse({ status: 200, description: 'Rate deleted' })

View File

@@ -3,6 +3,7 @@ import { ApiTags, ApiOperation, ApiBearerAuth, ApiParam, ApiQuery, ApiBody, ApiR
import { FleetService } from './fleet.service';
import { CreateTrainDto, CreateCoachDto, UpdateCoachDto, AssignCoachDto, ListCoachesDto, CreateCoachTypeDto, UpdateCoachTypeDto, CreateClassDto, UpdateClassDto, GenerateSeatMapDto } from './fleet.dto';
import { JwtGuard } from '../../common/jwt.guard';
import { PassengerAdmin } from '../../common/passenger-guards';
@ApiTags('Fleet')
@Controller('fleet')
@@ -38,6 +39,8 @@ export class FleetController {
}
@Delete('coach-types/:id')
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'Delete a coach type' })
@ApiParam({ name: 'id', description: 'Coach Type UUID' })
@ApiResponse({ status: 200, description: 'Coach type deleted' })
@@ -74,6 +77,8 @@ export class FleetController {
}
@Delete('classes/:id')
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'Delete a class' })
@ApiParam({ name: 'id', description: 'Class UUID' })
@ApiQuery({ name: 'cascade', required: false, type: Boolean, description: 'Force delete with all related data' })
@@ -111,6 +116,8 @@ export class FleetController {
}
@Delete('seat-classes/:id')
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'Delete a class (DEPRECATED - use /fleet/classes)' })
@ApiParam({ name: 'id', description: 'Class UUID' })
@ApiQuery({ name: 'cascade', required: false, type: Boolean, description: 'Force delete with all related data' })
@@ -147,6 +154,8 @@ export class FleetController {
}
@Delete('trains/:id')
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'Delete a train service' })
@ApiParam({ name: 'id', description: 'Train UUID' })
@ApiQuery({ name: 'cascade', required: false, type: Boolean, description: 'Force delete with all related data' })
@@ -310,6 +319,8 @@ export class FleetController {
}
@Delete('coaches/:id')
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'Delete a coach' })
@ApiParam({ name: 'id', description: 'Coach UUID' })
@ApiQuery({ name: 'cascade', required: false, type: Boolean, description: 'Force delete with all related data' })
@@ -329,6 +340,8 @@ export class FleetController {
}
@Delete('assignments/:id')
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'Remove a coach assignment' })
@ApiParam({ name: 'id', description: 'Assignment UUID' })
@ApiResponse({ status: 200, description: 'Assignment removed' })

View File

@@ -6,6 +6,7 @@ import { CreatePackageDto, BookPackageDto, CreatePriceTierDto, UpdatePriceTierDt
import { IamGuard } from '../../common/iam-adapter';
import { JwtGuard } from '../../common/jwt.guard';
import { OptionalJwtGuard } from '../verifayda/optional-jwt.guard';
import { PassengerAdmin } from '../../common/passenger-guards';
@ApiTags('Packages')
@Controller('packages')
@@ -41,7 +42,7 @@ export class PackagesController {
}
@Delete('inquiries/:id')
@UseGuards(IamGuard)
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'Delete inquiry (backoffice)' })
deleteInquiry(@Param('id') id: string) {
@@ -139,7 +140,7 @@ export class PackagesController {
}
@Delete(':id')
@UseGuards(IamGuard)
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'Delete package (admin)' })
@ApiQuery({ name: 'cascade', required: false, type: Boolean, description: 'Force delete even with active bookings' })
@@ -180,7 +181,7 @@ export class PackagesController {
}
@Delete('tiers/:tierId')
@UseGuards(IamGuard)
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'Delete price tier (admin)' })
deleteTier(@Param('tierId') tierId: string) {

View File

@@ -4,6 +4,7 @@ import { SkipThrottle, Throttle } from '@nestjs/throttler';
import { PassengersService } from './passengers.service';
import { CreateTravelerProfileDto, CreateSavedRouteDto, VerifyFaydaDto, SavePassengersDto, RegisterPassengerDto } from './passengers.dto';
import { JwtGuard } from '../../common/jwt.guard';
import { PassengerAdmin } from '../../common/passenger-guards';
import { VerifaydaService } from '../verifayda/verifayda.service';
import { OptionalJwtGuard } from '../verifayda/optional-jwt.guard';
import { PrismaService } from '../../common/prisma.service';
@@ -503,7 +504,8 @@ Returns saved passenger details with generated IDs and confirmation.`,
}
@Delete(':id')
@SetMetadata('isPublic', true)
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({
summary: 'Delete passenger (admin only)',
description: 'Permanently deletes a passenger record and associated data'

View File

@@ -3,6 +3,7 @@ import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
import { PromosService } from './promos.service';
import { CreatePromotionDto } from './promos.dto';
import { JwtGuard } from '../../common/jwt.guard';
import { PassengerAdmin } from '../../common/passenger-guards';
@ApiTags('Promotions')
@Controller('promos')
@@ -64,8 +65,8 @@ export class PromosController {
}
@Delete(':id')
@UseGuards(JwtGuard)
@ApiBearerAuth('JWT-auth')
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'Delete promo (admin)' })
delete(@Param('id') id: string) {
return this.service.delete(id);

View File

@@ -3,6 +3,7 @@ import { ApiTags, ApiOperation, ApiBearerAuth, ApiParam, ApiQuery, ApiResponse }
import { RoutesService } from './routes.service';
import { CreateRouteDto, AddRouteStopDto, UpdateRouteDto, SetRouteCoachTemplateDto } from './routes.dto';
import { JwtGuard } from '../../common/jwt.guard';
import { PassengerAdmin } from '../../common/passenger-guards';
@ApiTags('Routes')
@Controller('routes')
@@ -48,7 +49,8 @@ Route stops carry distanceKm for fare-by-distance calculations.`,
updateRoute(@Param('id') id: string, @Body() dto: UpdateRouteDto) { return this.service.updateRoute(id, dto); }
@Delete(':id')
@UseGuards(JwtGuard) @ApiBearerAuth('JWT-auth')
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'Delete a route' })
@ApiParam({ name: 'id', description: 'Route UUID' })
@ApiQuery({ name: 'cascade', required: false, type: Boolean, description: 'Force delete with all related data' })
@@ -75,7 +77,8 @@ Route stops carry distanceKm for fare-by-distance calculations.`,
addStop(@Param('id') id: string, @Body() dto: AddRouteStopDto) { return this.service.addStop(id, dto); }
@Delete(':id/stops/:sequence')
@UseGuards(JwtGuard) @ApiBearerAuth('JWT-auth')
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'Remove a stop from a route by sequence number' })
@ApiParam({ name: 'id', description: 'Route UUID' })
@ApiParam({ name: 'sequence', description: 'Stop sequence number to remove' })
@@ -119,7 +122,8 @@ Route stops carry distanceKm for fare-by-distance calculations.`,
}
@Delete(':id/coaches')
@UseGuards(JwtGuard) @ApiBearerAuth('JWT-auth')
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'Clear the default coach lineup for this route' })
@ApiParam({ name: 'id', description: 'Route UUID' })
@ApiResponse({ status: 200, description: 'Template cleared' })

View File

@@ -4,6 +4,7 @@ import { IsPublic } from '@tria-plc/api-common/modules/auth/decorators/public.de
import { SchedulesService } from './schedules.service';
import { CreateScheduleDto, UpdateScheduleDto, CreateFareRuleDto, UpdateScheduleStatusDto, UpdateStopTimeDto, ListSchedulesDto, BulkCreateSchedulesDto, BulkSchedulesResponseDto, TripStatus } from './schedules.dto';
import { JwtGuard } from '../../common/jwt.guard';
import { PassengerAdmin } from '../../common/passenger-guards';
@ApiTags('Schedule')
@Controller('schedules')
@@ -56,7 +57,8 @@ export class SchedulesController {
}
@Delete('fares/:id')
@UseGuards(JwtGuard) @ApiBearerAuth('JWT-auth')
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'Delete a fare rule' })
@ApiParam({ name: 'id', description: 'FareRule UUID' })
@ApiResponse({ status: 200, description: 'Fare rule deleted' })
@@ -80,7 +82,8 @@ export class SchedulesController {
updateSegmentFareRule(@Param('id') id: string, @Body() dto: any) { return this.service.updateSegmentFareRule(id, dto); }
@Delete('segment-fares/:id')
@UseGuards(JwtGuard) @ApiBearerAuth('JWT-auth')
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'Delete a segment fare rule' })
@ApiParam({ name: 'id', description: 'SegmentFareRule UUID' })
deleteSegmentFareRule(@Param('id') id: string) { return this.service.deleteSegmentFareRule(id); }
@@ -110,7 +113,8 @@ export class SchedulesController {
}
@Delete(':id')
@UseGuards(JwtGuard) @ApiBearerAuth('JWT-auth')
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'Delete a schedule' })
@ApiParam({ name: 'id', description: 'TrainSchedule UUID' })
@ApiQuery({ name: 'cascade', required: false, type: Boolean })
@@ -203,7 +207,8 @@ export class SchedulesController {
getAssignedCoaches(@Param('id') id: string) { return this.service.getAssignedCoaches(id); }
@Delete(':id/coaches/:coachId')
@UseGuards(JwtGuard) @ApiBearerAuth('JWT-auth')
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'Remove a coach assignment' })
@ApiParam({ name: 'id', description: 'TrainSchedule UUID' })
@ApiParam({ name: 'coachId', description: 'Coach UUID' })

View File

@@ -4,6 +4,7 @@ import { IsPublic } from '@tria-plc/api-common/modules/auth/decorators/public.de
import { SeatClassesService } from './seat-classes.service';
import { CreateSeatClassDto, UpdateSeatClassDto } from './seat-classes.dto';
import { JwtGuard } from '../../common/jwt.guard';
import { PassengerAdmin } from '../../common/passenger-guards';
@ApiTags('Seat Classes')
@Controller('seat-classes')
@@ -42,7 +43,8 @@ export class SeatClassesController {
updateSeatClass(@Param('id') id: string, @Body() dto: UpdateSeatClassDto) { return this.service.updateSeatClass(id, dto); }
@Delete(':id')
@UseGuards(JwtGuard) @ApiBearerAuth('JWT-auth')
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'Delete a seat class' })
@ApiParam({ name: 'id', description: 'Seat class UUID' })
@ApiResponse({ status: 200, description: 'Seat class deleted' })

View File

@@ -29,6 +29,11 @@ export class CreateSeatClassDto {
@IsInt()
basePrice: number;
@ApiPropertyOptional({ example: 1200, description: 'Flat insurance fee in minor units' })
@IsOptional()
@IsInt()
insuranceFeeMinor?: number;
@ApiPropertyOptional({ example: true })
@IsOptional()
@IsBoolean()

View File

@@ -4,6 +4,7 @@ import { IsPublic } from '@tria-plc/api-common/modules/auth/decorators/public.de
import { StationsService } from './stations.service';
import { CreateStationDto } from './stations.dto';
import { JwtGuard } from '../../common/jwt.guard';
import { PassengerAdmin } from '../../common/passenger-guards';
@ApiTags('Stations')
@Controller('stations')
@@ -133,8 +134,8 @@ export class StationsController {
}
@Delete(':id')
@UseGuards(JwtGuard)
@ApiBearerAuth('JWT-auth')
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'Delete station' })
@ApiQuery({ name: 'cascade', required: false, type: Boolean, description: 'Force delete with all related data' })
@ApiResponse({ status: 200, description: 'Station deleted successfully' })

View File

@@ -2,6 +2,7 @@ import { Body, Controller, Get, Param, Post, Query, UseGuards, Delete, Patch, Se
import { ApiTags, ApiOperation, ApiBearerAuth, ApiBody, ApiQuery } from '@nestjs/swagger';
import { TicketsService } from './tickets.service';
import { JwtGuard } from '../../common/jwt.guard';
import { PassengerAdmin } from '../../common/passenger-guards';
@ApiTags('Tickets')
@Controller('tickets')
@@ -9,7 +10,8 @@ export class TicketsController {
constructor(private service: TicketsService) {}
@Post('generate/:bookingId')
@SetMetadata('isPublic', true)
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({
summary: 'Generate ticket for booking (confirmation page)',
description: 'Creates a ticket when confirmation page is reached and permanently holds all associated seats with SeatBlock records.'

View File

@@ -406,6 +406,7 @@ export default function TariffRatesPage() {
name="insuranceFeeMinor"
className="input"
defaultValue={editingClass ? (editingClass.insuranceFeeMinor / 100).toFixed(2) : '0.00'}
key={editingClass?.id ?? 'new-insurance'}
min="0"
step="0.01"
placeholder="e.g. 25.00"

View File

@@ -90,21 +90,21 @@ const navigationSections: { title: string; items: NavItem[] }[] = [
{
title: 'Financial',
items: [
{ name: 'Pricing & Fares', href: '/pricing', icon: DollarSign, permission: PERMS.admin },
// { name: 'Pricing & Fares', href: '/pricing', icon: DollarSign, permission: PERMS.admin },
{ name: 'Tariff Rates', href: '/tariff-rates', icon: Banknote, permission: PERMS.admin },
{ name: 'Fare Rules', href: '/fare-management', icon: Settings, permission: PERMS.admin },
// { name: 'Fare Rules', href: '/fare-management', icon: Settings, permission: PERMS.admin },
{ name: 'Payments', href: '/payments', icon: CreditCard, permission: PERMS.payments.view },
{ name: 'Currencies', href: '/currencies', icon: Banknote, permission: PERMS.currencies.manage },
{ name: 'Promo Codes', href: '/promos', icon: Gift, permission: PERMS.admin },
// { name: 'Promo Codes', href: '/promos', icon: Gift, permission: PERMS.admin },
{ name: 'Payment Methods', href: '/payment-methods', icon: CreditCard, permission: PERMS.payments.view },
{ name: 'Wallet Accounts', href: '/wallet-accounts', icon: Wallet, permission: PERMS.payments.view },
// { name: 'Wallet Accounts', href: '/wallet-accounts', icon: Wallet, permission: PERMS.payments.view },
]
},
{
title: 'Customer Services',
items: [
{ name: 'Loyalty Program', href: '/loyalty', icon: Gift, permission: PERMS.passengers.view },
{ name: 'Support Center', href: '/support', icon: MessageSquare, permission: PERMS.bookings.view },
// { name: 'Loyalty Program', href: '/loyalty', icon: Gift, permission: PERMS.passengers.view },
// { name: 'Support Center', href: '/support', icon: MessageSquare, permission: PERMS.bookings.view },
{ name: 'Notifications', href: '/notifications', icon: Bell, permission: PERMS.notifications.send },
]
},
@@ -126,7 +126,7 @@ const navigationSections: { title: string; items: NavItem[] }[] = [
{
title: 'System',
items: [
{ name: 'Agents', href: '/agents', icon: Briefcase, permission: PERMS.agents.view },
// { name: 'Agents', href: '/agents', icon: Briefcase, permission: PERMS.agents.view },
{ name: 'Users', href: '/settings/users', icon: Users, permission: PERMS.admin },
{ name: 'Settings', href: '/settings', icon: Settings, permission: PERMS.admin },
{ name: 'Health', href: '/health', icon: Activity, permission: PERMS.admin },