mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 22:18:12 +00:00
Refactor business logic for train,schedule,coach,seat and search modules
This commit is contained in:
@@ -21,110 +21,44 @@ describe('Payments E2E', () => {
|
||||
|
||||
prisma = app.get<PrismaService>(PrismaService);
|
||||
|
||||
// Create test user and authenticate
|
||||
const testUser = await prisma.user.create({
|
||||
data: {
|
||||
email: 'payment-test@example.com',
|
||||
phone: '+251911111111',
|
||||
fullName: 'Payment Test User',
|
||||
passwordHash: '$2b$10$abcdefghijklmnopqrstuvwxyz', // Mock hash
|
||||
role: 'PASSENGER',
|
||||
},
|
||||
data: { email: 'payment-test@example.com', phone: '+251911111112', fullName: 'Payment Test User', passwordHash: '$2b$10$abcdefghijklmnopqrstuvwxyz', role: 'PASSENGER' },
|
||||
});
|
||||
|
||||
const passenger = await prisma.passenger.create({
|
||||
data: {
|
||||
userId: testUser.id,
|
||||
},
|
||||
});
|
||||
const passenger = await prisma.passenger.create({ data: { userId: testUser.id } });
|
||||
|
||||
// Create wallet for test user
|
||||
await prisma.walletAccount.create({
|
||||
data: {
|
||||
passengerId: passenger.id,
|
||||
balanceMinor: 100000, // 1000 ETB
|
||||
currency: 'ETB',
|
||||
},
|
||||
});
|
||||
await prisma.walletAccount.create({ data: { passengerId: passenger.id, balanceMinor: 100000, currency: 'ETB' } });
|
||||
|
||||
// Mock JWT token (in real test, call /auth/login)
|
||||
authToken = 'mock-jwt-token';
|
||||
|
||||
// Create test booking
|
||||
const station1 = await prisma.station.create({
|
||||
data: {
|
||||
code: 'TEST1',
|
||||
name: 'Test Station 1',
|
||||
city: 'Test City',
|
||||
lat: 9.0,
|
||||
lng: 38.0,
|
||||
},
|
||||
const station1 = await prisma.station.create({ data: { code: 'TST1', name: 'Test Station 1', city: 'Test City', lat: 9.0, lng: 38.0 } });
|
||||
const station2 = await prisma.station.create({ data: { code: 'TST2', name: 'Test Station 2', city: 'Test City 2', lat: 9.5, lng: 38.5 } });
|
||||
|
||||
const train = await prisma.train.create({ data: { number: 'TEST-001', name: 'Test Train' } });
|
||||
|
||||
const schedule = await prisma.trainSchedule.create({
|
||||
data: { trainId: train.id, originStationId: station1.id, destinationStationId: station2.id, departureAt: new Date(Date.now() + 86400000), arrivalAt: new Date(Date.now() + 90000000), durationMinutes: 60 },
|
||||
});
|
||||
|
||||
const station2 = await prisma.station.create({
|
||||
data: {
|
||||
code: 'TEST2',
|
||||
name: 'Test Station 2',
|
||||
city: 'Test City 2',
|
||||
lat: 9.5,
|
||||
lng: 38.5,
|
||||
},
|
||||
});
|
||||
|
||||
const service = await prisma.trainService.create({
|
||||
data: {
|
||||
number: 'TEST-001',
|
||||
name: 'Test Service',
|
||||
},
|
||||
});
|
||||
|
||||
const trip = await prisma.trip.create({
|
||||
data: {
|
||||
serviceId: service.id,
|
||||
originStationId: station1.id,
|
||||
destinationStationId: station2.id,
|
||||
departureAt: new Date(Date.now() + 86400000),
|
||||
arrivalAt: new Date(Date.now() + 90000000),
|
||||
durationMinutes: 60,
|
||||
},
|
||||
const seatClass = await prisma.seatClass.upsert({
|
||||
where: { name: 'Economy Regular' },
|
||||
update: {},
|
||||
create: { name: 'Economy Regular', description: 'Standard economy seating', basePrice: 45000, isActive: true },
|
||||
});
|
||||
|
||||
const coach = await prisma.coach.create({
|
||||
data: {
|
||||
tripId: trip.id,
|
||||
label: 'A',
|
||||
serviceClass: 'ECONOMY_REGULAR',
|
||||
},
|
||||
data: { coachNumber: 'TEST-C1', label: 'A', seatClassId: seatClass.id, mode: 'seat', totalUnits: 10 },
|
||||
});
|
||||
|
||||
const seat = await prisma.seat.create({
|
||||
data: {
|
||||
coachId: coach.id,
|
||||
row: 1,
|
||||
col: 'A',
|
||||
label: '1A',
|
||||
status: 'AVAILABLE',
|
||||
},
|
||||
});
|
||||
await prisma.coachAssignment.create({ data: { scheduleId: schedule.id, coachId: coach.id, positionNumber: 1 } });
|
||||
|
||||
const seat = await prisma.seat.create({ data: { coachId: coach.id, row: 1, col: 'A', label: '1A', status: 'AVAILABLE' } });
|
||||
|
||||
const booking = await prisma.booking.create({
|
||||
data: {
|
||||
bookingRef: 'TEST-BOOK-001',
|
||||
passengerId: passenger.id,
|
||||
tripId: trip.id,
|
||||
status: 'PENDING_PAYMENT',
|
||||
totalMinor: 50000, // 500 ETB
|
||||
currency: 'ETB',
|
||||
},
|
||||
data: { bookingRef: 'TEST-BOOK-001', passengerId: passenger.id, scheduleId: schedule.id, status: 'PENDING_PAYMENT', totalMinor: 50000, currency: 'ETB' },
|
||||
});
|
||||
|
||||
await prisma.bookingSeat.create({
|
||||
data: {
|
||||
bookingId: booking.id,
|
||||
seatId: seat.id,
|
||||
passengerName: 'Test Passenger',
|
||||
},
|
||||
});
|
||||
await prisma.bookingSeat.create({ data: { bookingId: booking.id, seatId: seat.id, passengerName: 'Test Passenger' } });
|
||||
|
||||
bookingId = booking.id;
|
||||
});
|
||||
@@ -134,15 +68,16 @@ describe('Payments E2E', () => {
|
||||
prisma.bookingSeat.deleteMany(),
|
||||
prisma.paymentIntent.deleteMany(),
|
||||
prisma.booking.deleteMany(),
|
||||
prisma.coachAssignment.deleteMany(),
|
||||
prisma.seat.deleteMany(),
|
||||
prisma.coach.deleteMany(),
|
||||
prisma.trip.deleteMany(),
|
||||
prisma.trainService.deleteMany(),
|
||||
prisma.station.deleteMany(),
|
||||
prisma.trainSchedule.deleteMany(),
|
||||
prisma.train.deleteMany(),
|
||||
prisma.station.deleteMany({ where: { code: { in: ['TST1', 'TST2'] } } }),
|
||||
prisma.walletLedgerEntry.deleteMany(),
|
||||
prisma.walletAccount.deleteMany(),
|
||||
prisma.passenger.deleteMany(),
|
||||
prisma.user.deleteMany(),
|
||||
prisma.user.deleteMany({ where: { email: 'payment-test@example.com' } }),
|
||||
]);
|
||||
await app.close();
|
||||
});
|
||||
@@ -152,12 +87,8 @@ describe('Payments E2E', () => {
|
||||
const response = await request(app.getHttpServer())
|
||||
.post('/payments/initiate')
|
||||
.set('Authorization', `Bearer ${authToken}`)
|
||||
.send({
|
||||
bookingId,
|
||||
method: 'WALLET',
|
||||
})
|
||||
.send({ bookingId, method: 'WALLET' })
|
||||
.expect(201);
|
||||
|
||||
expect(response.body.intentId).toBeDefined();
|
||||
expect(response.body.status).toBe('SUCCEEDED');
|
||||
});
|
||||
@@ -166,10 +97,7 @@ describe('Payments E2E', () => {
|
||||
await request(app.getHttpServer())
|
||||
.post('/payments/initiate')
|
||||
.set('Authorization', `Bearer ${authToken}`)
|
||||
.send({
|
||||
bookingId,
|
||||
method: 'INVALID_METHOD',
|
||||
})
|
||||
.send({ bookingId, method: 'INVALID_METHOD' })
|
||||
.expect(400);
|
||||
});
|
||||
|
||||
@@ -177,10 +105,7 @@ describe('Payments E2E', () => {
|
||||
await request(app.getHttpServer())
|
||||
.post('/payments/initiate')
|
||||
.set('Authorization', `Bearer ${authToken}`)
|
||||
.send({
|
||||
bookingId: 'non-existent-id',
|
||||
method: 'WALLET',
|
||||
})
|
||||
.send({ bookingId: 'non-existent-id', method: 'WALLET' })
|
||||
.expect(404);
|
||||
});
|
||||
});
|
||||
@@ -191,7 +116,6 @@ describe('Payments E2E', () => {
|
||||
.get(`/payments/intents/${bookingId}`)
|
||||
.set('Authorization', `Bearer ${authToken}`)
|
||||
.expect(200);
|
||||
|
||||
expect(response.body.intentId).toBeDefined();
|
||||
expect(response.body.status).toBeDefined();
|
||||
});
|
||||
@@ -208,38 +132,21 @@ describe('Payments E2E', () => {
|
||||
it('should handle Telebirr webhook', async () => {
|
||||
await request(app.getHttpServer())
|
||||
.post('/payments/webhooks/telebirr')
|
||||
.send({
|
||||
merch_order_id: 'TEST-ORDER-123',
|
||||
payment_order_id: 'PAY-123',
|
||||
trade_status: 'Completed',
|
||||
sign: 'mock-signature',
|
||||
})
|
||||
.send({ merch_order_id: 'TEST-ORDER-123', payment_order_id: 'PAY-123', trade_status: 'Completed', sign: 'mock-signature' })
|
||||
.expect(200);
|
||||
});
|
||||
|
||||
it('should handle CBE Birr webhook', async () => {
|
||||
await request(app.getHttpServer())
|
||||
.post('/payments/webhooks/cbe-birr')
|
||||
.send({
|
||||
merchantId: 'TEST-MERCHANT',
|
||||
merchantOrderId: 'TEST-ORDER-123',
|
||||
orderId: 'CBE-ORDER-123',
|
||||
status: 'SUCCESS',
|
||||
signature: 'mock-signature',
|
||||
})
|
||||
.send({ merchantId: 'TEST-MERCHANT', merchantOrderId: 'TEST-ORDER-123', orderId: 'CBE-ORDER-123', status: 'SUCCESS', signature: 'mock-signature' })
|
||||
.expect(200);
|
||||
});
|
||||
|
||||
it('should handle eBirr webhook', async () => {
|
||||
await request(app.getHttpServer())
|
||||
.post('/payments/webhooks/ebirr')
|
||||
.send({
|
||||
merchantCode: 'TEST-MERCHANT',
|
||||
orderNo: 'TEST-ORDER-123',
|
||||
tradeStatus: 'TRADE_SUCCESS',
|
||||
timestamp: Date.now(),
|
||||
sign: 'mock-signature',
|
||||
})
|
||||
.send({ merchantCode: 'TEST-MERCHANT', orderNo: 'TEST-ORDER-123', tradeStatus: 'TRADE_SUCCESS', timestamp: Date.now(), sign: 'mock-signature' })
|
||||
.expect(200);
|
||||
});
|
||||
|
||||
@@ -247,23 +154,7 @@ describe('Payments E2E', () => {
|
||||
await request(app.getHttpServer())
|
||||
.post('/payments/webhooks/card')
|
||||
.set('stripe-signature', 'mock-signature')
|
||||
.send({
|
||||
id: 'evt_123',
|
||||
type: 'payment_intent.succeeded',
|
||||
data: {
|
||||
object: {
|
||||
id: 'pi_123',
|
||||
status: 'succeeded',
|
||||
amount: 50000,
|
||||
currency: 'ETB',
|
||||
metadata: {
|
||||
merchantOrderId: 'TEST-ORDER-123',
|
||||
bookingRef: 'TEST-BOOK-001',
|
||||
},
|
||||
},
|
||||
},
|
||||
created: Math.floor(Date.now() / 1000),
|
||||
})
|
||||
.send({ id: 'evt_123', type: 'payment_intent.succeeded', data: { object: { id: 'pi_123', status: 'succeeded', amount: 50000, currency: 'ETB', metadata: { merchantOrderId: 'TEST-ORDER-123', bookingRef: 'TEST-BOOK-001' } } }, created: Math.floor(Date.now() / 1000) })
|
||||
.expect(200);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -18,7 +18,7 @@ describe('PaymentsService', () => {
|
||||
let ticketsService: TicketsService;
|
||||
let eventEmitter: EventEmitter2;
|
||||
|
||||
const mockPrisma = {
|
||||
const mockPrisma: Record<string, any> = {
|
||||
booking: {
|
||||
findUnique: jest.fn(),
|
||||
update: jest.fn(),
|
||||
@@ -44,7 +44,7 @@ describe('PaymentsService', () => {
|
||||
loyaltyLedgerEntry: {
|
||||
create: jest.fn(),
|
||||
},
|
||||
$transaction: jest.fn((callback) => callback(mockPrisma)),
|
||||
$transaction: jest.fn((callback: (tx: any) => any) => callback(mockPrisma)),
|
||||
};
|
||||
|
||||
const mockSeatsService = {
|
||||
|
||||
Reference in New Issue
Block a user