fix payment customer and dashboard settings
Build & Deploy / Build & Push Docker Image (push) Successful in 12m39s
Test / Type Check (all packages) (push) Successful in 5m8s
Build & Deploy / Deploy to VPS (push) Successful in 7s
Test / API Unit Tests (push) Failing after 4m24s
Test / Homepage Unit Tests (push) Successful in 3m27s
Test / Storefront Unit Tests (push) Successful in 4m48s
Test / Admin Unit Tests (push) Successful in 3m0s
Test / Dashboard Unit Tests (push) Successful in 4m18s
Test / API Integration Tests (push) Failing after 4m34s

This commit is contained in:
root
2026-06-29 22:15:34 -04:00
parent e1e2f55c93
commit a752a399c2
30 changed files with 4503 additions and 1214 deletions
@@ -52,6 +52,7 @@ const reservation = {
depositAmount: 300,
totalAmount: 1200,
paidAmount: 200,
rentalPayments: [],
vehicle: { make: 'Dacia', model: 'Duster' },
customer: { firstName: 'Nora', lastName: 'Driver', email: 'nora@example.com' },
}
@@ -106,7 +107,11 @@ describe('payment.service', () => {
})
it('refuses to initialize a charge for a fully paid reservation before touching gateways', async () => {
vi.mocked(repo.findReservationOrThrow).mockResolvedValue({ ...reservation, paymentStatus: 'PAID' } as never)
vi.mocked(repo.findReservationOrThrow).mockResolvedValue({
...reservation,
paymentStatus: 'PAID',
rentalPayments: [{ type: 'CHARGE', status: 'SUCCEEDED', amount: 1200 }],
} as never)
await expect(initCharge('reservation_1', 'company_1', {
provider: 'PAYPAL',
@@ -120,8 +125,36 @@ describe('payment.service', () => {
expect(repo.createPayment).not.toHaveBeenCalled()
})
it('allows an outstanding deposit when the rental invoice is fully paid', async () => {
vi.mocked(repo.findReservationOrThrow).mockResolvedValue({
...reservation,
paymentStatus: 'PAID',
rentalPayments: [{ type: 'CHARGE', status: 'SUCCEEDED', amount: 1200 }],
} as never)
vi.mocked(amanpay.isConfigured).mockReturnValue(true)
vi.mocked(amanpay.createCheckout).mockResolvedValue({ checkoutUrl: 'https://pay.example/checkout', transactionId: 'aman_txn_2' } as never)
vi.mocked(repo.createPayment).mockResolvedValue({ id: 'payment_2', status: 'PENDING' } as never)
await initCharge('reservation_1', 'company_1', {
provider: 'AMANPAY',
type: 'DEPOSIT',
currency: 'MAD',
successUrl: 'https://app.example/success',
failureUrl: 'https://app.example/failure',
})
expect(amanpay.createCheckout).toHaveBeenCalledWith(expect.objectContaining({ amount: 300 }))
expect(repo.createPayment).toHaveBeenCalledWith(expect.objectContaining({ type: 'DEPOSIT' }))
})
it('records manual payments and marks the reservation as partially or fully paid from the balance math', async () => {
vi.mocked(repo.findReservation).mockResolvedValue({ id: 'reservation_1', totalAmount: 1000, paidAmount: 700 } as never)
vi.mocked(repo.findReservation).mockResolvedValue({
id: 'reservation_1',
totalAmount: 1000,
depositAmount: 300,
paidAmount: 700,
rentalPayments: [{ type: 'CHARGE', status: 'SUCCEEDED', amount: 700 }],
} as never)
vi.mocked(repo.createPayment).mockResolvedValue({ id: 'payment_1', amount: 300, status: 'SUCCEEDED' } as never)
const payment = await recordManualPayment('reservation_1', 'company_1', {
@@ -133,7 +166,7 @@ describe('payment.service', () => {
expect(repo.createPayment).toHaveBeenCalledWith(expect.objectContaining({
status: 'SUCCEEDED',
paymentProvider: 'AMANPAY',
paymentProvider: 'MANUAL',
paymentMethod: 'CASH',
paidAt: expect.any(Date),
}))
@@ -142,7 +175,13 @@ describe('payment.service', () => {
})
it('rejects manual overpayments instead of silently corrupting the reservation balance', async () => {
vi.mocked(repo.findReservation).mockResolvedValue({ id: 'reservation_1', totalAmount: 1000, paidAmount: 950 } as never)
vi.mocked(repo.findReservation).mockResolvedValue({
id: 'reservation_1',
totalAmount: 1000,
depositAmount: 300,
paidAmount: 950,
rentalPayments: [{ type: 'CHARGE', status: 'SUCCEEDED', amount: 950 }],
} as never)
await expect(recordManualPayment('reservation_1', 'company_1', {
amount: 100,
@@ -156,8 +195,8 @@ describe('payment.service', () => {
})
it('applies paid AmanPay and denied PayPal webhook events to the matching records', async () => {
vi.mocked(repo.findByAmanpay).mockResolvedValue({ id: 'payment_1', reservationId: 'reservation_1', amount: 450 } as never)
vi.mocked(repo.findByPaypal).mockResolvedValue({ id: 'payment_2', reservationId: 'reservation_2', amount: 500 } as never)
vi.mocked(repo.findByAmanpay).mockResolvedValue({ id: 'payment_1', reservationId: 'reservation_1', amount: 450, type: 'CHARGE' } as never)
vi.mocked(repo.findByPaypal).mockResolvedValue({ id: 'payment_2', reservationId: 'reservation_2', amount: 500, type: 'CHARGE' } as never)
await handleAmanpayWebhook({ transaction_id: 'aman_txn_1', status: 'paid' })
await handlePaypalWebhook({ event_type: 'PAYMENT.CAPTURE.COMPLETED', resource: { id: 'paypal_capture_1' } })
@@ -171,7 +210,7 @@ describe('payment.service', () => {
})
it('captures PayPal orders, stores the capture id, and increments the original reservation payment', async () => {
vi.mocked(repo.findByPaypalForCompany).mockResolvedValue({ id: 'payment_1', reservationId: 'reservation_1', amount: 800 } as never)
vi.mocked(repo.findByPaypalForCompany).mockResolvedValue({ id: 'payment_1', reservationId: 'reservation_1', amount: 800, type: 'CHARGE' } as never)
vi.mocked(paypal.captureOrder).mockResolvedValue({ purchase_units: [{ payments: { captures: [{ id: 'capture_123' }] } }] } as never)
vi.mocked(repo.updatePaypalCapture).mockResolvedValue({ id: 'payment_1', status: 'SUCCEEDED', paypalCaptureId: 'capture_123' } as never)