@vulog/aima-booking 1.2.42 → 1.2.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -157,10 +157,10 @@ const getScheduledBookingById = async (client, bookingId) => {
157
157
  //#endregion
158
158
  //#region src/getAvailableVehicles.ts
159
159
  /** ISO date-time without milliseconds (e.g. 2025-02-10T12:00:00Z or 2025-02-10T12:00:00+01:00). */
160
- const isoDateTimeNoMs = zod.z.string().trim().datetime({ precision: 0 });
160
+ const isoDateTimeNoMs$2 = zod.z.string().trim().datetime({ precision: 0 });
161
161
  const getAvailableVehiclesSchema = zod.z.object({
162
162
  stationId: zod.z.string().trim().min(1),
163
- startDate: isoDateTimeNoMs
163
+ startDate: isoDateTimeNoMs$2
164
164
  });
165
165
  const getAvailableVehicles = async (client, stationId, startDate) => {
166
166
  const result = getAvailableVehiclesSchema.safeParse({
@@ -526,11 +526,117 @@ const createSubscription = async (client, body) => {
526
526
  return client.post(`/boapi/proxy/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/subscription/bookingrequests`, result.data).then(({ data }) => data);
527
527
  };
528
528
  //#endregion
529
+ //#region src/createBookingRequest.ts
530
+ const createBookingRequestBodySchema = zod.z.object({
531
+ startDate: zod.z.string().trim().min(1),
532
+ endDate: zod.z.string().trim().min(1),
533
+ modelId: zod.z.number().int().positive(),
534
+ profileId: zod.z.string().trim().min(1).uuid(),
535
+ serviceId: zod.z.string().trim().min(1).uuid(),
536
+ userId: zod.z.string().uuid().optional(),
537
+ vehicleId: zod.z.string().uuid().optional(),
538
+ station: zod.z.string().optional(),
539
+ latitude: zod.z.number().optional(),
540
+ longitude: zod.z.number().optional(),
541
+ radius: zod.z.number().int().optional(),
542
+ email: zod.z.string().email().optional(),
543
+ notes: zod.z.string().optional(),
544
+ plannedReturnDate: zod.z.string().optional(),
545
+ deliveryAddress: zod.z.string().optional(),
546
+ deliveryAddressAdditionalInfo: zod.z.string().optional(),
547
+ deliveryCity: zod.z.string().optional(),
548
+ deliveryPostalCode: zod.z.string().optional(),
549
+ dropOffStation: zod.z.string().optional(),
550
+ rollingContract: zod.z.boolean().optional(),
551
+ planDurationInMonths: zod.z.number().int().optional(),
552
+ planName: zod.z.string().optional(),
553
+ parentId: zod.z.string().optional(),
554
+ contractType: zod.z.enum(["SVS", "MVS"]).optional(),
555
+ productIds: zod.z.array(zod.z.string()).optional(),
556
+ preallocatedVehicleId: zod.z.string().optional(),
557
+ bookingReferenceId: zod.z.string().optional(),
558
+ providedPricingId: zod.z.string().uuid().optional(),
559
+ preferredPaymentMethods: zod.z.array(zod.z.object({
560
+ pspReference: zod.z.string(),
561
+ amount: zod.z.number()
562
+ })).optional(),
563
+ requiresActionReturnURL: zod.z.string().optional(),
564
+ cityId: zod.z.string().optional()
565
+ });
566
+ /**
567
+ * Create a new booking request.
568
+ *
569
+ * Swagger: `POST /scheduledBooking/fleets/{fleetId}/bookingrequests` (admin-booking).
570
+ */
571
+ const createBookingRequest = async (client, body, options = {}) => {
572
+ const result = createBookingRequestBodySchema.safeParse(body);
573
+ if (!result.success) throw new TypeError("Invalid args", { cause: result.error.issues });
574
+ const query = options.userStatusCheckRequired !== void 0 ? `?userStatusCheckRequired=${options.userStatusCheckRequired}` : "";
575
+ return client.post(`/boapi/proxy/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/bookingrequests${query}`, {
576
+ ...result.data,
577
+ fleetId: client.clientOptions.fleetId
578
+ }).then(({ data }) => data);
579
+ };
580
+ //#endregion
581
+ //#region src/getAvailableModels.ts
582
+ /** ISO date-time without milliseconds (e.g. 2020-09-20T00:00:00Z or 2020-09-20T00:00:00+01:00). */
583
+ const isoDateTimeNoMs$1 = zod.z.string().trim().datetime({ precision: 0 });
584
+ const getAvailableModelsSchema = zod.z.object({
585
+ startDate: isoDateTimeNoMs$1,
586
+ endDate: isoDateTimeNoMs$1,
587
+ cityId: zod.z.string().trim().min(1).optional(),
588
+ userId: zod.z.string().uuid().optional(),
589
+ profileId: zod.z.string().uuid().optional(),
590
+ oneWayTrip: zod.z.boolean().optional(),
591
+ showUnavailableModels: zod.z.boolean().optional()
592
+ });
593
+ /**
594
+ * Get available models grouped by station in a given time range.
595
+ *
596
+ * Swagger: `GET /scheduledBooking/fleets/{fleetId}/stations/models` (admin-booking / internal).
597
+ */
598
+ const getAvailableModels = async (client, params) => {
599
+ const result = getAvailableModelsSchema.safeParse(params);
600
+ if (!result.success) throw new TypeError("Invalid args", { cause: result.error.issues });
601
+ const searchParams = new URLSearchParams();
602
+ for (const [key, value] of Object.entries(result.data)) if (value !== void 0) searchParams.append(key, String(value));
603
+ return client.get(`/boapi/proxy/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/stations/models?${searchParams.toString()}`).then(({ data }) => data);
604
+ };
605
+ //#endregion
606
+ //#region src/getStationUnavailability.ts
607
+ /** ISO date-time without milliseconds (e.g. 2021-01-01T00:00:00Z). */
608
+ const isoDateTimeNoMs = zod.z.string().trim().datetime({ precision: 0 });
609
+ const getStationUnavailabilitySchema = zod.z.object({
610
+ stationId: zod.z.string().uuid(),
611
+ from: isoDateTimeNoMs,
612
+ to: isoDateTimeNoMs,
613
+ serviceId: zod.z.string().uuid()
614
+ });
615
+ /**
616
+ * Get the list of vehicle unavailabilities for a given station over a period.
617
+ *
618
+ * Swagger: `GET /fleets/{fleetId}/stations/{stationId}/unavailability` (admin-booking,
619
+ * operationId `getVehicleCalendarForPeriod`).
620
+ */
621
+ const getStationUnavailability = async (client, params) => {
622
+ const result = getStationUnavailabilitySchema.safeParse(params);
623
+ if (!result.success) throw new TypeError("Invalid args", { cause: result.error.issues });
624
+ const { stationId, from, to, serviceId } = result.data;
625
+ const searchParams = new URLSearchParams({
626
+ from,
627
+ to,
628
+ serviceId
629
+ });
630
+ return client.get(`/boapi/proxy/user/fleets/${client.clientOptions.fleetId}/stations/${stationId}/unavailability?${searchParams.toString()}`).then(({ data }) => data);
631
+ };
632
+ //#endregion
529
633
  exports.allocateVehicle = allocateVehicle;
530
634
  exports.cancelBookingRequest = cancelBookingRequest;
635
+ exports.createBookingRequest = createBookingRequest;
531
636
  exports.createSubscription = createSubscription;
532
637
  exports.deallocateVehicle = deallocateVehicle;
533
638
  exports.getAdditionalDrivers = getAdditionalDrivers;
639
+ exports.getAvailableModels = getAvailableModels;
534
640
  exports.getAvailableVehicles = getAvailableVehicles;
535
641
  exports.getBookingRequestById = getBookingRequestById;
536
642
  exports.getBookingRequestByTrip = getBookingRequestByTrip;
@@ -542,6 +648,7 @@ exports.getScheduleBookingRequests = getScheduleBookingRequests;
542
648
  exports.getScheduledBookingById = getScheduledBookingById;
543
649
  exports.getSlaves = getSlaves;
544
650
  exports.getStationById = getStationById;
651
+ exports.getStationUnavailability = getStationUnavailability;
545
652
  exports.getStations = getStations;
546
653
  exports.getSubscriptionBookingRequestById = getSubscriptionBookingRequestById;
547
654
  exports.getSubscriptionBookingRequests = getSubscriptionBookingRequests;
package/dist/index.d.cts CHANGED
@@ -317,6 +317,71 @@ type BookingRequestSlave = {
317
317
  traveledDistance: number;
318
318
  energyLevelEnd: number;
319
319
  };
320
+ /** Mileage allowance for an available model (Swagger: `MileageAllowanceDTO`). */
321
+ type MileageAllowance = {
322
+ allowancePerDay?: number;
323
+ totalAllowance?: number;
324
+ pricePerExceedingUnit?: number;
325
+ };
326
+ /** Estimated product embedded in a price breakdown (Swagger: `EstimatedProductDTO`). */
327
+ type EstimatedProduct = {
328
+ productId?: string;
329
+ price?: number;
330
+ };
331
+ /** Price breakdown for an available model (Swagger: `PriceBreakdownDTO`). */
332
+ type PriceBreakdown = {
333
+ tripPrice?: number;
334
+ productsPrice?: number;
335
+ productDetails?: EstimatedProduct[];
336
+ };
337
+ /** Pricing info for an available model (Swagger: `PricingInfo`). */
338
+ type PricingInfo = {
339
+ pricingId?: string;
340
+ type?: string;
341
+ priceBreakdown?: PriceBreakdown;
342
+ };
343
+ /** Available model entry returned by `getAvailableModels` (Swagger: `BookingRequestModelDTO`). */
344
+ type AvailableModel = {
345
+ id: number;
346
+ price?: string;
347
+ prePaymentPrice?: number;
348
+ mileageAllowance?: MileageAllowance;
349
+ pricingInfo?: PricingInfo;
350
+ };
351
+ /** Station entry returned by `getAvailableModels` (Swagger: `StationDTO`). */
352
+ type StationWithAvailableModels = {
353
+ id: string;
354
+ zoneId: string;
355
+ poiId: string;
356
+ models: AvailableModel[];
357
+ taxZoneId?: string;
358
+ cityId?: string;
359
+ serviceId?: string;
360
+ fleetId?: string;
361
+ openTime?: string;
362
+ closeTime?: string;
363
+ };
364
+ /** Single unavailability entry in a station vehicle calendar (Swagger: `UnavailabilityDTO`). */
365
+ type VehicleUnavailability = {
366
+ id?: string;
367
+ vehicleId?: string;
368
+ modelId?: number;
369
+ from?: string;
370
+ to?: string;
371
+ toWithMargin?: string;
372
+ type?: 'BOOKING' | 'MAINTENANCE';
373
+ userId?: string;
374
+ reason?: string;
375
+ serviceId?: string;
376
+ };
377
+ /** Vehicle calendar for a station over a period (Swagger: `VehicleCalendarResponseDTO`). */
378
+ type StationVehicleCalendar = {
379
+ timezone?: string;
380
+ from?: string;
381
+ to?: string;
382
+ vehicleIds?: string[];
383
+ unavailabilities?: VehicleUnavailability[];
384
+ };
320
385
  //#endregion
321
386
  //#region src/getBookingRequests.d.ts
322
387
  declare const BookingRequestStatusSchema: z.ZodEnum<{
@@ -490,4 +555,85 @@ type CreateSubscriptionBody = {
490
555
  };
491
556
  declare const createSubscription: (client: Client, body: CreateSubscriptionBody) => Promise<BookingRequest>;
492
557
  //#endregion
493
- export { AdditionalDriver, AvailableVehiclesResponse, BRPaymentItem, BaseBookingRequest, BookingCredit, BookingRequest, type BookingRequestFilters, BookingRequestSlave, type BookingRequestStatus, Contract, type CreateSubscriptionBody, CustomPrice, DayOpeningHours, Days, GeoInfo, IFormatSlave, IFormatSubscription, type Include, type IncludeStation, Master, OpeningHours, PaymentReceipts, PreferredPaymentMethod, SATBookingRequest, type SATBookingRequestStatus, Service, ServiceInfo, type ServiceType, Slave, Station, Timetable, TriggerBRPaymentResponse, Vehicle, allocateVehicle, cancelBookingRequest, createSubscription, deallocateVehicle, getAdditionalDrivers, getAvailableVehicles, getBookingRequestById, getBookingRequestByTrip, getBookingRequests, getBookingRequestsByUserId, getDigitalContracts, getSATBookingRequests, getScheduleBookingRequests, getScheduledBookingById, getSlaves, getStationById, getStations, getSubscriptionBookingRequestById, getSubscriptionBookingRequests, getSubscriptionsByUserId, releaseBRPayment, submitCancellationRequest, triggerBRPayment, updateScheduleBooking };
558
+ //#region src/createBookingRequest.d.ts
559
+ type CreateBookingRequestBody = {
560
+ startDate: string;
561
+ endDate: string;
562
+ modelId: number;
563
+ profileId: string;
564
+ serviceId: string;
565
+ userId?: string;
566
+ vehicleId?: string;
567
+ station?: string;
568
+ latitude?: number;
569
+ longitude?: number;
570
+ radius?: number;
571
+ email?: string;
572
+ notes?: string;
573
+ plannedReturnDate?: string;
574
+ deliveryAddress?: string;
575
+ deliveryAddressAdditionalInfo?: string;
576
+ deliveryCity?: string;
577
+ deliveryPostalCode?: string;
578
+ dropOffStation?: string;
579
+ rollingContract?: boolean;
580
+ planDurationInMonths?: number;
581
+ planName?: string;
582
+ parentId?: string;
583
+ contractType?: 'SVS' | 'MVS';
584
+ productIds?: string[];
585
+ preallocatedVehicleId?: string;
586
+ bookingReferenceId?: string;
587
+ providedPricingId?: string;
588
+ preferredPaymentMethods?: {
589
+ pspReference: string;
590
+ amount: number;
591
+ }[];
592
+ requiresActionReturnURL?: string;
593
+ cityId?: string;
594
+ };
595
+ type CreateBookingRequestOptions = {
596
+ /** When false, bypass the user status check (operator use). Default true server-side. */userStatusCheckRequired?: boolean;
597
+ };
598
+ /**
599
+ * Create a new booking request.
600
+ *
601
+ * Swagger: `POST /scheduledBooking/fleets/{fleetId}/bookingrequests` (admin-booking).
602
+ */
603
+ declare const createBookingRequest: (client: Client, body: CreateBookingRequestBody, options?: CreateBookingRequestOptions) => Promise<BookingRequest>;
604
+ //#endregion
605
+ //#region src/getAvailableModels.d.ts
606
+ declare const getAvailableModelsSchema: z.ZodObject<{
607
+ startDate: z.ZodString;
608
+ endDate: z.ZodString;
609
+ cityId: z.ZodOptional<z.ZodString>;
610
+ userId: z.ZodOptional<z.ZodString>;
611
+ profileId: z.ZodOptional<z.ZodString>;
612
+ oneWayTrip: z.ZodOptional<z.ZodBoolean>;
613
+ showUnavailableModels: z.ZodOptional<z.ZodBoolean>;
614
+ }, z.core.$strip>;
615
+ type GetAvailableModelsParams = z.infer<typeof getAvailableModelsSchema>;
616
+ /**
617
+ * Get available models grouped by station in a given time range.
618
+ *
619
+ * Swagger: `GET /scheduledBooking/fleets/{fleetId}/stations/models` (admin-booking / internal).
620
+ */
621
+ declare const getAvailableModels: (client: Client, params: GetAvailableModelsParams) => Promise<StationWithAvailableModels[]>;
622
+ //#endregion
623
+ //#region src/getStationUnavailability.d.ts
624
+ declare const getStationUnavailabilitySchema: z.ZodObject<{
625
+ stationId: z.ZodString;
626
+ from: z.ZodString;
627
+ to: z.ZodString;
628
+ serviceId: z.ZodString;
629
+ }, z.core.$strip>;
630
+ type GetStationUnavailabilityParams = z.infer<typeof getStationUnavailabilitySchema>;
631
+ /**
632
+ * Get the list of vehicle unavailabilities for a given station over a period.
633
+ *
634
+ * Swagger: `GET /fleets/{fleetId}/stations/{stationId}/unavailability` (admin-booking,
635
+ * operationId `getVehicleCalendarForPeriod`).
636
+ */
637
+ declare const getStationUnavailability: (client: Client, params: GetStationUnavailabilityParams) => Promise<StationVehicleCalendar>;
638
+ //#endregion
639
+ export { AdditionalDriver, AvailableModel, AvailableVehiclesResponse, BRPaymentItem, BaseBookingRequest, BookingCredit, BookingRequest, type BookingRequestFilters, BookingRequestSlave, type BookingRequestStatus, Contract, type CreateBookingRequestBody, type CreateBookingRequestOptions, type CreateSubscriptionBody, CustomPrice, DayOpeningHours, Days, EstimatedProduct, GeoInfo, type GetAvailableModelsParams, type GetStationUnavailabilityParams, IFormatSlave, IFormatSubscription, type Include, type IncludeStation, Master, MileageAllowance, OpeningHours, PaymentReceipts, PreferredPaymentMethod, PriceBreakdown, PricingInfo, SATBookingRequest, type SATBookingRequestStatus, Service, ServiceInfo, type ServiceType, Slave, Station, StationVehicleCalendar, StationWithAvailableModels, Timetable, TriggerBRPaymentResponse, Vehicle, VehicleUnavailability, allocateVehicle, cancelBookingRequest, createBookingRequest, createSubscription, deallocateVehicle, getAdditionalDrivers, getAvailableModels, getAvailableVehicles, getBookingRequestById, getBookingRequestByTrip, getBookingRequests, getBookingRequestsByUserId, getDigitalContracts, getSATBookingRequests, getScheduleBookingRequests, getScheduledBookingById, getSlaves, getStationById, getStationUnavailability, getStations, getSubscriptionBookingRequestById, getSubscriptionBookingRequests, getSubscriptionsByUserId, releaseBRPayment, submitCancellationRequest, triggerBRPayment, updateScheduleBooking };
package/dist/index.d.mts CHANGED
@@ -317,6 +317,71 @@ type BookingRequestSlave = {
317
317
  traveledDistance: number;
318
318
  energyLevelEnd: number;
319
319
  };
320
+ /** Mileage allowance for an available model (Swagger: `MileageAllowanceDTO`). */
321
+ type MileageAllowance = {
322
+ allowancePerDay?: number;
323
+ totalAllowance?: number;
324
+ pricePerExceedingUnit?: number;
325
+ };
326
+ /** Estimated product embedded in a price breakdown (Swagger: `EstimatedProductDTO`). */
327
+ type EstimatedProduct = {
328
+ productId?: string;
329
+ price?: number;
330
+ };
331
+ /** Price breakdown for an available model (Swagger: `PriceBreakdownDTO`). */
332
+ type PriceBreakdown = {
333
+ tripPrice?: number;
334
+ productsPrice?: number;
335
+ productDetails?: EstimatedProduct[];
336
+ };
337
+ /** Pricing info for an available model (Swagger: `PricingInfo`). */
338
+ type PricingInfo = {
339
+ pricingId?: string;
340
+ type?: string;
341
+ priceBreakdown?: PriceBreakdown;
342
+ };
343
+ /** Available model entry returned by `getAvailableModels` (Swagger: `BookingRequestModelDTO`). */
344
+ type AvailableModel = {
345
+ id: number;
346
+ price?: string;
347
+ prePaymentPrice?: number;
348
+ mileageAllowance?: MileageAllowance;
349
+ pricingInfo?: PricingInfo;
350
+ };
351
+ /** Station entry returned by `getAvailableModels` (Swagger: `StationDTO`). */
352
+ type StationWithAvailableModels = {
353
+ id: string;
354
+ zoneId: string;
355
+ poiId: string;
356
+ models: AvailableModel[];
357
+ taxZoneId?: string;
358
+ cityId?: string;
359
+ serviceId?: string;
360
+ fleetId?: string;
361
+ openTime?: string;
362
+ closeTime?: string;
363
+ };
364
+ /** Single unavailability entry in a station vehicle calendar (Swagger: `UnavailabilityDTO`). */
365
+ type VehicleUnavailability = {
366
+ id?: string;
367
+ vehicleId?: string;
368
+ modelId?: number;
369
+ from?: string;
370
+ to?: string;
371
+ toWithMargin?: string;
372
+ type?: 'BOOKING' | 'MAINTENANCE';
373
+ userId?: string;
374
+ reason?: string;
375
+ serviceId?: string;
376
+ };
377
+ /** Vehicle calendar for a station over a period (Swagger: `VehicleCalendarResponseDTO`). */
378
+ type StationVehicleCalendar = {
379
+ timezone?: string;
380
+ from?: string;
381
+ to?: string;
382
+ vehicleIds?: string[];
383
+ unavailabilities?: VehicleUnavailability[];
384
+ };
320
385
  //#endregion
321
386
  //#region src/getBookingRequests.d.ts
322
387
  declare const BookingRequestStatusSchema: z.ZodEnum<{
@@ -490,4 +555,85 @@ type CreateSubscriptionBody = {
490
555
  };
491
556
  declare const createSubscription: (client: Client, body: CreateSubscriptionBody) => Promise<BookingRequest>;
492
557
  //#endregion
493
- export { AdditionalDriver, AvailableVehiclesResponse, BRPaymentItem, BaseBookingRequest, BookingCredit, BookingRequest, type BookingRequestFilters, BookingRequestSlave, type BookingRequestStatus, Contract, type CreateSubscriptionBody, CustomPrice, DayOpeningHours, Days, GeoInfo, IFormatSlave, IFormatSubscription, type Include, type IncludeStation, Master, OpeningHours, PaymentReceipts, PreferredPaymentMethod, SATBookingRequest, type SATBookingRequestStatus, Service, ServiceInfo, type ServiceType, Slave, Station, Timetable, TriggerBRPaymentResponse, Vehicle, allocateVehicle, cancelBookingRequest, createSubscription, deallocateVehicle, getAdditionalDrivers, getAvailableVehicles, getBookingRequestById, getBookingRequestByTrip, getBookingRequests, getBookingRequestsByUserId, getDigitalContracts, getSATBookingRequests, getScheduleBookingRequests, getScheduledBookingById, getSlaves, getStationById, getStations, getSubscriptionBookingRequestById, getSubscriptionBookingRequests, getSubscriptionsByUserId, releaseBRPayment, submitCancellationRequest, triggerBRPayment, updateScheduleBooking };
558
+ //#region src/createBookingRequest.d.ts
559
+ type CreateBookingRequestBody = {
560
+ startDate: string;
561
+ endDate: string;
562
+ modelId: number;
563
+ profileId: string;
564
+ serviceId: string;
565
+ userId?: string;
566
+ vehicleId?: string;
567
+ station?: string;
568
+ latitude?: number;
569
+ longitude?: number;
570
+ radius?: number;
571
+ email?: string;
572
+ notes?: string;
573
+ plannedReturnDate?: string;
574
+ deliveryAddress?: string;
575
+ deliveryAddressAdditionalInfo?: string;
576
+ deliveryCity?: string;
577
+ deliveryPostalCode?: string;
578
+ dropOffStation?: string;
579
+ rollingContract?: boolean;
580
+ planDurationInMonths?: number;
581
+ planName?: string;
582
+ parentId?: string;
583
+ contractType?: 'SVS' | 'MVS';
584
+ productIds?: string[];
585
+ preallocatedVehicleId?: string;
586
+ bookingReferenceId?: string;
587
+ providedPricingId?: string;
588
+ preferredPaymentMethods?: {
589
+ pspReference: string;
590
+ amount: number;
591
+ }[];
592
+ requiresActionReturnURL?: string;
593
+ cityId?: string;
594
+ };
595
+ type CreateBookingRequestOptions = {
596
+ /** When false, bypass the user status check (operator use). Default true server-side. */userStatusCheckRequired?: boolean;
597
+ };
598
+ /**
599
+ * Create a new booking request.
600
+ *
601
+ * Swagger: `POST /scheduledBooking/fleets/{fleetId}/bookingrequests` (admin-booking).
602
+ */
603
+ declare const createBookingRequest: (client: Client, body: CreateBookingRequestBody, options?: CreateBookingRequestOptions) => Promise<BookingRequest>;
604
+ //#endregion
605
+ //#region src/getAvailableModels.d.ts
606
+ declare const getAvailableModelsSchema: z.ZodObject<{
607
+ startDate: z.ZodString;
608
+ endDate: z.ZodString;
609
+ cityId: z.ZodOptional<z.ZodString>;
610
+ userId: z.ZodOptional<z.ZodString>;
611
+ profileId: z.ZodOptional<z.ZodString>;
612
+ oneWayTrip: z.ZodOptional<z.ZodBoolean>;
613
+ showUnavailableModels: z.ZodOptional<z.ZodBoolean>;
614
+ }, z.core.$strip>;
615
+ type GetAvailableModelsParams = z.infer<typeof getAvailableModelsSchema>;
616
+ /**
617
+ * Get available models grouped by station in a given time range.
618
+ *
619
+ * Swagger: `GET /scheduledBooking/fleets/{fleetId}/stations/models` (admin-booking / internal).
620
+ */
621
+ declare const getAvailableModels: (client: Client, params: GetAvailableModelsParams) => Promise<StationWithAvailableModels[]>;
622
+ //#endregion
623
+ //#region src/getStationUnavailability.d.ts
624
+ declare const getStationUnavailabilitySchema: z.ZodObject<{
625
+ stationId: z.ZodString;
626
+ from: z.ZodString;
627
+ to: z.ZodString;
628
+ serviceId: z.ZodString;
629
+ }, z.core.$strip>;
630
+ type GetStationUnavailabilityParams = z.infer<typeof getStationUnavailabilitySchema>;
631
+ /**
632
+ * Get the list of vehicle unavailabilities for a given station over a period.
633
+ *
634
+ * Swagger: `GET /fleets/{fleetId}/stations/{stationId}/unavailability` (admin-booking,
635
+ * operationId `getVehicleCalendarForPeriod`).
636
+ */
637
+ declare const getStationUnavailability: (client: Client, params: GetStationUnavailabilityParams) => Promise<StationVehicleCalendar>;
638
+ //#endregion
639
+ export { AdditionalDriver, AvailableModel, AvailableVehiclesResponse, BRPaymentItem, BaseBookingRequest, BookingCredit, BookingRequest, type BookingRequestFilters, BookingRequestSlave, type BookingRequestStatus, Contract, type CreateBookingRequestBody, type CreateBookingRequestOptions, type CreateSubscriptionBody, CustomPrice, DayOpeningHours, Days, EstimatedProduct, GeoInfo, type GetAvailableModelsParams, type GetStationUnavailabilityParams, IFormatSlave, IFormatSubscription, type Include, type IncludeStation, Master, MileageAllowance, OpeningHours, PaymentReceipts, PreferredPaymentMethod, PriceBreakdown, PricingInfo, SATBookingRequest, type SATBookingRequestStatus, Service, ServiceInfo, type ServiceType, Slave, Station, StationVehicleCalendar, StationWithAvailableModels, Timetable, TriggerBRPaymentResponse, Vehicle, VehicleUnavailability, allocateVehicle, cancelBookingRequest, createBookingRequest, createSubscription, deallocateVehicle, getAdditionalDrivers, getAvailableModels, getAvailableVehicles, getBookingRequestById, getBookingRequestByTrip, getBookingRequests, getBookingRequestsByUserId, getDigitalContracts, getSATBookingRequests, getScheduleBookingRequests, getScheduledBookingById, getSlaves, getStationById, getStationUnavailability, getStations, getSubscriptionBookingRequestById, getSubscriptionBookingRequests, getSubscriptionsByUserId, releaseBRPayment, submitCancellationRequest, triggerBRPayment, updateScheduleBooking };
package/dist/index.mjs CHANGED
@@ -156,10 +156,10 @@ const getScheduledBookingById = async (client, bookingId) => {
156
156
  //#endregion
157
157
  //#region src/getAvailableVehicles.ts
158
158
  /** ISO date-time without milliseconds (e.g. 2025-02-10T12:00:00Z or 2025-02-10T12:00:00+01:00). */
159
- const isoDateTimeNoMs = z.string().trim().datetime({ precision: 0 });
159
+ const isoDateTimeNoMs$2 = z.string().trim().datetime({ precision: 0 });
160
160
  const getAvailableVehiclesSchema = z.object({
161
161
  stationId: z.string().trim().min(1),
162
- startDate: isoDateTimeNoMs
162
+ startDate: isoDateTimeNoMs$2
163
163
  });
164
164
  const getAvailableVehicles = async (client, stationId, startDate) => {
165
165
  const result = getAvailableVehiclesSchema.safeParse({
@@ -525,4 +525,108 @@ const createSubscription = async (client, body) => {
525
525
  return client.post(`/boapi/proxy/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/subscription/bookingrequests`, result.data).then(({ data }) => data);
526
526
  };
527
527
  //#endregion
528
- export { allocateVehicle, cancelBookingRequest, createSubscription, deallocateVehicle, getAdditionalDrivers, getAvailableVehicles, getBookingRequestById, getBookingRequestByTrip, getBookingRequests, getBookingRequestsByUserId, getDigitalContracts, getSATBookingRequests, getScheduleBookingRequests, getScheduledBookingById, getSlaves, getStationById, getStations, getSubscriptionBookingRequestById, getSubscriptionBookingRequests, getSubscriptionsByUserId, releaseBRPayment, submitCancellationRequest, triggerBRPayment, updateScheduleBooking };
528
+ //#region src/createBookingRequest.ts
529
+ const createBookingRequestBodySchema = z.object({
530
+ startDate: z.string().trim().min(1),
531
+ endDate: z.string().trim().min(1),
532
+ modelId: z.number().int().positive(),
533
+ profileId: z.string().trim().min(1).uuid(),
534
+ serviceId: z.string().trim().min(1).uuid(),
535
+ userId: z.string().uuid().optional(),
536
+ vehicleId: z.string().uuid().optional(),
537
+ station: z.string().optional(),
538
+ latitude: z.number().optional(),
539
+ longitude: z.number().optional(),
540
+ radius: z.number().int().optional(),
541
+ email: z.string().email().optional(),
542
+ notes: z.string().optional(),
543
+ plannedReturnDate: z.string().optional(),
544
+ deliveryAddress: z.string().optional(),
545
+ deliveryAddressAdditionalInfo: z.string().optional(),
546
+ deliveryCity: z.string().optional(),
547
+ deliveryPostalCode: z.string().optional(),
548
+ dropOffStation: z.string().optional(),
549
+ rollingContract: z.boolean().optional(),
550
+ planDurationInMonths: z.number().int().optional(),
551
+ planName: z.string().optional(),
552
+ parentId: z.string().optional(),
553
+ contractType: z.enum(["SVS", "MVS"]).optional(),
554
+ productIds: z.array(z.string()).optional(),
555
+ preallocatedVehicleId: z.string().optional(),
556
+ bookingReferenceId: z.string().optional(),
557
+ providedPricingId: z.string().uuid().optional(),
558
+ preferredPaymentMethods: z.array(z.object({
559
+ pspReference: z.string(),
560
+ amount: z.number()
561
+ })).optional(),
562
+ requiresActionReturnURL: z.string().optional(),
563
+ cityId: z.string().optional()
564
+ });
565
+ /**
566
+ * Create a new booking request.
567
+ *
568
+ * Swagger: `POST /scheduledBooking/fleets/{fleetId}/bookingrequests` (admin-booking).
569
+ */
570
+ const createBookingRequest = async (client, body, options = {}) => {
571
+ const result = createBookingRequestBodySchema.safeParse(body);
572
+ if (!result.success) throw new TypeError("Invalid args", { cause: result.error.issues });
573
+ const query = options.userStatusCheckRequired !== void 0 ? `?userStatusCheckRequired=${options.userStatusCheckRequired}` : "";
574
+ return client.post(`/boapi/proxy/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/bookingrequests${query}`, {
575
+ ...result.data,
576
+ fleetId: client.clientOptions.fleetId
577
+ }).then(({ data }) => data);
578
+ };
579
+ //#endregion
580
+ //#region src/getAvailableModels.ts
581
+ /** ISO date-time without milliseconds (e.g. 2020-09-20T00:00:00Z or 2020-09-20T00:00:00+01:00). */
582
+ const isoDateTimeNoMs$1 = z.string().trim().datetime({ precision: 0 });
583
+ const getAvailableModelsSchema = z.object({
584
+ startDate: isoDateTimeNoMs$1,
585
+ endDate: isoDateTimeNoMs$1,
586
+ cityId: z.string().trim().min(1).optional(),
587
+ userId: z.string().uuid().optional(),
588
+ profileId: z.string().uuid().optional(),
589
+ oneWayTrip: z.boolean().optional(),
590
+ showUnavailableModels: z.boolean().optional()
591
+ });
592
+ /**
593
+ * Get available models grouped by station in a given time range.
594
+ *
595
+ * Swagger: `GET /scheduledBooking/fleets/{fleetId}/stations/models` (admin-booking / internal).
596
+ */
597
+ const getAvailableModels = async (client, params) => {
598
+ const result = getAvailableModelsSchema.safeParse(params);
599
+ if (!result.success) throw new TypeError("Invalid args", { cause: result.error.issues });
600
+ const searchParams = new URLSearchParams();
601
+ for (const [key, value] of Object.entries(result.data)) if (value !== void 0) searchParams.append(key, String(value));
602
+ return client.get(`/boapi/proxy/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/stations/models?${searchParams.toString()}`).then(({ data }) => data);
603
+ };
604
+ //#endregion
605
+ //#region src/getStationUnavailability.ts
606
+ /** ISO date-time without milliseconds (e.g. 2021-01-01T00:00:00Z). */
607
+ const isoDateTimeNoMs = z.string().trim().datetime({ precision: 0 });
608
+ const getStationUnavailabilitySchema = z.object({
609
+ stationId: z.string().uuid(),
610
+ from: isoDateTimeNoMs,
611
+ to: isoDateTimeNoMs,
612
+ serviceId: z.string().uuid()
613
+ });
614
+ /**
615
+ * Get the list of vehicle unavailabilities for a given station over a period.
616
+ *
617
+ * Swagger: `GET /fleets/{fleetId}/stations/{stationId}/unavailability` (admin-booking,
618
+ * operationId `getVehicleCalendarForPeriod`).
619
+ */
620
+ const getStationUnavailability = async (client, params) => {
621
+ const result = getStationUnavailabilitySchema.safeParse(params);
622
+ if (!result.success) throw new TypeError("Invalid args", { cause: result.error.issues });
623
+ const { stationId, from, to, serviceId } = result.data;
624
+ const searchParams = new URLSearchParams({
625
+ from,
626
+ to,
627
+ serviceId
628
+ });
629
+ return client.get(`/boapi/proxy/user/fleets/${client.clientOptions.fleetId}/stations/${stationId}/unavailability?${searchParams.toString()}`).then(({ data }) => data);
630
+ };
631
+ //#endregion
632
+ export { allocateVehicle, cancelBookingRequest, createBookingRequest, createSubscription, deallocateVehicle, getAdditionalDrivers, getAvailableModels, getAvailableVehicles, getBookingRequestById, getBookingRequestByTrip, getBookingRequests, getBookingRequestsByUserId, getDigitalContracts, getSATBookingRequests, getScheduleBookingRequests, getScheduledBookingById, getSlaves, getStationById, getStationUnavailability, getStations, getSubscriptionBookingRequestById, getSubscriptionBookingRequests, getSubscriptionsByUserId, releaseBRPayment, submitCancellationRequest, triggerBRPayment, updateScheduleBooking };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vulog/aima-booking",
3
3
  "type": "module",
4
- "version": "1.2.42",
4
+ "version": "1.2.43",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.cts",
@@ -32,8 +32,8 @@
32
32
  "author": "Vulog",
33
33
  "license": "MIT",
34
34
  "dependencies": {
35
- "@vulog/aima-client": "1.2.42",
36
- "@vulog/aima-core": "1.2.42"
35
+ "@vulog/aima-client": "1.2.43",
36
+ "@vulog/aima-core": "1.2.43"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "es-toolkit": "^1.45.1",
@@ -0,0 +1,73 @@
1
+ import { describe, test, vi, expect, beforeEach } from 'vitest';
2
+
3
+ import { Client } from '@vulog/aima-client';
4
+
5
+ import { createBookingRequest, CreateBookingRequestBody } from './createBookingRequest';
6
+
7
+ describe('createBookingRequest', () => {
8
+ const postMock = vi.fn();
9
+ const client = {
10
+ post: postMock,
11
+ clientOptions: {
12
+ fleetId: 'VULOG-FRPAR',
13
+ },
14
+ } as unknown as Client;
15
+
16
+ const validBody: CreateBookingRequestBody = {
17
+ startDate: '2026-06-01T10:00:00Z',
18
+ endDate: '2026-06-05T10:00:00Z',
19
+ modelId: 141411,
20
+ profileId: '9f0fd479-28a9-4754-9c77-611ea48bfb8f',
21
+ serviceId: '9ed7d9d4-8c64-43ef-bb3d-e2b271fed682',
22
+ };
23
+
24
+ beforeEach(() => {
25
+ vi.clearAllMocks();
26
+ });
27
+
28
+ test('should throw on invalid args (missing required fields)', async () => {
29
+ const badBody = { startDate: '2026-06-01T10:00:00Z' } as unknown as CreateBookingRequestBody;
30
+ await expect(createBookingRequest(client, badBody)).rejects.toThrow('Invalid args');
31
+ expect(postMock).not.toHaveBeenCalled();
32
+ });
33
+
34
+ test('should throw on invalid UUID profileId', async () => {
35
+ await expect(
36
+ createBookingRequest(client, { ...validBody, profileId: 'not-a-uuid' })
37
+ ).rejects.toThrow('Invalid args');
38
+ expect(postMock).not.toHaveBeenCalled();
39
+ });
40
+
41
+ test('should post body with fleetId injected and return booking request', async () => {
42
+ const responseBody = {
43
+ id: '0b528336-2624-42ae-8640-59fb663e17f4',
44
+ fleetId: 'VULOG-FRPAR',
45
+ status: 'PENDING',
46
+ };
47
+ postMock.mockResolvedValueOnce({ data: responseBody });
48
+
49
+ const result = await createBookingRequest(client, validBody);
50
+
51
+ expect(postMock).toHaveBeenCalledWith(
52
+ '/boapi/proxy/user/scheduledBooking/fleets/VULOG-FRPAR/bookingrequests',
53
+ { ...validBody, fleetId: 'VULOG-FRPAR' }
54
+ );
55
+ expect(result).toEqual(responseBody);
56
+ });
57
+
58
+ test('should append userStatusCheckRequired query param when provided', async () => {
59
+ postMock.mockResolvedValueOnce({ data: {} });
60
+
61
+ await createBookingRequest(client, validBody, { userStatusCheckRequired: false });
62
+
63
+ expect(postMock).toHaveBeenCalledWith(
64
+ '/boapi/proxy/user/scheduledBooking/fleets/VULOG-FRPAR/bookingrequests?userStatusCheckRequired=false',
65
+ { ...validBody, fleetId: 'VULOG-FRPAR' }
66
+ );
67
+ });
68
+
69
+ test('should propagate client errors', async () => {
70
+ postMock.mockRejectedValueOnce(new Error('network down'));
71
+ await expect(createBookingRequest(client, validBody)).rejects.toThrow('network down');
72
+ });
73
+ });
@@ -0,0 +1,116 @@
1
+ import { Client } from '@vulog/aima-client';
2
+ import { z } from 'zod';
3
+
4
+ import { BookingRequest } from './types';
5
+
6
+ export type CreateBookingRequestBody = {
7
+ // Required fields (per Swagger BookingRequestDTO)
8
+ startDate: string;
9
+ endDate: string;
10
+ modelId: number;
11
+ profileId: string;
12
+ serviceId: string;
13
+
14
+ // Optional fields
15
+ userId?: string;
16
+ vehicleId?: string;
17
+ station?: string;
18
+ latitude?: number;
19
+ longitude?: number;
20
+ radius?: number;
21
+ email?: string;
22
+ notes?: string;
23
+ plannedReturnDate?: string;
24
+ deliveryAddress?: string;
25
+ deliveryAddressAdditionalInfo?: string;
26
+ deliveryCity?: string;
27
+ deliveryPostalCode?: string;
28
+ dropOffStation?: string;
29
+ rollingContract?: boolean;
30
+ planDurationInMonths?: number;
31
+ planName?: string;
32
+ parentId?: string;
33
+ contractType?: 'SVS' | 'MVS';
34
+ productIds?: string[];
35
+ preallocatedVehicleId?: string;
36
+ bookingReferenceId?: string;
37
+ providedPricingId?: string;
38
+ preferredPaymentMethods?: { pspReference: string; amount: number }[];
39
+ requiresActionReturnURL?: string;
40
+ cityId?: string;
41
+ };
42
+
43
+ export type CreateBookingRequestOptions = {
44
+ /** When false, bypass the user status check (operator use). Default true server-side. */
45
+ userStatusCheckRequired?: boolean;
46
+ };
47
+
48
+ const createBookingRequestBodySchema = z.object({
49
+ startDate: z.string().trim().min(1),
50
+ endDate: z.string().trim().min(1),
51
+ modelId: z.number().int().positive(),
52
+ profileId: z.string().trim().min(1).uuid(),
53
+ serviceId: z.string().trim().min(1).uuid(),
54
+
55
+ userId: z.string().uuid().optional(),
56
+ vehicleId: z.string().uuid().optional(),
57
+ station: z.string().optional(),
58
+ latitude: z.number().optional(),
59
+ longitude: z.number().optional(),
60
+ radius: z.number().int().optional(),
61
+ email: z.string().email().optional(),
62
+ notes: z.string().optional(),
63
+ plannedReturnDate: z.string().optional(),
64
+ deliveryAddress: z.string().optional(),
65
+ deliveryAddressAdditionalInfo: z.string().optional(),
66
+ deliveryCity: z.string().optional(),
67
+ deliveryPostalCode: z.string().optional(),
68
+ dropOffStation: z.string().optional(),
69
+ rollingContract: z.boolean().optional(),
70
+ planDurationInMonths: z.number().int().optional(),
71
+ planName: z.string().optional(),
72
+ parentId: z.string().optional(),
73
+ contractType: z.enum(['SVS', 'MVS']).optional(),
74
+ productIds: z.array(z.string()).optional(),
75
+ preallocatedVehicleId: z.string().optional(),
76
+ bookingReferenceId: z.string().optional(),
77
+ providedPricingId: z.string().uuid().optional(),
78
+ preferredPaymentMethods: z
79
+ .array(
80
+ z.object({
81
+ pspReference: z.string(),
82
+ amount: z.number(),
83
+ })
84
+ )
85
+ .optional(),
86
+ requiresActionReturnURL: z.string().optional(),
87
+ cityId: z.string().optional(),
88
+ });
89
+
90
+ /**
91
+ * Create a new booking request.
92
+ *
93
+ * Swagger: `POST /scheduledBooking/fleets/{fleetId}/bookingrequests` (admin-booking).
94
+ */
95
+ export const createBookingRequest = async (
96
+ client: Client,
97
+ body: CreateBookingRequestBody,
98
+ options: CreateBookingRequestOptions = {}
99
+ ): Promise<BookingRequest> => {
100
+ const result = createBookingRequestBodySchema.safeParse(body);
101
+ if (!result.success) {
102
+ throw new TypeError('Invalid args', { cause: result.error.issues });
103
+ }
104
+
105
+ const query =
106
+ options.userStatusCheckRequired !== undefined
107
+ ? `?userStatusCheckRequired=${options.userStatusCheckRequired}`
108
+ : '';
109
+
110
+ return client
111
+ .post<BookingRequest>(
112
+ `/boapi/proxy/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/bookingrequests${query}`,
113
+ { ...result.data, fleetId: client.clientOptions.fleetId }
114
+ )
115
+ .then(({ data }) => data);
116
+ };
@@ -0,0 +1,88 @@
1
+ import { describe, test, vi, expect, beforeEach } from 'vitest';
2
+
3
+ import { Client } from '@vulog/aima-client';
4
+
5
+ import { getAvailableModels } from './getAvailableModels';
6
+ import { StationWithAvailableModels } from './types';
7
+
8
+ describe('getAvailableModels', () => {
9
+ const getMock = vi.fn();
10
+ const client = {
11
+ get: getMock,
12
+ clientOptions: {
13
+ fleetId: 'VULOG-FRPAR',
14
+ },
15
+ } as unknown as Client;
16
+
17
+ const validParams = {
18
+ startDate: '2026-06-01T00:00:00Z',
19
+ endDate: '2026-06-05T00:00:00Z',
20
+ };
21
+
22
+ beforeEach(() => {
23
+ vi.clearAllMocks();
24
+ });
25
+
26
+ test('should throw on missing required dates', async () => {
27
+ await expect(
28
+ getAvailableModels(client, { startDate: '2026-06-01T00:00:00Z' } as never)
29
+ ).rejects.toThrow('Invalid args');
30
+ expect(getMock).not.toHaveBeenCalled();
31
+ });
32
+
33
+ test('should throw on invalid ISO datetime', async () => {
34
+ await expect(
35
+ getAvailableModels(client, { startDate: 'not-a-date', endDate: validParams.endDate })
36
+ ).rejects.toThrow('Invalid args');
37
+ });
38
+
39
+ test('should throw on invalid userId UUID', async () => {
40
+ await expect(
41
+ getAvailableModels(client, { ...validParams, userId: 'not-a-uuid' })
42
+ ).rejects.toThrow('Invalid args');
43
+ });
44
+
45
+ test('should call endpoint with required query params and return stations', async () => {
46
+ const mockResponse: StationWithAvailableModels[] = [
47
+ {
48
+ id: 'd63bd962-e846-11ea-adc1-0242ac120002',
49
+ zoneId: 'f99e9a545059439c99eb81a8a8a88f93',
50
+ poiId: 'd2760ed840654f25b2beeb0fc52b6cf7',
51
+ models: [{ id: 141411, price: '120.00', prePaymentPrice: 30 }],
52
+ },
53
+ ];
54
+ getMock.mockResolvedValueOnce({ data: mockResponse });
55
+
56
+ const result = await getAvailableModels(client, validParams);
57
+
58
+ expect(getMock).toHaveBeenCalledWith(
59
+ '/boapi/proxy/user/scheduledBooking/fleets/VULOG-FRPAR/stations/models?startDate=2026-06-01T00%3A00%3A00Z&endDate=2026-06-05T00%3A00%3A00Z'
60
+ );
61
+ expect(result).toEqual(mockResponse);
62
+ });
63
+
64
+ test('should include all optional query params when provided', async () => {
65
+ getMock.mockResolvedValueOnce({ data: [] });
66
+
67
+ await getAvailableModels(client, {
68
+ ...validParams,
69
+ cityId: 'PARIS',
70
+ userId: '9f0fd479-28a9-4754-9c77-611ea48bfb8f',
71
+ profileId: '245cb038-0bcd-415f-a3ce-d0a5b2fdb730',
72
+ oneWayTrip: true,
73
+ showUnavailableModels: false,
74
+ });
75
+
76
+ const url = getMock.mock.calls[0][0] as string;
77
+ expect(url).toContain('cityId=PARIS');
78
+ expect(url).toContain('userId=9f0fd479-28a9-4754-9c77-611ea48bfb8f');
79
+ expect(url).toContain('profileId=245cb038-0bcd-415f-a3ce-d0a5b2fdb730');
80
+ expect(url).toContain('oneWayTrip=true');
81
+ expect(url).toContain('showUnavailableModels=false');
82
+ });
83
+
84
+ test('should propagate client errors', async () => {
85
+ getMock.mockRejectedValueOnce(new Error('network down'));
86
+ await expect(getAvailableModels(client, validParams)).rejects.toThrow('network down');
87
+ });
88
+ });
@@ -0,0 +1,47 @@
1
+ import { Client } from '@vulog/aima-client';
2
+ import { z } from 'zod';
3
+
4
+ import { StationWithAvailableModels } from './types';
5
+
6
+ /** ISO date-time without milliseconds (e.g. 2020-09-20T00:00:00Z or 2020-09-20T00:00:00+01:00). */
7
+ const isoDateTimeNoMs = z.string().trim().datetime({ precision: 0 });
8
+
9
+ const getAvailableModelsSchema = z.object({
10
+ startDate: isoDateTimeNoMs,
11
+ endDate: isoDateTimeNoMs,
12
+ cityId: z.string().trim().min(1).optional(),
13
+ userId: z.string().uuid().optional(),
14
+ profileId: z.string().uuid().optional(),
15
+ oneWayTrip: z.boolean().optional(),
16
+ showUnavailableModels: z.boolean().optional(),
17
+ });
18
+
19
+ export type GetAvailableModelsParams = z.infer<typeof getAvailableModelsSchema>;
20
+
21
+ /**
22
+ * Get available models grouped by station in a given time range.
23
+ *
24
+ * Swagger: `GET /scheduledBooking/fleets/{fleetId}/stations/models` (admin-booking / internal).
25
+ */
26
+ export const getAvailableModels = async (
27
+ client: Client,
28
+ params: GetAvailableModelsParams
29
+ ): Promise<StationWithAvailableModels[]> => {
30
+ const result = getAvailableModelsSchema.safeParse(params);
31
+ if (!result.success) {
32
+ throw new TypeError('Invalid args', { cause: result.error.issues });
33
+ }
34
+
35
+ const searchParams = new URLSearchParams();
36
+ for (const [key, value] of Object.entries(result.data)) {
37
+ if (value !== undefined) {
38
+ searchParams.append(key, String(value));
39
+ }
40
+ }
41
+
42
+ return client
43
+ .get<
44
+ StationWithAvailableModels[]
45
+ >(`/boapi/proxy/user/scheduledBooking/fleets/${client.clientOptions.fleetId}/stations/models?${searchParams.toString()}`)
46
+ .then(({ data }) => data);
47
+ };
@@ -0,0 +1,79 @@
1
+ import { describe, test, vi, expect, beforeEach } from 'vitest';
2
+
3
+ import { Client } from '@vulog/aima-client';
4
+
5
+ import { getStationUnavailability } from './getStationUnavailability';
6
+ import { StationVehicleCalendar } from './types';
7
+
8
+ describe('getStationUnavailability', () => {
9
+ const getMock = vi.fn();
10
+ const client = {
11
+ get: getMock,
12
+ clientOptions: {
13
+ fleetId: 'VULOG-FRPAR',
14
+ },
15
+ } as unknown as Client;
16
+
17
+ const validParams = {
18
+ stationId: '57e64770-72c8-4256-b3f2-931242fa7d61',
19
+ from: '2026-01-01T00:00:00Z',
20
+ to: '2026-02-01T00:00:00Z',
21
+ serviceId: '14946b6e-caac-4608-ab92-6068cc7363cf',
22
+ };
23
+
24
+ beforeEach(() => {
25
+ vi.clearAllMocks();
26
+ });
27
+
28
+ test('should throw on invalid stationId UUID', async () => {
29
+ await expect(
30
+ getStationUnavailability(client, { ...validParams, stationId: 'not-a-uuid' })
31
+ ).rejects.toThrow('Invalid args');
32
+ expect(getMock).not.toHaveBeenCalled();
33
+ });
34
+
35
+ test('should throw on invalid serviceId UUID', async () => {
36
+ await expect(
37
+ getStationUnavailability(client, { ...validParams, serviceId: 'not-a-uuid' })
38
+ ).rejects.toThrow('Invalid args');
39
+ });
40
+
41
+ test('should throw on invalid ISO date', async () => {
42
+ await expect(
43
+ getStationUnavailability(client, { ...validParams, from: 'not-a-date' })
44
+ ).rejects.toThrow('Invalid args');
45
+ });
46
+
47
+ test('should call endpoint with required query params and return calendar', async () => {
48
+ const mockResponse: StationVehicleCalendar = {
49
+ timezone: 'Europe/Paris',
50
+ from: validParams.from,
51
+ to: validParams.to,
52
+ vehicleIds: ['veh-1', 'veh-2'],
53
+ unavailabilities: [
54
+ {
55
+ id: 'u-1',
56
+ vehicleId: 'veh-1',
57
+ modelId: 141411,
58
+ from: '2026-01-10T08:00:00Z',
59
+ to: '2026-01-12T18:00:00Z',
60
+ type: 'BOOKING',
61
+ serviceId: validParams.serviceId,
62
+ },
63
+ ],
64
+ };
65
+ getMock.mockResolvedValueOnce({ data: mockResponse });
66
+
67
+ const result = await getStationUnavailability(client, validParams);
68
+
69
+ expect(getMock).toHaveBeenCalledWith(
70
+ `/boapi/proxy/user/fleets/VULOG-FRPAR/stations/${validParams.stationId}/unavailability?from=2026-01-01T00%3A00%3A00Z&to=2026-02-01T00%3A00%3A00Z&serviceId=${validParams.serviceId}`
71
+ );
72
+ expect(result).toEqual(mockResponse);
73
+ });
74
+
75
+ test('should propagate client errors', async () => {
76
+ getMock.mockRejectedValueOnce(new Error('network down'));
77
+ await expect(getStationUnavailability(client, validParams)).rejects.toThrow('network down');
78
+ });
79
+ });
@@ -0,0 +1,41 @@
1
+ import { Client } from '@vulog/aima-client';
2
+ import { z } from 'zod';
3
+
4
+ import { StationVehicleCalendar } from './types';
5
+
6
+ /** ISO date-time without milliseconds (e.g. 2021-01-01T00:00:00Z). */
7
+ const isoDateTimeNoMs = z.string().trim().datetime({ precision: 0 });
8
+
9
+ const getStationUnavailabilitySchema = z.object({
10
+ stationId: z.string().uuid(),
11
+ from: isoDateTimeNoMs,
12
+ to: isoDateTimeNoMs,
13
+ serviceId: z.string().uuid(),
14
+ });
15
+
16
+ export type GetStationUnavailabilityParams = z.infer<typeof getStationUnavailabilitySchema>;
17
+
18
+ /**
19
+ * Get the list of vehicle unavailabilities for a given station over a period.
20
+ *
21
+ * Swagger: `GET /fleets/{fleetId}/stations/{stationId}/unavailability` (admin-booking,
22
+ * operationId `getVehicleCalendarForPeriod`).
23
+ */
24
+ export const getStationUnavailability = async (
25
+ client: Client,
26
+ params: GetStationUnavailabilityParams
27
+ ): Promise<StationVehicleCalendar> => {
28
+ const result = getStationUnavailabilitySchema.safeParse(params);
29
+ if (!result.success) {
30
+ throw new TypeError('Invalid args', { cause: result.error.issues });
31
+ }
32
+
33
+ const { stationId, from, to, serviceId } = result.data;
34
+ const searchParams = new URLSearchParams({ from, to, serviceId });
35
+
36
+ return client
37
+ .get<StationVehicleCalendar>(
38
+ `/boapi/proxy/user/fleets/${client.clientOptions.fleetId}/stations/${stationId}/unavailability?${searchParams.toString()}`
39
+ )
40
+ .then(({ data }) => data);
41
+ };
package/src/index.ts CHANGED
@@ -28,3 +28,9 @@ export { getSubscriptionsByUserId } from './getSubscriptionsByUserId';
28
28
  export { submitCancellationRequest } from './submitCancellationRequest';
29
29
  export { createSubscription } from './createSubscription';
30
30
  export type { CreateSubscriptionBody } from './createSubscription';
31
+ export { createBookingRequest } from './createBookingRequest';
32
+ export type { CreateBookingRequestBody, CreateBookingRequestOptions } from './createBookingRequest';
33
+ export { getAvailableModels } from './getAvailableModels';
34
+ export type { GetAvailableModelsParams } from './getAvailableModels';
35
+ export { getStationUnavailability } from './getStationUnavailability';
36
+ export type { GetStationUnavailabilityParams } from './getStationUnavailability';
package/src/types.ts CHANGED
@@ -342,3 +342,76 @@ export type BookingRequestSlave = {
342
342
  traveledDistance: number;
343
343
  energyLevelEnd: number;
344
344
  };
345
+
346
+ /** Mileage allowance for an available model (Swagger: `MileageAllowanceDTO`). */
347
+ export type MileageAllowance = {
348
+ allowancePerDay?: number;
349
+ totalAllowance?: number;
350
+ pricePerExceedingUnit?: number;
351
+ };
352
+
353
+ /** Estimated product embedded in a price breakdown (Swagger: `EstimatedProductDTO`). */
354
+ export type EstimatedProduct = {
355
+ productId?: string;
356
+ price?: number;
357
+ };
358
+
359
+ /** Price breakdown for an available model (Swagger: `PriceBreakdownDTO`). */
360
+ export type PriceBreakdown = {
361
+ tripPrice?: number;
362
+ productsPrice?: number;
363
+ productDetails?: EstimatedProduct[];
364
+ };
365
+
366
+ /** Pricing info for an available model (Swagger: `PricingInfo`). */
367
+ export type PricingInfo = {
368
+ pricingId?: string;
369
+ type?: string;
370
+ priceBreakdown?: PriceBreakdown;
371
+ };
372
+
373
+ /** Available model entry returned by `getAvailableModels` (Swagger: `BookingRequestModelDTO`). */
374
+ export type AvailableModel = {
375
+ id: number;
376
+ price?: string;
377
+ prePaymentPrice?: number;
378
+ mileageAllowance?: MileageAllowance;
379
+ pricingInfo?: PricingInfo;
380
+ };
381
+
382
+ /** Station entry returned by `getAvailableModels` (Swagger: `StationDTO`). */
383
+ export type StationWithAvailableModels = {
384
+ id: string;
385
+ zoneId: string;
386
+ poiId: string;
387
+ models: AvailableModel[];
388
+ taxZoneId?: string;
389
+ cityId?: string;
390
+ serviceId?: string;
391
+ fleetId?: string;
392
+ openTime?: string;
393
+ closeTime?: string;
394
+ };
395
+
396
+ /** Single unavailability entry in a station vehicle calendar (Swagger: `UnavailabilityDTO`). */
397
+ export type VehicleUnavailability = {
398
+ id?: string;
399
+ vehicleId?: string;
400
+ modelId?: number;
401
+ from?: string;
402
+ to?: string;
403
+ toWithMargin?: string;
404
+ type?: 'BOOKING' | 'MAINTENANCE';
405
+ userId?: string;
406
+ reason?: string;
407
+ serviceId?: string;
408
+ };
409
+
410
+ /** Vehicle calendar for a station over a period (Swagger: `VehicleCalendarResponseDTO`). */
411
+ export type StationVehicleCalendar = {
412
+ timezone?: string;
413
+ from?: string;
414
+ to?: string;
415
+ vehicleIds?: string[];
416
+ unavailabilities?: VehicleUnavailability[];
417
+ };