feat: deposit — history page, card info, cancel button, webhook notice, online booking email

- Migration 060: card_last4, card_brand columns in booking_deposits
- Backend: webhook saves card brand/last4 from YooKassa notification
- Backend: GET /api/hotels/:slug/deposits — payment history with guest/room info
- Backend: DELETE /api/hotels/:slug/bookings/:bookingId/deposit — cancel hold_created or paid_cash deposit
- Backend: auto-create YooKassa hold + send deposit email for source='online' bookings
- Frontend: DepositHistoryPage with filters, card display, retention reasons
- Frontend: deposit cancel button for hold_created and paid_cash states
- Frontend: show card last4/brand in hold_confirmed status
- Frontend: release form presets (full return / hold all) + improved UX
- Frontend: webhook setup instructions in DepositSettingsPage
- Frontend: "История платежей" link in deposit settings header

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-06 11:47:51 +03:00
parent 754f03b7fa
commit a4fc4a0972
8 changed files with 481 additions and 33 deletions

View File

@@ -764,6 +764,12 @@ export const api = {
captured_amount: capturedAmount,
reason,
}),
history: (slug: string) =>
req<BookingDeposit[]>('GET', `/api/hotels/${slug}/deposits`),
cancel: (slug: string, bookingId: string) =>
req<void>('DELETE', `/api/hotels/${slug}/bookings/${bookingId}/deposit`),
},
}
@@ -1380,9 +1386,17 @@ export interface BookingDeposit {
capturedAmount: number | null
retentionReason: string | null
guestEmailSent: boolean
cardLast4: string | null
cardBrand: string | null
createdAt: string
paidAt: string | null
releasedAt: string | null
// history enrichment
guestName?: string
guestEmail?: string
checkIn?: string
checkOut?: string
roomNumber?: string
}
function toHotelPayload(h: HotelPayload): Record<string, unknown> {