"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.openApiDocument = void 0; const zod_to_json_schema_1 = require("zod-to-json-schema"); // ── Vehicles ───────────────────────────────────────────────────────────────── const vehicle_schemas_1 = require("../modules/vehicles/vehicle.schemas"); // ── Reservations ───────────────────────────────────────────────────────────── const reservation_schemas_1 = require("../modules/reservations/reservation.schemas"); // ── Customers ───────────────────────────────────────────────────────────────── const customer_schemas_1 = require("../modules/customers/customer.schemas"); // ── Offers ──────────────────────────────────────────────────────────────────── const offer_schemas_1 = require("../modules/offers/offer.schemas"); // ── Payments ───────────────────────────────────────────────────────────────── const payment_schemas_1 = require("../modules/payments/payment.schemas"); // ── Reviews ─────────────────────────────────────────────────────────────────── const review_schemas_1 = require("../modules/reviews/review.schemas"); // ── Complaints ──────────────────────────────────────────────────────────────── const complaint_schemas_1 = require("../modules/complaints/complaint.schemas"); // ── Auth ────────────────────────────────────────────────────────────────────── const auth_company_schemas_1 = require("../modules/auth/auth.company.schemas"); const auth_employee_schemas_1 = require("../modules/auth/auth.employee.schemas"); const auth_renter_schemas_1 = require("../modules/auth/auth.renter.schemas"); // ───────────────────────────────────────────────────────────────────────────── function s(schema) { const { $schema, ...rest } = (0, zod_to_json_schema_1.zodToJsonSchema)(schema, { target: 'openApi3' }); return rest; } const idPath = (name = 'id') => ({ name, in: 'path', required: true, schema: { type: 'string' }, }); const pagingParams = [ { name: 'page', in: 'query', schema: { type: 'integer', default: 1 } }, { name: 'pageSize', in: 'query', schema: { type: 'integer', default: 20 } }, ]; const jsonBody = (ref) => ({ required: true, content: { 'application/json': { schema: { $ref: ref } } }, }); const ok = { description: 'Success' }; const err4 = { description: 'Validation error', content: { 'application/json': { schema: { type: 'object', properties: { error: { type: 'string' } } } } } }; const err401 = { description: 'Unauthorized' }; const err404 = { description: 'Not found' }; exports.openApiDocument = { openapi: '3.0.3', info: { title: 'RentalDriveGo API', description: 'REST API for the RentalDriveGo car rental management platform.\n\n**Auth:** Most browser endpoints use HttpOnly session cookies issued by `/auth/employee/login`, `/admin/auth/login`, or renter auth. Trusted server/mobile contexts may still use Bearer JWTs where documented.', version: '1.0.0', contact: { name: 'RentalDriveGo', email: 'support@rentaldrivego.com' }, }, servers: [{ url: '/api/v1', description: 'v1' }], security: [{ bearerAuth: [] }], tags: [ { name: 'Health', description: 'Service health' }, { name: 'Auth — Company', description: 'Company account registration' }, { name: 'Auth — Employee', description: 'Employee (dashboard) authentication' }, { name: 'Auth — Renter', description: 'Renter (mobile) authentication' }, { name: 'Vehicles', description: 'Fleet management' }, { name: 'Reservations', description: 'Booking lifecycle' }, { name: 'Customers', description: 'Customer profiles & documents' }, { name: 'Offers', description: 'Discounts & promo codes' }, { name: 'Payments', description: 'Charges, manual payments, refunds' }, { name: 'Reviews', description: 'Customer reviews' }, { name: 'Complaints', description: 'Complaint tracking' }, { name: 'Analytics', description: 'Dashboard & reports' }, { name: 'Notifications', description: 'In-app notifications' }, { name: 'Companies', description: 'Company profile & settings' }, { name: 'Team', description: 'Employee management' }, { name: 'Subscriptions', description: 'Plan management & billing' }, { name: 'Marketplace', description: 'Public booking portal' }, { name: 'Site', description: 'White-label site API' }, { name: 'Admin', description: 'Platform administration' }, ], components: { securitySchemes: { bearerAuth: { type: 'http', scheme: 'bearer', bearerFormat: 'JWT' }, }, schemas: { // ── Vehicles ──────────────────────────────────────────────── VehicleInput: s(vehicle_schemas_1.vehicleSchema), CalendarBlock: s(vehicle_schemas_1.calendarBlockSchema), MaintenanceLog: s(vehicle_schemas_1.maintenanceLogSchema), VehiclePublish: s(vehicle_schemas_1.publishSchema), VehicleStatus: s(vehicle_schemas_1.statusSchema), // ── Reservations ──────────────────────────────────────────── ReservationCreate: s(reservation_schemas_1.createSchema), ReservationUpdate: s(reservation_schemas_1.updateSchema), AdditionalDriver: s(reservation_schemas_1.additionalDriverSchema), Inspection: s(reservation_schemas_1.inspectionSchema), ReservationCheckin: s(reservation_schemas_1.checkinSchema), ReservationCheckout: s(reservation_schemas_1.checkoutSchema), ReservationExtend: s(reservation_schemas_1.extendSchema), ReservationCancel: s(reservation_schemas_1.cancelSchema), ReservationApproval: s(reservation_schemas_1.approvalSchema), // ── Customers ─────────────────────────────────────────────── CustomerInput: s(customer_schemas_1.customerSchema), ApproveLicense: s(customer_schemas_1.approveLicenseSchema), FlagCustomer: s(customer_schemas_1.flagSchema), // ── Offers ────────────────────────────────────────────────── OfferInput: s(offer_schemas_1.offerSchema), // ── Payments ──────────────────────────────────────────────── PaymentCharge: s(payment_schemas_1.chargeSchema), ManualPayment: s(payment_schemas_1.manualPaymentSchema), Refund: s(payment_schemas_1.refundSchema), // ── Reviews ───────────────────────────────────────────────── ReviewReply: s(review_schemas_1.replySchema), // ── Complaints ────────────────────────────────────────────── ComplaintCreate: s(complaint_schemas_1.createSchema), ComplaintUpdate: s(complaint_schemas_1.updateSchema), // ── Auth ──────────────────────────────────────────────────── CompanySignup: s(auth_company_schemas_1.companySignupSchema), EmployeeLogin: s(auth_employee_schemas_1.employeeLoginSchema), EmployeeForgotPassword: s(auth_employee_schemas_1.employeeForgotPasswordSchema), EmployeeResetPassword: s(auth_employee_schemas_1.employeeResetPasswordSchema), EmployeeLanguage: s(auth_employee_schemas_1.employeeLanguageSchema), RenterUpdate: s(auth_renter_schemas_1.renterUpdateSchema), RenterFcmToken: s(auth_renter_schemas_1.renterFcmTokenSchema), }, }, paths: { // ════════════════════════════════════════════════════════════════ // HEALTH (no /api/v1 prefix — served directly from app root) // ════════════════════════════════════════════════════════════════ '/health': { get: { tags: ['Health'], summary: 'Health check', security: [], servers: [{ url: '/' }], responses: { '200': { description: 'OK', content: { 'application/json': { schema: { type: 'object', properties: { status: { type: 'string', example: 'ok' }, version: { type: 'string' }, timestamp: { type: 'string', format: 'date-time' } } } } } }, }, }, }, // ════════════════════════════════════════════════════════════════ // AUTH — COMPANY // ════════════════════════════════════════════════════════════════ '/auth/company/signup': { post: { tags: ['Auth — Company'], summary: 'Register a new company', security: [], requestBody: jsonBody('#/components/schemas/CompanySignup'), responses: { '201': ok, '400': err4, '409': { description: 'Email already in use' } }, }, }, // ════════════════════════════════════════════════════════════════ // AUTH — EMPLOYEE // ════════════════════════════════════════════════════════════════ '/auth/employee/login': { post: { tags: ['Auth — Employee'], summary: 'Login', security: [], requestBody: jsonBody('#/components/schemas/EmployeeLogin'), responses: { '200': { description: 'Token + employee object', content: { 'application/json': { schema: { type: 'object', properties: { token: { type: 'string' }, employee: { type: 'object' } } } } } }, '401': err401, }, }, }, '/auth/employee/forgot-password': { post: { tags: ['Auth — Employee'], summary: 'Request password-reset email', security: [], requestBody: jsonBody('#/components/schemas/EmployeeForgotPassword'), responses: { '200': ok }, }, }, '/auth/employee/reset-password': { post: { tags: ['Auth — Employee'], summary: 'Reset password with token', security: [], requestBody: jsonBody('#/components/schemas/EmployeeResetPassword'), responses: { '200': ok, '400': err4 }, }, }, '/auth/employee/me': { get: { tags: ['Auth — Employee'], summary: 'Current employee profile', responses: { '200': ok, '401': err401 }, }, }, '/auth/employee/me/language': { patch: { tags: ['Auth — Employee'], summary: 'Update preferred language', requestBody: jsonBody('#/components/schemas/EmployeeLanguage'), responses: { '200': ok }, }, }, // ════════════════════════════════════════════════════════════════ // AUTH — RENTER // ════════════════════════════════════════════════════════════════ '/auth/renter/me': { get: { tags: ['Auth — Renter'], summary: 'Current renter profile', responses: { '200': ok, '401': err401 }, }, patch: { tags: ['Auth — Renter'], summary: 'Update renter profile', requestBody: jsonBody('#/components/schemas/RenterUpdate'), responses: { '200': ok }, }, }, '/auth/renter/me/fcm-token': { post: { tags: ['Auth — Renter'], summary: 'Register FCM push token', requestBody: jsonBody('#/components/schemas/RenterFcmToken'), responses: { '200': ok }, }, }, // ════════════════════════════════════════════════════════════════ // VEHICLES // ════════════════════════════════════════════════════════════════ '/vehicles': { get: { tags: ['Vehicles'], summary: 'List vehicles', parameters: [ { name: 'status', in: 'query', schema: { type: 'string', enum: ['AVAILABLE', 'RESERVED', 'READY', 'RENTED', 'RETURNED', 'NEEDS_CLEANING', 'MAINTENANCE', 'DAMAGE_REVIEW', 'OUT_OF_SERVICE'] } }, { name: 'category', in: 'query', schema: { type: 'string', enum: ['ECONOMY', 'COMPACT', 'MIDSIZE', 'FULLSIZE', 'SUV', 'LUXURY', 'VAN', 'TRUCK'] } }, { name: 'published', in: 'query', schema: { type: 'string', enum: ['true', 'false'] } }, ...pagingParams, ], responses: { '200': ok }, }, post: { tags: ['Vehicles'], summary: 'Create vehicle', requestBody: jsonBody('#/components/schemas/VehicleInput'), responses: { '201': ok, '400': err4 }, }, }, '/vehicles/{id}': { get: { tags: ['Vehicles'], summary: 'Get vehicle', parameters: [idPath()], responses: { '200': ok, '404': err404 }, }, patch: { tags: ['Vehicles'], summary: 'Update vehicle', parameters: [idPath()], requestBody: jsonBody('#/components/schemas/VehicleInput'), responses: { '200': ok, '404': err404 }, }, delete: { tags: ['Vehicles'], summary: 'Delete vehicle', parameters: [idPath()], responses: { '200': ok }, }, }, '/vehicles/{id}/status': { patch: { tags: ['Vehicles'], summary: 'Set vehicle status', parameters: [idPath()], requestBody: jsonBody('#/components/schemas/VehicleStatus'), responses: { '200': ok }, }, }, '/vehicles/{id}/publish': { patch: { tags: ['Vehicles'], summary: 'Publish / unpublish vehicle', parameters: [idPath()], requestBody: jsonBody('#/components/schemas/VehiclePublish'), responses: { '200': ok }, }, }, '/vehicles/{id}/photos': { post: { tags: ['Vehicles'], summary: 'Upload photos (multipart, max 10)', parameters: [idPath()], requestBody: { required: true, content: { 'multipart/form-data': { schema: { type: 'object', properties: { photos: { type: 'array', items: { type: 'string', format: 'binary' } } } } } } }, responses: { '200': ok }, }, }, '/vehicles/{id}/photos/{idx}': { delete: { tags: ['Vehicles'], summary: 'Delete photo by index', parameters: [idPath(), { name: 'idx', in: 'path', required: true, schema: { type: 'integer' } }], responses: { '200': ok }, }, }, '/vehicles/{id}/availability': { get: { tags: ['Vehicles'], summary: 'Check availability for a date range', parameters: [ idPath(), { name: 'startDate', in: 'query', required: true, schema: { type: 'string', format: 'date-time' } }, { name: 'endDate', in: 'query', required: true, schema: { type: 'string', format: 'date-time' } }, ], responses: { '200': ok }, }, }, '/vehicles/{id}/calendar': { get: { tags: ['Vehicles'], summary: 'Get monthly calendar events', parameters: [ idPath(), { name: 'year', in: 'query', required: true, schema: { type: 'integer' } }, { name: 'month', in: 'query', required: true, schema: { type: 'integer', minimum: 1, maximum: 12 } }, ], responses: { '200': ok }, }, }, '/vehicles/{id}/calendar/blocks': { post: { tags: ['Vehicles'], summary: 'Create calendar block', parameters: [idPath()], requestBody: jsonBody('#/components/schemas/CalendarBlock'), responses: { '201': ok }, }, }, '/vehicles/{id}/calendar/blocks/{blockId}': { delete: { tags: ['Vehicles'], summary: 'Delete calendar block', parameters: [idPath(), idPath('blockId')], responses: { '200': ok }, }, }, '/vehicles/{id}/maintenance': { get: { tags: ['Vehicles'], summary: 'List maintenance logs', parameters: [idPath()], responses: { '200': ok }, }, post: { tags: ['Vehicles'], summary: 'Add maintenance log', parameters: [idPath()], requestBody: jsonBody('#/components/schemas/MaintenanceLog'), responses: { '201': ok }, }, }, // ════════════════════════════════════════════════════════════════ // RESERVATIONS // ════════════════════════════════════════════════════════════════ '/reservations': { get: { tags: ['Reservations'], summary: 'List reservations', parameters: [ { name: 'status', in: 'query', schema: { type: 'string' } }, { name: 'vehicleId', in: 'query', schema: { type: 'string' } }, { name: 'source', in: 'query', schema: { type: 'string' } }, { name: 'startDate', in: 'query', schema: { type: 'string' } }, { name: 'endDate', in: 'query', schema: { type: 'string' } }, ...pagingParams, ], responses: { '200': ok }, }, post: { tags: ['Reservations'], summary: 'Create reservation', requestBody: jsonBody('#/components/schemas/ReservationCreate'), responses: { '201': ok, '400': err4 }, }, }, '/reservations/{id}': { get: { tags: ['Reservations'], summary: 'Get reservation', parameters: [idPath()], responses: { '200': ok, '404': err404 }, }, patch: { tags: ['Reservations'], summary: 'Update reservation', parameters: [idPath()], requestBody: jsonBody('#/components/schemas/ReservationUpdate'), responses: { '200': ok }, }, }, '/reservations/{id}/confirm': { post: { tags: ['Reservations'], summary: 'Confirm reservation', parameters: [idPath()], responses: { '200': ok }, }, }, '/reservations/{id}/approve': { patch: { tags: ['Reservations'], summary: 'Approve or reject pending reservation', parameters: [idPath()], requestBody: jsonBody('#/components/schemas/ReservationApproval'), responses: { '200': ok }, }, }, '/reservations/{id}/checkin': { post: { tags: ['Reservations'], summary: 'Check in', parameters: [idPath()], requestBody: jsonBody('#/components/schemas/ReservationCheckin'), responses: { '200': ok }, }, }, '/reservations/{id}/checkout': { post: { tags: ['Reservations'], summary: 'Check out', parameters: [idPath()], requestBody: jsonBody('#/components/schemas/ReservationCheckout'), responses: { '200': ok }, }, }, '/reservations/{id}/close': { post: { tags: ['Reservations'], summary: 'Close reservation', parameters: [idPath()], responses: { '200': ok }, }, }, '/reservations/{id}/extend': { post: { tags: ['Reservations'], summary: 'Extend reservation end date', parameters: [idPath()], requestBody: jsonBody('#/components/schemas/ReservationExtend'), responses: { '200': ok }, }, }, '/reservations/{id}/cancel': { post: { tags: ['Reservations'], summary: 'Cancel reservation', parameters: [idPath()], requestBody: jsonBody('#/components/schemas/ReservationCancel'), responses: { '200': ok }, }, }, '/reservations/{id}/contract': { get: { tags: ['Reservations'], summary: 'Download rental contract (PDF)', parameters: [idPath()], responses: { '200': { description: 'PDF file', content: { 'application/pdf': {} } } }, }, }, '/reservations/{id}/billing': { get: { tags: ['Reservations'], summary: 'Get billing summary', parameters: [idPath()], responses: { '200': ok }, }, }, '/reservations/{id}/inspections': { get: { tags: ['Reservations'], summary: 'List inspections', parameters: [idPath()], responses: { '200': ok }, }, }, '/reservations/{id}/inspections/{type}': { put: { tags: ['Reservations'], summary: 'Save inspection (CHECKIN or CHECKOUT)', parameters: [ idPath(), { name: 'type', in: 'path', required: true, schema: { type: 'string', enum: ['CHECKIN', 'CHECKOUT'] } }, ], requestBody: jsonBody('#/components/schemas/Inspection'), responses: { '200': ok }, }, }, '/reservations/{id}/photos': { get: { tags: ['Reservations'], summary: 'List reservation photos', parameters: [idPath()], responses: { '200': ok }, }, post: { tags: ['Reservations'], summary: 'Upload reservation photo', parameters: [idPath()], requestBody: { required: true, content: { 'multipart/form-data': { schema: { type: 'object', properties: { photo: { type: 'string', format: 'binary' } } } } } }, responses: { '201': ok }, }, }, '/reservations/{id}/photos/{photoId}': { delete: { tags: ['Reservations'], summary: 'Delete reservation photo', parameters: [idPath(), idPath('photoId')], responses: { '200': ok }, }, }, '/reservations/{id}/additional-drivers/{driverId}/approval': { patch: { tags: ['Reservations'], summary: 'Approve/reject additional driver', parameters: [idPath(), idPath('driverId')], requestBody: jsonBody('#/components/schemas/ReservationApproval'), responses: { '200': ok }, }, }, // ════════════════════════════════════════════════════════════════ // CUSTOMERS // ════════════════════════════════════════════════════════════════ '/customers': { get: { tags: ['Customers'], summary: 'List customers', parameters: [ { name: 'q', in: 'query', schema: { type: 'string' } }, { name: 'flagged', in: 'query', schema: { type: 'string', enum: ['true', 'false'] } }, ...pagingParams, ], responses: { '200': ok }, }, post: { tags: ['Customers'], summary: 'Create customer', requestBody: jsonBody('#/components/schemas/CustomerInput'), responses: { '201': ok, '400': err4 }, }, }, '/customers/{id}': { get: { tags: ['Customers'], summary: 'Get customer', parameters: [idPath()], responses: { '200': ok, '404': err404 }, }, patch: { tags: ['Customers'], summary: 'Update customer', parameters: [idPath()], requestBody: jsonBody('#/components/schemas/CustomerInput'), responses: { '200': ok }, }, }, '/customers/{id}/flag': { post: { tags: ['Customers'], summary: 'Flag customer', parameters: [idPath()], requestBody: jsonBody('#/components/schemas/FlagCustomer'), responses: { '200': ok }, }, delete: { tags: ['Customers'], summary: 'Unflag customer', parameters: [idPath()], responses: { '200': ok }, }, }, '/customers/{id}/validate-license': { post: { tags: ['Customers'], summary: 'Validate customer driving license', parameters: [idPath()], responses: { '200': ok }, }, }, '/customers/{id}/license-image': { post: { tags: ['Customers'], summary: 'Upload license image', parameters: [idPath()], requestBody: { required: true, content: { 'multipart/form-data': { schema: { type: 'object', properties: { file: { type: 'string', format: 'binary' } } } } } }, responses: { '200': ok }, }, }, '/customers/{id}/approve-license': { post: { tags: ['Customers'], summary: 'Approve or deny license', parameters: [idPath()], requestBody: jsonBody('#/components/schemas/ApproveLicense'), responses: { '200': ok }, }, }, // ════════════════════════════════════════════════════════════════ // OFFERS // ════════════════════════════════════════════════════════════════ '/offers': { get: { tags: ['Offers'], summary: 'List offers', parameters: [ { name: 'active', in: 'query', schema: { type: 'string', enum: ['true', 'false'] } }, { name: 'public', in: 'query', schema: { type: 'string', enum: ['true', 'false'] } }, ], responses: { '200': ok }, }, post: { tags: ['Offers'], summary: 'Create offer', requestBody: jsonBody('#/components/schemas/OfferInput'), responses: { '201': ok, '400': err4 }, }, }, '/offers/{id}': { get: { tags: ['Offers'], summary: 'Get offer', parameters: [idPath()], responses: { '200': ok, '404': err404 }, }, patch: { tags: ['Offers'], summary: 'Update offer', parameters: [idPath()], requestBody: jsonBody('#/components/schemas/OfferInput'), responses: { '200': ok }, }, delete: { tags: ['Offers'], summary: 'Delete offer', parameters: [idPath()], responses: { '200': ok }, }, }, '/offers/{id}/activate': { post: { tags: ['Offers'], summary: 'Activate offer', parameters: [idPath()], responses: { '200': ok } }, }, '/offers/{id}/deactivate': { post: { tags: ['Offers'], summary: 'Deactivate offer', parameters: [idPath()], responses: { '200': ok } }, }, '/offers/{id}/stats': { get: { tags: ['Offers'], summary: 'Offer usage stats', parameters: [idPath()], responses: { '200': ok } }, }, // ════════════════════════════════════════════════════════════════ // PAYMENTS // ════════════════════════════════════════════════════════════════ '/payments/company': { get: { tags: ['Payments'], summary: 'List all company payments', responses: { '200': ok }, }, }, '/payments/reservations/{id}': { get: { tags: ['Payments'], summary: 'Get payments for a reservation', parameters: [idPath()], responses: { '200': ok }, }, }, '/payments/reservations/{id}/charge': { post: { tags: ['Payments'], summary: 'Initiate online payment (AmanPay / PayPal)', parameters: [idPath()], requestBody: jsonBody('#/components/schemas/PaymentCharge'), responses: { '200': ok, '400': err4 }, }, }, '/payments/reservations/{id}/capture-paypal': { post: { tags: ['Payments'], summary: 'Capture PayPal order', parameters: [idPath()], responses: { '200': ok }, }, }, '/payments/reservations/{id}/manual': { post: { tags: ['Payments'], summary: 'Record manual payment', parameters: [idPath()], requestBody: jsonBody('#/components/schemas/ManualPayment'), responses: { '201': ok, '400': err4 }, }, }, '/payments/reservations/{reservationId}/payments/{paymentId}/refund': { post: { tags: ['Payments'], summary: 'Refund a payment', parameters: [idPath('reservationId'), idPath('paymentId')], requestBody: jsonBody('#/components/schemas/Refund'), responses: { '200': ok }, }, }, // ════════════════════════════════════════════════════════════════ // REVIEWS // ════════════════════════════════════════════════════════════════ '/reviews': { get: { tags: ['Reviews'], summary: 'List reviews', parameters: [ { name: 'rating', in: 'query', schema: { type: 'integer', minimum: 1, maximum: 5 } }, ...pagingParams, ], responses: { '200': ok }, }, }, '/reviews/stats': { get: { tags: ['Reviews'], summary: 'Review statistics', responses: { '200': ok } }, }, '/reviews/{id}': { get: { tags: ['Reviews'], summary: 'Get review', parameters: [idPath()], responses: { '200': ok, '404': err404 } }, }, '/reviews/{id}/reply': { patch: { tags: ['Reviews'], summary: 'Reply to review', parameters: [idPath()], requestBody: jsonBody('#/components/schemas/ReviewReply'), responses: { '200': ok }, }, }, '/reviews/{id}/remind': { post: { tags: ['Reviews'], summary: 'Send review reminder', parameters: [idPath()], responses: { '200': ok } }, }, // ════════════════════════════════════════════════════════════════ // COMPLAINTS // ════════════════════════════════════════════════════════════════ '/complaints': { get: { tags: ['Complaints'], summary: 'List complaints', parameters: [ { name: 'status', in: 'query', schema: { type: 'string' } }, { name: 'severity', in: 'query', schema: { type: 'string' } }, { name: 'category', in: 'query', schema: { type: 'string' } }, ...pagingParams, ], responses: { '200': ok }, }, post: { tags: ['Complaints'], summary: 'Create complaint', requestBody: jsonBody('#/components/schemas/ComplaintCreate'), responses: { '201': ok, '400': err4 }, }, }, '/complaints/{id}': { get: { tags: ['Complaints'], summary: 'Get complaint', parameters: [idPath()], responses: { '200': ok, '404': err404 }, }, patch: { tags: ['Complaints'], summary: 'Update complaint', parameters: [idPath()], requestBody: jsonBody('#/components/schemas/ComplaintUpdate'), responses: { '200': ok }, }, delete: { tags: ['Complaints'], summary: 'Delete complaint', parameters: [idPath()], responses: { '200': ok }, }, }, // ════════════════════════════════════════════════════════════════ // ANALYTICS // ════════════════════════════════════════════════════════════════ '/analytics/summary': { get: { tags: ['Analytics'], summary: 'Quick summary stats', responses: { '200': ok } }, }, '/analytics/dashboard': { get: { tags: ['Analytics'], summary: 'Full dashboard analytics', responses: { '200': ok } }, }, '/analytics/sources': { get: { tags: ['Analytics'], summary: 'Reservation source breakdown', responses: { '200': ok } }, }, '/analytics/report': { get: { tags: ['Analytics'], summary: 'Detailed report (Manager+)', parameters: [ { name: 'startDate', in: 'query', schema: { type: 'string', format: 'date' } }, { name: 'endDate', in: 'query', schema: { type: 'string', format: 'date' } }, ], responses: { '200': ok }, }, }, // ════════════════════════════════════════════════════════════════ // NOTIFICATIONS // ════════════════════════════════════════════════════════════════ '/notifications/company': { get: { tags: ['Notifications'], summary: 'Company notifications', responses: { '200': ok } }, }, '/notifications/unread-count': { get: { tags: ['Notifications'], summary: 'Unread count', responses: { '200': ok } }, }, '/notifications/company/{id}/read': { post: { tags: ['Notifications'], summary: 'Mark notification as read', parameters: [idPath()], responses: { '200': ok } }, }, '/notifications/company/read-all': { post: { tags: ['Notifications'], summary: 'Mark all notifications as read', responses: { '200': ok } }, }, '/notifications/company/preferences': { get: { tags: ['Notifications'], summary: 'Get notification preferences', responses: { '200': ok } }, patch: { tags: ['Notifications'], summary: 'Update notification preferences', responses: { '200': ok } }, }, '/notifications/history': { get: { tags: ['Notifications'], summary: 'Notification history', responses: { '200': ok } }, }, // ════════════════════════════════════════════════════════════════ // COMPANIES // ════════════════════════════════════════════════════════════════ '/companies/me': { get: { tags: ['Companies'], summary: 'Current company profile', responses: { '200': ok } }, patch: { tags: ['Companies'], summary: 'Update company profile (Owner)', responses: { '200': ok } }, }, '/companies/me/brand': { get: { tags: ['Companies'], summary: 'Brand settings', responses: { '200': ok } }, patch: { tags: ['Companies'], summary: 'Update brand settings (Owner)', responses: { '200': ok } }, }, '/companies/me/brand/logo': { post: { tags: ['Companies'], summary: 'Upload brand logo', requestBody: { required: true, content: { 'multipart/form-data': { schema: { type: 'object', properties: { file: { type: 'string', format: 'binary' } } } } } }, responses: { '200': ok } }, }, '/companies/me/brand/hero': { post: { tags: ['Companies'], summary: 'Upload brand hero image', requestBody: { required: true, content: { 'multipart/form-data': { schema: { type: 'object', properties: { file: { type: 'string', format: 'binary' } } } } } }, responses: { '200': ok } }, }, '/companies/me/brand/subdomain/check': { post: { tags: ['Companies'], summary: 'Check subdomain availability', responses: { '200': ok } }, }, '/companies/me/brand/custom-domain': { post: { tags: ['Companies'], summary: 'Set custom domain', responses: { '200': ok } }, delete: { tags: ['Companies'], summary: 'Remove custom domain', responses: { '200': ok } }, }, '/companies/me/brand/custom-domain/status': { get: { tags: ['Companies'], summary: 'Custom domain DNS status', responses: { '200': ok } }, }, '/companies/me/contract-settings': { get: { tags: ['Companies'], summary: 'Contract settings', responses: { '200': ok } }, patch: { tags: ['Companies'], summary: 'Update contract settings', responses: { '200': ok } }, }, '/companies/me/insurance-policies': { get: { tags: ['Companies'], summary: 'List insurance policies', responses: { '200': ok } }, post: { tags: ['Companies'], summary: 'Create insurance policy', responses: { '201': ok } }, }, '/companies/me/insurance-policies/{id}': { patch: { tags: ['Companies'], summary: 'Update insurance policy', parameters: [idPath()], responses: { '200': ok } }, delete: { tags: ['Companies'], summary: 'Delete insurance policy', parameters: [idPath()], responses: { '200': ok } }, }, '/companies/me/pricing-rules': { get: { tags: ['Companies'], summary: 'List pricing rules', responses: { '200': ok } }, post: { tags: ['Companies'], summary: 'Create pricing rule', responses: { '201': ok } }, }, '/companies/me/pricing-rules/{id}': { patch: { tags: ['Companies'], summary: 'Update pricing rule', parameters: [idPath()], responses: { '200': ok } }, }, // ════════════════════════════════════════════════════════════════ // TEAM // ════════════════════════════════════════════════════════════════ '/team': { get: { tags: ['Team'], summary: 'List team members', responses: { '200': ok } }, }, '/team/stats': { get: { tags: ['Team'], summary: 'Team statistics', responses: { '200': ok } }, }, '/team/invite': { post: { tags: ['Team'], summary: 'Invite member (Owner)', responses: { '201': ok } }, }, '/team/{id}/role': { patch: { tags: ['Team'], summary: 'Update member role (Owner)', parameters: [idPath()], responses: { '200': ok } }, }, '/team/{id}/deactivate': { post: { tags: ['Team'], summary: 'Deactivate member (Owner)', parameters: [idPath()], responses: { '200': ok } }, }, '/team/{id}/reactivate': { post: { tags: ['Team'], summary: 'Reactivate member (Owner)', parameters: [idPath()], responses: { '200': ok } }, }, '/team/{id}': { delete: { tags: ['Team'], summary: 'Remove member (Owner)', parameters: [idPath()], responses: { '200': ok } }, }, // ════════════════════════════════════════════════════════════════ // SUBSCRIPTIONS // ════════════════════════════════════════════════════════════════ '/subscriptions/plans': { get: { tags: ['Subscriptions'], summary: 'List available plans', security: [], responses: { '200': ok } }, }, '/subscriptions/features': { get: { tags: ['Subscriptions'], summary: 'Plan feature matrix', security: [], responses: { '200': ok } }, }, '/subscriptions/me': { get: { tags: ['Subscriptions'], summary: 'Current subscription', responses: { '200': ok } }, }, '/subscriptions/invoices': { get: { tags: ['Subscriptions'], summary: 'Billing invoices', responses: { '200': ok } }, }, '/subscriptions/events': { get: { tags: ['Subscriptions'], summary: 'Subscription events', responses: { '200': ok } }, }, '/subscriptions/entitlement': { get: { tags: ['Subscriptions'], summary: 'Feature entitlements', responses: { '200': ok } }, }, '/subscriptions/trial': { post: { tags: ['Subscriptions'], summary: 'Start trial (Owner)', responses: { '200': ok } }, }, '/subscriptions/checkout': { post: { tags: ['Subscriptions'], summary: 'Checkout new subscription (Owner)', responses: { '200': ok } }, }, '/subscriptions/change-plan': { post: { tags: ['Subscriptions'], summary: 'Change plan (Owner)', responses: { '200': ok } }, }, '/subscriptions/cancel': { post: { tags: ['Subscriptions'], summary: 'Cancel subscription (Owner)', responses: { '200': ok } }, }, '/subscriptions/reactivate': { post: { tags: ['Subscriptions'], summary: 'Reactivate subscription (Owner)', responses: { '200': ok } }, }, '/subscriptions/resume': { post: { tags: ['Subscriptions'], summary: 'Resume subscription (Owner)', responses: { '200': ok } }, }, // ════════════════════════════════════════════════════════════════ // MARKETPLACE (public — no auth required) // ════════════════════════════════════════════════════════════════ '/marketplace/cities': { get: { tags: ['Marketplace'], summary: 'Cities with active companies', security: [], responses: { '200': ok } }, }, '/marketplace/companies': { get: { tags: ['Marketplace'], summary: 'List companies', security: [], responses: { '200': ok } }, }, '/marketplace/offers': { get: { tags: ['Marketplace'], summary: 'Public offers', security: [], responses: { '200': ok } }, }, '/marketplace/search': { get: { tags: ['Marketplace'], summary: 'Search available vehicles', security: [], parameters: [ { name: 'city', in: 'query', schema: { type: 'string' } }, { name: 'startDate', in: 'query', schema: { type: 'string', format: 'date-time' } }, { name: 'endDate', in: 'query', schema: { type: 'string', format: 'date-time' } }, { name: 'category', in: 'query', schema: { type: 'string' } }, ], responses: { '200': ok }, }, }, '/marketplace/reservations': { post: { tags: ['Marketplace'], summary: 'Create marketplace booking', security: [], responses: { '201': ok } }, }, '/marketplace/offers/{code}/validate': { post: { tags: ['Marketplace'], summary: 'Validate promo code', security: [], parameters: [{ name: 'code', in: 'path', required: true, schema: { type: 'string' } }], responses: { '200': ok } }, }, '/marketplace/review/{token}': { get: { tags: ['Marketplace'], summary: 'Get review form by token', security: [], parameters: [{ name: 'token', in: 'path', required: true, schema: { type: 'string' } }], responses: { '200': ok } }, post: { tags: ['Marketplace'], summary: 'Submit review', security: [], parameters: [{ name: 'token', in: 'path', required: true, schema: { type: 'string' } }], responses: { '200': ok } }, }, '/marketplace/{slug}': { get: { tags: ['Marketplace'], summary: 'Company public page', security: [], parameters: [{ name: 'slug', in: 'path', required: true, schema: { type: 'string' } }], responses: { '200': ok } }, }, '/marketplace/{slug}/reviews': { get: { tags: ['Marketplace'], summary: 'Company reviews', security: [], parameters: [{ name: 'slug', in: 'path', required: true, schema: { type: 'string' } }], responses: { '200': ok } }, }, '/marketplace/{slug}/vehicles': { get: { tags: ['Marketplace'], summary: 'Company vehicles', security: [], parameters: [{ name: 'slug', in: 'path', required: true, schema: { type: 'string' } }], responses: { '200': ok } }, }, '/marketplace/{slug}/vehicles/{id}': { get: { tags: ['Marketplace'], summary: 'Vehicle details', security: [], parameters: [{ name: 'slug', in: 'path', required: true, schema: { type: 'string' } }, idPath()], responses: { '200': ok } }, }, '/marketplace/{slug}/offers': { get: { tags: ['Marketplace'], summary: 'Company offers', security: [], parameters: [{ name: 'slug', in: 'path', required: true, schema: { type: 'string' } }], responses: { '200': ok } }, }, // ════════════════════════════════════════════════════════════════ // SITE (white-label) // ════════════════════════════════════════════════════════════════ '/site/platform/homepage': { get: { tags: ['Site'], summary: 'Platform homepage content', security: [], responses: { '200': ok } }, }, '/site/platform/pricing': { get: { tags: ['Site'], summary: 'Platform pricing page content', security: [], responses: { '200': ok } }, }, '/site/{slug}/brand': { get: { tags: ['Site'], summary: 'Brand config for white-label site', security: [], parameters: [{ name: 'slug', in: 'path', required: true, schema: { type: 'string' } }], responses: { '200': ok } }, }, '/site/{slug}/vehicles': { get: { tags: ['Site'], summary: 'Vehicles for white-label site', security: [], parameters: [{ name: 'slug', in: 'path', required: true, schema: { type: 'string' } }], responses: { '200': ok } }, }, '/site/{slug}/vehicles/{id}': { get: { tags: ['Site'], summary: 'Vehicle detail', security: [], parameters: [{ name: 'slug', in: 'path', required: true, schema: { type: 'string' } }, idPath()], responses: { '200': ok } }, }, '/site/{slug}/offers': { get: { tags: ['Site'], summary: 'Offers for white-label site', security: [], parameters: [{ name: 'slug', in: 'path', required: true, schema: { type: 'string' } }], responses: { '200': ok } }, }, '/site/{slug}/booking-options': { get: { tags: ['Site'], summary: 'Booking options', security: [], parameters: [{ name: 'slug', in: 'path', required: true, schema: { type: 'string' } }], responses: { '200': ok } }, }, '/site/{slug}/availability': { post: { tags: ['Site'], summary: 'Check availability', security: [], parameters: [{ name: 'slug', in: 'path', required: true, schema: { type: 'string' } }], responses: { '200': ok } }, }, '/site/{slug}/book/validate-code': { post: { tags: ['Site'], summary: 'Validate promo code', security: [], parameters: [{ name: 'slug', in: 'path', required: true, schema: { type: 'string' } }], responses: { '200': ok } }, }, '/site/{slug}/book': { post: { tags: ['Site'], summary: 'Create booking', security: [], parameters: [{ name: 'slug', in: 'path', required: true, schema: { type: 'string' } }], responses: { '201': ok } }, }, '/site/{slug}/booking/{id}': { get: { tags: ['Site'], summary: 'Get booking status', security: [], parameters: [{ name: 'slug', in: 'path', required: true, schema: { type: 'string' } }, idPath()], responses: { '200': ok } }, }, '/site/{slug}/booking/{id}/pay': { post: { tags: ['Site'], summary: 'Pay booking', security: [], parameters: [{ name: 'slug', in: 'path', required: true, schema: { type: 'string' } }, idPath()], responses: { '200': ok } }, }, '/site/{slug}/contact': { post: { tags: ['Site'], summary: 'Contact form', security: [], parameters: [{ name: 'slug', in: 'path', required: true, schema: { type: 'string' } }], responses: { '200': ok } }, }, // ════════════════════════════════════════════════════════════════ // ADMIN // ════════════════════════════════════════════════════════════════ '/admin/auth/login': { post: { tags: ['Admin'], summary: 'Admin login', security: [], responses: { '200': ok } }, }, '/admin/auth/forgot-password': { post: { tags: ['Admin'], summary: 'Admin forgot password', security: [], responses: { '200': ok } }, }, '/admin/auth/reset-password': { post: { tags: ['Admin'], summary: 'Admin reset password', security: [], responses: { '200': ok } }, }, '/admin/auth/me': { get: { tags: ['Admin'], summary: 'Current admin profile', responses: { '200': ok } }, }, '/admin/auth/2fa/setup': { post: { tags: ['Admin'], summary: 'Setup 2FA', responses: { '200': ok } }, }, '/admin/auth/2fa/verify': { post: { tags: ['Admin'], summary: 'Verify 2FA code', responses: { '200': ok } }, }, '/admin/companies': { get: { tags: ['Admin'], summary: 'List all companies', responses: { '200': ok } }, }, '/admin/companies/{id}': { get: { tags: ['Admin'], summary: 'Get company', parameters: [idPath()], responses: { '200': ok } }, patch: { tags: ['Admin'], summary: 'Update company', parameters: [idPath()], responses: { '200': ok } }, delete: { tags: ['Admin'], summary: 'Delete company (Admin)', parameters: [idPath()], responses: { '200': ok } }, }, '/admin/companies/{id}/status': { patch: { tags: ['Admin'], summary: 'Update company status', parameters: [idPath()], responses: { '200': ok } }, }, '/admin/companies/{id}/impersonate': { post: { tags: ['Admin'], summary: 'Impersonate company (Admin)', parameters: [idPath()], responses: { '200': ok } }, }, '/admin/renters': { get: { tags: ['Admin'], summary: 'List renters', responses: { '200': ok } }, }, '/admin/renters/{id}/block': { post: { tags: ['Admin'], summary: 'Block renter', parameters: [idPath()], responses: { '200': ok } }, }, '/admin/renters/{id}/unblock': { post: { tags: ['Admin'], summary: 'Unblock renter', parameters: [idPath()], responses: { '200': ok } }, }, '/admin/metrics': { get: { tags: ['Admin'], summary: 'Platform metrics (Finance)', responses: { '200': ok } }, }, '/admin/notifications': { get: { tags: ['Admin'], summary: 'Admin notifications', responses: { '200': ok } }, }, '/admin/audit-logs': { get: { tags: ['Admin'], summary: 'Audit logs (Admin)', responses: { '200': ok } }, }, '/admin/admins': { get: { tags: ['Admin'], summary: 'List admins (Super Admin)', responses: { '200': ok } }, post: { tags: ['Admin'], summary: 'Create admin (Super Admin)', responses: { '201': ok } }, }, }, }; //# sourceMappingURL=openapi.js.map