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
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:
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user