All files / src/utils serviceFromAppointment.ts

72.72% Statements 24/33
65.11% Branches 28/43
75% Functions 3/4
72.72% Lines 24/33

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116                                  17x 2x     15x 15x 14x     17x 13x 13x 4x   13x                         13x 13x           13x     2x 1x     1x 1x 1x     1x                       17x           17x                 14x 14x 14x                                              
import { AppointmentDTO } from "@/api/models/AppointmentDTO";
import { Service } from "@/api/models/Service";
import { OfficeImpl } from "@/types/OfficeImpl";
import { ServiceImpl } from "@/types/ServiceImpl";
import { SubService } from "@/types/SubService";
 
/**
 * Resolve the booked service for an appointment overview/detail view.
 * Prefer the public catalog (variants, rootParentId). Fall back to
 * appointment.serviceName so internal/unpublished bookings still show Leistung.
 */
export function serviceFromAppointment(
  appointment: AppointmentDTO | undefined | null,
  catalogServices: Service[] | undefined | null,
  getProvidersForService: (serviceId: string) => OfficeImpl[],
  fallbackProvider?: OfficeImpl
): ServiceImpl | undefined {
  if (!appointment?.serviceId) {
    return undefined;
  }
 
  const serviceId = String(appointment.serviceId);
  const fromCatalog = (catalogServices ?? []).find(
    (service) => String(service.id) === serviceId
  );
 
  if (fromCatalog) {
    const providers = getProvidersForService(serviceId);
    if (providers.length === 0 && fallbackProvider) {
      providers.push(fallbackProvider);
    }
    const selected = new ServiceImpl(
      serviceId,
      appointment.serviceName || fromCatalog.name,
      fromCatalog.maxQuantity,
      fromCatalog.combinable,
      providers,
      [],
      appointment.serviceCount,
      fromCatalog.parentId ?? null,
      fromCatalog.variantId ?? null,
      fromCatalog.showOnStartPage,
      fromCatalog.variantOverwrite
    );
    selected.rootParentId = fromCatalog.rootParentId ?? fromCatalog.id;
    attachSubServices(
      selected,
      appointment,
      catalogServices ?? [],
      getProvidersForService
    );
    return selected;
  }
 
  if (!appointment.serviceName) {
    return undefined;
  }
 
  const providers = getProvidersForService(serviceId);
  Eif (providers.length === 0 && fallbackProvider) {
    providers.push(fallbackProvider);
  }
 
  const selected = new ServiceImpl(
    serviceId,
    appointment.serviceName,
    appointment.serviceCount ?? 1,
    undefined,
    providers,
    [],
    appointment.serviceCount ?? 1,
    null,
    null,
    false
  );
  attachSubServices(
    selected,
    appointment,
    catalogServices ?? [],
    getProvidersForService
  );
  return selected;
}
 
function attachSubServices(
  selected: ServiceImpl,
  appointment: AppointmentDTO,
  catalogServices: Service[],
  getProvidersForService: (serviceId: string) => OfficeImpl[]
): void {
  const subRequestCounts = appointment.subRequestCounts ?? [];
  Eif (subRequestCounts.length === 0) {
    return;
  }
  selected.subServices = [];
  for (const subRequestCount of subRequestCounts) {
    const subId = String(subRequestCount.id);
    const fromCatalog = catalogServices.find(
      (service) => String(service.id) === subId
    );
    const name = fromCatalog?.name ?? subRequestCount.name;
    if (!name) {
      continue;
    }
    selected.subServices.push(
      new SubService(
        subId,
        name,
        fromCatalog?.maxQuantity ?? subRequestCount.count ?? 1,
        getProvidersForService(subId),
        subRequestCount.count
      )
    );
  }
}