diff --git a/apps/delivery-options/package.json b/apps/delivery-options/package.json index e3b0777a..221c2985 100644 --- a/apps/delivery-options/package.json +++ b/apps/delivery-options/package.json @@ -51,7 +51,7 @@ }, "dependencies": { "@myparcel-do/shared": "workspace:*", - "@myparcel/constants": "^2.0.0", + "@myparcel/constants": "^2.2.0", "@myparcel/sdk": "^4.0.0", "@myparcel/ts-utils": "^1.12.0", "@myparcel/vue-form-builder": "^1.0.0-beta.1", diff --git a/apps/delivery-options/src/__tests__/constants.ts b/apps/delivery-options/src/__tests__/constants.ts index afd29a81..3e6e4aaf 100644 --- a/apps/delivery-options/src/__tests__/constants.ts +++ b/apps/delivery-options/src/__tests__/constants.ts @@ -23,6 +23,7 @@ export enum TestValue { DeliveryTypeSaturday = 1 << 6, DeliveryTypeSameDay = 1 << 7, DeliveryTypePickup = 1 << 8, + DeliveryTypeExpress = 1 << 9, // Carriers CarrierPostNl = 1 << 20, @@ -76,4 +77,5 @@ export const TEST_VALUE_MAP_PRICES = Object.freeze({ [CarrierSetting.PriceSaturdayDelivery]: TestValue.DeliveryTypeSaturday, [CarrierSetting.PriceSignature]: TestValue.ShipmentOptionSignature, [CarrierSetting.PriceStandardDelivery]: TestValue.Default, + [CarrierSetting.PriceExpressDelivery]: TestValue.DeliveryTypeExpress, }); diff --git a/apps/delivery-options/src/__tests__/utils/__snapshots__/createTestConfiguration.spec.ts.snap b/apps/delivery-options/src/__tests__/utils/__snapshots__/createTestConfiguration.spec.ts.snap index 301e05f9..d7c97856 100644 --- a/apps/delivery-options/src/__tests__/utils/__snapshots__/createTestConfiguration.spec.ts.snap +++ b/apps/delivery-options/src/__tests__/utils/__snapshots__/createTestConfiguration.spec.ts.snap @@ -11,6 +11,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni "config": { "allowDeliveryOptions": true, "allowEveningDelivery": true, + "allowExpressDelivery": true, "allowMondayDelivery": true, "allowMorningDelivery": true, "allowOnlyRecipient": true, @@ -22,6 +23,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni "carrierSettings": { "bpost": { "priceEveningDelivery": 2097168, + "priceExpressDelivery": 2097664, "priceMondayDelivery": 2097184, "priceMorningDelivery": 2097160, "priceOnlyRecipient": 2097664, @@ -36,6 +38,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni }, "bpost:1": { "priceEveningDelivery": 2359312, + "priceExpressDelivery": 2359808, "priceMondayDelivery": 2359328, "priceMorningDelivery": 2359304, "priceOnlyRecipient": 2359808, @@ -50,6 +53,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni }, "bpost:2": { "priceEveningDelivery": 2621456, + "priceExpressDelivery": 2621952, "priceMondayDelivery": 2621472, "priceMorningDelivery": 2621448, "priceOnlyRecipient": 2621952, @@ -64,6 +68,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni }, "dhl": { "priceEveningDelivery": 33554448, + "priceExpressDelivery": 33554944, "priceMondayDelivery": 33554464, "priceMorningDelivery": 33554440, "priceOnlyRecipient": 33554944, @@ -78,6 +83,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni }, "dhl:1": { "priceEveningDelivery": 33816592, + "priceExpressDelivery": 33817088, "priceMondayDelivery": 33816608, "priceMorningDelivery": 33816584, "priceOnlyRecipient": 33817088, @@ -92,6 +98,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni }, "dhl:2": { "priceEveningDelivery": 34078736, + "priceExpressDelivery": 34079232, "priceMondayDelivery": 34078752, "priceMorningDelivery": 34078728, "priceOnlyRecipient": 34079232, @@ -106,6 +113,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni }, "dhleuroplus": { "priceEveningDelivery": 1073741840, + "priceExpressDelivery": 1073742336, "priceMondayDelivery": 1073741856, "priceMorningDelivery": 1073741832, "priceOnlyRecipient": 1073742336, @@ -120,6 +128,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni }, "dhleuroplus:1": { "priceEveningDelivery": 1074003984, + "priceExpressDelivery": 1074004480, "priceMondayDelivery": 1074004000, "priceMorningDelivery": 1074003976, "priceOnlyRecipient": 1074004480, @@ -134,6 +143,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni }, "dhleuroplus:2": { "priceEveningDelivery": 1074266128, + "priceExpressDelivery": 1074266624, "priceMondayDelivery": 1074266144, "priceMorningDelivery": 1074266120, "priceOnlyRecipient": 1074266624, @@ -148,6 +158,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni }, "dhlforyou": { "priceEveningDelivery": 268435472, + "priceExpressDelivery": 268435968, "priceMondayDelivery": 268435488, "priceMorningDelivery": 268435464, "priceOnlyRecipient": 268435968, @@ -162,6 +173,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni }, "dhlforyou:1": { "priceEveningDelivery": 268697616, + "priceExpressDelivery": 268698112, "priceMondayDelivery": 268697632, "priceMorningDelivery": 268697608, "priceOnlyRecipient": 268698112, @@ -176,6 +188,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni }, "dhlforyou:2": { "priceEveningDelivery": 268959760, + "priceExpressDelivery": 268960256, "priceMondayDelivery": 268959776, "priceMorningDelivery": 268959752, "priceOnlyRecipient": 268960256, @@ -190,6 +203,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni }, "dhlparcelconnect": { "priceEveningDelivery": 536870928, + "priceExpressDelivery": 536871424, "priceMondayDelivery": 536870944, "priceMorningDelivery": 536870920, "priceOnlyRecipient": 536871424, @@ -204,6 +218,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni }, "dhlparcelconnect:1": { "priceEveningDelivery": 537133072, + "priceExpressDelivery": 537133568, "priceMondayDelivery": 537133088, "priceMorningDelivery": 537133064, "priceOnlyRecipient": 537133568, @@ -218,6 +233,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni }, "dhlparcelconnect:2": { "priceEveningDelivery": 537395216, + "priceExpressDelivery": 537395712, "priceMondayDelivery": 537395232, "priceMorningDelivery": 537395208, "priceOnlyRecipient": 537395712, @@ -232,6 +248,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni }, "dpd": { "priceEveningDelivery": 8388624, + "priceExpressDelivery": 8389120, "priceMondayDelivery": 8388640, "priceMorningDelivery": 8388616, "priceOnlyRecipient": 8389120, @@ -246,6 +263,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni }, "dpd:1": { "priceEveningDelivery": 8650768, + "priceExpressDelivery": 8651264, "priceMondayDelivery": 8650784, "priceMorningDelivery": 8650760, "priceOnlyRecipient": 8651264, @@ -260,6 +278,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni }, "dpd:2": { "priceEveningDelivery": 8912912, + "priceExpressDelivery": 8913408, "priceMondayDelivery": 8912928, "priceMorningDelivery": 8912904, "priceOnlyRecipient": 8913408, @@ -274,6 +293,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni }, "postnl": { "priceEveningDelivery": 1048592, + "priceExpressDelivery": 1049088, "priceMondayDelivery": 1048608, "priceMorningDelivery": 1048584, "priceOnlyRecipient": 1049088, @@ -288,6 +308,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni }, "postnl:1": { "priceEveningDelivery": 1310736, + "priceExpressDelivery": 1311232, "priceMondayDelivery": 1310752, "priceMorningDelivery": 1310728, "priceOnlyRecipient": 1311232, @@ -302,6 +323,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni }, "postnl:2": { "priceEveningDelivery": 1572880, + "priceExpressDelivery": 1573376, "priceMondayDelivery": 1572896, "priceMorningDelivery": 1572872, "priceOnlyRecipient": 1573376, @@ -316,6 +338,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni }, "ups": { "priceEveningDelivery": 134217744, + "priceExpressDelivery": 134218240, "priceMondayDelivery": 134217760, "priceMorningDelivery": 134217736, "priceOnlyRecipient": 134218240, @@ -330,6 +353,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni }, "ups:1": { "priceEveningDelivery": 134479888, + "priceExpressDelivery": 134480384, "priceMondayDelivery": 134479904, "priceMorningDelivery": 134479880, "priceOnlyRecipient": 134480384, @@ -344,6 +368,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni }, "ups:2": { "priceEveningDelivery": 134742032, + "priceExpressDelivery": 134742528, "priceMondayDelivery": 134742048, "priceMorningDelivery": 134742024, "priceOnlyRecipient": 134742528, @@ -358,6 +383,7 @@ exports[`createTestConfiguration > creates a default test configuration with uni }, }, "priceEveningDelivery": 16, + "priceExpressDelivery": 512, "priceMondayDelivery": 32, "priceMorningDelivery": 8, "priceOnlyRecipient": 512, diff --git a/apps/delivery-options/src/__tests__/utils/createTestConfiguration.ts b/apps/delivery-options/src/__tests__/utils/createTestConfiguration.ts index 055f920a..35fc99ff 100644 --- a/apps/delivery-options/src/__tests__/utils/createTestConfiguration.ts +++ b/apps/delivery-options/src/__tests__/utils/createTestConfiguration.ts @@ -46,6 +46,7 @@ export const createTestConfiguration = (): InputDeliveryOptionsConfiguration => [CarrierSetting.AllowSaturdayDelivery]: true, [CarrierSetting.AllowSignature]: true, [CarrierSetting.AllowStandardDelivery]: true, + [CarrierSetting.AllowExpressDelivery]: true, ...Object.entries(TEST_VALUE_MAP_PRICES).reduce((acc, [optionKey, priceValue]) => { return {...acc, [optionKey]: priceValue}; }, {}), diff --git a/apps/delivery-options/src/composables/useResolvedDeliveryOptions.spec.ts b/apps/delivery-options/src/composables/useResolvedDeliveryOptions.spec.ts index f26be987..e364d3d7 100644 --- a/apps/delivery-options/src/composables/useResolvedDeliveryOptions.spec.ts +++ b/apps/delivery-options/src/composables/useResolvedDeliveryOptions.spec.ts @@ -23,12 +23,12 @@ import {useResolvedDeliveryOptions} from './useResolvedDeliveryOptions'; const CARRIER_IDENTIFIER_WITH_CONTRACT = `${CarrierName.PostNl}:1234`; -const doTestSetup = async (config: RecursivePartial = {}): Promise => { +const setupPostNl = async (config: RecursivePartial = {}): Promise => { const morning = normalizeDate('2022-01-01T09:00:00'); const standard = normalizeDate('2022-01-01T15:00:00'); const evening = normalizeDate('2022-01-01T20:00:00'); - mockGetDeliveryOptions.mockReturnValueOnce( + mockGetDeliveryOptions.mockReturnValue( Promise.resolve([ { date: createTimestamp(standard), @@ -63,10 +63,48 @@ const doTestSetup = async (config: RecursivePartial = {}): Promise => { + const today = normalizeDate('2022-01-01T09:00:00'); + const tomorrow = normalizeDate('2022-01-02T09:00:00'); + const inTwoDays = normalizeDate('2022-01-03T09:00:00'); + + mockGetDeliveryOptions.mockReturnValue( + Promise.resolve([ + { + date: createTimestamp(today), + possibilities: [ + createDeliveryPossibility(tomorrow, {type: DeliveryTypeName.Express}), + createDeliveryPossibility(inTwoDays, {type: DeliveryTypeName.Express}), + createDeliveryPossibility(inTwoDays, {type: DeliveryTypeName.Standard}), + ], + }, + ]), + ); + + mockDeliveryOptionsConfig( + getMockDeliveryOptionsConfiguration( + assign( + { + [KEY_CONFIG]: { + [KEY_CARRIER_SETTINGS]: { + [CarrierName.Ups]: { + [CarrierSetting.AllowDeliveryOptions]: true, + // Provide standard/express setting via config arg. + }, + }, + }, + }, + config, + ), + ), + ); + + await waitForDeliveryOptions(CarrierName.Ups); +}; + describe('useResolvedDeliveryOptions', () => { beforeEach(() => { useResolvedDeliveryOptions.clear(); @@ -74,7 +112,7 @@ describe('useResolvedDeliveryOptions', () => { }); it('sorts options by time', async () => { - await doTestSetup(); + await setupPostNl(); const options = useResolvedDeliveryOptions(); @@ -90,12 +128,53 @@ describe('useResolvedDeliveryOptions', () => { ]); }); + it('prefers standard delivery over express in the same time window', async () => { + await setupUps({ + [KEY_CONFIG]: { + [KEY_CARRIER_SETTINGS]: { + [CarrierName.Ups]: { + [CarrierSetting.AllowStandardDelivery]: true, + [CarrierSetting.AllowExpressDelivery]: true, + }, + }, + }, + }); + + const options = useResolvedDeliveryOptions(); + const resolvedOptions = options.value.map(({carrier, deliveryType}) => ({carrier, deliveryType})); + + // It should prefer standard to express on day 2. + expect(resolvedOptions).toEqual([ + {carrier: CarrierName.Ups, deliveryType: DeliveryTypeName.Express}, + {carrier: CarrierName.Ups, deliveryType: DeliveryTypeName.Standard}, + ]); + }); + + it('does not filter out standard delivery when express is disabled', async () => { + await setupUps({ + [KEY_CONFIG]: { + [KEY_CARRIER_SETTINGS]: { + [CarrierName.Ups]: { + [CarrierSetting.AllowStandardDelivery]: true, + [CarrierSetting.AllowExpressDelivery]: false, + }, + }, + }, + }); + + const options = useResolvedDeliveryOptions(); + + const resolvedOptions = options.value.map(({carrier, deliveryType}) => ({carrier, deliveryType})); + + // Verify that it doesn't filter out Standard now + expect(resolvedOptions).toEqual([{carrier: CarrierName.Ups, deliveryType: DeliveryTypeName.Standard}]); + }); + it('handles fake delivery', async () => { // DE is not a delivery country for PostNL. - await doTestSetup({[KEY_ADDRESS]: {cc: 'DE'}}); + await setupPostNl({[KEY_ADDRESS]: {cc: 'DE'}}); const options = useResolvedDeliveryOptions(); - const resolvedOptions = options.value.map(({carrier, deliveryType}) => ({carrier, deliveryType})); expect(resolvedOptions).toEqual([ diff --git a/apps/delivery-options/src/composables/useResolvedDeliveryOptions.ts b/apps/delivery-options/src/composables/useResolvedDeliveryOptions.ts index 5d7b3537..01b4a0a5 100644 --- a/apps/delivery-options/src/composables/useResolvedDeliveryOptions.ts +++ b/apps/delivery-options/src/composables/useResolvedDeliveryOptions.ts @@ -1,5 +1,5 @@ /* eslint-disable max-nested-callbacks */ -import {toValue, computed} from 'vue'; +import {toValue} from 'vue'; import {useMemoize} from '@vueuse/core'; import { useDeliveryOptionsRequest, @@ -8,12 +8,11 @@ import { DELIVERY_TYPE_DEFAULT, type AnyTranslatable, createUntranslatable, - resolveCarrierName, type ComputedAsync, - addLoadingProperties, } from '@myparcel-do/shared'; import {type Replace} from '@myparcel/ts-utils'; import {type Timestamp, type DeliveryOption, type DeliveryPossibility, type DeliveryTimeFrame} from '@myparcel/sdk'; +import {DeliveryTypeName} from '@myparcel/constants'; import {createGetDeliveryOptionsParameters, getResolvedDeliveryType, createDeliveryTypeTranslatable} from '../utils'; import {type SelectedDeliveryMoment} from '../types'; import {useTimeRange} from './useTimeRange'; @@ -47,7 +46,7 @@ type UseResolvedDeliveryOptions = ComputedAsync; const callback = (): UseResolvedDeliveryOptions => { const carriers = useActiveCarriers(); - const asyncComputed = computedAsync(async () => { + return computedAsync(async () => { const resolvedDates = await Promise.all( toValue(carriers) .filter((carrier) => toValue(carrier.hasAnyDelivery)) @@ -87,15 +86,36 @@ const callback = (): UseResolvedDeliveryOptions => { ? createUntranslatable(useTimeRange(start.date_time.date, end.date_time.date).value) : createDeliveryTypeTranslatable(datePossibility.type); + const deliveryType = getResolvedDeliveryType( + carrier.config.value?.deliveryTypes ?? [], + dateOption.date?.date, + datePossibility.type, + ); + + // Skip any type that is not supported by the carrier + if (!carrier?.deliveryTypes.value.has(deliveryType)) { + return; + } + + // Given a possibility with the same start/end timeFrame, don't add the express option if standard is already present. + if ( + deliveryType === DeliveryTypeName.Express && + carrier?.deliveryTypes.value.has(DeliveryTypeName.Standard) && + possibilities.some( + (possibility) => + possibility.type === DeliveryTypeName.Standard && + possibility.delivery_time_frames[0]?.date_time.date === start.date_time.date && + possibility.delivery_time_frames[1]?.date_time.date === end.date_time.date, + ) + ) { + return; + } + acc.push({ carrier: carrier.carrier.value.identifier, date: dateOption.date?.date, time: timeString, - deliveryType: getResolvedDeliveryType( - carrier.config.value?.deliveryTypes ?? [], - dateOption.date?.date, - datePossibility.type, - ), + deliveryType, packageType: datePossibility.package_type, shipmentOptions: datePossibility.shipment_options, }); @@ -105,17 +125,6 @@ const callback = (): UseResolvedDeliveryOptions => { return acc; }, [] as SelectedDeliveryMoment[]); }, []); - - const final = computed(() => { - return asyncComputed.value.filter((option) => { - const carrierName = resolveCarrierName(option.carrier); - const carrier = carriers.value.find(({carrier}) => carrier.value.name === carrierName); - - return carrier?.deliveryTypes.value.has(option.deliveryType); - }); - }); - - return addLoadingProperties(final, asyncComputed.load, asyncComputed.loading); }; export const useResolvedDeliveryOptions = useMemoize(callback); diff --git a/apps/delivery-options/src/config/__snapshots__/getDefaultConfigForPlatform.spec.ts.snap b/apps/delivery-options/src/config/__snapshots__/getDefaultConfigForPlatform.spec.ts.snap index 630f0930..68347412 100644 --- a/apps/delivery-options/src/config/__snapshots__/getDefaultConfigForPlatform.spec.ts.snap +++ b/apps/delivery-options/src/config/__snapshots__/getDefaultConfigForPlatform.spec.ts.snap @@ -4,6 +4,7 @@ exports[`getDefaultConfigForPlatform > should return the correct default config { "allowDeliveryOptions": true, "allowEveningDelivery": true, + "allowExpressDelivery": false, "allowMondayDelivery": true, "allowMorningDelivery": true, "allowOnlyRecipient": true, @@ -42,6 +43,7 @@ exports[`getDefaultConfigForPlatform > should return the correct default config "pickupShowDistance": false, "platform": "belgie", "priceEveningDelivery": 0, + "priceExpressDelivery": 0, "priceMondayDelivery": 0, "priceMorningDelivery": 0, "priceOnlyRecipient": 0, @@ -63,6 +65,7 @@ exports[`getDefaultConfigForPlatform > should return the correct default config { "allowDeliveryOptions": true, "allowEveningDelivery": true, + "allowExpressDelivery": false, "allowMondayDelivery": true, "allowMorningDelivery": true, "allowOnlyRecipient": true, @@ -101,6 +104,7 @@ exports[`getDefaultConfigForPlatform > should return the correct default config "pickupShowDistance": true, "platform": "myparcel", "priceEveningDelivery": 0, + "priceExpressDelivery": 0, "priceMondayDelivery": 0, "priceMorningDelivery": 0, "priceOnlyRecipient": 0, diff --git a/apps/delivery-options/src/config/handleDeprecatedOptions.ts b/apps/delivery-options/src/config/handleDeprecatedOptions.ts index 9395a741..8fd5e996 100644 --- a/apps/delivery-options/src/config/handleDeprecatedOptions.ts +++ b/apps/delivery-options/src/config/handleDeprecatedOptions.ts @@ -45,11 +45,12 @@ export const handleDeprecatedOptions = { it.each([ [DeliveryTypeName.Standard, CarrierSetting.PriceStandardDelivery], + [DeliveryTypeName.Express, CarrierSetting.PriceExpressDelivery], [DeliveryTypeName.Evening, CarrierSetting.PriceEveningDelivery], [DeliveryTypeName.Morning, CarrierSetting.PriceMorningDelivery], [DeliveryTypeName.Pickup, CarrierSetting.PricePickup], diff --git a/apps/delivery-options/src/utils/getDeliveryTypePrice.spec.ts b/apps/delivery-options/src/utils/getDeliveryTypePrice.spec.ts index 92b3e855..b0284534 100644 --- a/apps/delivery-options/src/utils/getDeliveryTypePrice.spec.ts +++ b/apps/delivery-options/src/utils/getDeliveryTypePrice.spec.ts @@ -49,6 +49,11 @@ describe('getDeliveryTypePrice', () => { deliveryType: DeliveryTypeName.Standard, result: TestValue.CarrierUps | TestValue.Default, }, + { + carrier: defineCarrier(CARRIER_UPS), + deliveryType: DeliveryTypeName.Express, + result: TestValue.CarrierUps | TestValue.DeliveryTypeExpress, + }, { carrier: defineCarrier(CARRIER_POST_NL), deliveryType: DeliveryTypeName.Pickup, diff --git a/apps/delivery-options/src/utils/getResolvedCarrier.spec.ts b/apps/delivery-options/src/utils/getResolvedCarrier.spec.ts index 7b78b5e0..9a69b40a 100644 --- a/apps/delivery-options/src/utils/getResolvedCarrier.spec.ts +++ b/apps/delivery-options/src/utils/getResolvedCarrier.spec.ts @@ -153,14 +153,14 @@ describe('getResolvedCarrier', () => { }); describe('hasDelivery', () => { - it('returns true if any delivery type is enabled', () => { - const carrier = getResolvedCarrier(CarrierName.DhlForYou, PlatformName.MyParcel); + it('returns true if only standard delivery type is enabled', () => { + const carrier = getResolvedCarrier(CarrierName.Ups, PlatformName.MyParcel); mockDeliveryOptionsConfig( getMockDeliveryOptionsConfiguration({ [KEY_CONFIG]: { [KEY_CARRIER_SETTINGS]: { - [CarrierName.DhlForYou]: { + [CarrierName.Ups]: { [CarrierSetting.AllowDeliveryOptions]: true, [CarrierSetting.AllowStandardDelivery]: true, }, @@ -172,8 +172,28 @@ describe('getResolvedCarrier', () => { expect(carrier.hasDelivery.value).toEqual(true); }); + it('returns true if only express delivery type is enabled', () => { + const carrier = getResolvedCarrier(CarrierName.Ups, PlatformName.MyParcel); + + mockDeliveryOptionsConfig( + getMockDeliveryOptionsConfiguration({ + [KEY_CONFIG]: { + [KEY_CARRIER_SETTINGS]: { + [CarrierName.Ups]: { + [CarrierSetting.AllowDeliveryOptions]: true, + [CarrierSetting.AllowStandardDelivery]: false, + [CarrierSetting.AllowExpressDelivery]: true, + }, + }, + }, + }), + ); + + expect(carrier.hasDelivery.value).toEqual(true); + }); + it('returns false if no delivery types are enabled', () => { - const carrier = getResolvedCarrier(CarrierName.DhlForYou, PlatformName.MyParcel); + const carrier = getResolvedCarrier(CarrierName.Ups, PlatformName.MyParcel); expect(carrier.hasDelivery.value).toEqual(false); }); @@ -217,15 +237,32 @@ describe('getResolvedCarrier', () => { describe('hasAnyDelivery', () => { it('returns true if any delivery type is available', () => { - const carrier = getResolvedCarrier(CarrierName.DhlForYou, PlatformName.MyParcel); + const carrier = getResolvedCarrier(CarrierName.Ups, PlatformName.MyParcel); mockDeliveryOptionsConfig( getMockDeliveryOptionsConfiguration({ [KEY_CONFIG]: { [KEY_CARRIER_SETTINGS]: { - [CarrierName.DhlForYou]: { + [CarrierName.Ups]: { [CarrierSetting.AllowDeliveryOptions]: true, [CarrierSetting.AllowStandardDelivery]: true, + [CarrierSetting.AllowExpressDelivery]: false, + }, + }, + }, + }), + ); + + expect(carrier.hasAnyDelivery.value).toEqual(true); + + mockDeliveryOptionsConfig( + getMockDeliveryOptionsConfiguration({ + [KEY_CONFIG]: { + [KEY_CARRIER_SETTINGS]: { + [CarrierName.Ups]: { + [CarrierSetting.AllowDeliveryOptions]: true, + [CarrierSetting.AllowStandardDelivery]: false, + [CarrierSetting.AllowExpressDelivery]: true, }, }, }, diff --git a/apps/delivery-options/src/utils/getResolvedCarrier.ts b/apps/delivery-options/src/utils/getResolvedCarrier.ts index 297b1bcb..dedfcfdf 100644 --- a/apps/delivery-options/src/utils/getResolvedCarrier.ts +++ b/apps/delivery-options/src/utils/getResolvedCarrier.ts @@ -14,7 +14,12 @@ import {useAddressStore} from '../stores'; import {type UseResolvedCarrier} from '../composables'; import {getResolvedValue} from './getResolvedValue'; -const DELIVERY_TYPES = [DeliveryTypeName.Standard, DeliveryTypeName.Evening, DeliveryTypeName.Morning]; +const DELIVERY_TYPES = [ + DeliveryTypeName.Standard, + DeliveryTypeName.Express, + DeliveryTypeName.Evening, + DeliveryTypeName.Morning, +]; const resolveOption = ( input: SupportedDeliveryTypeName | SupportedShipmentOptionName, diff --git a/apps/delivery-options/src/utils/getResolvedDeliveryType.ts b/apps/delivery-options/src/utils/getResolvedDeliveryType.ts index 5bfb60cc..e0ec7f3a 100644 --- a/apps/delivery-options/src/utils/getResolvedDeliveryType.ts +++ b/apps/delivery-options/src/utils/getResolvedDeliveryType.ts @@ -14,6 +14,9 @@ const DAYS_MAP = Object.freeze>>({ [DAY_SATURDAY]: CustomDeliveryType.Saturday, }); +/** + * Gets an available non-standard delivery type based on the delivery date. + */ export const getResolvedDeliveryType = useMemoize( ( deliveryTypes: SupportedDeliveryTypeName[], diff --git a/apps/sandbox/package.json b/apps/sandbox/package.json index 8aee3650..b17a7148 100644 --- a/apps/sandbox/package.json +++ b/apps/sandbox/package.json @@ -19,7 +19,7 @@ }, "dependencies": { "@myparcel-do/shared": "workspace:*", - "@myparcel/constants": "^2.0.0", + "@myparcel/constants": "^2.2.0", "@myparcel/delivery-options": "workspace:*", "@myparcel/sdk": "^3.2.0", "@myparcel/ts-utils": "^1.12.0", diff --git a/apps/sandbox/src/config/getDefaultSandboxCarrierSettings.ts b/apps/sandbox/src/config/getDefaultSandboxCarrierSettings.ts index b50d9723..2b46cf20 100644 --- a/apps/sandbox/src/config/getDefaultSandboxCarrierSettings.ts +++ b/apps/sandbox/src/config/getDefaultSandboxCarrierSettings.ts @@ -29,6 +29,8 @@ export const getDefaultSandboxCarrierSettings = (): CarrierSettingsObject => { [CarrierSetting.AllowDeliveryOptions]: true, [CarrierSetting.AllowStandardDelivery]: true, [CarrierSetting.PriceStandardDelivery]: numberBetween(5, 7), + [CarrierSetting.AllowExpressDelivery]: true, + [CarrierSetting.PriceExpressDelivery]: numberBetween(10, 15), [CarrierSetting.AllowMorningDelivery]: true, [CarrierSetting.PriceMorningDelivery]: numberBetween(7, 10), [CarrierSetting.AllowEveningDelivery]: true, diff --git a/apps/sandbox/src/form/availableInPlatform.ts b/apps/sandbox/src/form/availableInPlatform.ts index 5d4e6089..c55c2939 100644 --- a/apps/sandbox/src/form/availableInPlatform.ts +++ b/apps/sandbox/src/form/availableInPlatform.ts @@ -28,6 +28,10 @@ const featureIsEnabled = ( ): boolean => { const {features} = useCarrier({carrierIdentifier, platformName}); + if (!toValue(features)?.size) { + return false; + } + const isEnabled = toValue(features).has(field); if (!isEnabled) { diff --git a/apps/sandbox/src/form/getAllSandboxConfigOptions.ts b/apps/sandbox/src/form/getAllSandboxConfigOptions.ts index a695fbc5..24a201f1 100644 --- a/apps/sandbox/src/form/getAllSandboxConfigOptions.ts +++ b/apps/sandbox/src/form/getAllSandboxConfigOptions.ts @@ -11,6 +11,9 @@ const extended = Object.freeze([ {key: CarrierSetting.AllowSameDayDelivery, parents: [CarrierSetting.AllowDeliveryOptions]}, {key: CarrierSetting.PriceSameDayDelivery, parents: [CarrierSetting.AllowSameDayDelivery]}, + {key: CarrierSetting.AllowExpressDelivery, parents: [CarrierSetting.AllowDeliveryOptions]}, + {key: CarrierSetting.PriceExpressDelivery, parents: [CarrierSetting.AllowExpressDelivery]}, + {key: CarrierSetting.AllowMorningDelivery, parents: [CarrierSetting.AllowDeliveryOptions]}, {key: CarrierSetting.PriceMorningDelivery, parents: [CarrierSetting.AllowMorningDelivery]}, diff --git a/apps/sandbox/src/form/getConfigSandboxSections.ts b/apps/sandbox/src/form/getConfigSandboxSections.ts index 63b386c3..8359404c 100644 --- a/apps/sandbox/src/form/getConfigSandboxSections.ts +++ b/apps/sandbox/src/form/getConfigSandboxSections.ts @@ -11,6 +11,7 @@ const CONFIG_GROUPS = Object.freeze([ name: OptionGroup.DeliveryMoments, items: [ CarrierSetting.AllowStandardDelivery, + CarrierSetting.AllowExpressDelivery, CarrierSetting.AllowMorningDelivery, CarrierSetting.AllowEveningDelivery, CarrierSetting.AllowSameDayDelivery, diff --git a/libs/shared/package.json b/libs/shared/package.json index 66c874ed..a40b6db0 100644 --- a/libs/shared/package.json +++ b/libs/shared/package.json @@ -32,7 +32,7 @@ }, "dependencies": { "@myparcel-do/shared": "workspace:*", - "@myparcel/constants": "^2.0.0", + "@myparcel/constants": "^2.2.0", "@myparcel/sdk": "^3.3.1", "@myparcel/ts-utils": "^1.12.0", "@myparcel/vue-form-builder": "^1.0.0-beta.1", diff --git a/libs/shared/src/__tests__/mocks/delivery-options/entries/getDeliveryOptionsEntry.ts b/libs/shared/src/__tests__/mocks/delivery-options/entries/getDeliveryOptionsEntry.ts index 864dbe2d..1e662994 100644 --- a/libs/shared/src/__tests__/mocks/delivery-options/entries/getDeliveryOptionsEntry.ts +++ b/libs/shared/src/__tests__/mocks/delivery-options/entries/getDeliveryOptionsEntry.ts @@ -6,7 +6,12 @@ import {createTimestamp} from '../../../../utils'; import {DELIVERY_TIMEFRAME_TYPE_END, DELIVERY_TIMEFRAME_TYPE_START} from '../../../../data'; import {getShipmentOptions} from './getShipmentOptions'; -export const getDeliveryOptionsEntry = (today: Date, isExtraDropOffDay: boolean, isSameDay = false): DeliveryOption => { +export const getDeliveryOptionsEntry = ( + today: Date, + isExtraDropOffDay: boolean, + isSameDay = false, + hasExpressDelivery = false, +): DeliveryOption => { const formattedDate = format(today, 'yyyy-MM-dd'); return { @@ -53,6 +58,22 @@ export const getDeliveryOptionsEntry = (today: Date, isExtraDropOffDay: boolean, ], shipment_options: getShipmentOptions(isSameDay ? [ShipmentOptionName.SameDayDelivery] : []), }, + + ...(hasExpressDelivery + ? [ + { + type: DeliveryTypeName.Express, + package_type: PackageTypeName.Package, + delivery_time_frames: [ + // @ts-expect-error todo + createDeliveryTimeframe(`${formattedDate} 08:30:00.000000`, DELIVERY_TIMEFRAME_TYPE_START), + // @ts-expect-error todo + createDeliveryTimeframe(`${formattedDate} 18:00:00.000000`, DELIVERY_TIMEFRAME_TYPE_END), + ], + shipment_options: [], + }, + ] + : []), ], }; }; diff --git a/libs/shared/src/__tests__/mocks/delivery-options/getNextDeliveryOption.ts b/libs/shared/src/__tests__/mocks/delivery-options/getNextDeliveryOption.ts index 2252e02e..d210d1b4 100644 --- a/libs/shared/src/__tests__/mocks/delivery-options/getNextDeliveryOption.ts +++ b/libs/shared/src/__tests__/mocks/delivery-options/getNextDeliveryOption.ts @@ -27,6 +27,7 @@ export const getNextDeliveryOption = async ( const canHaveSameDay = carrierInstance.features.value.has(CarrierSetting.AllowSameDayDelivery); const hasSameDayDelivery = daysOffset === 0 && canHaveSameDay; + const hasExpressDelivery = carrierInstance.features.value.has(CarrierSetting.AllowExpressDelivery); const extraDelivery = hasSameDayDelivery ? undefined @@ -41,6 +42,6 @@ export const getNextDeliveryOption = async ( return { index: daysOffset, - data: getDeliveryOptionsEntry(currentDeliveryDate, Boolean(extraDelivery), hasSameDayDelivery), + data: getDeliveryOptionsEntry(currentDeliveryDate, Boolean(extraDelivery), hasSameDayDelivery, hasExpressDelivery), }; }; diff --git a/libs/shared/src/config/getMyParcelConfig.ts b/libs/shared/src/config/getMyParcelConfig.ts index 87ea574f..2c246549 100644 --- a/libs/shared/src/config/getMyParcelConfig.ts +++ b/libs/shared/src/config/getMyParcelConfig.ts @@ -163,8 +163,10 @@ export const getMyParcelConfig = (): PlatformConfiguration => ({ name: CarrierName.Ups, subscription: SubscriptionType.Required, packageTypes: [PackageTypeName.Package], - deliveryTypes: [DeliveryTypeName.Standard, DeliveryTypeName.Pickup], + deliveryTypes: [DeliveryTypeName.Standard, DeliveryTypeName.Pickup, DeliveryTypeName.Express], deliveryCountries: [ + AUSTRIA, + BELGIUM, BULGARIA, GERMANY, ESTONIA, @@ -177,7 +179,7 @@ export const getMyParcelConfig = (): PlatformConfiguration => ({ LATVIA, LITHUANIA, LUXEMBOURG, - AUSTRIA, + NETHERLANDS, POLAND, PORTUGAL, ROMANIA, @@ -187,8 +189,6 @@ export const getMyParcelConfig = (): PlatformConfiguration => ({ CZECH_REPUBLIC, ], pickupCountries: [GERMANY], - fakeDelivery: true, - fakeDeliveryBlacklist: [NETHERLANDS], addressFields: [AddressField.PostalCode, AddressField.Street, AddressField.City], unsupportedParameters: ['package_type'], }, diff --git a/libs/shared/src/data/enums.ts b/libs/shared/src/data/enums.ts index f6c2db7c..6afabec6 100644 --- a/libs/shared/src/data/enums.ts +++ b/libs/shared/src/data/enums.ts @@ -19,6 +19,8 @@ export enum CarrierSetting { AllowSaturdayDelivery = 'allowSaturdayDelivery', AllowSignature = 'allowSignature', AllowStandardDelivery = 'allowStandardDelivery', + AllowExpressDelivery = 'allowExpressDelivery', + Collect = 'collect', CutoffTime = 'cutoffTime', CutoffTimeSameDay = 'cutoffTimeSameDay', DeliveryDaysWindow = 'deliveryDaysWindow', @@ -34,6 +36,7 @@ export enum CarrierSetting { PricePackageTypePackageSmall = 'pricePackageTypePackageSmall', PricePickup = 'pricePickup', PriceSameDayDelivery = 'priceSameDayDelivery', + PriceExpressDelivery = 'priceExpressDelivery', PriceSaturdayDelivery = 'priceSaturdayDelivery', PriceSignature = 'priceSignature', PriceStandardDelivery = 'priceStandardDelivery', diff --git a/libs/shared/src/types/config.types.ts b/libs/shared/src/types/config.types.ts index a565fd16..32606296 100644 --- a/libs/shared/src/types/config.types.ts +++ b/libs/shared/src/types/config.types.ts @@ -55,12 +55,14 @@ export interface CarrierSettings extends Partial should return the correct config map 1`] = ` { "evening": "allowEveningDelivery", + "express": "allowExpressDelivery", "monday": "allowMondayDelivery", "morning": "allowMorningDelivery", "pickup": "allowPickupLocations", diff --git a/libs/shared/src/utils/__snapshots__/getPlatformConfig.spec.ts.snap b/libs/shared/src/utils/__snapshots__/getPlatformConfig.spec.ts.snap index bdcd51e8..d3e948c2 100644 --- a/libs/shared/src/utils/__snapshots__/getPlatformConfig.spec.ts.snap +++ b/libs/shared/src/utils/__snapshots__/getPlatformConfig.spec.ts.snap @@ -333,6 +333,8 @@ exports[`getPlatformConfig > gets config for platform myparcel 1`] = ` "city", ], "deliveryCountries": [ + "AT", + "BE", "BG", "DE", "EE", @@ -345,7 +347,7 @@ exports[`getPlatformConfig > gets config for platform myparcel 1`] = ` "LV", "LT", "LU", - "AT", + "NL", "PL", "PT", "RO", @@ -357,10 +359,7 @@ exports[`getPlatformConfig > gets config for platform myparcel 1`] = ` "deliveryTypes": [ "standard", "pickup", - ], - "fakeDelivery": true, - "fakeDeliveryBlacklist": [ - "NL", + "express", ], "name": "ups", "packageTypes": [ diff --git a/libs/shared/src/utils/getAllConfigOptions.ts b/libs/shared/src/utils/getAllConfigOptions.ts index e81556c4..3caf3bc6 100644 --- a/libs/shared/src/utils/getAllConfigOptions.ts +++ b/libs/shared/src/utils/getAllConfigOptions.ts @@ -19,6 +19,7 @@ export const getAllConfigOptions = useMemoize((): ConfigOption[] => [ declareOption({key: CarrierSetting.AllowDeliveryOptions, perCarrier: true}), ...declareOptionWithPrice(CarrierSetting.AllowStandardDelivery, CarrierSetting.PriceStandardDelivery), + ...declareOptionWithPrice(CarrierSetting.AllowExpressDelivery, CarrierSetting.PriceExpressDelivery), ...declareOptionWithPrice(CarrierSetting.AllowMorningDelivery, CarrierSetting.PriceMorningDelivery), ...declareOptionWithPrice(CarrierSetting.AllowEveningDelivery, CarrierSetting.PriceEveningDelivery), ...declareOptionWithPrice(CarrierSetting.AllowSameDayDelivery, CarrierSetting.PriceSameDayDelivery), diff --git a/libs/shared/src/utils/getDeliveryTypeConfigMap.ts b/libs/shared/src/utils/getDeliveryTypeConfigMap.ts index 9c9ff2c7..0018dbfb 100644 --- a/libs/shared/src/utils/getDeliveryTypeConfigMap.ts +++ b/libs/shared/src/utils/getDeliveryTypeConfigMap.ts @@ -4,6 +4,7 @@ import {CarrierSetting, CustomDeliveryType} from '../data'; export const getDeliveryTypeConfigMap = (): Record => ({ [DeliveryTypeName.Standard]: CarrierSetting.AllowStandardDelivery, + [DeliveryTypeName.Express]: CarrierSetting.AllowExpressDelivery, [DeliveryTypeName.Evening]: CarrierSetting.AllowEveningDelivery, [DeliveryTypeName.Morning]: CarrierSetting.AllowMorningDelivery, [DeliveryTypeName.Pickup]: CarrierSetting.AllowPickupLocations, diff --git a/package.json b/package.json index 66fa6bf9..584fa8f9 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ }, "prettier": "@myparcel/prettier-config", "resolutions": { - "@myparcel/constants": "^2.0.0", + "@myparcel/constants": "^2.2.0", "conventional-changelog-conventionalcommits": ">= 8.0.0", "eslint-plugin-prettier": "^4.2.1", "typescript": "^5.4.0" diff --git a/yarn.lock b/yarn.lock index 7f5fce82..0fa47655 100644 --- a/yarn.lock +++ b/yarn.lock @@ -823,7 +823,7 @@ __metadata: "@edielemoine/google-docs-importer": "npm:^2.0.0" "@myparcel-do/build-vite": "workspace:*" "@myparcel-do/shared": "workspace:*" - "@myparcel/constants": "npm:^2.0.0" + "@myparcel/constants": "npm:^2.2.0" "@myparcel/delivery-options": "workspace:*" "@myparcel/sdk": "npm:^3.2.0" "@myparcel/ts-utils": "npm:^1.12.0" @@ -867,7 +867,7 @@ __metadata: "@myparcel-do/build-vite": "workspace:*" "@myparcel-do/semantic-release-plugin": "workspace:*" "@myparcel-do/shared": "workspace:*" - "@myparcel/constants": "npm:^2.0.0" + "@myparcel/constants": "npm:^2.2.0" "@myparcel/sdk": "npm:^3.3.1" "@myparcel/ts-utils": "npm:^1.12.0" "@myparcel/vue-form-builder": "npm:^1.0.0-beta.1" @@ -1097,12 +1097,12 @@ __metadata: languageName: node linkType: hard -"@myparcel/constants@npm:^2.0.0": - version: 2.0.0 - resolution: "@myparcel/constants@npm:2.0.0" +"@myparcel/constants@npm:^2.2.0": + version: 2.2.0 + resolution: "@myparcel/constants@npm:2.2.0" dependencies: "@myparcel/ts-utils": "npm:^1.7.0" - checksum: 10c0/77e190badd762e0d862afe09bf351ca3d7a57b2f9c98c835e94f26ff71d551cba6748bd6c9e40b2ccc44cf05982798527982448a56b67e0756daa16c746a72f0 + checksum: 10c0/242a8d2294937e3a3c86d45f76bcb8f7cc6518a72ed4fdaa0e62e27267bb84bd46b03c68e6c50a315309c928cdf72b939e2077f4231df991bb36b79163c6c3c1 languageName: node linkType: hard @@ -1115,7 +1115,7 @@ __metadata: "@myparcel-do/build-vite": "workspace:*" "@myparcel-do/semantic-release-plugin": "workspace:*" "@myparcel-do/shared": "workspace:*" - "@myparcel/constants": "npm:^2.0.0" + "@myparcel/constants": "npm:^2.2.0" "@myparcel/sdk": "npm:^4.0.0" "@myparcel/semantic-release-config": "npm:^5.0.0" "@myparcel/ts-utils": "npm:^1.12.0"