@sabstravtech/obtservices 0.2.2511131440 → 0.2.2511200338

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.
@@ -7,14 +7,15 @@ export type Required = Record<string, BasketItemManagementInfo[]>;
7
7
  export type RequiresReasonType = {
8
8
  basket: UserBasketResult;
9
9
  required: Required;
10
+ isDualSingleFlight?: boolean;
10
11
  };
11
12
  export interface RequiresReasonServiceInterface {
12
13
  currentBasketid: string;
13
14
  reasonChecked: BehaviorSubject<ReasonCheckedInterface>;
14
- reasonSelected: BehaviorSubject<Boolean>;
15
+ reasonSelected: BehaviorSubject<boolean>;
15
16
  isReasonCancel: boolean;
16
17
  isBooking: boolean;
17
- isReadyToBook: BehaviorSubject<Boolean>;
18
+ isReadyToBook: BehaviorSubject<boolean>;
18
19
  }
19
20
  export interface ReasonCheckedInterface {
20
21
  basketId: string;
@@ -25,12 +26,18 @@ export declare class BaseRequiresReasonService implements RequiresReasonServiceI
25
26
  private basketService;
26
27
  currentBasketid: string;
27
28
  private workingOn;
29
+ private processedDualSingleBasketItems;
30
+ private pendingDualSingleBasketItem;
28
31
  reasonChecked: BehaviorSubject<ReasonCheckedInterface>;
29
- reasonSelected: BehaviorSubject<Boolean>;
32
+ reasonSelected: BehaviorSubject<boolean>;
30
33
  isReasonCancel: boolean;
31
34
  isBooking: boolean;
32
- isReadyToBook: BehaviorSubject<Boolean>;
35
+ isReadyToBook: BehaviorSubject<boolean>;
33
36
  constructor(modalService: BaseModalOpenerService, basketService: EnterpriseBasketServiceInterface);
37
+ private isDualSingleFlight;
38
+ private isFirstLegOfDualSingle;
39
+ private getFilteredManagementInfo;
40
+ private buildWorkingOnForItems;
34
41
  addBasketItem(basket: UserBasketResult, basketItemId: string): Promise<void>;
35
42
  showDialogueWithNewData(workingOn: RequiresReasonType): Promise<void>;
36
43
  reasonKeysOverlap(biReasonKeys: string[], miReasonKeys: string[]): boolean;
@@ -992,22 +992,32 @@ export interface FavouriteGuest extends Guest {
992
992
  }
993
993
  export declare enum MealType {
994
994
  None = "None",
995
- VGML = "Vegetarian-Vegan",
996
- VOML = "Asian Vegetarian",
997
- RVML = "Raw Vegetarian/Vegan",
995
+ AVML = "Asian Vegetarian",
996
+ BLML = "Bland",
997
+ CHML = "Child",
998
+ DBML = "Diabetic",
998
999
  FPML = "Fruit Plate",
999
- SFML = "Seafood",
1000
- KSML = "Kosher",
1001
- MOML = "Muslim",
1000
+ FSML = "Fish",
1001
+ GFML = "Gluten intolerant",
1002
1002
  HNML = "Hindu",
1003
+ IVML = "Indian Vegetarian",
1004
+ JPML = "Japanese",
1005
+ KSML = "Kosher",
1006
+ KVML = "Kosher Vegetarian",
1007
+ LCML = "Low Calorie",
1003
1008
  LFML = "Low Fat/Cholesterol",
1004
- VLML = "Vegetarian Lacto-Ovo",
1005
1009
  LSML = "Low Sodium",
1006
- GFML = "Gluten intolerant",
1007
- DBML = "Diabetic",
1010
+ MOML = "Muslim",
1011
+ NFML = "No Fish",
1008
1012
  NLML = "Non-Lactose",
1009
- CHML = "Child",
1010
- BLML = "Bland"
1013
+ NSML = "No Salt",
1014
+ PFML = "Peanuts Free",
1015
+ RVML = "Raw Vegetarian/Vegan",
1016
+ SFML = "Seafood",
1017
+ VGML = "Vegetarian-Vegan",
1018
+ VJML = "Vegetarian Jain",
1019
+ VLML = "Vegetarian Lacto-Ovo",
1020
+ VOML = "Vegetarian Oriental"
1011
1021
  }
1012
1022
  export declare enum SpecialNeeds {
1013
1023
  None = "None",
@@ -2844,22 +2844,32 @@ const genders = [
2844
2844
  Gender.Unspecified_Others
2845
2845
  ];
2846
2846
  const PREFERENCE_VALUES$1 = [
2847
+ { label: "Asian Vegetarian", type: PreferenceKey.MealRequest, code: "AVML" },
2847
2848
  { label: "Bland", type: PreferenceKey.MealRequest, code: "BLML" },
2848
2849
  { label: "Child", type: PreferenceKey.MealRequest, code: "CHML" },
2849
2850
  { label: "Diabetic", type: PreferenceKey.MealRequest, code: "DBML" },
2851
+ { label: "Fish", type: PreferenceKey.MealRequest, code: "FSML" },
2850
2852
  { label: "Fruit Plate", type: PreferenceKey.MealRequest, code: "FPML" },
2851
- { label: "Gluten intolerant", type: PreferenceKey.MealRequest, code: "GFML" },
2853
+ { label: "Gluten Free", type: PreferenceKey.MealRequest, code: "GFML" },
2852
2854
  { label: "Hindu", type: PreferenceKey.MealRequest, code: "HNML" },
2855
+ { label: "Indian Vegetarian", type: PreferenceKey.MealRequest, code: "IVML" },
2856
+ { label: "Japanese", type: PreferenceKey.MealRequest, code: "JPML" },
2853
2857
  { label: "Kosher", type: PreferenceKey.MealRequest, code: "KSML" },
2858
+ { label: "Kosher Vegetarian", type: PreferenceKey.MealRequest, code: "KVML" },
2859
+ { label: "Low Calorie", type: PreferenceKey.MealRequest, code: "LCML" },
2854
2860
  { label: "Low Fat/Cholesterol", type: PreferenceKey.MealRequest, code: "LFML" },
2855
2861
  { label: "Low Sodium", type: PreferenceKey.MealRequest, code: "LSML" },
2856
2862
  { label: "Muslim", type: PreferenceKey.MealRequest, code: "MOML" },
2863
+ { label: "No Fish", type: PreferenceKey.MealRequest, code: "NFML" },
2857
2864
  { label: "Non-Lactose", type: PreferenceKey.MealRequest, code: "NLML" },
2865
+ { label: "No Salt", type: PreferenceKey.MealRequest, code: "NSML" },
2866
+ { label: "Peanuts Free", type: PreferenceKey.MealRequest, code: "PFML" },
2858
2867
  { label: "Raw Vegetarian/Vegan", type: PreferenceKey.MealRequest, code: "RVML" },
2859
2868
  { label: "Seafood", type: PreferenceKey.MealRequest, code: "SFML" },
2860
2869
  { label: "Vegetarian-Vegan", type: PreferenceKey.MealRequest, code: "VGML" },
2870
+ { label: "Vegetarian Jain", type: PreferenceKey.MealRequest, code: "VJML" },
2861
2871
  { label: "Vegetarian Lacto-Ovo", type: PreferenceKey.MealRequest, code: "VLML" },
2862
- { label: "Asian Vegetarian", type: PreferenceKey.MealRequest, code: "VOML" },
2872
+ { label: "Vegetarian Oriental", type: PreferenceKey.MealRequest, code: "VOML" },
2863
2873
  { label: "Aisle", type: PreferenceKey.SeatingPreference },
2864
2874
  { label: "Window", type: PreferenceKey.SeatingPreference },
2865
2875
  { label: "Bassinet", type: PreferenceKey.SpecialNeed, code: "BSCT" },
@@ -4623,22 +4633,32 @@ var ErmFareTypes;
4623
4633
  var MealType;
4624
4634
  (function (MealType) {
4625
4635
  MealType["None"] = "None";
4626
- MealType["VGML"] = "Vegetarian-Vegan";
4627
- MealType["VOML"] = "Asian Vegetarian";
4628
- MealType["RVML"] = "Raw Vegetarian/Vegan";
4636
+ MealType["AVML"] = "Asian Vegetarian";
4637
+ MealType["BLML"] = "Bland";
4638
+ MealType["CHML"] = "Child";
4639
+ MealType["DBML"] = "Diabetic";
4629
4640
  MealType["FPML"] = "Fruit Plate";
4630
- MealType["SFML"] = "Seafood";
4631
- MealType["KSML"] = "Kosher";
4632
- MealType["MOML"] = "Muslim";
4641
+ MealType["FSML"] = "Fish";
4642
+ MealType["GFML"] = "Gluten intolerant";
4633
4643
  MealType["HNML"] = "Hindu";
4644
+ MealType["IVML"] = "Indian Vegetarian";
4645
+ MealType["JPML"] = "Japanese";
4646
+ MealType["KSML"] = "Kosher";
4647
+ MealType["KVML"] = "Kosher Vegetarian";
4648
+ MealType["LCML"] = "Low Calorie";
4634
4649
  MealType["LFML"] = "Low Fat/Cholesterol";
4635
- MealType["VLML"] = "Vegetarian Lacto-Ovo";
4636
4650
  MealType["LSML"] = "Low Sodium";
4637
- MealType["GFML"] = "Gluten intolerant";
4638
- MealType["DBML"] = "Diabetic";
4651
+ MealType["MOML"] = "Muslim";
4652
+ MealType["NFML"] = "No Fish";
4639
4653
  MealType["NLML"] = "Non-Lactose";
4640
- MealType["CHML"] = "Child";
4641
- MealType["BLML"] = "Bland";
4654
+ MealType["NSML"] = "No Salt";
4655
+ MealType["PFML"] = "Peanuts Free";
4656
+ MealType["RVML"] = "Raw Vegetarian/Vegan";
4657
+ MealType["SFML"] = "Seafood";
4658
+ MealType["VGML"] = "Vegetarian-Vegan";
4659
+ MealType["VJML"] = "Vegetarian Jain";
4660
+ MealType["VLML"] = "Vegetarian Lacto-Ovo";
4661
+ MealType["VOML"] = "Vegetarian Oriental";
4642
4662
  })(MealType || (MealType = {}));
4643
4663
  var SpecialNeeds;
4644
4664
  (function (SpecialNeeds) {
@@ -12249,7 +12269,6 @@ class FlightEnterpriseSearch extends BaseEnterpriseSearch {
12249
12269
  returnTimeWindow: ss.returnDepartureTimeWindow
12250
12270
  }
12251
12271
  : null);
12252
- this.searchService.saveRecentSearch(this.getRecentSearchQuery(query));
12253
12272
  delete this.ssoObject;
12254
12273
  console.warn('+++ starting sso search +++');
12255
12274
  return this._startSearch(this.flightfetcher.fetchList(query));
@@ -16504,7 +16523,7 @@ class HotelEnterpriseSearch extends BaseEnterpriseSearch {
16504
16523
  // build the query
16505
16524
  this.buildQuery();
16506
16525
  const query = this.getSearchQuery();
16507
- this.searchService.saveRecentSearch(this.getRecentSearchQuery(this.getSearchQuery()));
16526
+ this.searchService.saveRecentSearch(this.getRecentSearchQuery(query));
16508
16527
  return this._startSearch(this.tempParams.location_type_select === LocationTypes.Shortlist
16509
16528
  ? this.quickListFetcher.fetchList({
16510
16529
  countryCode: this.country.cCode,
@@ -16541,7 +16560,10 @@ class HotelEnterpriseSearch extends BaseEnterpriseSearch {
16541
16560
  countryCode: locationDetails.countryCode
16542
16561
  }
16543
16562
  };
16544
- this.boltSearchQuery = originalSearchHotel;
16563
+ this.boltSearchQuery = _.clone(query);
16564
+ this.boltSearchQuery.location_type_select = 'Address';
16565
+ this.boltSearchQuery.checkin_date = moment(this.boltSearchQuery.startDate);
16566
+ this.boltSearchQuery.checkout_date = moment(this.boltSearchQuery.endDate);
16545
16567
  this.resetSearch();
16546
16568
  this.checkin_date = null;
16547
16569
  this.checkout_date = null;
@@ -16631,7 +16653,11 @@ class HotelEnterpriseSearch extends BaseEnterpriseSearch {
16631
16653
  return this.helpers.removeNulls(this.query);
16632
16654
  }
16633
16655
  buildQuery(ogSearch = false) {
16634
- const tempParams = ogSearch && this.originalUserSearch ? this.originalUserSearch : this.tempParams;
16656
+ const tempParams = ogSearch && this.originalUserSearch
16657
+ ? this.originalUserSearch
16658
+ : this.boltSearchQuery && this.boltSearchQuery?.length
16659
+ ? this.boltSearchQuery
16660
+ : this.tempParams;
16635
16661
  const currencyObject = this.userService.getUserFavoriteObject(UserFavorurite.PreferredCurrency);
16636
16662
  if ((!this.userCurrency || this.userCurrency !== currencyObject?.currency) &&
16637
16663
  currencyObject?.hotel?.enable) {
@@ -16672,46 +16698,56 @@ class HotelEnterpriseSearch extends BaseEnterpriseSearch {
16672
16698
  this.getRoomNumber();
16673
16699
  switch (tempParams.location_type_select) {
16674
16700
  case LocationTypes.Address:
16675
- switch (tempParams.location.type) {
16676
- case LocationTypes.Airport:
16677
- query.iata = tempParams.location.iata;
16678
- break;
16679
- case LocationTypes.City:
16680
- query.countryCode = tempParams.location.countryCode;
16681
- if (tempParams.location?.city || tempParams.location?.name) {
16682
- query.cityName = tempParams.location?.city || tempParams.location?.name;
16683
- }
16684
- else if (tempParams.location.postcode) {
16701
+ if (tempParams.location?.type) {
16702
+ switch (tempParams.location.type) {
16703
+ case LocationTypes.Airport:
16704
+ query.iata = tempParams.location.iata;
16705
+ query.countryCode = tempParams.location.countryCode;
16706
+ break;
16707
+ case LocationTypes.City:
16708
+ query.countryCode = tempParams.location.countryCode;
16709
+ if (tempParams.location?.name || tempParams.location?.city) {
16710
+ query.cityName = tempParams.location?.name || tempParams.location?.city;
16711
+ }
16712
+ else if (tempParams.location.postcode) {
16713
+ query.postOrZipCode = tempParams.location.postcode;
16714
+ }
16715
+ query.latitude = tempParams.location.latitude;
16716
+ query.longitude = tempParams.location.longitude;
16717
+ break;
16718
+ case LocationTypes.Hotel:
16685
16719
  query.postOrZipCode = tempParams.location.postcode;
16686
- }
16687
- query.latitude = tempParams.location.latitude;
16688
- query.longitude = tempParams.location.longitude;
16689
- break;
16690
- case LocationTypes.Hotel:
16691
- query.postOrZipCode = tempParams.location.postcode;
16692
- query.latitude = tempParams.location.latitude;
16693
- query.longitude = tempParams.location.longitude;
16694
- query.hotelName = tempParams.location.hotelTitle;
16695
- query.countryCode = tempParams.location.countryCode;
16696
- // Use location name as fallback for hotel name if hotel_name field is empty (for recent searches)
16697
- if (!tempParams.hotel_name && tempParams.location?.name && !query.hotelName) {
16698
- query.hotelName = tempParams.location.name;
16699
- }
16700
- // Also set cityName if location has city property
16701
- if (tempParams.location?.city) {
16702
- query.cityName = tempParams.location.city;
16703
- }
16704
- break;
16705
- case LocationTypes.TrainStation:
16706
- if (tempParams.location.latitude && tempParams.location.longitude) {
16707
- //For EU stations
16708
16720
  query.latitude = tempParams.location.latitude;
16709
16721
  query.longitude = tempParams.location.longitude;
16710
- if (tempParams.location.stationCode || tempParams.location.trainStationCode) {
16711
- query.trainStationCode = tempParams.location.stationCode || tempParams.location.trainStationCode;
16722
+ query.hotelName = tempParams.location.hotelTitle;
16723
+ query.countryCode = tempParams.location.countryCode;
16724
+ // Use location name as fallback for hotel name if hotel_name field is empty (for recent searches)
16725
+ if (!tempParams.hotel_name && tempParams.location?.name && !query.hotelName) {
16726
+ query.hotelName = tempParams.location.name;
16712
16727
  }
16713
- }
16714
- break;
16728
+ // Also set cityName if location has city property
16729
+ if (tempParams.location?.city) {
16730
+ query.cityName = tempParams.location.city;
16731
+ }
16732
+ break;
16733
+ case LocationTypes.TrainStation:
16734
+ if (tempParams.location.latitude && tempParams.location.longitude) {
16735
+ //For EU stations
16736
+ query.latitude = tempParams.location.latitude;
16737
+ query.longitude = tempParams.location.longitude;
16738
+ query.countryCode = tempParams.location.countryCode;
16739
+ if (tempParams.location.stationCode || tempParams.location.trainStationCode) {
16740
+ query.trainStationCode =
16741
+ tempParams.location.stationCode || tempParams.location.trainStationCode;
16742
+ }
16743
+ }
16744
+ break;
16745
+ }
16746
+ }
16747
+ else {
16748
+ query.countryCode = 'GB';
16749
+ query.latitude = tempParams.latitude;
16750
+ query.longitude = tempParams.longitude;
16715
16751
  }
16716
16752
  break;
16717
16753
  case LocationTypes.Office:
@@ -17428,7 +17464,13 @@ class HotelEnterpriseSearch extends BaseEnterpriseSearch {
17428
17464
  const arriveLocation = outboundFlights[outboundFlights.length - 1]?.destinationAirportDetail;
17429
17465
  if (arriveLocation) {
17430
17466
  this.country = { cCode: arriveLocation.countryCode, cName: arriveLocation.countryName };
17431
- this.location = { countryCode: arriveLocation.countryCode, latitude: arriveLocation.latitude, longitude: arriveLocation.longitude, type: LocationTypes.City, name: arriveLocation.city };
17467
+ this.location = {
17468
+ countryCode: arriveLocation.countryCode,
17469
+ latitude: arriveLocation.latitude,
17470
+ longitude: arriveLocation.longitude,
17471
+ type: LocationTypes.City,
17472
+ name: arriveLocation.city
17473
+ };
17432
17474
  }
17433
17475
  else {
17434
17476
  this.location = null;
@@ -17450,6 +17492,9 @@ class HotelEnterpriseSearch extends BaseEnterpriseSearch {
17450
17492
  if (railstation?.stationCode) {
17451
17493
  locationDetail.stationCode = railstation.stationCode;
17452
17494
  }
17495
+ if (railstation?.locationDetails?.countryCode) {
17496
+ locationDetail.countryCode = railstation.locationDetails.countryCode;
17497
+ }
17453
17498
  this.location = locationDetail;
17454
17499
  }
17455
17500
  catch {
@@ -17470,6 +17515,9 @@ class HotelEnterpriseSearch extends BaseEnterpriseSearch {
17470
17515
  if (railstation?.stationCode) {
17471
17516
  locationDetail.stationCode = railstation.stationCode;
17472
17517
  }
17518
+ if (railstation?.locationDetails?.countryCode) {
17519
+ locationDetail.countryCode = railstation.locationDetails.countryCode;
17520
+ }
17473
17521
  this.location = locationDetail;
17474
17522
  }
17475
17523
  catch {
@@ -17485,7 +17533,13 @@ class HotelEnterpriseSearch extends BaseEnterpriseSearch {
17485
17533
  const arriveLocation = outboundFlights[outboundFlights.length - 1]?.destinationAirportDetail;
17486
17534
  if (arriveLocation) {
17487
17535
  this.country = { cCode: arriveLocation.countryCode, cName: arriveLocation.countryName };
17488
- this.location = { countryCode: arriveLocation.countryCode, latitude: arriveLocation.latitude, longitude: arriveLocation.longitude, type: LocationTypes.City, name: arriveLocation.city };
17536
+ this.location = {
17537
+ countryCode: arriveLocation.countryCode,
17538
+ latitude: arriveLocation.latitude,
17539
+ longitude: arriveLocation.longitude,
17540
+ type: LocationTypes.City,
17541
+ name: arriveLocation.city
17542
+ };
17489
17543
  }
17490
17544
  else {
17491
17545
  this.location = null;
@@ -17508,13 +17562,25 @@ class HotelEnterpriseSearch extends BaseEnterpriseSearch {
17508
17562
  switch (carHireSearch.locationType) {
17509
17563
  case LocationTypes.Airport:
17510
17564
  this.country = { cCode: pickup_location.countryCode, cName: pickup_location.country };
17511
- this.location = { countryCode: pickup_location.countryCode, latitude: pickup_location.latitude, longitude: pickup_location.longitude, type: LocationTypes.City, name: pickup_location.destination };
17565
+ this.location = {
17566
+ countryCode: pickup_location.countryCode,
17567
+ latitude: pickup_location.latitude,
17568
+ longitude: pickup_location.longitude,
17569
+ type: LocationTypes.City,
17570
+ name: pickup_location.destination
17571
+ };
17512
17572
  break;
17513
17573
  case LocationTypes.City:
17514
17574
  {
17515
17575
  const cityCountryInfo = Countries.find(c => c.cCode === cityPickup.countryCode);
17516
17576
  this.country = { cCode: cityCountryInfo.cCode, cName: cityCountryInfo.cName };
17517
- this.location = { countryCode: cityPickup.countryCode, latitude: cityPickup.latitude, longitude: cityPickup.longitude, type: LocationTypes.City, name: cityPickup.city ? cityPickup.city : cityPickup.name };
17577
+ this.location = {
17578
+ countryCode: cityPickup.countryCode,
17579
+ latitude: cityPickup.latitude,
17580
+ longitude: cityPickup.longitude,
17581
+ type: LocationTypes.City,
17582
+ name: cityPickup.city ? cityPickup.city : cityPickup.name
17583
+ };
17518
17584
  }
17519
17585
  break;
17520
17586
  case LocationTypes.Postcode:
@@ -17522,7 +17588,12 @@ class HotelEnterpriseSearch extends BaseEnterpriseSearch {
17522
17588
  const postCodeCountryInfo = Countries.find(c => c.cCode === postcodePickup.countryCode);
17523
17589
  this.country = { cCode: postCodeCountryInfo.cCode, cName: postCodeCountryInfo.cName };
17524
17590
  this.location = null;
17525
- this.location = { countryCode: postcodePickup.countryCode, postcode: postcodePickupRaw.postcode, type: LocationTypes.City, name: postcodePickupRaw.postcode };
17591
+ this.location = {
17592
+ countryCode: postcodePickup.countryCode,
17593
+ postcode: postcodePickupRaw.postcode,
17594
+ type: LocationTypes.City,
17595
+ name: postcodePickupRaw.postcode
17596
+ };
17526
17597
  this.postcode = postcodePickupRaw;
17527
17598
  }
17528
17599
  break;
@@ -18020,9 +18091,7 @@ class HotelEnterpriseSearch extends BaseEnterpriseSearch {
18020
18091
  this.no_of_rooms = query.rooms;
18021
18092
  // Don't populate hotel_name from recent search to avoid duplication with location field
18022
18093
  // The hotel name will be used from location.name as fallback in buildQuery()
18023
- this.hotel_name = cloneBasketItem
18024
- ? this.clonedBasketItemDetails.hotelName
18025
- : null;
18094
+ this.hotel_name = cloneBasketItem ? this.clonedBasketItemDetails.hotelName : null;
18026
18095
  this.hotel_chain = query.groupName ? { name: query.groupName } : null;
18027
18096
  this.country = query.countryCode
18028
18097
  ? (this.country = {
@@ -29317,6 +29386,8 @@ class BaseRequiresReasonService {
29317
29386
  basketService;
29318
29387
  currentBasketid;
29319
29388
  workingOn;
29389
+ processedDualSingleBasketItems = new Set();
29390
+ pendingDualSingleBasketItem = null;
29320
29391
  reasonChecked = new BehaviorSubject(null);
29321
29392
  reasonSelected = new BehaviorSubject(false);
29322
29393
  isReasonCancel;
@@ -29326,13 +29397,47 @@ class BaseRequiresReasonService {
29326
29397
  this.modalService = modalService;
29327
29398
  this.basketService = basketService;
29328
29399
  }
29400
+ isDualSingleFlight(basket) {
29401
+ return basket.basketItems.length === 2 &&
29402
+ basket.basketItems.every(item => item?.service?.type === ServiceType.Flight && item?.detail?.journeyType === 'single') &&
29403
+ basket.basketItems.every(item => item?.reasonKeys?.length > 0) &&
29404
+ JSON.stringify(basket.basketItems[0]?.searchQuery) === JSON.stringify(basket.basketItems[1]?.searchQuery);
29405
+ }
29406
+ isFirstLegOfDualSingle(basket) {
29407
+ return basket.basketItems.length === 1 &&
29408
+ basket.basketItems[0]?.service?.type === ServiceType.Flight &&
29409
+ basket.basketItems[0]?.detail?.journeyType === 'single' &&
29410
+ basket.basketItems[0]?.reasonKeys?.length > 0 &&
29411
+ basket.basketItems[0]?.searchQuery?.returnTrip === true;
29412
+ }
29413
+ getFilteredManagementInfo(basketItem) {
29414
+ return basketItem.managementInfo?.filter((mi) => {
29415
+ return mi.required && this.reasonKeysOverlap(basketItem.reasonKeys, mi.managementInfo.reasonKeys);
29416
+ }) || [];
29417
+ }
29418
+ buildWorkingOnForItems(basket, basketItems, isDualSingle) {
29419
+ return {
29420
+ basket,
29421
+ isDualSingleFlight: isDualSingle,
29422
+ required: basketItems.reduce((required, bi) => {
29423
+ required[bi.id] = this.getFilteredManagementInfo(bi);
29424
+ return required;
29425
+ }, {})
29426
+ };
29427
+ }
29329
29428
  async addBasketItem(basket, basketItemId) {
29330
29429
  if (basket.id !== this.currentBasketid) {
29430
+ this.processedDualSingleBasketItems.clear();
29431
+ this.pendingDualSingleBasketItem = null;
29432
+ return;
29433
+ }
29434
+ const isDualSingle = this.isDualSingleFlight(basket);
29435
+ if (isDualSingle && this.processedDualSingleBasketItems.has(basketItemId)) {
29331
29436
  return;
29332
29437
  }
29333
29438
  const basketItems = basket.basketItems.filter((bi) => {
29334
- return (!bi.agentOverrodeUnavailable && // we ask for reason and override in the override modal if applicable
29335
- basketItemId === bi.id &&
29439
+ return (!bi.agentOverrodeUnavailable &&
29440
+ (isDualSingle ? true : basketItemId === bi.id) &&
29336
29441
  bi.reasonKeys?.length &&
29337
29442
  !!bi.managementInfo?.filter((mi) => {
29338
29443
  return mi.required && !mi.selectedValue && this.reasonKeysOverlap(bi.reasonKeys, mi.managementInfo.reasonKeys);
@@ -29340,22 +29445,31 @@ class BaseRequiresReasonService {
29340
29445
  });
29341
29446
  this.isReadyToBook.next(false);
29342
29447
  if (basketItems.length > 0) {
29343
- this.workingOn = {
29344
- basket,
29345
- required: basketItems.reduce((required, bi) => {
29346
- required[bi.id] = bi.managementInfo?.filter((mi) => {
29347
- return mi.required && this.reasonKeysOverlap(bi.reasonKeys, mi.managementInfo.reasonKeys);
29348
- });
29349
- return required;
29350
- }, {})
29351
- };
29352
- // Check if dialog is not already open
29448
+ const isFirstLeg = this.isFirstLegOfDualSingle(basket);
29449
+ const hasPendingItemThatNeedsModal = this.pendingDualSingleBasketItem && basket.basketItems.length === 2 && !isDualSingle;
29450
+ if (hasPendingItemThatNeedsModal) {
29451
+ const pendingItem = basket.basketItems.find(item => item.id === this.pendingDualSingleBasketItem);
29452
+ if (pendingItem) {
29453
+ this.workingOn = this.buildWorkingOnForItems(basket, [pendingItem], false);
29454
+ }
29455
+ this.pendingDualSingleBasketItem = null;
29456
+ }
29457
+ else if (isFirstLeg && !hasPendingItemThatNeedsModal) {
29458
+ this.pendingDualSingleBasketItem = basketItemId;
29459
+ return;
29460
+ }
29461
+ else {
29462
+ this.workingOn = this.buildWorkingOnForItems(basket, basketItems, isDualSingle);
29463
+ }
29353
29464
  if (!this.basketService.isDialogOpen.value) {
29354
29465
  this.basketService.isDialogOpen.next(true);
29355
29466
  await this.showDialogueWithNewData(this.workingOn);
29356
29467
  }
29357
29468
  }
29358
29469
  else {
29470
+ if (this.pendingDualSingleBasketItem && basket.basketItems.length === 2) {
29471
+ this.pendingDualSingleBasketItem = null;
29472
+ }
29359
29473
  this.reasonChecked.next({
29360
29474
  basketId: this.currentBasketid,
29361
29475
  reason: ''
@@ -29373,16 +29487,28 @@ class BaseRequiresReasonService {
29373
29487
  this.basketService.isDialogOpen.next(false);
29374
29488
  this.basketService.toggleMenu();
29375
29489
  this.reasonSelected.next(true);
29490
+ workingOn.basket?.basketItems.forEach(bi => {
29491
+ this.processedDualSingleBasketItems.add(bi.id);
29492
+ });
29493
+ const parentMiIdToValue = {};
29494
+ Object.keys(results).forEach(miId => {
29495
+ const bi = workingOn.basket?.basketItems.find(item => item.managementInfo?.some(mi => mi.managementInfo.id === miId));
29496
+ const mi = bi?.managementInfo?.find(m => m.managementInfo.id === miId);
29497
+ if (mi && results[miId]) {
29498
+ parentMiIdToValue[mi.managementInfo.parentManagementInfoId] = results[miId];
29499
+ }
29500
+ });
29376
29501
  await Promise.all(workingOn.basket?.basketItems.map((bi) => {
29377
29502
  return Promise.all((bi.managementInfo || []).map((mi) => {
29378
- if (results[mi.managementInfo.id]) {
29503
+ const selectedValue = results[mi.managementInfo.id] || parentMiIdToValue[mi.managementInfo.parentManagementInfoId];
29504
+ if (selectedValue && mi.required && this.reasonKeysOverlap(bi.reasonKeys, mi.managementInfo.reasonKeys)) {
29379
29505
  this.reasonChecked.next({
29380
29506
  basketId: this.currentBasketid,
29381
- reason: results[mi.managementInfo.id]
29507
+ reason: selectedValue
29382
29508
  });
29383
29509
  const value = {
29384
29510
  miId: mi.managementInfo.id,
29385
- miValueId: results[mi.managementInfo.id],
29511
+ miValueId: selectedValue,
29386
29512
  miFreeValue: ''
29387
29513
  };
29388
29514
  return this.basketService.setMiValues(false, value);
@@ -29398,6 +29524,10 @@ class BaseRequiresReasonService {
29398
29524
  workingOn = null;
29399
29525
  }
29400
29526
  else {
29527
+ // Clear processed items for cancelled items
29528
+ workingOn.basket?.basketItems.forEach(bi => {
29529
+ this.processedDualSingleBasketItems.delete(bi.id);
29530
+ });
29401
29531
  await Promise.all(Object.entries(workingOn.required).map(([biId, mis]) => {
29402
29532
  return this.basketService.removeBasketItem(workingOn.basket.id, workingOn.basket.basketItems.find((bi) => bi.id === biId));
29403
29533
  }));
@@ -29692,16 +29822,20 @@ class InternalBasket {
29692
29822
  };
29693
29823
  toSend.mixedCurrency = Object.keys(toSend.prices).length > 1;
29694
29824
  this._basketSubject.next(toSend);
29695
- if (basket.basketItems.every(item => item?.detail?.outwardDetail?.splitID)) {
29696
- if (!(basket.basketItems.length % 2)) {
29825
+ // Only check for requires-reason when a specific basket item is being added
29826
+ // Don't trigger when basketItemId is empty (basket-wide updates like setting MI values)
29827
+ if (basketItemId !== '') {
29828
+ if (basket.basketItems.every(item => item?.detail?.outwardDetail?.splitID)) {
29829
+ if (!(basket.basketItems.length % 2)) {
29830
+ this.requiresService.addBasketItem(basket, basketItemId);
29831
+ this.requiresOverrideService.addBasketItem(basket);
29832
+ }
29833
+ }
29834
+ else {
29697
29835
  this.requiresService.addBasketItem(basket, basketItemId);
29698
29836
  this.requiresOverrideService.addBasketItem(basket);
29699
29837
  }
29700
29838
  }
29701
- else {
29702
- this.requiresService.addBasketItem(basket, basketItemId);
29703
- this.requiresOverrideService.addBasketItem(basket);
29704
- }
29705
29839
  }
29706
29840
  }
29707
29841
  class BaseEnterpriseBasketService {
@@ -30924,6 +31058,11 @@ class BaseEnterpriseBasketService {
30924
31058
  intBasketItem.pnrLocator = basket.basketItems[i].pnrLocator;
30925
31059
  intBasketItem.bookingDetail =
30926
31060
  basket.basketItems[i]?.bookingDetail || intBasketItem.bookingDetail;
31061
+ intBasketItem.price = basket.basketItems[i].price;
31062
+ intBasketItem.latestValidationPrice = basket.basketItems[i].latestValidationPrice;
31063
+ intBasketItem.latestValidationPriceDifference = basket.basketItems[i].latestValidationPriceDifference;
31064
+ intBasketItem.latestValidationAvailable = basket.basketItems[i].latestValidationAvailable;
31065
+ intBasketItem.validated = basket.basketItems[i].validated;
30927
31066
  }
30928
31067
  else {
30929
31068
  console.error(`+++ Unable to find basket item with id: ${responseBasketItems.id} +++`);
@@ -31699,22 +31838,32 @@ const PREFERENCE_KEYS = [
31699
31838
  { key: "7", label: "Flight Notifications", value: "FLIGHT_NOTIFICATIONS_ENABLED", type: "FLIGHT" },
31700
31839
  ];
31701
31840
  const PREFERENCE_VALUES = [
31841
+ { label: "Asian Vegetarian", type: "MEAL_REQUEST", code: "AVML" },
31702
31842
  { label: "Bland", type: "MEAL_REQUEST", code: "BLML" },
31703
31843
  { label: "Child", type: "MEAL_REQUEST", code: "CHML" },
31704
31844
  { label: "Diabetic", type: "MEAL_REQUEST", code: "DBML" },
31845
+ { label: "Fish", type: "MEAL_REQUEST", code: "FSML" },
31705
31846
  { label: "Fruit Plate", type: "MEAL_REQUEST", code: "FPML" },
31706
- { label: "Gluten intolerant", type: "MEAL_REQUEST", code: "GFML" },
31847
+ { label: "Gluten Free", type: "MEAL_REQUEST", code: "GFML" },
31707
31848
  { label: "Hindu", type: "MEAL_REQUEST", code: "HNML" },
31849
+ { label: "Indian Vegetarian", type: "MEAL_REQUEST", code: "IVML" },
31850
+ { label: "Japanese", type: "MEAL_REQUEST", code: "JPML" },
31708
31851
  { label: "Kosher", type: "MEAL_REQUEST", code: "KSML" },
31852
+ { label: "Kosher Vegetarian", type: "MEAL_REQUEST", code: "KVML" },
31853
+ { label: "Low Calorie", type: "MEAL_REQUEST", code: "LCML" },
31709
31854
  { label: "Low Fat/Cholesterol", type: "MEAL_REQUEST", code: "LFML" },
31710
31855
  { label: "Low Sodium", type: "MEAL_REQUEST", code: "LSML" },
31711
31856
  { label: "Muslim", type: "MEAL_REQUEST", code: "MOML" },
31857
+ { label: "No Fish", type: "MEAL_REQUEST", code: "NFML" },
31712
31858
  { label: "Non-Lactose", type: "MEAL_REQUEST", code: "NLML" },
31859
+ { label: "No Salt", type: "MEAL_REQUEST", code: "NSML" },
31860
+ { label: "Peanuts Free", type: "MEAL_REQUEST", code: "PFML" },
31713
31861
  { label: "Raw Vegetarian/Vegan", type: "MEAL_REQUEST", code: "RVML" },
31714
31862
  { label: "Seafood", type: "MEAL_REQUEST", code: "SFML" },
31715
31863
  { label: "Vegetarian-Vegan", type: "MEAL_REQUEST", code: "VGML" },
31864
+ { label: "Vegetarian Jain", type: "MEAL_REQUEST", code: "VJML" },
31716
31865
  { label: "Vegetarian Lacto-Ovo", type: "MEAL_REQUEST", code: "VLML" },
31717
- { label: "Asian Vegetarian", type: "MEAL_REQUEST", code: "VOML" },
31866
+ { label: "Vegetarian Oriental", type: "MEAL_REQUEST", code: "VOML" },
31718
31867
  { label: "Aisle", type: "SEATING_PREFERENCE" },
31719
31868
  { label: "Window", type: "SEATING_PREFERENCE" },
31720
31869
  { label: "Bassinet", type: "SPECIAL_NEED", code: "BSCT" },