File indexing completed on 2024-11-24 04:45:11

0001 /*
0002     SPDX-FileCopyrightText: 2018 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "iatabcbpparser.h"
0008 #include "logging.h"
0009 #include "iata/iatabcbp.h"
0010 
0011 #include <KItinerary/Flight>
0012 #include <KItinerary/Organization>
0013 #include <KItinerary/Person>
0014 #include <KItinerary/Place>
0015 #include <KItinerary/Reservation>
0016 #include <KItinerary/Ticket>
0017 
0018 #include <QVariant>
0019 
0020 using namespace KItinerary;
0021 
0022 static QString stripLeadingZeros(const QString &s)
0023 {
0024     const auto it = std::find_if(s.begin(), s.end(), [](const QChar &c) { return c != QLatin1Char('0'); });
0025     const auto d = std::distance(s.begin(), it);
0026     return s.mid(d);
0027 }
0028 
0029 QList<QVariant> IataBcbpParser::parse(const QString &message,
0030                                       const QDateTime &externalIssueDate) {
0031     IataBcbp bcbp(message);
0032     if (!bcbp.isValid()) {
0033         return {};
0034     }
0035     return parse(bcbp, externalIssueDate.isValid() ? externalIssueDate : QDateTime({1970, 1, 1}, {}));
0036 }
0037 
0038 QList<QVariant> IataBcbpParser::parse(const IataBcbp &bcbp,
0039                                       const QDateTime &contextDate) {
0040     const auto count = bcbp.uniqueMandatorySection().numberOfLegs();
0041     const auto issueDate = bcbp.uniqueConditionalSection().dateOfIssue(contextDate);
0042 
0043     QList<QVariant> result;
0044     result.reserve(count);
0045 
0046     Person person;
0047     {
0048         const auto fullName = bcbp.uniqueMandatorySection().passengerName();
0049         const auto idx = fullName.indexOf(QLatin1Char('/'));
0050         if (idx > 0 && idx < fullName.size() - 1) {
0051             person.setFamilyName(fullName.left(idx));
0052             person.setGivenName(fullName.mid(idx + 1));
0053         } else {
0054             person.setName(fullName);
0055         }
0056     }
0057 
0058     Ticket ticket;
0059     ticket.setTicketToken(QStringLiteral("aztecCode:") + bcbp.rawData());
0060 
0061     for (auto i = 0; i < count; ++i) {
0062         Flight flight;
0063 
0064         const auto rms = bcbp.repeatedMandatorySection(i);
0065         flight.setDepartureDay(rms.dateOfFlight(issueDate.isValid() ? QDateTime(issueDate, {}) : contextDate));
0066 
0067         Airport dep;
0068         dep.setIataCode(rms.fromCityAirportCode());
0069         flight.setDepartureAirport(dep);
0070         Airport arr;
0071         arr.setIataCode(rms.toCityAirportCode());
0072         flight.setArrivalAirport(arr);
0073         Airline airline;
0074         airline.setIataCode(rms.operatingCarrierDesignator());
0075         flight.setAirline(airline);
0076         flight.setFlightNumber(stripLeadingZeros(rms.flightNumber()));
0077 
0078         FlightReservation res;
0079         res.setReservationFor(flight);
0080         res.setPassengerSequenceNumber(stripLeadingZeros(rms.checkinSequenceNumber()));
0081         res.setAirplaneSeat(stripLeadingZeros(rms.seatNumber()));
0082         res.setReservationNumber(rms.operatingCarrierPNRCode());
0083         res.setUnderName(person);
0084         res.setReservedTicket(ticket);
0085 
0086         const auto rcs = bcbp.repeatedConditionalSection(i);
0087         if (!rcs.frequenFlyerNumber().isEmpty()) {
0088             ProgramMembership program;
0089             program.setMembershipNumber(rcs.frequenFlyerNumber());
0090             program.setProgramName(rcs.frequentFlyerAirlineDesignator());
0091             program.setMember(person);
0092             res.setProgramMembershipUsed(program);
0093         }
0094 
0095         result.push_back(std::move(res));
0096     }
0097 
0098     return result;
0099 }