From f4d1e541016677795e98d24cd462cbecec26d68b Mon Sep 17 00:00:00 2001
From: Edie Lemoine <edie@myparcel.nl>
Date: Fri, 27 Sep 2024 13:00:54 +0200
Subject: [PATCH] fix: don't output false for shipment options that are
 disabled

---
 .../events/useResolvedValues.spec.ts          | 39 +++++++++++++----
 .../composables/events/useResolvedValues.ts   | 42 ++++++++++++++-----
 apps/delivery-options/src/types/form.types.ts |  9 +++-
 libs/shared/src/types/config.types.ts         |  2 +-
 4 files changed, 69 insertions(+), 23 deletions(-)

diff --git a/apps/delivery-options/src/composables/events/useResolvedValues.spec.ts b/apps/delivery-options/src/composables/events/useResolvedValues.spec.ts
index 7d7e05f7..0efa1c28 100644
--- a/apps/delivery-options/src/composables/events/useResolvedValues.spec.ts
+++ b/apps/delivery-options/src/composables/events/useResolvedValues.spec.ts
@@ -9,6 +9,7 @@ import {
   KEY_CONFIG,
   useCarrierRequest,
   ConfigSetting,
+  type InputDeliveryOptionsConfig,
 } from '@myparcel-do/shared';
 import {CarrierName, DeliveryTypeName, PackageTypeName, ShipmentOptionName} from '@myparcel/constants';
 import {
@@ -32,6 +33,7 @@ import {
 import {useResolvedValues} from './useResolvedValues';
 
 interface TestInput {
+  config?: Partial<InputDeliveryOptionsConfig>;
   external: DeliveryOptionsOutput;
   internal: InternalOutput;
   name: string;
@@ -73,15 +75,28 @@ describe('useResolvedValues', () => {
       name: 'default values',
       internal: createInternalOutput(),
       external: createExternalOutput({
-        shipmentOptions: {
+        [FIELD_SHIPMENT_OPTIONS]: {
           onlyRecipient: false,
           signature: false,
         },
       }),
     },
+    {
+      name: 'default values with signature and only recipient disabled',
+      config: {
+        [CarrierSetting.AllowSignature]: false,
+        [CarrierSetting.AllowOnlyRecipient]: false,
+      },
+      internal: createInternalOutput(),
+      external: createExternalOutput(),
+    },
 
     {
-      name: 'onlyRecipient',
+      name: 'onlyRecipient enabled but not selected',
+      config: {
+        [CarrierSetting.AllowOnlyRecipient]: true,
+      },
+
       internal: createInternalOutput({
         [FIELD_DELIVERY_DATE]: '2023-12-31',
         [FIELD_DELIVERY_MOMENT]: {
@@ -106,6 +121,8 @@ describe('useResolvedValues', () => {
 
     {
       name: 'pickup',
+      config: {},
+
       internal: createInternalOutput({
         [FIELD_HOME_OR_PICKUP]: HOME_OR_PICKUP_PICKUP,
         [FIELD_PICKUP_LOCATION]: '176688',
@@ -120,16 +137,20 @@ describe('useResolvedValues', () => {
         }),
       }),
     },
-  ] satisfies TestInput[])('converts internal output to external output with $name', async ({internal, external}) => {
-    expect.assertions(1);
+  ] satisfies TestInput[])(
+    'converts internal output to external output with $name',
+    async ({internal, external, config}) => {
+      expect.assertions(1);
 
-    mockSelectedDeliveryOptions(internal);
-    await flushPromises();
+      mockDeliveryOptionsConfig({[KEY_CONFIG]: config});
+      mockSelectedDeliveryOptions(internal);
+      await flushPromises();
 
-    const resolvedValues = useResolvedValues();
+      const resolvedValues = useResolvedValues();
 
-    expect(resolvedValues.value).toEqual(external);
-  });
+      expect(resolvedValues.value).toEqual(external);
+    },
+  );
 
   it('should not expose delivery date if it is disabled', async () => {
     mockDeliveryOptionsConfig({[KEY_CONFIG]: {[ConfigSetting.ShowDeliveryDate]: true}});
diff --git a/apps/delivery-options/src/composables/events/useResolvedValues.ts b/apps/delivery-options/src/composables/events/useResolvedValues.ts
index fe0c7d54..6eee8c0e 100644
--- a/apps/delivery-options/src/composables/events/useResolvedValues.ts
+++ b/apps/delivery-options/src/composables/events/useResolvedValues.ts
@@ -5,21 +5,44 @@ import {
   type DeliveryOutput,
   type PickupOutput,
   type SupportedDeliveryTypeName,
-  type DeliveryDeliveryType,
+  type SupportedShipmentOptionName,
+  getConfigKey,
+  type CarrierIdentifier,
 } from '@myparcel-do/shared';
 import {DeliveryTypeName, PackageTypeName, ShipmentOptionName} from '@myparcel/constants';
 import {useSelectedValues} from '../useSelectedValues';
 import {useSelectedPickupLocation} from '../useSelectedPickupLocation';
 import {useResolvedDeliveryOptions} from '../useResolvedDeliveryOptions';
 import {getResolvedValue, parseJson} from '../../utils';
-import {type SelectedDeliveryMoment} from '../../types';
+import {type SelectedDeliveryMomentDelivery} from '../../types';
 import {FIELD_DELIVERY_MOMENT, FIELD_SHIPMENT_OPTIONS, HOME_OR_PICKUP_PICKUP} from '../../data';
 
-const DELIVERY_DELIVERY_TYPES: readonly SupportedDeliveryTypeName[] = Object.freeze([
+const DELIVERY_DELIVERY_TYPES = Object.freeze([
   DeliveryTypeName.Morning,
   DeliveryTypeName.Evening,
   DeliveryTypeName.Standard,
-]);
+] satisfies SupportedDeliveryTypeName[]);
+
+const SHIPMENT_OPTION_OUTPUT_MAP = Object.freeze({
+  [ShipmentOptionName.Signature]: 'signature',
+  [ShipmentOptionName.OnlyRecipient]: 'onlyRecipient',
+} as Record<SupportedShipmentOptionName, keyof DeliveryOutput['shipmentOptions']>);
+
+const createResolvedShipmentOptions = (
+  carrier: CarrierIdentifier,
+  shipmentOptions: string[],
+): DeliveryOutput['shipmentOptions'] => {
+  return Object.entries(SHIPMENT_OPTION_OUTPUT_MAP).reduce((acc, [shipmentOption, objectKey]) => {
+    const enabledKey = getConfigKey(shipmentOption as SupportedShipmentOptionName);
+    const enabled = getResolvedValue(enabledKey, carrier, false);
+
+    if (enabled) {
+      acc[objectKey] = shipmentOptions.includes(shipmentOption);
+    }
+
+    return acc;
+  }, {} as DeliveryOutput['shipmentOptions']);
+};
 
 export const useResolvedValues = (): ComputedRef<PickupOutput | DeliveryOutput | undefined> => {
   const selectedValues = useSelectedValues();
@@ -48,12 +71,12 @@ export const useResolvedValues = (): ComputedRef<PickupOutput | DeliveryOutput |
       } satisfies PickupOutput;
     }
 
-    const parsedMoment = parseJson<SelectedDeliveryMoment>(selectedValues[FIELD_DELIVERY_MOMENT].value);
+    const parsedMoment = parseJson<SelectedDeliveryMomentDelivery>(selectedValues[FIELD_DELIVERY_MOMENT].value);
     const showDeliveryDate = getResolvedValue(ConfigSetting.ShowDeliveryDate);
     const shipmentOptions = selectedValues[FIELD_SHIPMENT_OPTIONS].value ?? [];
 
-    const deliveryType: DeliveryDeliveryType = DELIVERY_DELIVERY_TYPES.includes(parsedMoment.deliveryType)
-      ? (parsedMoment.deliveryType as DeliveryDeliveryType)
+    const deliveryType = DELIVERY_DELIVERY_TYPES.includes(parsedMoment.deliveryType)
+      ? parsedMoment.deliveryType
       : DeliveryTypeName.Standard;
 
     return {
@@ -62,10 +85,7 @@ export const useResolvedValues = (): ComputedRef<PickupOutput | DeliveryOutput |
       deliveryType,
       isPickup: false,
       packageType: parsedMoment.packageType,
-      shipmentOptions: {
-        signature: shipmentOptions.includes(ShipmentOptionName.Signature) ?? false,
-        onlyRecipient: shipmentOptions.includes(ShipmentOptionName.OnlyRecipient) ?? false,
-      },
+      shipmentOptions: createResolvedShipmentOptions(parsedMoment.carrier, shipmentOptions),
     } satisfies DeliveryOutput;
   });
 };
diff --git a/apps/delivery-options/src/types/form.types.ts b/apps/delivery-options/src/types/form.types.ts
index 212b0704..5804cb51 100644
--- a/apps/delivery-options/src/types/form.types.ts
+++ b/apps/delivery-options/src/types/form.types.ts
@@ -4,6 +4,7 @@ import {
   type OutputPickupLocation,
   type SupportedDeliveryTypeName,
   type AnyTranslatable,
+  type DeliveryDeliveryType,
 } from '@myparcel-do/shared';
 import {type Replace} from '@myparcel/ts-utils';
 import {type DeliveryOption, type StartEndDate} from '@myparcel/sdk';
@@ -28,7 +29,11 @@ export interface ResolvedPickupLocation extends OutputPickupLocation {
   openingHours: OpeningHoursEntry[];
 }
 
-export interface SelectedDeliveryMoment
-  extends Replace<Omit<ResolvedDeliveryOptions, 'carrier'>, 'deliveryType', SupportedDeliveryTypeName> {
+export interface SelectedDeliveryMoment<T extends SupportedDeliveryTypeName = SupportedDeliveryTypeName>
+  extends Replace<Omit<ResolvedDeliveryOptions, 'carrier'>, 'deliveryType', T> {
   carrier: CarrierIdentifier;
 }
+
+export type SelectedDeliveryMomentDelivery = SelectedDeliveryMoment<DeliveryDeliveryType>;
+
+export type SelectedDeliveryMomentPickup = SelectedDeliveryMoment<DeliveryTypeName.Pickup>;
diff --git a/libs/shared/src/types/config.types.ts b/libs/shared/src/types/config.types.ts
index 2e42f9cb..a565fd16 100644
--- a/libs/shared/src/types/config.types.ts
+++ b/libs/shared/src/types/config.types.ts
@@ -191,4 +191,4 @@ export type ResolvedConfigOption<O extends ConfigKey | ConfigOption> = O extends
 
 export type CarrierSettingsKey = CarrierSetting;
 
-export type ConfigKey = ConfigSetting | CarrierSettingsKey | SupportedPackageTypeName;
+export type ConfigKey = ConfigSetting | CarrierSettingsKey;