SimFQT Logo  1.00.0
C++ Simulated Fare Quote System Library
 All Classes Namespaces Files Functions Variables Typedefs Friends Pages
FareQuoter.cpp
Go to the documentation of this file.
1 // //////////////////////////////////////////////////////////////////////
2 // Import section
3 // //////////////////////////////////////////////////////////////////////
4 // STL
5 #include <cassert>
6 #include <sstream>
7 // StdAir
8 #include <stdair/basic/BasConst_BomDisplay.hpp>
9 #include <stdair/basic/BasConst_Request.hpp>
10 #include <stdair/bom/BomKeyManager.hpp>
11 #include <stdair/bom/ParsedKey.hpp>
12 #include <stdair/bom/BomManager.hpp>
13 #include <stdair/bom/BomRoot.hpp>
14 #include <stdair/bom/InventoryKey.hpp>
15 #include <stdair/bom/FlightDateKey.hpp>
16 #include <stdair/bom/SegmentDateKey.hpp>
17 #include <stdair/bom/AirlineClassList.hpp>
18 #include <stdair/bom/AirportPair.hpp>
19 #include <stdair/bom/PosChannel.hpp>
20 #include <stdair/bom/DatePeriod.hpp>
21 #include <stdair/bom/TimePeriod.hpp>
22 #include <stdair/bom/FareFeatures.hpp>
23 #include <stdair/bom/BookingRequestStruct.hpp>
24 #include <stdair/bom/TravelSolutionStruct.hpp>
25 #include <stdair/service/Logger.hpp>
26 #include <stdair/bom/key_types.hpp>
27 // SimFQT
28 #include <simfqt/SIMFQT_Types.hpp>
30 
31 namespace SIMFQT {
32 
33  bool FareQuoter::_atLeastOneAvailableDateRule = false;
34  bool FareQuoter::_atLeastOneAvailablePosChannel = false;
35  bool FareQuoter::_atLeastOneAvailableTimeRule = false;
36  bool FareQuoter::_atLeastOneAvailableFeaturesRule = false;
37  bool FareQuoter::_atLeastOneAvailableAirlineClassRule= false;
38 
39  // //////////////////////////////////////////////////////////////////////
40  FareQuoter::FareQuoter() {
41  assert (false);
42  }
43 
44  // //////////////////////////////////////////////////////////////////////
45  FareQuoter::FareQuoter(const FareQuoter&) {
46  assert (false);
47  }
48 
49  // //////////////////////////////////////////////////////////////////////
50  FareQuoter::~FareQuoter() {
51  }
52 
53  // //////////////////////////////////////////////////////////////////////
54  void FareQuoter::reset() {
55  _atLeastOneAvailableDateRule = false;
56  _atLeastOneAvailablePosChannel = false;
57  _atLeastOneAvailableTimeRule = false;
58  _atLeastOneAvailableFeaturesRule = false;
59  _atLeastOneAvailableAirlineClassRule = false;
60  }
61 
62 
63  // //////////////////////////////////////////////////////////////////////
64  void FareQuoter::
65  priceQuote (const stdair::BookingRequestStruct& iBookingRequest,
66  stdair::TravelSolutionList_T& ioTravelSolutionList,
67  const stdair::BomRoot& iBomRoot) {
68 
69  // Do an independent price quote for each travel solution related to the
70  // booking request.
71  for (stdair::TravelSolutionList_T::iterator itTravelSolution =
72  ioTravelSolutionList.begin();
73  itTravelSolution != ioTravelSolutionList.end(); ++itTravelSolution) {
74  reset();
75  // Select a travel solution.
76  stdair::TravelSolutionStruct& lTravelSolutionStruct = *itTravelSolution;
77  // Price quote the travel solution into question.
78  priceQuote (iBookingRequest, lTravelSolutionStruct, iBomRoot);
79  }
80  }
81 
82  // //////////////////////////////////////////////////////////////////////
83  void FareQuoter::
84  priceQuote (const stdair::BookingRequestStruct& iBookingRequest,
85  stdair::TravelSolutionStruct& ioTravelSolution,
86  const stdair::BomRoot& iBomRoot) {
87 
88  // Get the origin of the first segment in order to get the origin of
89  // the solution.
90  const stdair::ParsedKey& lFirstSegmentKey =
91  getFirstSPParsedKey(ioTravelSolution);
92  const stdair::AirportCode_T& lOrigin = lFirstSegmentKey._boardingPoint;
93 
94  // Get the destination of the last segment in order to get the
95  // destination of the solution.
96  const stdair::ParsedKey& lLastSegmentKey =
97  getLastSPParsedKey(ioTravelSolution);
98  const stdair::AirportCode_T& lDestination = lLastSegmentKey._offPoint;
99 
100  // Construct the Airport pair stream of the segment path.
101  const stdair::AirportPairKey lAirportPairKey (lOrigin, lDestination);
102 
103  // Search for the fare rules having the same origin and destination airports
104  // as the travel solution
105  const stdair::AirportPair* lAirportPair_ptr = stdair::BomManager::
106  getObjectPtr<stdair::AirportPair> (iBomRoot, lAirportPairKey.toString());
107 
108  // If no fare rule has the same origin and destination airports, the pricing
109  // is not possible, throw an exception.
110  if (lAirportPair_ptr == NULL) {
111  STDAIR_LOG_ERROR ("No available fare rule for the "
112  << "Origin-Destination pair: "
113  << lAirportPairKey.toString());
114  throw AirportPairNotFoundException ("No available fare rule for "
115  "the Origin-Destination pair: "
116  + lAirportPairKey.toString());
117  }
118  // Sanity check.
119  assert(lAirportPair_ptr != NULL);
120 
121  // Fare rule(s) with the same origin and destination airports exist(s), now
122  // the date range need to be checked.
123  const stdair::AirportPair& lAirportPair = *lAirportPair_ptr;
124  priceQuote(iBookingRequest, ioTravelSolution, lAirportPair);
125 
126  if (_atLeastOneAvailableAirlineClassRule == false) {
127  displayMissingFareRuleMessage(iBookingRequest, ioTravelSolution);
128  }
129  }
130 
131  // //////////////////////////////////////////////////////////////////////
132  void FareQuoter::
133  priceQuote (const stdair::BookingRequestStruct& iBookingRequest,
134  stdair::TravelSolutionStruct& ioTravelSolution,
135  const stdair::AirportPair& iAirportPair) {
136 
137  // Get the first segment path parsed key.
138  const stdair::ParsedKey lFirstSPParsedKey =
139  getFirstSPParsedKey(ioTravelSolution);
140 
141  // Get the date of the first segment date key.
142  const stdair::FlightDateKey& lFlightDateKey =
143  lFirstSPParsedKey.getFlightDateKey();
144  const stdair::Date_T& lSPDate = lFlightDateKey.getDepartureDate();
145 
146  // Get the list of the fare date ranges.
147  const stdair::DatePeriodList_T& lFareDatePeriodList =
148  stdair::BomManager::getList<stdair::DatePeriod> (iAirportPair);
149 
150  // Browse the list of the fare rules date range.
151  for (stdair::DatePeriodList_T::const_iterator itDateRange =
152  lFareDatePeriodList.begin();
153  itDateRange != lFareDatePeriodList.end(); ++itDateRange) {
154 
155  const stdair::DatePeriod* lCurrentFareDatePeriod_ptr = *itDateRange ;
156  assert (lCurrentFareDatePeriod_ptr != NULL);
157 
158  // Select the fare rules having a corresponding date range.
159  const bool isDepartureDateValid =
160  lCurrentFareDatePeriod_ptr->isDepartureDateValid (lSPDate);
161 
162  // If a fare rule has a corresponding date range, its channel and position
163  // need to be checked.
164  if (isDepartureDateValid == true) {
165  _atLeastOneAvailableDateRule = true;
166  const stdair::DatePeriod& lCurrentFareDatePeriod =
167  *lCurrentFareDatePeriod_ptr;
168  priceQuote (iBookingRequest, ioTravelSolution,
169  lCurrentFareDatePeriod, iAirportPair);
170  }
171  }
172 
173  }
174 
175  // //////////////////////////////////////////////////////////////////////
176  void FareQuoter::
177  priceQuote (const stdair::BookingRequestStruct& iBookingRequest,
178  stdair::TravelSolutionStruct& ioTravelSolution,
179  const stdair::DatePeriod& iFareDatePeriod,
180  const stdair::AirportPair& iAirportPair) {
181 
182  // Get the point-of-sale of the booking request.
183  const stdair::CityCode_T& lPointOfSale = iBookingRequest.getPOS();
184 
185  // Get the booking request channel.
186  const stdair::ChannelLabel_T& lChannel =
187  iBookingRequest.getBookingChannel();
188 
189  // Construct the corresponding POS-channel primary key.
190  const stdair::PosChannelKey lFarePosChannelKey (lPointOfSale, lChannel);
191 
192  // Search for the fare rules having the same point-of-sale and channel as
193  // the travel solution.
194  const stdair::PosChannelList_T lFarePosChannelList =
195  stdair::BomManager::getList<stdair::PosChannel> (iFareDatePeriod);
196 
197  // Browse the list of the fare rules pos channel.
198  for (stdair::PosChannelList_T::const_iterator itPosChannel =
199  lFarePosChannelList.begin();
200  itPosChannel != lFarePosChannelList.end();
201  ++itPosChannel) {
202  const stdair::PosChannel* lCurrentFarePosChannel_ptr = *itPosChannel;
203  assert (lCurrentFarePosChannel_ptr != NULL);
204 
205  // Get the point-of-sale and channel of the current fare rule.
206  const stdair::CityCode_T& lCurrentPointOfSale =
207  lCurrentFarePosChannel_ptr->getPos();
208  const stdair::ChannelLabel_T& lCurrentChannel =
209  lCurrentFarePosChannel_ptr->getChannel();
210 
211  // Select the fare rules having a corresponding pos channel.
212  if (lCurrentPointOfSale == lPointOfSale || lCurrentPointOfSale == stdair::DEFAULT_POS) {
213  if (lCurrentChannel == lChannel || lCurrentChannel == stdair::DEFAULT_CHANNEL) {
214  _atLeastOneAvailablePosChannel = true;
215  // Fare rule(s) with the same point-of-sale and channel exist(s), now
216  // the time range need to be checked.
217  const stdair::PosChannel& lFarePosChannel= *lCurrentFarePosChannel_ptr;
218  STDAIR_LOG_DEBUG (lCurrentPointOfSale + " " + lCurrentChannel);
219  priceQuote (iBookingRequest, ioTravelSolution, lFarePosChannel);
220  }
221  }
222  }
223 
224  }
225 
226  // //////////////////////////////////////////////////////////////////////
227  void FareQuoter::
228  priceQuote (const stdair::BookingRequestStruct& iBookingRequest,
229  stdair::TravelSolutionStruct& ioTravelSolution,
230  const stdair::PosChannel& iFarePosChannel) {
231 
232  // Get the first segment path parsed key.
233  const stdair::ParsedKey lFirstSPParsedKey =
234  getFirstSPParsedKey(ioTravelSolution);
235 
236  // Get the segment boarding time of the segment path.
237  const stdair::Duration_T& lSPTime = lFirstSPParsedKey.getBoardingTime();
238 
239  // Get the list of the fare rules time period.
240  const stdair::TimePeriodList_T& lFareTimePeriodList =
241  stdair::BomManager::getList<stdair::TimePeriod> (iFarePosChannel);
242 
243  // Browse the list of the fare rules time range.
244  for (stdair::TimePeriodList_T::const_iterator itTimeRange =
245  lFareTimePeriodList.begin();
246  itTimeRange != lFareTimePeriodList.end();
247  ++itTimeRange) {
248  const stdair::TimePeriod* lCurrentFareTimePeriod_ptr = *itTimeRange ;
249  assert (lCurrentFareTimePeriod_ptr != NULL);
250 
251  // Select the fare rules having a corresponding time range.
252  const bool isDepartureTimeValid =
253  lCurrentFareTimePeriod_ptr->isDepartureTimeValid (lSPTime);
254 
255  // If a fare rule has a corresponding time range, its advanced purchase,
256  // trip type and minimum stay duration need to be checked.
257  if (isDepartureTimeValid) {
258  _atLeastOneAvailableTimeRule = true;
259  const stdair::TimePeriod& lCurrentFareTimePeriod =
260  *lCurrentFareTimePeriod_ptr;
261  priceQuote (iBookingRequest, ioTravelSolution,
262  lCurrentFareTimePeriod, iFarePosChannel);
263  }
264  }
265 
266  }
267 
268  // //////////////////////////////////////////////////////////////////////
269  void FareQuoter::
270  priceQuote (const stdair::BookingRequestStruct& iBookingRequest,
271  stdair::TravelSolutionStruct& ioTravelSolution,
272  const stdair::TimePeriod& iFareTimePeriod,
273  const stdair::PosChannel& iFarePosChannel) {
274 
275  // Get the stay duration of the booking request.
276  const stdair::DayDuration_T& lStayDuration=
277  iBookingRequest.getStayDuration();
278 
279  // Get the booking request trip type.
280  const stdair::TripType_T& lTripType =
281  iBookingRequest.getTripType();
282 
283  // Get the booking request date time.
284  const stdair::DateTime_T& lRequestDateTime =
285  iBookingRequest.getRequestDateTime();
286 
287  // Get the referenced departure date of the segment path.
288  const stdair::ParsedKey lFirstSPParsedKey =
289  getFirstSPParsedKey(ioTravelSolution);
290  const stdair::Date_T& lSPDate =
291  lFirstSPParsedKey.getFlightDateKey().getDepartureDate();
292 
293  // Get the segment boarding time of the segment path.
294  const stdair::Duration_T& lSPTime = lFirstSPParsedKey.getBoardingTime();
295 
296  // Construct the date-time type correponding to the flight date
297  const stdair::DateTime_T lSPDateTime (lSPDate, lSPTime);
298 
299  bool isTripTypeValid = false;
300  bool isStayDurationValid = false;
301  bool isAdvancePurchaseValid = false;
302 
303  // Get the list of the fare features (if such list exists: the POS
304  // and channel couple can be only present in a yield rule).
305  const bool hasFareFeaturesList =
306  stdair::BomManager::hasList<stdair::FareFeatures> (iFareTimePeriod);
307  if (hasFareFeaturesList == false) {
308  return;
309  }
310  assert (hasFareFeaturesList == true);
311  const stdair::FareFeaturesList_T& lFareFeaturesList =
312  stdair::BomManager::getList<stdair::FareFeatures> (iFareTimePeriod);
313 
314  // Browse the list of the fare rules features.
315  for (stdair::FareFeaturesList_T::const_iterator itFareFeatures =
316  lFareFeaturesList.begin();
317  itFareFeatures != lFareFeaturesList.end();
318  ++itFareFeatures) {
319  const stdair::FareFeatures* lCurrentFareFeatures_ptr =
320  *itFareFeatures;
321  assert (lCurrentFareFeatures_ptr != NULL);
322 
323  // Does the current fare features correspond to a correct trip
324  // type?
325  isTripTypeValid =
326  lCurrentFareFeatures_ptr->isTripTypeValid (lTripType);
327  // Does the current fare features correspond to a correct stay
328  // duration?
329  isStayDurationValid =
330  lCurrentFareFeatures_ptr->isStayDurationValid (lStayDuration);
331  // Does the current fare features correspond to a correct advanced
332  // purchase?
333  isAdvancePurchaseValid = lCurrentFareFeatures_ptr->
334  isAdvancePurchaseValid (lRequestDateTime,
335  lSPDateTime);
336 
337  // Search for the fare rules having corresponding features.
338  if (isStayDurationValid && isAdvancePurchaseValid && isTripTypeValid){
339  _atLeastOneAvailableFeaturesRule = true;
340  // Create a fare structure for the travel solution.
341  stdair::FareOptionStruct lFareOption;
342  const stdair::ChangeFees_T& lChangeFees =
343  lCurrentFareFeatures_ptr->getChangeFees();
344  // Set the fare change fees.
345  lFareOption.setChangeFees (lChangeFees);
346  const stdair::NonRefundable_T& lNonRefundable =
347  lCurrentFareFeatures_ptr->getRefundableOption();
348  // Set the fare refundable option.
349  lFareOption.setNonRefundable (lNonRefundable);
350  const stdair::SaturdayStay_T& lSaturdayStay =
351  lCurrentFareFeatures_ptr->getSaturdayStay();
352  // Set the fare saturday night stay option.
353  lFareOption.setSaturdayStay (lSaturdayStay);
354  const stdair::FareFeatures& lCurrentFareFeatures =
355  *lCurrentFareFeatures_ptr;
356  priceQuote (iBookingRequest, ioTravelSolution,
357  lCurrentFareFeatures, iFarePosChannel,
358  lFareOption);
359  }
360  }
361 
362  }
363 
364 
365  // //////////////////////////////////////////////////////////////////////
366  void FareQuoter::
367  priceQuote (const stdair::BookingRequestStruct& iBookingRequest,
368  stdair::TravelSolutionStruct& ioTravelSolution,
369  const stdair::FareFeatures& iFareFeatures,
370  const stdair::PosChannel& iFarePosChannel,
371  stdair::FareOptionStruct& iFareOption) {
372 
373  // Get the segment-path of the travel solution.
374  const stdair::SegmentPath_T& lSegmentPath =
375  ioTravelSolution.getSegmentPath();
376 
377  // Get the list of the fare rules.
378  const stdair::AirlineClassListList_T& lAirlineClassListList =
379  stdair::BomManager::getList<stdair::AirlineClassList> (iFareFeatures);
380 
381  bool lCorrectAirlineRule = false;
382  bool lAtLeastOneDifferentAirline = false;
383 
384  // Browse the list of airline code list and search for the fare rules
385  // having a corresponding airline list.
386  for (stdair::AirlineClassListList_T::const_iterator itAirlineClassList =
387  lAirlineClassListList.begin();
388  itAirlineClassList != lAirlineClassListList.end();
389  ++itAirlineClassList) {
390  const stdair::AirlineClassList* lCurrentAirlineClassList_ptr =
391  *itAirlineClassList;
392  assert (lCurrentAirlineClassList_ptr != NULL);
393 
394  lCorrectAirlineRule = true;
395  lAtLeastOneDifferentAirline = false;
396 
397  const stdair::ClassList_StringList_T lClassList_StringList =
398  lCurrentAirlineClassList_ptr->getAirlineCodeList();
399 
400  // Compare the segment path airline list with the fare rule airline list.
401  if (lClassList_StringList.size() == lSegmentPath.size()) {
402  // If the two sizes are equal, we need to compare the airline codes.
403  stdair::SegmentPath_T::const_iterator itSegmentPath =
404  lSegmentPath.begin();
405 
406  stdair::ClassList_StringList_T::const_iterator itClassList_String =
407  lClassList_StringList.begin();
408  // Browse the segment path airline code list (while the segment path
409  // airline list is equal to the fare rule airline list).
410  while (itSegmentPath != lSegmentPath.end()
411  && lAtLeastOneDifferentAirline == false) {
412 
413  // Get the segment airline code.
414  const std::string lSegmentDateKey = *itSegmentPath;
415  const stdair::ParsedKey& lParsedKey =
416  stdair::BomKeyManager::extractKeys (lSegmentDateKey);
417  const stdair::InventoryKey& lInventoryKey =
418  lParsedKey.getInventoryKey();
419  const stdair::AirlineCode_T& lSegmentAirlineCode =
420  lInventoryKey.getAirlineCode();
421 
422  // Get the fare rule airline code.
423  const stdair::AirlineCode_T& lFareRuleAirlineCode =
424  *itClassList_String;
425 
426  if (lSegmentAirlineCode != lFareRuleAirlineCode) {
427  lAtLeastOneDifferentAirline = true;
428  }
429  itSegmentPath++;
430  itClassList_String++;
431  }
432 
433  } else {
434  // If the two sizes are different, the fare rule does not match the
435  // travel solution into question.
436  lCorrectAirlineRule = false;
437  }
438 
439  // If one segment airline code and one fare rule airline code are
440  // different then the fare rule does not match the travel solution.
441  if (lAtLeastOneDifferentAirline == true) {
442  lCorrectAirlineRule = false;
443  }
444 
445  // If the current fare rule is a match, add the fare option structure
446  // to the travel solution into question.
447  if (lCorrectAirlineRule == true) {
448  _atLeastOneAvailableAirlineClassRule = true;
449  // Get the booking request trip type.
450  const stdair::TripType_T& lTripType =
451  iBookingRequest.getTripType();
452 
453  // Get the travel fare.
454  stdair::Fare_T lFare =
455  lCurrentAirlineClassList_ptr->getFare();
456  // If the trip into question is the inbound or outbound part of a round trip,
457  // the applicable fare is a half RT fare.
458  if (lTripType == "RI" || lTripType == "RO") {
459  lFare /= 2;
460  }
461  // Set the travel fare option.
462  iFareOption.setFare (lFare);
463  // Copy the class path list into the fare option.
464  const stdair::ClassList_StringList_T& lClassCodeList =
465  lCurrentAirlineClassList_ptr->getClassCodeList();
466  for (stdair::ClassList_StringList_T::const_iterator itClassCodeList =
467  lClassCodeList.begin();
468  itClassCodeList != lClassCodeList.end(); ++itClassCodeList ) {
469  const stdair::ClassList_String_T& lClassCodeList = *itClassCodeList;
470  iFareOption.addClassList (lClassCodeList);
471  }
472 
473  // Add the fare option to the travel solution into question.
474  ioTravelSolution.addFareOption (iFareOption);
475 
476  // DEBUG
477  STDAIR_LOG_DEBUG (ioTravelSolution.describeSegmentPath()
478  << ". A corresponding fare option for the '"
479  << lCurrentAirlineClassList_ptr->describeKey()
480  << "' class is: " << iFareOption);
481 
482  iFareOption.emptyClassList();
483  }
484  }
485 
486  }
487 
488  // //////////////////////////////////////////////////////////////////////
489  stdair::ParsedKey FareQuoter::
490  getFirstSPParsedKey (stdair::TravelSolutionStruct& ioTravelSolution) {
491 
492  // Get the segment-path of the travel solution.
493  const stdair::SegmentPath_T& lSegmentPath =
494  ioTravelSolution.getSegmentPath();
495 
496  // Get the number of segments of the travel solution.
497  const stdair::NbOfSegments_T& lNbSegments = lSegmentPath.size();
498 
499  // Sanity check: there is at least one segment in the travel solution.
500  assert (lNbSegments >= 1);
501 
502  // Get the first segment of the travel solution.
503  const std::string& lFirstSegmentDateKey = lSegmentPath.front();
504 
505  // Get the parsed key of the first segment of the travel solution.
506  const stdair::ParsedKey& lFirstSegmentParsedKey =
507  stdair::BomKeyManager::extractKeys (lFirstSegmentDateKey);
508 
509  return lFirstSegmentParsedKey;
510 
511  }
512 
513  // //////////////////////////////////////////////////////////////////////
514  stdair::ParsedKey FareQuoter::
515  getLastSPParsedKey (stdair::TravelSolutionStruct& ioTravelSolution) {
516 
517  // Get the segment-path of the travel solution.
518  const stdair::SegmentPath_T& lSegmentPath =
519  ioTravelSolution.getSegmentPath();
520 
521  // Get the number of segments of the travel solution.
522  const stdair::NbOfSegments_T& lNbSegments = lSegmentPath.size();
523 
524  // Sanity check: there is at least one segment in the travel solution.
525  assert (lNbSegments >= 1);
526 
527  // Get the last segment of the travel solution.
528  const std::string& lLastSegmentDateKey = lSegmentPath.back();
529 
530  // Get the parsed key of the last segment of the travel solution.
531  const stdair::ParsedKey& lLastSegmentParsedKey =
532  stdair::BomKeyManager::extractKeys (lLastSegmentDateKey);
533 
534  return lLastSegmentParsedKey;
535 
536  }
537 
538  // //////////////////////////////////////////////////////////////////////
539  void FareQuoter::
540  displayMissingFareRuleMessage (const stdair::BookingRequestStruct& iBookingRequest,
541  stdair::TravelSolutionStruct& ioTravelSolution) {
542 
543  // Get the origin of the first segment in order to get the origin of
544  // the solution.
545  const stdair::ParsedKey lFirstSPParsedKey =
546  getFirstSPParsedKey(ioTravelSolution);
547  const stdair::AirportCode_T& lOrigin = lFirstSPParsedKey._boardingPoint;
548 
549  // Get the destination of the last segment in order to get the
550  // destination of the solution.
551  const stdair::ParsedKey& lLastSegmentKey =
552  getLastSPParsedKey(ioTravelSolution);
553  const stdair::AirportCode_T& lDestination = lLastSegmentKey._offPoint;
554 
555  // Construct the Airport pair stream of the segment path.
556  const stdair::AirportPairKey lAirportPairKey (lOrigin, lDestination);
557 
558  // Get the date of the first segment date key.
559  const stdair::FlightDateKey& lFlightDateKey =
560  lFirstSPParsedKey.getFlightDateKey();
561 
562  // Get the point-of-sale of the booking request.
563  const stdair::CityCode_T& lPointOfSale = iBookingRequest.getPOS();
564  // Get the booking request channel.
565  const stdair::ChannelLabel_T& lChannel =
566  iBookingRequest.getBookingChannel();
567  // Construct the corresponding POS-channel primary key.
568  const stdair::PosChannelKey lFarePosChannelKey (lPointOfSale, lChannel);
569 
570  // Get the booking request date time.
571  const stdair::DateTime_T& lRequestDateTime =
572  iBookingRequest.getRequestDateTime();
573 
574  // If no fare rule has a corresponding date range, the pricing is not
575  // possible, throw an exception.
576  if (_atLeastOneAvailableDateRule == false) {
577  const stdair::SegmentDateKey lSegmentDateKey =
578  lFirstSPParsedKey.getSegmentKey();
579  STDAIR_LOG_ERROR ("No available fare rule corresponding to the "
580  "flight date " << lFlightDateKey.toString()
581  << " and the Origin-Destination pair: "
582  << lSegmentDateKey.toString());
583  throw FlightDateNotFoundException ("No available fare rule for the "
584  "flight date "
585  + lFlightDateKey.toString()
586  + " and the Origin-Destination pair: "
587  + lSegmentDateKey.toString());
588  }
589  // If no fare rule has a corresponding pos channel, the pricing is not possible,
590  // throw an exception.
591  else if (_atLeastOneAvailablePosChannel == false) {
592  STDAIR_LOG_ERROR ("No available fare rule corresponding to the "
593  "point of sale " << lPointOfSale
594  << ", to the channel " << lChannel
595  << ", to the flight date "
596  << lFlightDateKey.toString()
597  << " and to the Origin-Destination pair: "
598  << lAirportPairKey.toString());
599  throw PosOrChannelNotFoundException ("No available fare rule for the "
600  "point of sale " + lPointOfSale
601  + ", the channel " + lChannel
602  + ", the flight date "
603  + lFlightDateKey.toString()
604  + " and the Origin-Destination pair: "
605  + lAirportPairKey.toString());
606  }
607  // If no fare rule has a corresponding time range, the pricing is not possible,
608  // throw an exception.
609  else if (_atLeastOneAvailableTimeRule == false) {
610  STDAIR_LOG_ERROR ("No available fare rule corresponding to '"
611  << lFirstSPParsedKey.toString() << "' (parsed key) and to '"
612  << lFarePosChannelKey.toString() << "' (POS and channel)");
613  throw FlightTimeNotFoundException ("No available fare rule corresponding "
614  "to '" + lFirstSPParsedKey.toString()
615  + "' (parsed key) and to '"
616  + lFarePosChannelKey.toString()
617  + "' (POS and channel)");
618  }
619  // If no fare rule matches the advance purchase, trip type and stay
620  // duration criterion, the pricing is not possible, throw an exception.
621  else if (_atLeastOneAvailableFeaturesRule == false) {
622  // Get the stay duration of the booking request.
623  const stdair::DayDuration_T& lStayDuration=
624  iBookingRequest.getStayDuration();
625  std::ostringstream lStayDurationStream;
626  lStayDurationStream << lStayDuration;
627  const std::string lStayDurationString (lStayDurationStream.str());
628 
629  // Get the booking request trip type.
630  const stdair::TripType_T& lTripType =
631  iBookingRequest.getTripType();
632 
633  STDAIR_LOG_ERROR ("No available fare rule corresponding to a "
634  "trip type " << lTripType
635  << ", to a stay duration of " << lStayDurationString
636  << ", to a request date time of " << lRequestDateTime
637  << ", to '" << lFirstSPParsedKey.toString()
638  << "' (parsed key) and to '"
639  << lFarePosChannelKey << "' (POS and channel)");
640  throw FeaturesNotFoundException ("No available fare rule corresponding to a "
641  "trip type " + lTripType
642  + ", to a stay duration of "
643  + lStayDurationString
644  + ", to a request date time of "
645  + boost::posix_time::to_simple_string(lRequestDateTime)
646  + ", to '" + lFirstSPParsedKey.toString()
647  + "' (parsed key) and to '"
648  + lFarePosChannelKey.toString()
649  + "' (POS and channel)");
650  }
651  assert (_atLeastOneAvailableAirlineClassRule == false);
652  // If no fare rule matches the airline class path, the pricing is not
653  // possible, throw an exception.
654  STDAIR_LOG_ERROR ("No available fare rule corresponding to '"
655  << lFirstSPParsedKey .toString() << "' (parsed key), to '"
656  << iBookingRequest.describe()
657  << "' (booking request) and to '"
658  << lFarePosChannelKey.toString() << "' (POS and channel)");
659  throw AirlineNotFoundException ("No available fare rule corresponding to '"
660  + lFirstSPParsedKey .toString()
661  + "' (parsed key), to '"
662  + iBookingRequest.describe()
663  + "' (booking request) and to '"
664  + lFarePosChannelKey.toString()
665  + "' (POS and channel)");
666  }
667 }
668