242 lines
6.1 KiB
TypeScript
242 lines
6.1 KiB
TypeScript
import bcrypt from 'bcryptjs'
|
|
import jwt from 'jsonwebtoken'
|
|
import { prisma } from '../../lib/prisma'
|
|
|
|
const JWT_SECRET = process.env.JWT_SECRET ?? 'test-secret'
|
|
|
|
let counter = 0
|
|
function uid() {
|
|
return `${Date.now()}-${++counter}-${Math.random().toString(36).slice(2, 7)}`
|
|
}
|
|
|
|
export async function createCompanyWithEmployee(overrides: {
|
|
role?: 'OWNER' | 'MANAGER' | 'AGENT'
|
|
companyStatus?: 'ACTIVE' | 'TRIALING' | 'PAST_DUE' | 'SUSPENDED' | 'PENDING'
|
|
} = {}) {
|
|
const slug = `test-${uid()}`
|
|
const company = await prisma.company.create({
|
|
data: {
|
|
name: `Test Company ${slug}`,
|
|
slug,
|
|
email: `company-${slug}@test.com`,
|
|
status: (overrides.companyStatus ?? 'ACTIVE') as any,
|
|
subscription: {
|
|
create: { status: 'TRIALING', plan: 'STARTER' },
|
|
},
|
|
},
|
|
})
|
|
|
|
const employee = await prisma.employee.create({
|
|
data: {
|
|
companyId: company.id,
|
|
clerkUserId: `clerk_${uid()}`,
|
|
firstName: 'Test',
|
|
lastName: 'User',
|
|
email: `employee-${uid()}@test.com`,
|
|
role: overrides.role ?? 'OWNER',
|
|
},
|
|
})
|
|
|
|
return { company, employee }
|
|
}
|
|
|
|
export async function createVehicle(companyId: string, overrides: Record<string, unknown> = {}) {
|
|
return prisma.vehicle.create({
|
|
data: {
|
|
companyId,
|
|
make: 'Toyota',
|
|
model: 'Corolla',
|
|
year: 2022,
|
|
color: 'White',
|
|
licensePlate: `PL-${uid()}`,
|
|
dailyRate: 500,
|
|
status: 'AVAILABLE',
|
|
isPublished: true,
|
|
...overrides,
|
|
} as any,
|
|
})
|
|
}
|
|
|
|
export async function createCustomer(companyId: string, overrides: Record<string, unknown> = {}) {
|
|
return prisma.customer.create({
|
|
data: {
|
|
companyId,
|
|
firstName: 'Jane',
|
|
lastName: 'Doe',
|
|
email: `customer-${uid()}@test.com`,
|
|
...overrides,
|
|
},
|
|
})
|
|
}
|
|
|
|
export async function createRenter(overrides: {
|
|
firstName?: string
|
|
lastName?: string
|
|
email?: string
|
|
password?: string
|
|
isActive?: boolean
|
|
} = {}) {
|
|
return prisma.renter.create({
|
|
data: {
|
|
firstName: overrides.firstName ?? 'Renter',
|
|
lastName: overrides.lastName ?? 'User',
|
|
email: overrides.email ?? `renter-${uid()}@test.com`,
|
|
passwordHash: await bcrypt.hash(overrides.password ?? 'RenterPass123!', 10),
|
|
isActive: overrides.isActive ?? true,
|
|
},
|
|
})
|
|
}
|
|
|
|
export async function createAdminUser(overrides: {
|
|
email?: string
|
|
firstName?: string
|
|
lastName?: string
|
|
password?: string
|
|
role?: 'SUPER_ADMIN' | 'ADMIN' | 'SUPPORT' | 'FINANCE' | 'VIEWER'
|
|
isActive?: boolean
|
|
totpEnabled?: boolean
|
|
totpSecret?: string | null
|
|
} = {}) {
|
|
return prisma.adminUser.create({
|
|
data: {
|
|
email: overrides.email ?? `admin-${uid()}@test.com`,
|
|
firstName: overrides.firstName ?? 'Admin',
|
|
lastName: overrides.lastName ?? 'User',
|
|
passwordHash: await bcrypt.hash(overrides.password ?? 'AdminPass123!', 10),
|
|
role: (overrides.role ?? 'ADMIN') as any,
|
|
isActive: overrides.isActive ?? true,
|
|
totpEnabled: overrides.totpEnabled ?? false,
|
|
totpSecret: overrides.totpSecret ?? null,
|
|
},
|
|
})
|
|
}
|
|
|
|
export async function createReservation(
|
|
companyId: string,
|
|
vehicleId: string,
|
|
customerId: string,
|
|
overrides: Record<string, unknown> = {},
|
|
) {
|
|
return prisma.reservation.create({
|
|
data: {
|
|
companyId,
|
|
vehicleId,
|
|
customerId,
|
|
startDate: new Date(Date.now() + 24 * 60 * 60 * 1000),
|
|
endDate: new Date(Date.now() + 4 * 24 * 60 * 60 * 1000),
|
|
dailyRate: 500,
|
|
totalDays: 3,
|
|
totalAmount: 1500,
|
|
depositAmount: 300,
|
|
status: 'CONFIRMED',
|
|
paymentStatus: 'UNPAID',
|
|
paidAmount: 0,
|
|
...overrides,
|
|
} as any,
|
|
})
|
|
}
|
|
|
|
export async function createRentalPayment(
|
|
companyId: string,
|
|
reservationId: string,
|
|
overrides: Record<string, unknown> = {},
|
|
) {
|
|
return prisma.rentalPayment.create({
|
|
data: {
|
|
companyId,
|
|
reservationId,
|
|
amount: 500,
|
|
currency: 'MAD',
|
|
status: 'SUCCEEDED',
|
|
type: 'CHARGE',
|
|
paymentProvider: 'AMANPAY',
|
|
amanpayTransactionId: `aman-${uid()}`,
|
|
paidAt: new Date(),
|
|
...overrides,
|
|
} as any,
|
|
})
|
|
}
|
|
|
|
export async function createSubscriptionInvoice(
|
|
companyId: string,
|
|
subscriptionId: string,
|
|
overrides: Record<string, unknown> = {},
|
|
) {
|
|
return prisma.subscriptionInvoice.create({
|
|
data: {
|
|
companyId,
|
|
subscriptionId,
|
|
amount: 29900,
|
|
currency: 'MAD',
|
|
status: 'PENDING',
|
|
paymentProvider: 'AMANPAY',
|
|
amanpayTransactionId: `sub-${uid()}`,
|
|
...overrides,
|
|
} as any,
|
|
})
|
|
}
|
|
|
|
export async function createCompanyNotification(
|
|
companyId: string,
|
|
employeeId?: string,
|
|
overrides: Record<string, unknown> = {},
|
|
) {
|
|
return prisma.notification.create({
|
|
data: {
|
|
companyId,
|
|
employeeId,
|
|
type: 'PAYMENT_RECEIVED',
|
|
title: 'Payment received',
|
|
body: 'A payment was recorded.',
|
|
channel: 'IN_APP',
|
|
status: 'PENDING',
|
|
...overrides,
|
|
} as any,
|
|
})
|
|
}
|
|
|
|
export async function createRenterNotification(
|
|
renterId: string,
|
|
overrides: Record<string, unknown> = {},
|
|
) {
|
|
return prisma.notification.create({
|
|
data: {
|
|
renterId,
|
|
type: 'BOOKING_CONFIRMED',
|
|
title: 'Booking confirmed',
|
|
body: 'Your booking is confirmed.',
|
|
channel: 'IN_APP',
|
|
status: 'PENDING',
|
|
...overrides,
|
|
} as any,
|
|
})
|
|
}
|
|
|
|
export function signEmployeeToken(employeeId: string, companyId: string, role: string = 'OWNER') {
|
|
return jwt.sign(
|
|
{ sub: employeeId, companyId, role, type: 'employee' },
|
|
JWT_SECRET,
|
|
{ expiresIn: '1h' },
|
|
)
|
|
}
|
|
|
|
export function signAdminToken(adminId: string) {
|
|
return jwt.sign(
|
|
{ sub: adminId, type: 'admin' },
|
|
JWT_SECRET,
|
|
{ expiresIn: '1h' },
|
|
)
|
|
}
|
|
|
|
export function signRenterToken(renterId: string) {
|
|
return jwt.sign(
|
|
{ sub: renterId, type: 'renter' },
|
|
JWT_SECRET,
|
|
{ expiresIn: '1h' },
|
|
)
|
|
}
|
|
|
|
export function authHeader(token: string) {
|
|
return { Authorization: `Bearer ${token}` }
|
|
}
|