File indexing completed on 2024-12-22 04:59:46
0001 /* 0002 SPDX-FileCopyrightText: 2023 Volker Krause <vkrause@kde.org> 0003 SPDX-License-Identifier: LGPL-2.0-or-later 0004 */ 0005 0006 #include "priceutil.h" 0007 0008 #include <KItinerary/JsonLdDocument> 0009 #include <KItinerary/Reservation> 0010 #include <KItinerary/Ticket> 0011 0012 #include <cmath> 0013 0014 using namespace KItinerary; 0015 0016 bool PriceUtil::hasPrice(const QVariant &item) 0017 { 0018 if (!PriceUtil::canHavePrice(item)) { 0019 return false; 0020 } 0021 0022 if (!std::isnan(JsonLdDocument::readProperty(item, "totalPrice").toDouble()) && !JsonLdDocument::readProperty(item, "priceCurrency").isNull()) { 0023 return true; 0024 } 0025 0026 if (JsonLd::canConvert<Reservation>(item)) { 0027 return PriceUtil::hasPrice(JsonLd::convert<Reservation>(item).reservedTicket()); 0028 } 0029 0030 return false; 0031 } 0032 0033 bool PriceUtil::canHavePrice(const QVariant &item) 0034 { 0035 return JsonLd::isA<Ticket>(item) || (JsonLd::canConvert<Reservation>(item) && !JsonLd::isA<FoodEstablishmentReservation>(item)); 0036 } 0037 0038 double PriceUtil::price(const QVariant &item) 0039 { 0040 if (JsonLd::canConvert<Reservation>(item)) { 0041 const auto res = JsonLd::convert<Reservation>(item); 0042 return !std::isnan(res.totalPrice()) ? res.totalPrice() : PriceUtil::price(res.reservedTicket()); 0043 } 0044 0045 if (JsonLd::isA<Ticket>(item)) { 0046 return item.value<Ticket>().totalPrice(); 0047 } 0048 0049 return NAN; 0050 } 0051 0052 QString PriceUtil::currency(const QVariant &item) 0053 { 0054 if (JsonLd::canConvert<Reservation>(item)) { 0055 const auto res = JsonLd::convert<Reservation>(item); 0056 return !res.priceCurrency().isEmpty() ? res.priceCurrency() : PriceUtil::currency(res.reservedTicket()); 0057 } 0058 0059 if (JsonLd::isA<Ticket>(item)) { 0060 return item.value<Ticket>().priceCurrency(); 0061 } 0062 0063 return {}; 0064 } 0065 0066 void PriceUtil::setPrice(QVariant &item, double price, const QString ¤cy) 0067 { 0068 // TODO check if there is a price on a nested ticket already, and set/replace that 0069 JsonLdDocument::writeProperty(item, "totalPrice", price); 0070 JsonLdDocument::writeProperty(item, "priceCurrency", currency); 0071 } 0072 0073 // ### keep sorted by ISO code, only needs to contain those != 2 0074 // @see https://en.wikipedia.org/wiki/List_of_circulating_currencies 0075 struct { 0076 const char isoCode[4]; 0077 const uint8_t decimals; 0078 } static constexpr const currency_decimals_map[] = { 0079 { "BHD", 3 }, 0080 { "CNY", 1 }, 0081 { "IQD", 3 }, 0082 { "IRR", 0 }, 0083 { "KWD", 3 }, 0084 { "LYD", 3 }, 0085 { "MGA", 1 }, 0086 { "MRU", 1 }, 0087 { "OMR", 3 }, 0088 { "TND", 3 }, 0089 { "VND", 1 }, 0090 }; 0091 0092 int PriceUtil::decimalCount(QStringView currency) 0093 { 0094 const auto it = std::lower_bound( 0095 std::begin(currency_decimals_map), std::end(currency_decimals_map), 0096 currency, [](const auto &m, QStringView isoCode) { 0097 return QLatin1StringView(m.isoCode, 3) < isoCode; 0098 }); 0099 if (it != std::end(currency_decimals_map) && 0100 QLatin1StringView((*it).isoCode, 3) == currency) { 0101 return (*it).decimals; 0102 } 0103 return 2; 0104 } 0105 0106 int PriceUtil::decimalCount(const QString ¤cy) 0107 { 0108 return PriceUtil::decimalCount(QStringView(currency)); 0109 } 0110 0111 #include "moc_priceutil.cpp"