save experimental
This commit is contained in:
		@@ -107,7 +107,7 @@ QDateTime Calculator::GetDailyTicketDuration(Configuration* cfg, const QDateTime
 | 
			
		||||
            int diff = abs(inputDateTime.time().secsTo(worktime_to));
 | 
			
		||||
            inputDateTime = inputDateTime.addSecs(diff);
 | 
			
		||||
 | 
			
		||||
            //qDebug() << "Ticket is valid until: " << inputDateTime.toString(Qt::ISODate) << "price = " << daily_card_price << ", duration = " << diff / 60;            
 | 
			
		||||
            //qDebug() << "Ticket is valid until: " << inputDateTime.toString(Qt::ISODate) << "price = " << daily_card_price << ", duration = " << diff / 60;
 | 
			
		||||
            return inputDateTime;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -2106,7 +2106,8 @@ QList<int> &Calculator::GetTimeSteps(Configuration *cfg, int paymentOptionIndex)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QDateTime start = QDateTime::currentDateTime();
 | 
			
		||||
    start.setTime(QTime(start.time().hour(), start.time().minute(), 0));
 | 
			
		||||
    //start.setTime(QTime(start.time().hour(), start.time().minute(), 0));
 | 
			
		||||
    start.setTime(QTime(7, start.time().minute(), 0));
 | 
			
		||||
 | 
			
		||||
    int const pop_id = cfg->getPaymentOptions(paymentOptionIndex).pop_id;
 | 
			
		||||
    int const pop_carry_over = cfg->getPaymentOptions(paymentOptionIndex).pop_carry_over;
 | 
			
		||||
@@ -2136,10 +2137,22 @@ QList<int> &Calculator::GetTimeSteps(Configuration *cfg, int paymentOptionIndex)
 | 
			
		||||
 | 
			
		||||
            if (pop_carry_over) {
 | 
			
		||||
                int const pop_carry_over_time_range_id = cfg->getPaymentOptions(paymentOptionIndex).pop_carry_over_time_range_id;
 | 
			
		||||
                int const pop_carry_over_option_id = cfg->getPaymentOptions(paymentOptionIndex).pop_carry_over_option_id;
 | 
			
		||||
                QTime const carryOverTimeRangeFrom = cfg->TimeRange.find(pop_carry_over_time_range_id)->second.time_range_from;
 | 
			
		||||
                QTime const carryOverTimeRangeTo = cfg->TimeRange.find(pop_carry_over_time_range_id)->second.time_range_to;
 | 
			
		||||
 | 
			
		||||
                qCritical() << "(" << __func__ << ":" << __LINE__ << ")        carry over time range id:" << pop_carry_over_time_range_id;
 | 
			
		||||
                qCritical() << "(" << __func__ << ":" << __LINE__ << ")            carry over option id:" << pop_carry_over_time_range_id;
 | 
			
		||||
                qCritical() << "(" << __func__ << ":" << __LINE__ << ")            carry over time from:" << carryOverTimeRangeFrom.toString(Qt::ISODate);
 | 
			
		||||
                qCritical() << "(" << __func__ << ":" << __LINE__ << ")              carry over time to:" << carryOverTimeRangeTo.toString(Qt::ISODate);
 | 
			
		||||
 | 
			
		||||
                int weekDay = start.date().dayOfWeek();
 | 
			
		||||
                QTime const carryOverStart = cfg->TariffCarryOverOptions.find(pop_carry_over_option_id)->second.carryover[weekDay].static_start;
 | 
			
		||||
                QTime const carryOverEnd = cfg->TariffCarryOverOptions.find(pop_carry_over_option_id)->second.carryover[weekDay].static_end;
 | 
			
		||||
 | 
			
		||||
                qCritical() << "(" << __func__ << ":" << __LINE__ << ")         carry over start:" << carryOverStart.toString(Qt::ISODate);
 | 
			
		||||
                qCritical() << "(" << __func__ << ":" << __LINE__ << ")           carry over end:" << carryOverEnd.toString(Qt::ISODate);
 | 
			
		||||
                // TODO: reparieren
 | 
			
		||||
 | 
			
		||||
                if (carryOverTimeRangeFrom.secsTo(carryOverTimeRangeTo) <= 60) { // carry over time point, usually 00:00:00
 | 
			
		||||
                    if (carryOverTimeRangeFrom == QTime(0, 0, 0)) {
 | 
			
		||||
@@ -2189,14 +2202,26 @@ QList<int> &Calculator::GetTimeSteps(Configuration *cfg, int paymentOptionIndex)
 | 
			
		||||
 | 
			
		||||
                        m_timeSteps[paymentOptionIndex].clear();
 | 
			
		||||
 | 
			
		||||
                        std::optional<QDateTime> adaptedStart = cfg->adaptStart(start, pop_prepaid_option_id);
 | 
			
		||||
                        if (adaptedStart) {
 | 
			
		||||
                            start = adaptedStart.value();
 | 
			
		||||
                        std::optional<QDateTime> prepaidStart = cfg->prepaidStart(start, pop_prepaid_option_id);
 | 
			
		||||
                        // TODO: zusaetzlicher faktor falls vorkauf-option zieht
 | 
			
		||||
                        if (prepaidStart) {
 | 
			
		||||
                            start = prepaidStart.value();
 | 
			
		||||
                            qCritical() << "(" << __func__ << ":" << __LINE__ << ")         prepaid adapted start:" << start.toString(Qt::ISODate);
 | 
			
		||||
                        } else {
 | 
			
		||||
                            // TODO
 | 
			
		||||
                            qCritical() << "(" << __func__ << ":" << __LINE__ << ") TODO";
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        QDateTime interpolationEnd;
 | 
			
		||||
                        std::optional<QDateTime> interpolationEndDate = cfg->getInterpolationEnd(start, paymentOptionIndex);
 | 
			
		||||
                        if (interpolationEndDate) {
 | 
			
		||||
                            interpolationEnd = interpolationEndDate.value();
 | 
			
		||||
                            qCritical() << "(" << __func__ << ":" << __LINE__ << ")             interpolation end:" << interpolationEnd.toString(Qt::ISODate);
 | 
			
		||||
                        } else {
 | 
			
		||||
                            qCritical() << "(" << __func__ << ":" << __LINE__ << ") TODO";
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        int const start_time = start.time().hour() * 60 + start.time().minute();
 | 
			
		||||
                        QDateTime nextTimeStep = start;
 | 
			
		||||
 | 
			
		||||
                        for (auto[itr, rangeEnd] = cfg->PaymentRate.equal_range(pop_id); itr != rangeEnd; ++itr) {
 | 
			
		||||
                            int const durationId = itr->second.pra_payment_unit_id;
 | 
			
		||||
@@ -2219,9 +2244,11 @@ QList<int> &Calculator::GetTimeSteps(Configuration *cfg, int paymentOptionIndex)
 | 
			
		||||
                                if (ipolCheck) {
 | 
			
		||||
                                    ATBInterpolation interpolation = ipolCheck.value();
 | 
			
		||||
 | 
			
		||||
                                    if (duration.pun_interpolation_id == (int)ATBInterpolation::DYNAMIC_ABSTRACT_TIMEPOINT_AND_STATIC_END_TIME) {
 | 
			
		||||
                                    if (duration.pun_interpolation_id == (int)ATBInterpolation::DYNAMIC_ABSTRACT_TIMEPOINT_AND_STATIC_PRICE) {
 | 
			
		||||
 | 
			
		||||
                                        interpolation.dynamic_start = start.time();
 | 
			
		||||
                                        interpolation.dynamic_start.setHMS(start.time().hour(), start.time().minute(), 0);
 | 
			
		||||
 | 
			
		||||
                                        //qCritical() << "(" << __func__ << ":" << __LINE__ << ")                            pun_id:" << duration.pun_id;
 | 
			
		||||
                                        int const end_time = interpolation.dynamic_end.hour() * 60 + interpolation.dynamic_end.minute();
 | 
			
		||||
 | 
			
		||||
                                        //qCritical() << "(" << __func__ << ":" << __LINE__ << ")                      pun_duration:" << duration.pun_duration;
 | 
			
		||||
@@ -2234,9 +2261,12 @@ QList<int> &Calculator::GetTimeSteps(Configuration *cfg, int paymentOptionIndex)
 | 
			
		||||
 | 
			
		||||
                                        int pop_min_time = cfg->getPaymentOptions(paymentOptionIndex).pop_min_time;
 | 
			
		||||
 | 
			
		||||
                                        int nextTimeStep = start_time + duration.pun_duration;
 | 
			
		||||
                                        int rest = end_time - nextTimeStep;
 | 
			
		||||
                                        if (nextTimeStep <= end_time) {
 | 
			
		||||
                                        nextTimeStep = nextTimeStep.addSecs(duration.pun_duration * 60);
 | 
			
		||||
 | 
			
		||||
                                        // int nextTimeStep = start_time + duration.pun_duration;
 | 
			
		||||
                                        //int rest = end_time - nextTimeStep;
 | 
			
		||||
                                        int rest = nextTimeStep.secsTo(interpolationEnd);
 | 
			
		||||
                                        if (nextTimeStep <= interpolationEnd) {
 | 
			
		||||
 | 
			
		||||
                                            if (durationId == 1) {
 | 
			
		||||
 | 
			
		||||
@@ -2247,17 +2277,17 @@ QList<int> &Calculator::GetTimeSteps(Configuration *cfg, int paymentOptionIndex)
 | 
			
		||||
                                                qCritical() << "(" << __func__ << ":" << __LINE__ << ")         interpolation dynamic end:" << interpolation.dynamic_end.toString(Qt::ISODate);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                                                int const timeStep = nextTimeStep;
 | 
			
		||||
                                                int const timeStep = start.secsTo(nextTimeStep) / 60;
 | 
			
		||||
 | 
			
		||||
                                                qCritical() << "(" << __func__ << ":" << __LINE__ << ")                          time step:" << timeStep;
 | 
			
		||||
 | 
			
		||||
                                                if (timeStep < duration.pun_duration_min || timeStep > duration.pun_duration_max) {
 | 
			
		||||
                                                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                                                << QString("ERROR timeStep (%1) < durationMin (%2) || timeStep (%3)) > durationMax (%4)")
 | 
			
		||||
                                                    .arg(timeStep).arg(duration.pun_duration_min)
 | 
			
		||||
                                                    .arg(timeStep).arg(duration.pun_duration_max);
 | 
			
		||||
                                                    break;
 | 
			
		||||
                                                }
 | 
			
		||||
                                                //if (timeStep < duration.pun_duration_min || timeStep > duration.pun_duration_max) {
 | 
			
		||||
                                                //    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                                //                << QString("ERROR timeStep (%1) < durationMin (%2) || timeStep (%3)) > durationMax (%4)")
 | 
			
		||||
                                                //    .arg(timeStep).arg(duration.pun_duration_min)
 | 
			
		||||
                                                //    .arg(timeStep).arg(duration.pun_duration_max);
 | 
			
		||||
                                                //    break;
 | 
			
		||||
                                                //}
 | 
			
		||||
 | 
			
		||||
                                                qCritical() << "(" << __func__ << ":" << __LINE__ << ") configured minimal parking time:" << cfg->getPaymentOptions(paymentOptionIndex).pop_min_time;
 | 
			
		||||
 | 
			
		||||
@@ -2267,7 +2297,7 @@ QList<int> &Calculator::GetTimeSteps(Configuration *cfg, int paymentOptionIndex)
 | 
			
		||||
                                                qCritical() << "(" << __func__ << ":" << __LINE__ << ")   computed minimal parking time:" << cfg->getPaymentOptions(paymentOptionIndex).pop_min_time;
 | 
			
		||||
 | 
			
		||||
                                                duration.pun_duration = timeStep;
 | 
			
		||||
                                                timeStepCompensation = end_time - start_time;
 | 
			
		||||
                                                timeStepCompensation = start.secsTo(interpolationEnd) / 60;
 | 
			
		||||
 | 
			
		||||
                                                if (duration.pun_duration > 0) {
 | 
			
		||||
                                                    m_timeSteps[paymentOptionIndex] << duration.pun_duration;
 | 
			
		||||
@@ -2280,7 +2310,9 @@ QList<int> &Calculator::GetTimeSteps(Configuration *cfg, int paymentOptionIndex)
 | 
			
		||||
                                                qCritical() << "(" << __func__ << ":" << __LINE__ << ")          time step compensation:" << timeStepCompensation;
 | 
			
		||||
#endif
 | 
			
		||||
                                            } else {
 | 
			
		||||
                                                duration.pun_duration = nextTimeStep;
 | 
			
		||||
                                                // duration.pun_duration = nextTimeStep;
 | 
			
		||||
 | 
			
		||||
                                                // HIER WEITER
 | 
			
		||||
 | 
			
		||||
#if DEBUG_GET_TIME_STEPS==1
 | 
			
		||||
                                                QTime nextTime(0, 0, 0);
 | 
			
		||||
@@ -2338,9 +2370,11 @@ QList<int> &Calculator::GetTimeSteps(Configuration *cfg, int paymentOptionIndex)
 | 
			
		||||
                    }
 | 
			
		||||
                } else { // if (carryOverTimeRangeFrom == carryOverTimeRangeTo) {
 | 
			
		||||
                    // TODO
 | 
			
		||||
                    qCritical() << "(" << __func__ << ":" << __LINE__ << ") TODO";
 | 
			
		||||
                }
 | 
			
		||||
            } else { // if (pop_carry_over) {
 | 
			
		||||
                // TODO
 | 
			
		||||
                 qCritical() << "(" << __func__ << ":" << __LINE__ << ") TODO";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
 
 | 
			
		||||
@@ -115,8 +115,8 @@ QDateTime Calculator::GetDailyTicketDuration(Configuration* cfg, const QDateTime
 | 
			
		||||
/// <inheritdoc/>
 | 
			
		||||
std::string Calculator::GetDurationFromCost(Configuration* cfg,
 | 
			
		||||
                                            uint8_t payment_option,
 | 
			
		||||
                                            char const* start_datetime, // given in local time
 | 
			
		||||
                                            double price,
 | 
			
		||||
                                            char const *startDatetimePassed, // given in local time
 | 
			
		||||
                                            double cost,
 | 
			
		||||
                                            bool nextDay,
 | 
			
		||||
                                            bool prepaid)
 | 
			
		||||
{
 | 
			
		||||
@@ -124,14 +124,14 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
 | 
			
		||||
    Q_UNUSED(nextDay);
 | 
			
		||||
 | 
			
		||||
    // Get input date
 | 
			
		||||
    QDateTime inputDate = QDateTime::fromString(start_datetime,Qt::ISODate);
 | 
			
		||||
    QDateTime inputDate = QDateTime::fromString(startDatetimePassed,Qt::ISODate);
 | 
			
		||||
 | 
			
		||||
    static const PaymentMethod paymentMethodId = Utilities::getPaymentMethodId(cfg);
 | 
			
		||||
    if (paymentMethodId == PaymentMethod::Steps) {
 | 
			
		||||
        if (tariffIs24_7(cfg)) {
 | 
			
		||||
            // use tariff with structure as for instance Schoenau, Koenigsee:
 | 
			
		||||
            // without given YearPeriod, SpecialDays and SpecialDaysWorktime
 | 
			
		||||
            inputDate = inputDate.addSecs(GetDurationForPrice(cfg, price) * 60);
 | 
			
		||||
            inputDate = inputDate.addSecs(GetDurationForPrice(cfg, cost) * 60);
 | 
			
		||||
            return inputDate.toString(Qt::ISODate).toStdString();
 | 
			
		||||
        } else {
 | 
			
		||||
            if (Utilities::IsYearPeriodActive(cfg, inputDate)) {
 | 
			
		||||
@@ -147,9 +147,226 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
 | 
			
		||||
                return "";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    } else
 | 
			
		||||
    if (paymentMethodId == PaymentMethod::Progressive) {
 | 
			
		||||
        // started with Neuhauser, Kirchdorf: merge into main algo. later
 | 
			
		||||
        // for now try out some ideas
 | 
			
		||||
 | 
			
		||||
        // started with Neuhauser, Kirchdorf: merge into main algo. later
 | 
			
		||||
        // for now try out some ideas
 | 
			
		||||
 | 
			
		||||
        static const bool carryOverNotSet = Utilities::isCarryOverNotSet(cfg, paymentMethodId);
 | 
			
		||||
        static const uint minParkingPrice = Utilities::getMinimalParkingPrice(cfg, paymentMethodId);
 | 
			
		||||
        static const uint maxParkingPrice = Utilities::getMaximalParkingPrice(cfg, paymentMethodId);
 | 
			
		||||
 | 
			
		||||
        if (cost < minParkingPrice) {
 | 
			
		||||
            qCritical() << QString("ERROR: COST < MIN_PARKING_PRICE (%1 < %2)").arg(cost).arg(minParkingPrice);
 | 
			
		||||
            return QDateTime().toString(Qt::ISODate).toStdString();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (cost > maxParkingPrice) {
 | 
			
		||||
            qCritical() << QString("WARN: COST > MAX_PARKING_PRICE (%1 > %2)").arg(cost).arg(maxParkingPrice);
 | 
			
		||||
            cost = maxParkingPrice;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Q_ASSERT_X(carryOverNotSet, __func__, "CARRYOVER SET (FOR KIRCHDORF)");
 | 
			
		||||
        Q_ASSERT_X(prepaid, __func__, "PREPAID NOT SET (FOR KIRCHDORF)");
 | 
			
		||||
 | 
			
		||||
        QDateTime start_datetime = QDateTime::fromString(QString(startDatetimePassed), Qt::ISODate);
 | 
			
		||||
        QDateTime start = start_datetime;
 | 
			
		||||
        QDateTime end_datetime = QDateTime();
 | 
			
		||||
 | 
			
		||||
        int weekdayId = -1;
 | 
			
		||||
        int weekdayIdLast = -1;
 | 
			
		||||
        int durationMinutes = Utilities::getMaximalParkingTime(cfg, paymentMethodId);
 | 
			
		||||
        int durationMinutesBrutto = 0;
 | 
			
		||||
 | 
			
		||||
        QDateTime current = start;
 | 
			
		||||
 | 
			
		||||
        int days = 7;
 | 
			
		||||
        while (--days > 0) {
 | 
			
		||||
            weekdayId = current.date().dayOfWeek();
 | 
			
		||||
            weekdayIdLast = weekdayId; // TODO: some end condition in json-file
 | 
			
		||||
 | 
			
		||||
            while (cfg->WeekDaysWorktime.count(weekdayId) == 0) {
 | 
			
		||||
                current = current.addDays(1);
 | 
			
		||||
                weekdayId = current.date().dayOfWeek();
 | 
			
		||||
                if (weekdayId == weekdayIdLast) {
 | 
			
		||||
                    qCritical() << "ERROR: NO VALID WORKDAY-TIMES DEFINED";
 | 
			
		||||
                    return QDateTime().toString(Qt::ISODate).toStdString();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            using WTIterator = std::multimap<int, ATBWeekDaysWorktime>::const_iterator;
 | 
			
		||||
            std::pair<WTIterator, WTIterator> p = cfg->WeekDaysWorktime.equal_range(weekdayId);
 | 
			
		||||
 | 
			
		||||
            QTime to = QTime(0, 0, 0);
 | 
			
		||||
            for (WTIterator itr = p.first; itr != p.second; ++itr) {
 | 
			
		||||
                QTime const &t = Utilities::WeekDaysWorkTimeUntil(itr);
 | 
			
		||||
 | 
			
		||||
                if (to < t) {
 | 
			
		||||
                    to = t;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (current.time() >= to) {
 | 
			
		||||
                if (carryOverNotSet) {
 | 
			
		||||
                    return end_datetime.toString(Qt::ISODate).toStdString();
 | 
			
		||||
                } else {
 | 
			
		||||
                    QDateTime const dt = start;
 | 
			
		||||
                    start = start.addDays(1);
 | 
			
		||||
                    start.setTime(QTime(0, 0, 0));
 | 
			
		||||
 | 
			
		||||
                    durationMinutesBrutto += dt.secsTo(start) / 60;
 | 
			
		||||
                    current = start;
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        int durationMinutesNetto = 0;
 | 
			
		||||
        uint price = 0;
 | 
			
		||||
 | 
			
		||||
        if (carryOverNotSet) {
 | 
			
		||||
            int range = 0;
 | 
			
		||||
            int minsToCarryOver = 0; // from one work-time to the other on the same day
 | 
			
		||||
            int minsUsed = 0;
 | 
			
		||||
            QDateTime lastCurrent = QDateTime();
 | 
			
		||||
 | 
			
		||||
            auto timeRangeIt = cfg->TimeRange.cbegin();
 | 
			
		||||
            for (; timeRangeIt != cfg->TimeRange.cend(); ++timeRangeIt) {
 | 
			
		||||
                using WTIterator = std::multimap<int, ATBWeekDaysWorktime>::const_iterator;
 | 
			
		||||
                std::pair<WTIterator, WTIterator> p = cfg->WeekDaysWorktime.equal_range(weekdayId);
 | 
			
		||||
 | 
			
		||||
                for (WTIterator itr = p.first; itr != p.second; ++itr) {
 | 
			
		||||
                    ++range;
 | 
			
		||||
 | 
			
		||||
                    QTime const &from = Utilities::WeekDaysWorkTimeFrom(itr);
 | 
			
		||||
                    QTime const &to = Utilities::WeekDaysWorkTimeUntil(itr);
 | 
			
		||||
 | 
			
		||||
                    Q_ASSERT_X(from < to, __func__, "MISCONFIGURED WORK-TIMES");
 | 
			
		||||
 | 
			
		||||
                    if (current.time() >= to) {
 | 
			
		||||
                        continue; // try to use next available work-time
 | 
			
		||||
                    } else
 | 
			
		||||
                    if (current.time() <= from) {
 | 
			
		||||
                        if (prepaid) {
 | 
			
		||||
                            lastCurrent = current;
 | 
			
		||||
                            current.setTime(from); // move current forward (range==1),
 | 
			
		||||
                                                   // as prepaid is set
 | 
			
		||||
                            uint const minutesMoved = lastCurrent.secsTo(current) / 60;
 | 
			
		||||
                            durationMinutesBrutto += minutesMoved;
 | 
			
		||||
 | 
			
		||||
                            if (range == 1) {
 | 
			
		||||
                                start_datetime = current;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    while (timeRangeIt != cfg->TimeRange.cend()) {
 | 
			
		||||
                        ATBTimeRange timeRange = timeRangeIt->second;
 | 
			
		||||
 | 
			
		||||
                        timeRange.computeQTimes(current.time());
 | 
			
		||||
 | 
			
		||||
                        int duration = timeRange.time_range_to_in_minutes_from_start -
 | 
			
		||||
                                       timeRange.time_range_from_in_minutes_from_start;
 | 
			
		||||
 | 
			
		||||
                        if (minsUsed > 0) {
 | 
			
		||||
                            duration -= minsUsed;
 | 
			
		||||
                            minsUsed = 0;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        if (current.addSecs(duration * 60).time() <= to) {
 | 
			
		||||
                            if (minsToCarryOver > 0) {  // the price for this time range
 | 
			
		||||
                                                        // has been is paid already
 | 
			
		||||
                                durationMinutes -= duration;
 | 
			
		||||
                                durationMinutesNetto += duration;
 | 
			
		||||
                                durationMinutesBrutto += duration;
 | 
			
		||||
                                current = current.addSecs(duration*60);
 | 
			
		||||
                                minsToCarryOver = 0;
 | 
			
		||||
                            } else {
 | 
			
		||||
                                for(const auto &x: cfg->PaymentRate) {
 | 
			
		||||
                                    ATBPaymentRate const rate = x.second;
 | 
			
		||||
                                    if (rate.pra_payment_unit_id == timeRange.time_range_payment_type_id) {
 | 
			
		||||
                                        price += (uint)rate.pra_price;
 | 
			
		||||
 | 
			
		||||
                                        if (price >= maxParkingPrice) {
 | 
			
		||||
                                            price = maxParkingPrice;
 | 
			
		||||
                                        }
 | 
			
		||||
 | 
			
		||||
                                        durationMinutes -= duration;
 | 
			
		||||
                                        durationMinutesNetto += duration;
 | 
			
		||||
                                        durationMinutesBrutto += duration;
 | 
			
		||||
 | 
			
		||||
                                        current = current.addSecs(duration * 60);
 | 
			
		||||
 | 
			
		||||
                                        if (price >= cost) {
 | 
			
		||||
                                            end_datetime = current;
 | 
			
		||||
                                            return end_datetime.toString(Qt::ISODate).toStdString();
 | 
			
		||||
                                        }
 | 
			
		||||
 | 
			
		||||
                                        break;
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            if (durationMinutes <= 0) {
 | 
			
		||||
                                end_datetime = current;
 | 
			
		||||
                                return end_datetime.toString(Qt::ISODate).toStdString();
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            ++timeRangeIt;
 | 
			
		||||
 | 
			
		||||
                        } else {
 | 
			
		||||
 | 
			
		||||
                            lastCurrent = current;
 | 
			
		||||
                            current.setTime(to);
 | 
			
		||||
                            minsUsed = lastCurrent.secsTo(current) / 60;
 | 
			
		||||
 | 
			
		||||
                            // mod duration: possibly discard some minutes in
 | 
			
		||||
                            // the next time-range
 | 
			
		||||
                            if (durationMinutes >= minsUsed) {
 | 
			
		||||
                                minsToCarryOver = durationMinutes - minsUsed;
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            durationMinutes -= minsUsed;
 | 
			
		||||
                            durationMinutesNetto += minsUsed;
 | 
			
		||||
                            durationMinutesBrutto += minsUsed;
 | 
			
		||||
 | 
			
		||||
                            if (minsUsed > 0) {
 | 
			
		||||
                                for(const auto &x: cfg->PaymentRate) {
 | 
			
		||||
                                    ATBPaymentRate const rate = x.second;
 | 
			
		||||
                                    if (rate.pra_payment_unit_id == timeRange.time_range_payment_type_id) {
 | 
			
		||||
                                        price += (uint)rate.pra_price;
 | 
			
		||||
 | 
			
		||||
                                        if (price >= maxParkingPrice) {
 | 
			
		||||
                                            price = maxParkingPrice;
 | 
			
		||||
                                        }
 | 
			
		||||
 | 
			
		||||
                                        if (price >= cost) {
 | 
			
		||||
                                            end_datetime = current;
 | 
			
		||||
                                            // return end_datetime.toString(Qt::ISODate).toStdString();
 | 
			
		||||
                                        }
 | 
			
		||||
                                        break;
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                end_datetime = start.addSecs(durationMinutesBrutto * 60);
 | 
			
		||||
                return end_datetime.toString(Qt::ISODate).toStdString();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        end_datetime = QDateTime();
 | 
			
		||||
        return end_datetime.toString(Qt::ISODate).toStdString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Ticket t = private_GetDurationFromCost(cfg, inputDate, price, prepaid);
 | 
			
		||||
    Ticket t = private_GetDurationFromCost(cfg, inputDate, cost, prepaid);
 | 
			
		||||
 | 
			
		||||
    // qCritical().noquote() << t;
 | 
			
		||||
 | 
			
		||||
@@ -279,9 +496,11 @@ double Calculator::GetCostFromDuration(Configuration* cfg,
 | 
			
		||||
                        end_datetime.setTime(cs.getAllowedTimeRange().getTimeUntil());
 | 
			
		||||
                        return cost;
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    // it might be that in such a case even prepaid ("vorkauf")
 | 
			
		||||
                    // is not allowed at any moment
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                qCritical() << __PRETTY_FUNCTION__ << "NOT YET IMPLEMENTED";
 | 
			
		||||
                qCritical() << "(" << __func__ << ":" << __LINE__ << ")" << "NOT YET IMPLEMENTED";
 | 
			
		||||
                end_datetime = QDateTime();
 | 
			
		||||
                return 0;
 | 
			
		||||
            }
 | 
			
		||||
@@ -299,34 +518,18 @@ double Calculator::GetCostFromDuration(Configuration* cfg,
 | 
			
		||||
 | 
			
		||||
        QDateTime start = start_datetime;
 | 
			
		||||
 | 
			
		||||
#define DEBUG 0
 | 
			
		||||
#if DEBUG==1
 | 
			
		||||
        qCritical() << "start" << start.toString(Qt::ISODate) << durationMinutes;
 | 
			
		||||
#endif
 | 
			
		||||
        int weekdayId = -1;
 | 
			
		||||
        int weekdayIdLast = -1;
 | 
			
		||||
        int timeRanges = 0;
 | 
			
		||||
        int durationMinutesBrutto = 0;
 | 
			
		||||
 | 
			
		||||
        QDateTime current = start;
 | 
			
		||||
 | 
			
		||||
        //if ((durationMinutes % 5) != 0) {
 | 
			
		||||
        //    qCritical() << "ERROR DURATION (" << durationMinutes
 | 
			
		||||
        //                << ") NOT A MULTIPLE Of 5";
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        int days = 7;
 | 
			
		||||
        while (--days > 0) {
 | 
			
		||||
 | 
			
		||||
#if DEBUG==1
 | 
			
		||||
        qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                    << "start" << start.toString(Qt::ISODate)
 | 
			
		||||
                    << "current" << current.toString(Qt::ISODate);
 | 
			
		||||
#endif
 | 
			
		||||
            weekdayId = current.date().dayOfWeek();
 | 
			
		||||
            weekdayIdLast = weekdayId; // TODO: some end condition in json-file
 | 
			
		||||
 | 
			
		||||
            while ((timeRanges = cfg->WeekDaysWorktime.count(weekdayId)) == 0) {
 | 
			
		||||
            while (cfg->WeekDaysWorktime.count(weekdayId) == 0) {
 | 
			
		||||
                current = current.addDays(1);
 | 
			
		||||
                weekdayId = current.date().dayOfWeek();
 | 
			
		||||
                if (weekdayId == weekdayIdLast) {
 | 
			
		||||
@@ -335,11 +538,6 @@ double Calculator::GetCostFromDuration(Configuration* cfg,
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
#if DEBUG==1
 | 
			
		||||
        qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                    << "current" << current.toString(Qt::ISODate);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
            using WTIterator = std::multimap<int, ATBWeekDaysWorktime>::const_iterator;
 | 
			
		||||
            std::pair<WTIterator, WTIterator> p = cfg->WeekDaysWorktime.equal_range(weekdayId);
 | 
			
		||||
 | 
			
		||||
@@ -347,235 +545,169 @@ double Calculator::GetCostFromDuration(Configuration* cfg,
 | 
			
		||||
            for (WTIterator itr = p.first; itr != p.second; ++itr) {
 | 
			
		||||
                QTime const &t = Utilities::WeekDaysWorkTimeUntil(itr);
 | 
			
		||||
 | 
			
		||||
#if DEBUG==1
 | 
			
		||||
                qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                            << "current" << current.time().toString(Qt::ISODate)
 | 
			
		||||
                            << "t" << t.toString(Qt::ISODate)
 | 
			
		||||
                            << "to" << to.toString(Qt::ISODate);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                if (to < t) {
 | 
			
		||||
                    to = t;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            if (current.time() >= to) {
 | 
			
		||||
                QDateTime const dt = start;
 | 
			
		||||
                start = start.addDays(1);
 | 
			
		||||
                start.setTime(QTime(0, 0, 0));
 | 
			
		||||
                if (carryOverNotSet) {
 | 
			
		||||
                    end_datetime = start;
 | 
			
		||||
                    return 0;
 | 
			
		||||
                } else {
 | 
			
		||||
                    QDateTime const dt = start;
 | 
			
		||||
                    start = start.addDays(1);
 | 
			
		||||
                    start.setTime(QTime(0, 0, 0));
 | 
			
		||||
 | 
			
		||||
                durationMinutesBrutto += dt.secsTo(start) / 60;
 | 
			
		||||
                current = start;
 | 
			
		||||
                    durationMinutesBrutto += dt.secsTo(start) / 60;
 | 
			
		||||
                    current = start;
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
 | 
			
		||||
#if DEBUG==1
 | 
			
		||||
                qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                            << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                            << "durationMinutesBrutto" << durationMinutesBrutto;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
#if DEBUG==1
 | 
			
		||||
        qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                    << "timeRanges" << timeRanges << weekdayId
 | 
			
		||||
                    << "durationMinutesBrutto" << durationMinutesBrutto
 | 
			
		||||
                    << "start" << start.toString(Qt::ISODate)
 | 
			
		||||
                    << "current" << current.toString(Qt::ISODate);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        int durationMinutesNetto = 0;
 | 
			
		||||
        uint price = 0;
 | 
			
		||||
 | 
			
		||||
        if (carryOverNotSet) {
 | 
			
		||||
            int range = 0;
 | 
			
		||||
            int minsToCarryOver = 0; // from one work-time to the other on the same day
 | 
			
		||||
            int minsUsed = 0;
 | 
			
		||||
            QDateTime lastCurrent = QDateTime();
 | 
			
		||||
 | 
			
		||||
            auto timeRangeIt = cfg->TimeRange.cbegin();
 | 
			
		||||
            for (; timeRangeIt != cfg->TimeRange.cend(); ++timeRangeIt) {
 | 
			
		||||
                using WTIterator = std::multimap<int, ATBWeekDaysWorktime>::const_iterator;
 | 
			
		||||
                std::pair<WTIterator, WTIterator> p = cfg->WeekDaysWorktime.equal_range(weekdayId);
 | 
			
		||||
            using WTIterator = std::multimap<int, ATBWeekDaysWorktime>::const_iterator;
 | 
			
		||||
            std::pair<WTIterator, WTIterator> p = cfg->WeekDaysWorktime.equal_range(weekdayId);
 | 
			
		||||
 | 
			
		||||
                for (WTIterator itr = p.first; itr != p.second; ++itr) {
 | 
			
		||||
                    ++range;
 | 
			
		||||
            for (WTIterator itr = p.first; itr != p.second; ++itr) {
 | 
			
		||||
                ++range;
 | 
			
		||||
 | 
			
		||||
                    QTime const &from = Utilities::WeekDaysWorkTimeFrom(itr);
 | 
			
		||||
                    QTime const &to = Utilities::WeekDaysWorkTimeUntil(itr);
 | 
			
		||||
                QTime const &from = Utilities::WeekDaysWorkTimeFrom(itr);
 | 
			
		||||
                QTime const &to = Utilities::WeekDaysWorkTimeUntil(itr);
 | 
			
		||||
 | 
			
		||||
                    Q_ASSERT_X(from < to, __func__, "MISCONFIGURED WORK-TIMES");
 | 
			
		||||
                Q_ASSERT_X(from < to, __func__, "MISCONFIGURED WORK-TIMES");
 | 
			
		||||
 | 
			
		||||
                if (current.time() >= to) {
 | 
			
		||||
                    continue; // try to use next available work-time
 | 
			
		||||
                } else
 | 
			
		||||
                if (current.time() <= from) {
 | 
			
		||||
                    if (prepaid) {
 | 
			
		||||
                        lastCurrent = current;
 | 
			
		||||
                        current.setTime(from); // move current forward (range==1),
 | 
			
		||||
                                               // as prepaid is set
 | 
			
		||||
                        uint const minutesMoved = lastCurrent.secsTo(current) / 60;
 | 
			
		||||
                        durationMinutesBrutto += minutesMoved;
 | 
			
		||||
 | 
			
		||||
                    if (current.time() >= to) {
 | 
			
		||||
#if DEBUG==1
 | 
			
		||||
                        qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                    << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                                    << "from" << from.toString(Qt::ISODate)
 | 
			
		||||
                                    << "to" << to.toString(Qt::ISODate);
 | 
			
		||||
#endif
 | 
			
		||||
                        continue; // try to use next available work-time
 | 
			
		||||
                    } else
 | 
			
		||||
                    if (current.time() <= from) {
 | 
			
		||||
                        if (prepaid) {
 | 
			
		||||
                            lastCurrent = current;
 | 
			
		||||
                            current.setTime(from); // move current forward (range==1),
 | 
			
		||||
                                                   // as prepaid is set
 | 
			
		||||
                            uint const minutesMoved = lastCurrent.secsTo(current) / 60;
 | 
			
		||||
#if DEBUG==1
 | 
			
		||||
                            qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                        << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                                        << "lastCurrent" << lastCurrent.toString(Qt::ISODate)
 | 
			
		||||
                                        << "minutesMoved" << minutesMoved
 | 
			
		||||
                                        << "durationMinutes" << durationMinutes;
 | 
			
		||||
#endif
 | 
			
		||||
                            durationMinutesBrutto += minutesMoved;
 | 
			
		||||
 | 
			
		||||
                            if (range == 1) {
 | 
			
		||||
                                start_datetime = current;
 | 
			
		||||
                            }
 | 
			
		||||
                        if (range == 1) {
 | 
			
		||||
                            start_datetime = current;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
#if DEBUG==1
 | 
			
		||||
                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                << "from" << from.toString(Qt::ISODate)
 | 
			
		||||
                                << "to" << to.toString(Qt::ISODate)
 | 
			
		||||
                for (auto timeRangeIt = cfg->TimeRange.cbegin(); timeRangeIt != cfg->TimeRange.cend(); ++timeRangeIt) {
 | 
			
		||||
 | 
			
		||||
                    ATBTimeRange timeRange = timeRangeIt->second;
 | 
			
		||||
 | 
			
		||||
                    timeRange.computeQTimes(current.time());
 | 
			
		||||
 | 
			
		||||
                    int duration = timeRange.time_range_to_in_minutes_from_start -
 | 
			
		||||
                                   timeRange.time_range_from_in_minutes_from_start;
 | 
			
		||||
 | 
			
		||||
                    qCritical() << __func__ << ":" << __LINE__
 | 
			
		||||
                                << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                                << "durationMinutes" << durationMinutes;
 | 
			
		||||
#endif
 | 
			
		||||
                                << "duration" << duration
 | 
			
		||||
                                << "minsUsed" << minsUsed
 | 
			
		||||
                                << "minsToCarryOver" << minsToCarryOver;
 | 
			
		||||
 | 
			
		||||
                    while (timeRangeIt != cfg->TimeRange.cend()) {
 | 
			
		||||
                        ATBTimeRange timeRange = timeRangeIt->second;
 | 
			
		||||
 | 
			
		||||
                        timeRange.computeQTimes(current.time());
 | 
			
		||||
                    //if (minsUsed > 0) {
 | 
			
		||||
                    //    duration -= minsUsed;
 | 
			
		||||
                    //    minsUsed = 0;
 | 
			
		||||
                    //}
 | 
			
		||||
 | 
			
		||||
                        int duration = timeRange.time_range_to_in_minutes_from_start -
 | 
			
		||||
                                       timeRange.time_range_from_in_minutes_from_start;
 | 
			
		||||
 | 
			
		||||
#if DEBUG==1
 | 
			
		||||
                        qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                    << "duration" << duration << timeRange.time_range_id
 | 
			
		||||
                                    << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                                    << "minsToCarryOver" <<  minsToCarryOver
 | 
			
		||||
                                    << "durationMinutes" << durationMinutes;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                        if (current.addSecs(duration * 60).time() <= to) {
 | 
			
		||||
 | 
			
		||||
                            for(const auto &x: cfg->PaymentRate) {
 | 
			
		||||
                                ATBPaymentRate const rate = x.second;
 | 
			
		||||
                                if (rate.pra_payment_unit_id == timeRange.time_range_payment_type_id) {
 | 
			
		||||
                                    if (minsToCarryOver > 0) {
 | 
			
		||||
                                        durationMinutes -= minsToCarryOver;
 | 
			
		||||
                                        durationMinutesNetto += minsToCarryOver;
 | 
			
		||||
                                        durationMinutesBrutto += minsToCarryOver;
 | 
			
		||||
                                        current = current.addSecs(minsToCarryOver*60);
 | 
			
		||||
                                        minsToCarryOver = 0;
 | 
			
		||||
#if DEBUG==1
 | 
			
		||||
                                        qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                                    << "durationMinutes" << durationMinutes
 | 
			
		||||
                                                    << "durationMinutesNetto" << durationMinutesNetto
 | 
			
		||||
                                                    << "durationMinutesBrutto" << durationMinutesBrutto
 | 
			
		||||
                                                    << "current" << current.toString(Qt::ISODate);
 | 
			
		||||
#endif
 | 
			
		||||
                                    } else {
 | 
			
		||||
                    if (current.addSecs(duration * 60).time() <= to) {
 | 
			
		||||
                        if (minsToCarryOver > 0) {  // the price for this time range
 | 
			
		||||
                                                    // has been is paid already
 | 
			
		||||
                            if (minsUsed == 0) {
 | 
			
		||||
                                for(const auto &x: cfg->PaymentRate) {
 | 
			
		||||
                                    ATBPaymentRate const rate = x.second;
 | 
			
		||||
                                    if (rate.pra_payment_unit_id == timeRange.time_range_payment_type_id) {
 | 
			
		||||
                                        price += (uint)rate.pra_price;
 | 
			
		||||
 | 
			
		||||
                                        durationMinutes -= duration;
 | 
			
		||||
                                        durationMinutesNetto += duration;
 | 
			
		||||
                                        durationMinutesBrutto += duration;
 | 
			
		||||
 | 
			
		||||
#if DEBUG==1
 | 
			
		||||
                                        qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                                    << "duration" << duration
 | 
			
		||||
                                                    << "durationMinutes" << durationMinutes
 | 
			
		||||
                                                    << "durationMinutesNetto" << durationMinutesNetto
 | 
			
		||||
                                                    << "durationMinutesBrutto" << durationMinutesBrutto;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                                        current = current.addSecs(duration * 60);
 | 
			
		||||
 | 
			
		||||
#if DEBUG==1
 | 
			
		||||
                                        qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                                    << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                                                    << "price" << price;
 | 
			
		||||
#endif
 | 
			
		||||
                                    }
 | 
			
		||||
                                        if (durationMinutes <= 0) {
 | 
			
		||||
                                            end_datetime = current;
 | 
			
		||||
                                            return price;
 | 
			
		||||
                                        }
 | 
			
		||||
 | 
			
		||||
                                    break;
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            if (durationMinutes <= 0) {
 | 
			
		||||
                                end_datetime = current;
 | 
			
		||||
#if DEBUG==1
 | 
			
		||||
                                qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                            << "duration" << durationMinutesNetto << ", price" << price
 | 
			
		||||
                                            << current.toString(Qt::ISODate)
 | 
			
		||||
                                            << end_datetime.toString(Qt::ISODate);
 | 
			
		||||
#endif
 | 
			
		||||
                                return price;
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            ++timeRangeIt;
 | 
			
		||||
 | 
			
		||||
                        } else {
 | 
			
		||||
 | 
			
		||||
                            lastCurrent = current;
 | 
			
		||||
                            current.setTime(to);
 | 
			
		||||
                            int const minsLeft = lastCurrent.secsTo(current) / 60;
 | 
			
		||||
 | 
			
		||||
                            // mod duration: possibly discard some minutes in
 | 
			
		||||
                            // the next time-range
 | 
			
		||||
                            minsToCarryOver = (durationMinutes - minsLeft) % duration;
 | 
			
		||||
 | 
			
		||||
                            durationMinutes -= minsLeft;
 | 
			
		||||
                            durationMinutesNetto += minsLeft;
 | 
			
		||||
                            durationMinutesBrutto += minsLeft;
 | 
			
		||||
 | 
			
		||||
#if DEBUG==1
 | 
			
		||||
                            qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                        << "lastCurrent" << lastCurrent.toString(Qt::ISODate)
 | 
			
		||||
                                        << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                                        << "minsLeft" << minsLeft;
 | 
			
		||||
                            qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                        << "duration" << duration
 | 
			
		||||
                                        << "durationMinutes" << durationMinutes
 | 
			
		||||
                                        << "durationMinutesNetto" << durationMinutesNetto
 | 
			
		||||
                                        << "durationMinutesBrutto" << durationMinutesBrutto
 | 
			
		||||
                                        << "minsToCarryOver" << minsToCarryOver;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                            if (minsLeft > 0) {
 | 
			
		||||
                                for(const auto &x: cfg->PaymentRate) {
 | 
			
		||||
                                    ATBPaymentRate const rate = x.second;
 | 
			
		||||
                                    if (rate.pra_payment_unit_id == timeRange.time_range_payment_type_id) {
 | 
			
		||||
                                        price += (uint)rate.pra_price;
 | 
			
		||||
#if DEBUG==1
 | 
			
		||||
                                        qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                                    << "price" << price;
 | 
			
		||||
#endif
 | 
			
		||||
                                        break;
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                            } else {
 | 
			
		||||
                                durationMinutes -= duration;
 | 
			
		||||
                                durationMinutesNetto += duration;
 | 
			
		||||
                                durationMinutesBrutto += duration;
 | 
			
		||||
                                current = current.addSecs(duration*60);
 | 
			
		||||
                                minsToCarryOver = 0;
 | 
			
		||||
                            }
 | 
			
		||||
                        } else {
 | 
			
		||||
                            for(const auto &x: cfg->PaymentRate) {
 | 
			
		||||
                                ATBPaymentRate const rate = x.second;
 | 
			
		||||
                                if (rate.pra_payment_unit_id == timeRange.time_range_payment_type_id) {
 | 
			
		||||
                                    price += (uint)rate.pra_price;
 | 
			
		||||
 | 
			
		||||
                            break;
 | 
			
		||||
                                    durationMinutes -= duration;
 | 
			
		||||
                                    durationMinutesNetto += duration;
 | 
			
		||||
                                    durationMinutesBrutto += duration;
 | 
			
		||||
 | 
			
		||||
                                    current = current.addSecs(duration * 60);
 | 
			
		||||
                                    break;
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        if (durationMinutes <= 0) {
 | 
			
		||||
                            end_datetime = current;
 | 
			
		||||
                            return price;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        //++timeRangeIt;
 | 
			
		||||
 | 
			
		||||
                    } else {
 | 
			
		||||
 | 
			
		||||
                        lastCurrent = current;
 | 
			
		||||
                        current.setTime(to);
 | 
			
		||||
                        minsUsed = lastCurrent.secsTo(current) / 60;
 | 
			
		||||
 | 
			
		||||
                        // mod duration: possibly discard some minutes in
 | 
			
		||||
                        // the next time-range
 | 
			
		||||
                        if (durationMinutes >= minsUsed) {
 | 
			
		||||
                            minsToCarryOver = durationMinutes - minsUsed;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        durationMinutes -= minsUsed;
 | 
			
		||||
                        durationMinutesNetto += minsUsed;
 | 
			
		||||
                        durationMinutesBrutto += minsUsed;
 | 
			
		||||
 | 
			
		||||
                        if (minsUsed > 0) {
 | 
			
		||||
                            for(const auto &x: cfg->PaymentRate) {
 | 
			
		||||
                                ATBPaymentRate const rate = x.second;
 | 
			
		||||
                                if (rate.pra_payment_unit_id == timeRange.time_range_payment_type_id) {
 | 
			
		||||
                                    price += (uint)rate.pra_price;
 | 
			
		||||
                                    break;
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        // break;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                } // for (WTIterator itr = p.first; itr != p.second; ++itr) {
 | 
			
		||||
 | 
			
		||||
                end_datetime = start.addSecs(durationMinutesBrutto * 60);
 | 
			
		||||
#if DEBUG==1
 | 
			
		||||
                qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                            << "duration" << durationMinutesNetto
 | 
			
		||||
                            << ", price" << std::max(price, minParkingPrice)
 | 
			
		||||
                            << start.toString(Qt::ISODate)
 | 
			
		||||
                            << end_datetime.toString(Qt::ISODate);
 | 
			
		||||
#endif
 | 
			
		||||
                return std::max(price, minParkingPrice);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -1072,6 +1204,8 @@ QList<int> Calculator::GetTimeSteps(Configuration *cfg) const {
 | 
			
		||||
    int const pop_carry_over = cfg->getPaymentOptions().pop_carry_over;
 | 
			
		||||
    int const pop_time_step_config = cfg->getPaymentOptions().pop_time_step_config;
 | 
			
		||||
 | 
			
		||||
    static PaymentMethod const paymentMethodId = Utilities::getPaymentMethodId(cfg);
 | 
			
		||||
 | 
			
		||||
    qCritical() << __func__ << ":" << __LINE__ << "       start parking time:" << start.toString(Qt::ISODate);
 | 
			
		||||
    qCritical() << __func__ << ":" << __LINE__ << "        payment option id:" << pop_id;
 | 
			
		||||
    qCritical() << __func__ << ":" << __LINE__ << "payment option carry over:" << pop_carry_over;
 | 
			
		||||
@@ -1079,63 +1213,71 @@ QList<int> Calculator::GetTimeSteps(Configuration *cfg) const {
 | 
			
		||||
    if (pop_time_step_config == (int)ATBTimeStepConfig::TimeStepConfig::DYNAMIC) {
 | 
			
		||||
        //qCritical() << __PRETTY_FUNCTION__ << "payment option time step config:" << "TimeStepConfig::DYNAMIC";
 | 
			
		||||
 | 
			
		||||
        uint16_t timeStepCompensation = 0;
 | 
			
		||||
        if (paymentMethodId == PaymentMethod::Progressive) { // e.g. neuhauser kirchdorf (743)
 | 
			
		||||
            std::size_t const s = cfg->TimeRange.size();
 | 
			
		||||
            for (std::size_t id = 1; id <= s; ++id) {
 | 
			
		||||
                int const step = Utilities::getTimeRangeStep(cfg, id, paymentMethodId);
 | 
			
		||||
                m_timeSteps.append(step);
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            uint16_t timeStepCompensation = 0;
 | 
			
		||||
 | 
			
		||||
        if (pop_carry_over) {
 | 
			
		||||
            int const pop_carry_over_time_range_id = cfg->getPaymentOptions().pop_carry_over_time_range_id;
 | 
			
		||||
            QTime const carryOverTimeRangeFrom = cfg->TimeRange.find(pop_carry_over_time_range_id)->second.time_range_from;
 | 
			
		||||
            QTime const carryOverTimeRangeTo = cfg->TimeRange.find(pop_carry_over_time_range_id)->second.time_range_to;
 | 
			
		||||
            if (pop_carry_over) {
 | 
			
		||||
                int const pop_carry_over_time_range_id = cfg->getPaymentOptions().pop_carry_over_time_range_id;
 | 
			
		||||
                QTime const carryOverTimeRangeFrom = cfg->TimeRange.find(pop_carry_over_time_range_id)->second.time_range_from;
 | 
			
		||||
                QTime const carryOverTimeRangeTo = cfg->TimeRange.find(pop_carry_over_time_range_id)->second.time_range_to;
 | 
			
		||||
 | 
			
		||||
            if (carryOverTimeRangeFrom.secsTo(carryOverTimeRangeTo) <= 60) { // carry over time point, usually 00:00:00
 | 
			
		||||
                if (carryOverTimeRangeFrom == QTime(0, 0, 0)) {
 | 
			
		||||
                    for (auto[itr, rangeEnd] = cfg->PaymentRate.equal_range(pop_id); itr != rangeEnd; ++itr) {
 | 
			
		||||
                        int const durationId = itr->second.pra_payment_unit_id;
 | 
			
		||||
                        auto search = cfg->Duration.find(durationId);
 | 
			
		||||
                        if (search != cfg->Duration.end()) {
 | 
			
		||||
                            ATBDuration duration = search->second;
 | 
			
		||||
                            if (durationId == 1) {
 | 
			
		||||
                                QDateTime carryOver = start;
 | 
			
		||||
                                carryOver = carryOver.addDays(1);
 | 
			
		||||
                                carryOver.setTime(QTime(0, 0, 0));
 | 
			
		||||
                if (carryOverTimeRangeFrom.secsTo(carryOverTimeRangeTo) <= 60) { // carry over time point, usually 00:00:00
 | 
			
		||||
                    if (carryOverTimeRangeFrom == QTime(0, 0, 0)) {
 | 
			
		||||
                        for (auto[itr, rangeEnd] = cfg->PaymentRate.equal_range(pop_id); itr != rangeEnd; ++itr) {
 | 
			
		||||
                            int const durationId = itr->second.pra_payment_unit_id;
 | 
			
		||||
                            auto search = cfg->Duration.find(durationId);
 | 
			
		||||
                            if (search != cfg->Duration.end()) {
 | 
			
		||||
                                ATBDuration duration = search->second;
 | 
			
		||||
                                if (durationId == 1) {
 | 
			
		||||
                                    QDateTime carryOver = start;
 | 
			
		||||
                                    carryOver = carryOver.addDays(1);
 | 
			
		||||
                                    carryOver.setTime(QTime(0, 0, 0));
 | 
			
		||||
 | 
			
		||||
                                int const timeStep = std::ceil(start.secsTo(carryOver) / 60.0);
 | 
			
		||||
                                if (timeStep < duration.pun_duration_min || timeStep > duration.pun_duration_max) {
 | 
			
		||||
                                    qCritical()
 | 
			
		||||
                                        << QString("ERROR timeStep (%1) < durationMin (%2) || timeStep (%3)) > durationMax (%4)")
 | 
			
		||||
                                            .arg(timeStep).arg(duration.pun_duration_min)
 | 
			
		||||
                                            .arg(timeStep).arg(duration.pun_duration_max);
 | 
			
		||||
                                    break;
 | 
			
		||||
                                    int const timeStep = std::ceil(start.secsTo(carryOver) / 60.0);
 | 
			
		||||
                                    if (timeStep < duration.pun_duration_min || timeStep > duration.pun_duration_max) {
 | 
			
		||||
                                        qCritical()
 | 
			
		||||
                                            << QString("ERROR timeStep (%1) < durationMin (%2) || timeStep (%3)) > durationMax (%4)")
 | 
			
		||||
                                                .arg(timeStep).arg(duration.pun_duration_min)
 | 
			
		||||
                                                .arg(timeStep).arg(duration.pun_duration_max);
 | 
			
		||||
                                        break;
 | 
			
		||||
                                    }
 | 
			
		||||
                                    qCritical() << __PRETTY_FUNCTION__ << "configured minimal parking time:" << cfg->getPaymentOptions().pop_min_time;
 | 
			
		||||
 | 
			
		||||
                                    // set dynamic minimal parking time
 | 
			
		||||
                                    cfg->getPaymentOptions().pop_min_time = timeStep;
 | 
			
		||||
 | 
			
		||||
                                    qCritical() << __PRETTY_FUNCTION__ << "  computed minimal parking time:" << cfg->getPaymentOptions().pop_min_time;
 | 
			
		||||
 | 
			
		||||
                                    duration.pun_duration = timeStep;
 | 
			
		||||
                                    timeStepCompensation = duration.pun_duration_max - duration.pun_duration;
 | 
			
		||||
                                    m_timeSteps << duration.pun_duration;
 | 
			
		||||
                                } else {
 | 
			
		||||
                                    duration.pun_duration = duration.pun_duration_max - timeStepCompensation;
 | 
			
		||||
                                    m_timeSteps << duration.pun_duration;;
 | 
			
		||||
                                }
 | 
			
		||||
                                qCritical() << __PRETTY_FUNCTION__ << "configured minimal parking time:" << cfg->getPaymentOptions().pop_min_time;
 | 
			
		||||
 | 
			
		||||
                                // set dynamic minimal parking time
 | 
			
		||||
                                cfg->getPaymentOptions().pop_min_time = timeStep;
 | 
			
		||||
                                cfg->Duration.erase(search);
 | 
			
		||||
                                cfg->Duration.insert(pair<int, ATBDuration>(duration.pun_id, duration));
 | 
			
		||||
 | 
			
		||||
                                qCritical() << __PRETTY_FUNCTION__ << "  computed minimal parking time:" << cfg->getPaymentOptions().pop_min_time;
 | 
			
		||||
 | 
			
		||||
                                duration.pun_duration = timeStep;
 | 
			
		||||
                                timeStepCompensation = duration.pun_duration_max - duration.pun_duration;
 | 
			
		||||
                                m_timeSteps << duration.pun_duration;
 | 
			
		||||
                            } else {
 | 
			
		||||
                                duration.pun_duration = duration.pun_duration_max - timeStepCompensation;
 | 
			
		||||
                                m_timeSteps << duration.pun_duration;;
 | 
			
		||||
                            } else { // if (search != cfg->Duration.end()) {
 | 
			
		||||
                               // TODO
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            cfg->Duration.erase(search);
 | 
			
		||||
                            cfg->Duration.insert(pair<int, ATBDuration>(duration.pun_id, duration));
 | 
			
		||||
 | 
			
		||||
                        } else { // if (search != cfg->Duration.end()) {
 | 
			
		||||
                           // TODO
 | 
			
		||||
                        }
 | 
			
		||||
                    } else { // if (carryOverTimeRangeFrom == QTime(0, 0, 0)) {
 | 
			
		||||
                        // TODO
 | 
			
		||||
                    }
 | 
			
		||||
                } else { // if (carryOverTimeRangeFrom == QTime(0, 0, 0)) {
 | 
			
		||||
                } else { // if (carryOverTimeRangeFrom == carryOverTimeRangeTo) {
 | 
			
		||||
                    // TODO
 | 
			
		||||
                }
 | 
			
		||||
            } else { // if (carryOverTimeRangeFrom == carryOverTimeRangeTo) {
 | 
			
		||||
            } else { // if (pop_carry_over) {
 | 
			
		||||
                // TODO
 | 
			
		||||
            }
 | 
			
		||||
        } else { // if (pop_carry_over) {
 | 
			
		||||
            // TODO
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        qCritical() << __PRETTY_FUNCTION__ << "payment option time step config:" << "TimeStepConfig::STATIC";
 | 
			
		||||
@@ -1308,6 +1450,18 @@ Calculator::GetDailyTicketPrice(Configuration* cfg,
 | 
			
		||||
                case PERMIT_TYPE::INVALID:
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            // for projects which have not defined a daily ticket in their
 | 
			
		||||
            // tariff-files (e.g. szeged)
 | 
			
		||||
            price.netto = cfg->getPaymentOptions().pop_daily_card_price;
 | 
			
		||||
 | 
			
		||||
            qCritical() << "( GetDailyTicketPrice():" << __LINE__ << ")";
 | 
			
		||||
            qCritical() << "                  start:" << startDatetime.toString(Qt::ISODate);
 | 
			
		||||
            qCritical() << "          workTime from:" << QTime::fromString(QString(wt.pwd_time_from.c_str()), Qt::ISODate);
 | 
			
		||||
            qCritical() << "            workTime to:" << QTime::fromString(QString(wt.pwd_time_to.c_str()), Qt::ISODate);
 | 
			
		||||
            qCritical() << "daily_ticket_card_price:" << price.netto;
 | 
			
		||||
 | 
			
		||||
            value = value.value_or(price);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@
 | 
			
		||||
#include "tariff_business_hours.h"
 | 
			
		||||
#include "tariff_global_defines.h"
 | 
			
		||||
#include "tariff_carryover.h"
 | 
			
		||||
#include "tariff_global_defines.h"
 | 
			
		||||
 | 
			
		||||
#include <QString>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
@@ -15,16 +16,16 @@
 | 
			
		||||
/// <inheritdoc/>
 | 
			
		||||
MemberType Configuration::IdentifyJsonMember(const char* member_name)
 | 
			
		||||
{
 | 
			
		||||
        if (strcmp(member_name, "Currency") == 0) return MemberType::CurrencyType;
 | 
			
		||||
        if (strcmp(member_name, "PaymentMethod") == 0) return MemberType::PaymentMethodType;
 | 
			
		||||
        if (strcmp(member_name, "PaymentRate") == 0) return MemberType::PaymentRateType;
 | 
			
		||||
        if (strcmp(member_name, "PaymentOption") == 0) return MemberType::PaymentOptionType;
 | 
			
		||||
        if (strcmp(member_name, "Duration") == 0) return MemberType::DurationType;
 | 
			
		||||
        //if (strcmp(member_name, "WeekDays") == 0) return MemberType::WeekDaysType;
 | 
			
		||||
        if (strcmp(member_name, "WeekDaysWorktime") == 0) return MemberType::WeekDaysWorkTimeType;
 | 
			
		||||
        if (strcmp(member_name, "SpecialDaysWorktime") == 0) return MemberType::SpecialDaysWorktimeType;
 | 
			
		||||
        if (strcmp(member_name, "SpecialDays") == 0) return MemberType::SpecialDaysType;
 | 
			
		||||
        if (strcmp(member_name, "PeriodYear") == 0) return MemberType::PeriodYearType;
 | 
			
		||||
    if (strcmp(member_name, "Currency") == 0) return MemberType::CurrencyType;
 | 
			
		||||
    if (strcmp(member_name, "PaymentMethod") == 0) return MemberType::PaymentMethodType;
 | 
			
		||||
    if (strcmp(member_name, "PaymentRate") == 0) return MemberType::PaymentRateType;
 | 
			
		||||
    if (strcmp(member_name, "PaymentOption") == 0) return MemberType::PaymentOptionType;
 | 
			
		||||
    if (strcmp(member_name, "Duration") == 0) return MemberType::DurationType;
 | 
			
		||||
    //if (strcmp(member_name, "WeekDays") == 0) return MemberType::WeekDaysType;
 | 
			
		||||
    if (strcmp(member_name, "WeekDaysWorktime") == 0) return MemberType::WeekDaysWorkTimeType;
 | 
			
		||||
    if (strcmp(member_name, "SpecialDaysWorktime") == 0) return MemberType::SpecialDaysWorktimeType;
 | 
			
		||||
    if (strcmp(member_name, "SpecialDays") == 0) return MemberType::SpecialDaysType;
 | 
			
		||||
    if (strcmp(member_name, "PeriodYear") == 0) return MemberType::PeriodYearType;
 | 
			
		||||
    if (strcmp(member_name, "DailyTicket") == 0) return MemberType::DailyTicketType;
 | 
			
		||||
    if (strcmp(member_name, "TimeBase") == 0) return MemberType::TimeBaseType;
 | 
			
		||||
    if (strcmp(member_name, "Customer") == 0) return MemberType::CustomerType;
 | 
			
		||||
@@ -42,36 +43,36 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json)
 | 
			
		||||
{
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
                if (cfg == nullptr)
 | 
			
		||||
                {
 | 
			
		||||
                        printf("TariffConfiguration pointer not set\n");
 | 
			
		||||
                        return false;
 | 
			
		||||
                }
 | 
			
		||||
                if (json == NULL)
 | 
			
		||||
                {
 | 
			
		||||
                        printf("%s", "Input JSON string is NULL\n");
 | 
			
		||||
                        return false;
 | 
			
		||||
                }
 | 
			
		||||
            if (cfg == nullptr)
 | 
			
		||||
            {
 | 
			
		||||
                    printf("TariffConfiguration pointer not set\n");
 | 
			
		||||
                    return false;
 | 
			
		||||
            }
 | 
			
		||||
            if (json == NULL)
 | 
			
		||||
            {
 | 
			
		||||
                    printf("%s", "Input JSON string is NULL\n");
 | 
			
		||||
                    return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
                // Parse JSON to document
 | 
			
		||||
                Document document;
 | 
			
		||||
                document.Parse(json);
 | 
			
		||||
            // Parse JSON to document
 | 
			
		||||
            Document document;
 | 
			
		||||
            document.Parse(json);
 | 
			
		||||
 | 
			
		||||
                // Return if parse error has been found
 | 
			
		||||
                ParseErrorCode err = document.GetParseError();
 | 
			
		||||
                if (err != 0)
 | 
			
		||||
                {
 | 
			
		||||
                        printf("%s %d (%s)\n", "Unable to parse JSON, error code:", err, GetParseError_En(err));
 | 
			
		||||
                        return false;
 | 
			
		||||
                }
 | 
			
		||||
            // Return if parse error has been found
 | 
			
		||||
            ParseErrorCode err = document.GetParseError();
 | 
			
		||||
            if (err != 0)
 | 
			
		||||
            {
 | 
			
		||||
                    printf("%s %d (%s)\n", "Unable to parse JSON, error code:", err, GetParseError_En(err));
 | 
			
		||||
                    return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
                // Validate JSON, check if it's a JSON object
 | 
			
		||||
        qCritical() << "JSON parsing has been successful";
 | 
			
		||||
            // Validate JSON, check if it's a JSON object
 | 
			
		||||
            qCritical() << "JSON parsing has been successful";
 | 
			
		||||
                if (!document.IsObject()) {
 | 
			
		||||
                        printf("%s", "Error: not a (valid) JSON object\n");
 | 
			
		||||
                        return false;
 | 
			
		||||
                }
 | 
			
		||||
        qCritical() << "Valid JSON object identified";
 | 
			
		||||
            qCritical() << "Valid JSON object identified";
 | 
			
		||||
 | 
			
		||||
                // Validate JSON, check configuration members
 | 
			
		||||
                if (!document.HasMember("Currency")
 | 
			
		||||
@@ -80,36 +81,36 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json)
 | 
			
		||||
                        || !document.HasMember("PaymentRate")
 | 
			
		||||
                        || !document.HasMember("Duration")
 | 
			
		||||
                        //|| !document.HasMember("WeekDays")
 | 
			
		||||
            //|| !document.HasMember("SpecialDaysWorktime")
 | 
			
		||||
            //|| !document.HasMember("SpecialDays")
 | 
			
		||||
            )
 | 
			
		||||
                    //|| !document.HasMember("SpecialDaysWorktime")
 | 
			
		||||
                    //|| !document.HasMember("SpecialDays")
 | 
			
		||||
                )
 | 
			
		||||
                {
 | 
			
		||||
                        printf("%s", "Error: not a valid configuration JSON\n");
 | 
			
		||||
                        return false;
 | 
			
		||||
                }
 | 
			
		||||
        qCritical() << "Valid JSON configuration identified";
 | 
			
		||||
            qCritical() << "Valid JSON configuration identified";
 | 
			
		||||
 | 
			
		||||
        ATBCurrency Currency;
 | 
			
		||||
        ATBDuration Duration;
 | 
			
		||||
        ATBPaymentMethod PaymentMethod;
 | 
			
		||||
        ATBPaymentRate PaymentRate;
 | 
			
		||||
        ATBSpecialDaysWorktime SpecialDaysWorktime;
 | 
			
		||||
        ATBSpecialDays SpecialDays;
 | 
			
		||||
        ATBWeekDays  WeekDays;
 | 
			
		||||
        ATBWeekDaysWorktime  WeekDaysWorktime;
 | 
			
		||||
        ATBPeriodYear YearPeriod;
 | 
			
		||||
        ATBDailyTicket DailyTicket;
 | 
			
		||||
        ATBTimeBase TimeBase;
 | 
			
		||||
        ATBCustomer Customer;
 | 
			
		||||
        ATBTimeRange TimeRange;
 | 
			
		||||
        ATBTimeStepConfig TimeStepConfig;
 | 
			
		||||
        ATBTariffProduct TariffProduct;
 | 
			
		||||
        ATBInterpolation TariffInterpolation;
 | 
			
		||||
        ATBPrepaid TariffPrepaidOption;
 | 
			
		||||
        ATBCarryOver TariffCarryOver;
 | 
			
		||||
            ATBCurrency Currency;
 | 
			
		||||
            ATBDuration Duration;
 | 
			
		||||
            ATBPaymentMethod PaymentMethod;
 | 
			
		||||
            ATBPaymentRate PaymentRate;
 | 
			
		||||
            ATBSpecialDaysWorktime SpecialDaysWorktime;
 | 
			
		||||
            ATBSpecialDays SpecialDays;
 | 
			
		||||
            ATBWeekDays  WeekDays;
 | 
			
		||||
            ATBWeekDaysWorktime  WeekDaysWorktime;
 | 
			
		||||
            ATBPeriodYear YearPeriod;
 | 
			
		||||
            ATBDailyTicket DailyTicket;
 | 
			
		||||
            ATBTimeBase TimeBase;
 | 
			
		||||
            ATBCustomer Customer;
 | 
			
		||||
            ATBTimeRange TimeRange;
 | 
			
		||||
            ATBTimeStepConfig TimeStepConfig;
 | 
			
		||||
            ATBTariffProduct TariffProduct;
 | 
			
		||||
            ATBInterpolation TariffInterpolation;
 | 
			
		||||
            ATBPrepaid TariffPrepaidOption;
 | 
			
		||||
            ATBCarryOver TariffCarryOver;
 | 
			
		||||
 | 
			
		||||
        MemberType mb_type = MemberType::UnknownType;
 | 
			
		||||
        this->currentPaymentOptions.clear();
 | 
			
		||||
            MemberType mb_type = MemberType::UnknownType;
 | 
			
		||||
            this->currentPaymentOptions.clear();
 | 
			
		||||
 | 
			
		||||
                // Get all JSON object members
 | 
			
		||||
                // This code should run only once (to load JSON variables into memory)
 | 
			
		||||
@@ -142,35 +143,34 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json)
 | 
			
		||||
 | 
			
		||||
            qCritical() << " -" << mb_name;
 | 
			
		||||
 | 
			
		||||
                        // Get array for each JSON object member
 | 
			
		||||
                        auto mb_array = document[mb_name].GetArray();
 | 
			
		||||
                        if (mb_array.Size() <= 0) break;
 | 
			
		||||
            // Get array for each JSON object member
 | 
			
		||||
            auto mb_array = document[mb_name].GetArray();
 | 
			
		||||
            if (mb_array.Size() <= 0) break;
 | 
			
		||||
 | 
			
		||||
                        //Iterate over provided array
 | 
			
		||||
            for (rapidjson::SizeType j = 0; j < mb_array.Size(); j++)
 | 
			
		||||
                        {
 | 
			
		||||
                                // Get all inner objects, don't print name if NULL
 | 
			
		||||
                                auto inner_obj = mb_array[j].GetObject();
 | 
			
		||||
                                if (inner_obj.MemberCount() <= 0) break;
 | 
			
		||||
            for (rapidjson::SizeType j = 0; j < mb_array.Size(); j++) {
 | 
			
		||||
                // Get all inner objects, don't print name if NULL
 | 
			
		||||
                auto inner_obj = mb_array[j].GetObject();
 | 
			
		||||
                if (inner_obj.MemberCount() <= 0) break;
 | 
			
		||||
 | 
			
		||||
                                // Iterate over inner object JSON members
 | 
			
		||||
                                for (auto k = inner_obj.MemberBegin(); k != inner_obj.MemberEnd(); k++)
 | 
			
		||||
                                {
 | 
			
		||||
                                        // Get inner object JSON member, don't print name if NULL
 | 
			
		||||
                                        const char* inner_obj_name = k->name.GetString();
 | 
			
		||||
                                        if (inner_obj_name == NULL)
 | 
			
		||||
                                        {
 | 
			
		||||
                                                printf("Inner object name is NULL\n");
 | 
			
		||||
                                                continue;
 | 
			
		||||
                                        }
 | 
			
		||||
                // Iterate over inner object JSON members
 | 
			
		||||
                for (auto k = inner_obj.MemberBegin(); k != inner_obj.MemberEnd(); k++)
 | 
			
		||||
                {
 | 
			
		||||
                    // Get inner object JSON member, don't print name if NULL
 | 
			
		||||
                    const char* inner_obj_name = k->name.GetString();
 | 
			
		||||
                    if (inner_obj_name == NULL)
 | 
			
		||||
                    {
 | 
			
		||||
                            printf("Inner object name is NULL\n");
 | 
			
		||||
                            continue;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                                        // Identify member type
 | 
			
		||||
                                        mb_type = IdentifyJsonMember(mb_name);
 | 
			
		||||
                    // Identify member type
 | 
			
		||||
                    mb_type = IdentifyJsonMember(mb_name);
 | 
			
		||||
 | 
			
		||||
                                        switch (mb_type)
 | 
			
		||||
                                        {
 | 
			
		||||
                                        case MemberType::UnknownType:
 | 
			
		||||
                                                break;
 | 
			
		||||
                    switch (mb_type)
 | 
			
		||||
                    {
 | 
			
		||||
                    case MemberType::UnknownType:
 | 
			
		||||
                        break;
 | 
			
		||||
                    case MemberType::CarryOverType: {
 | 
			
		||||
                        if (QString(inner_obj_name) == QString("carry_over_id")) {
 | 
			
		||||
                            if (k->value.IsInt()) {
 | 
			
		||||
@@ -196,6 +196,11 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json)
 | 
			
		||||
                                                    TariffCarryOver.carryover[day].day = day;
 | 
			
		||||
                                                }
 | 
			
		||||
                                            } else
 | 
			
		||||
                                            if (member == "carry_over_duration") {
 | 
			
		||||
                                                if (w->value.IsInt()) {
 | 
			
		||||
                                                    TariffCarryOver.carryover[day].duration = w->value.GetInt();
 | 
			
		||||
                                                }
 | 
			
		||||
                                            } else
 | 
			
		||||
                                            if (member == "carry_over_seemless") {
 | 
			
		||||
                                                if (w->value.IsBool()) {
 | 
			
		||||
                                                    bool b = w->value.GetBool();
 | 
			
		||||
@@ -330,6 +335,18 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json)
 | 
			
		||||
                                int const x = k->value.GetInt();
 | 
			
		||||
                                TariffInterpolation.dynamic_until_price = x;
 | 
			
		||||
                            }
 | 
			
		||||
                        } else
 | 
			
		||||
                        if (QString(inner_obj_name) == QString("interpol_seemless")) {
 | 
			
		||||
                            if (k->value.IsBool()) {
 | 
			
		||||
                                bool const x = k->value.GetBool();
 | 
			
		||||
                                TariffInterpolation.seemless = x;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        if (QString(inner_obj_name) == QString("interpol_never")) {
 | 
			
		||||
                            if (k->value.IsBool()) {
 | 
			
		||||
                                bool const x = k->value.GetBool();
 | 
			
		||||
                                TariffInterpolation.never = x;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    } break;
 | 
			
		||||
                    case MemberType::ProductType: {
 | 
			
		||||
@@ -543,22 +560,22 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json)
 | 
			
		||||
                        }
 | 
			
		||||
                        break;
 | 
			
		||||
                    case MemberType::CurrencyType:
 | 
			
		||||
                                                if (strcmp(inner_obj_name, "pcu_id") == 0) Currency.pcu_id = k->value.GetInt();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "pcu_sign") == 0) Currency.pcu_sign = k->value.GetString();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "pcu_major") == 0) Currency.pcu_major = k->value.GetString();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "pcu_minor") == 0) Currency.pcu_minor = k->value.GetString();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "pcu_active") == 0) Currency.pcu_active = k->value.GetBool();
 | 
			
		||||
                                                break;
 | 
			
		||||
                                        case MemberType::PaymentMethodType:
 | 
			
		||||
                                                if (strcmp(inner_obj_name, "pme_id") == 0) PaymentMethod.pme_id = k->value.GetInt();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "pme_label") == 0) PaymentMethod.pme_label = k->value.GetString();
 | 
			
		||||
                                                break;
 | 
			
		||||
                                        case MemberType::PaymentRateType:
 | 
			
		||||
                                                if (strcmp(inner_obj_name, "pra_payment_option_id") == 0) PaymentRate.pra_payment_option_id = k->value.GetInt();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "pra_payment_unit_id") == 0) PaymentRate.pra_payment_unit_id = k->value.GetInt();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "pra_price") == 0) PaymentRate.pra_price = k->value.GetDouble();
 | 
			
		||||
                                                break;
 | 
			
		||||
                                        case MemberType::PaymentOptionType:
 | 
			
		||||
                        if (strcmp(inner_obj_name, "pcu_id") == 0) Currency.pcu_id = k->value.GetInt();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pcu_sign") == 0) Currency.pcu_sign = k->value.GetString();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pcu_major") == 0) Currency.pcu_major = k->value.GetString();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pcu_minor") == 0) Currency.pcu_minor = k->value.GetString();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pcu_active") == 0) Currency.pcu_active = k->value.GetBool();
 | 
			
		||||
                        break;
 | 
			
		||||
                    case MemberType::PaymentMethodType:
 | 
			
		||||
                        if (strcmp(inner_obj_name, "pme_id") == 0) PaymentMethod.pme_id = k->value.GetInt();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pme_label") == 0) PaymentMethod.pme_label = k->value.GetString();
 | 
			
		||||
                        break;
 | 
			
		||||
                    case MemberType::PaymentRateType:
 | 
			
		||||
                        if (strcmp(inner_obj_name, "pra_payment_option_id") == 0) PaymentRate.pra_payment_option_id = k->value.GetInt();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pra_payment_unit_id") == 0) PaymentRate.pra_payment_unit_id = k->value.GetInt();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pra_price") == 0) PaymentRate.pra_price = k->value.GetDouble();
 | 
			
		||||
                        break;
 | 
			
		||||
                    case MemberType::PaymentOptionType:
 | 
			
		||||
                        if (strcmp(inner_obj_name, "pop_id") == 0) {
 | 
			
		||||
                            this->currentPaymentOptions.append(ATBPaymentOption());
 | 
			
		||||
                            this->currentPaymentOptions.last().reset();
 | 
			
		||||
@@ -583,6 +600,8 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json)
 | 
			
		||||
                            this->currentPaymentOptions.last().pop_min_price = k->value.GetDouble();
 | 
			
		||||
                        } else if (strcmp(inner_obj_name, "pop_prepaid_option_id") == 0) {
 | 
			
		||||
                            this->currentPaymentOptions.last().pop_prepaid_option_id = k->value.GetInt();
 | 
			
		||||
                        } else if (strcmp(inner_obj_name, "pop_truncate_last_interpolation_step") == 0) {
 | 
			
		||||
                            this->currentPaymentOptions.last().pop_truncate_last_interpolation_step = k->value.GetBool();
 | 
			
		||||
                        } else if (strcmp(inner_obj_name, "pop_carry_over_option_id") == 0) {
 | 
			
		||||
                            this->currentPaymentOptions.last().pop_carry_over_option_id = k->value.GetInt();
 | 
			
		||||
                        } else if (strcmp(inner_obj_name, "pop_carry_over") == 0) {
 | 
			
		||||
@@ -665,93 +684,92 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json)
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        break;
 | 
			
		||||
                                        case MemberType::DurationType:
 | 
			
		||||
                                                if (strcmp(inner_obj_name, "pun_id") == 0) Duration.pun_id = k->value.GetInt();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "pun_label") == 0) Duration.pun_label = k->value.GetString();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "pun_duration") == 0) Duration.pun_duration = k->value.GetDouble();
 | 
			
		||||
                    case MemberType::DurationType:
 | 
			
		||||
                        if (strcmp(inner_obj_name, "pun_id") == 0) Duration.pun_id = k->value.GetInt();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pun_label") == 0) Duration.pun_label = k->value.GetString();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pun_duration") == 0) Duration.pun_duration = k->value.GetDouble();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pun_duration_min") == 0) Duration.pun_duration_min = k->value.GetInt();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pun_duration_max") == 0) Duration.pun_duration_max = k->value.GetInt();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pun_interpolation_id") == 0) Duration.pun_interpolation_id = k->value.GetInt();
 | 
			
		||||
                        break;
 | 
			
		||||
                                        case MemberType::SpecialDaysWorktimeType:
 | 
			
		||||
                                                if (strcmp(inner_obj_name, "pedwt_id") == 0) SpecialDaysWorktime.pedwt_id = k->value.GetInt();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "pedwt_period_exc_day_id") == 0) SpecialDaysWorktime.pedwt_period_exc_day_id = k->value.GetInt();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "pedwt_time_from") == 0) SpecialDaysWorktime.pedwt_time_from = k->value.GetString();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "pedwt_time_to") == 0) SpecialDaysWorktime.pedwt_time_to = k->value.GetString();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "pedwt_price") == 0) SpecialDaysWorktime.pedwt_price = k->value.GetDouble();
 | 
			
		||||
                                                break;
 | 
			
		||||
                                        /*case MemberType::WeekDaysType:
 | 
			
		||||
                                                if (strcmp(inner_obj_name, "pdiw_id") == 0) WeekDays.pdiw_id = k->value.GetInt();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "pdiw_label") == 0) WeekDays.pdiw_label = k->value.GetString();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "pdiw_index") == 0) WeekDays.pdiw_index = k->value.GetInt();
 | 
			
		||||
                                                break;*/
 | 
			
		||||
                                        case MemberType::WeekDaysWorkTimeType:
 | 
			
		||||
                                                if (strcmp(inner_obj_name, "pwd_id") == 0) WeekDaysWorktime.pwd_id = k->value.GetInt();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "pwd_period_week_day_id") == 0) WeekDaysWorktime.pwd_period_week_day_id = k->value.GetInt();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "pwd_period_day_in_week_id") == 0) WeekDaysWorktime.pwd_period_day_in_week_id = k->value.GetInt();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "pwd_time_from") == 0) WeekDaysWorktime.pwd_time_from = k->value.GetString();
 | 
			
		||||
                     case MemberType::SpecialDaysWorktimeType:
 | 
			
		||||
                        if (strcmp(inner_obj_name, "pedwt_id") == 0) SpecialDaysWorktime.pedwt_id = k->value.GetInt();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pedwt_period_exc_day_id") == 0) SpecialDaysWorktime.pedwt_period_exc_day_id = k->value.GetInt();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pedwt_time_from") == 0) SpecialDaysWorktime.pedwt_time_from = k->value.GetString();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pedwt_time_to") == 0) SpecialDaysWorktime.pedwt_time_to = k->value.GetString();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pedwt_price") == 0) SpecialDaysWorktime.pedwt_price = k->value.GetDouble();
 | 
			
		||||
                        break;
 | 
			
		||||
                /*case MemberType::WeekDaysType:
 | 
			
		||||
                        if (strcmp(inner_obj_name, "pdiw_id") == 0) WeekDays.pdiw_id = k->value.GetInt();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pdiw_label") == 0) WeekDays.pdiw_label = k->value.GetString();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pdiw_index") == 0) WeekDays.pdiw_index = k->value.GetInt();
 | 
			
		||||
                        break;*/
 | 
			
		||||
                     case MemberType::WeekDaysWorkTimeType:
 | 
			
		||||
                        if (strcmp(inner_obj_name, "pwd_id") == 0) WeekDaysWorktime.pwd_id = k->value.GetInt();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pwd_period_week_day_id") == 0) WeekDaysWorktime.pwd_period_week_day_id = k->value.GetInt();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pwd_period_day_in_week_id") == 0) WeekDaysWorktime.pwd_period_day_in_week_id = k->value.GetInt();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pwd_time_from") == 0) WeekDaysWorktime.pwd_time_from = k->value.GetString();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pwd_time_to") == 0) WeekDaysWorktime.pwd_time_to = k->value.GetString();
 | 
			
		||||
                        break;
 | 
			
		||||
                                        case MemberType::SpecialDaysType:
 | 
			
		||||
                                                if (strcmp(inner_obj_name, "ped_id") == 0) SpecialDays.ped_id = k->value.GetInt();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "ped_label") == 0) SpecialDays.ped_label = k->value.GetString();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "ped_date_start") == 0) SpecialDays.ped_date_start = k->value.GetString();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "ped_date_end") == 0) SpecialDays.ped_date_end = k->value.GetString();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "ped_period_special_day_id") == 0) SpecialDays.ped_period_special_day_id = k->value.GetInt();
 | 
			
		||||
                     case MemberType::SpecialDaysType:
 | 
			
		||||
                        if (strcmp(inner_obj_name, "ped_id") == 0) SpecialDays.ped_id = k->value.GetInt();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "ped_label") == 0) SpecialDays.ped_label = k->value.GetString();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "ped_date_start") == 0) SpecialDays.ped_date_start = k->value.GetString();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "ped_date_end") == 0) SpecialDays.ped_date_end = k->value.GetString();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "ped_period_special_day_id") == 0) SpecialDays.ped_period_special_day_id = k->value.GetInt();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "ped_payment_option_id") == 0) SpecialDays.ped_payment_option_id = k->value.GetInt();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "ped_year") == 0) SpecialDays.ped_year = k->value.GetInt();
 | 
			
		||||
                                                break;
 | 
			
		||||
                                        case MemberType::PeriodYearType:
 | 
			
		||||
                                                if (strcmp(inner_obj_name, "pye_id") == 0) YearPeriod.pye_id = k->value.GetInt();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "pye_label") == 0) YearPeriod.pye_label = k->value.GetString();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "pye_start_month") == 0) YearPeriod.pye_start_month = k->value.GetInt();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "pye_start_day") == 0) YearPeriod.pye_start_day = k->value.GetInt();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "pye_end_month") == 0) YearPeriod.pye_end_month = k->value.GetInt();
 | 
			
		||||
                                                else if (strcmp(inner_obj_name, "pye_end_day") == 0) YearPeriod.pye_end_day = k->value.GetInt();
 | 
			
		||||
                                                break;
 | 
			
		||||
                                        default:
 | 
			
		||||
                                                break;
 | 
			
		||||
                                        }
 | 
			
		||||
                        break;
 | 
			
		||||
                     case MemberType::PeriodYearType:
 | 
			
		||||
                        if (strcmp(inner_obj_name, "pye_id") == 0) YearPeriod.pye_id = k->value.GetInt();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pye_label") == 0) YearPeriod.pye_label = k->value.GetString();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pye_start_month") == 0) YearPeriod.pye_start_month = k->value.GetInt();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pye_start_day") == 0) YearPeriod.pye_start_day = k->value.GetInt();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pye_end_month") == 0) YearPeriod.pye_end_month = k->value.GetInt();
 | 
			
		||||
                        else if (strcmp(inner_obj_name, "pye_end_day") == 0) YearPeriod.pye_end_day = k->value.GetInt();
 | 
			
		||||
                        break;
 | 
			
		||||
                    default:
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
//#pragma endregion
 | 
			
		||||
                                }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                                // Push to specific list depending on member type
 | 
			
		||||
                                switch (mb_type)
 | 
			
		||||
                                {
 | 
			
		||||
                                case MemberType::UnknownType:
 | 
			
		||||
                                        break;
 | 
			
		||||
                switch (mb_type) {
 | 
			
		||||
                case MemberType::UnknownType:
 | 
			
		||||
                    break;
 | 
			
		||||
                case MemberType::PaymentMethodType:
 | 
			
		||||
                                        cfg->PaymentMethod.insert(pair<int, ATBPaymentMethod>(PaymentMethod.pme_id, PaymentMethod));
 | 
			
		||||
                                        break;
 | 
			
		||||
                    cfg->PaymentMethod.insert(pair<int, ATBPaymentMethod>(PaymentMethod.pme_id, PaymentMethod));
 | 
			
		||||
                    break;
 | 
			
		||||
                case MemberType::PaymentRateType:
 | 
			
		||||
                    // qCritical() << "PaymentRate" << PaymentRate;
 | 
			
		||||
                    // qCritical() << "PaymentRate" << PaymentRate.pra_price << PaymentRate.pra_payment_option_id;
 | 
			
		||||
                    cfg->PaymentRate.insert(pair<int, ATBPaymentRate>(PaymentRate.pra_payment_option_id, PaymentRate));
 | 
			
		||||
                                        break;
 | 
			
		||||
                    break;
 | 
			
		||||
                case MemberType::PaymentOptionType: {
 | 
			
		||||
                    if (!this->currentPaymentOptions.isEmpty()) {
 | 
			
		||||
                        ATBPaymentOption const &PaymentOption = this->currentPaymentOptions.last();
 | 
			
		||||
                        cfg->PaymentOption.insert(pair<int, ATBPaymentOption>(PaymentOption.pop_payment_method_id, PaymentOption));
 | 
			
		||||
                    }
 | 
			
		||||
                } break;
 | 
			
		||||
                                case MemberType::DurationType:
 | 
			
		||||
                case MemberType::DurationType:
 | 
			
		||||
                                        cfg->Duration.insert(pair<int, ATBDuration>(Duration.pun_id, Duration));
 | 
			
		||||
                    // qCritical() << Duration;
 | 
			
		||||
                    break;
 | 
			
		||||
                                case MemberType::SpecialDaysWorktimeType:
 | 
			
		||||
                                        cfg->SpecialDaysWorktime.insert(pair<int, ATBSpecialDaysWorktime>(SpecialDaysWorktime.pedwt_period_exc_day_id, SpecialDaysWorktime));
 | 
			
		||||
                                        break;
 | 
			
		||||
                case MemberType::SpecialDaysWorktimeType:
 | 
			
		||||
                    cfg->SpecialDaysWorktime.insert(pair<int, ATBSpecialDaysWorktime>(SpecialDaysWorktime.pedwt_period_exc_day_id, SpecialDaysWorktime));
 | 
			
		||||
                    break;
 | 
			
		||||
                                //case MemberType::WeekDaysType:
 | 
			
		||||
                                //      cfg->WeekDays.insert(pair<int, ATBWeekDays>(WeekDays.pdiw_index, WeekDays));
 | 
			
		||||
                                //      break;
 | 
			
		||||
                                case MemberType::WeekDaysWorkTimeType:
 | 
			
		||||
                                        cfg->WeekDaysWorktime.insert(pair<int, ATBWeekDaysWorktime>(WeekDaysWorktime.pwd_period_day_in_week_id, WeekDaysWorktime));
 | 
			
		||||
                                        break;
 | 
			
		||||
                                case MemberType::SpecialDaysType:
 | 
			
		||||
                                        cfg->SpecialDays.insert(pair<int, ATBSpecialDays>(SpecialDays.ped_id, SpecialDays));
 | 
			
		||||
                                        break;
 | 
			
		||||
                                case MemberType::PeriodYearType:
 | 
			
		||||
                                        cfg->YearPeriod.insert(pair<int, ATBPeriodYear>(YearPeriod.pye_id, YearPeriod));
 | 
			
		||||
                                        break;
 | 
			
		||||
                case MemberType::WeekDaysWorkTimeType:
 | 
			
		||||
                    cfg->WeekDaysWorktime.insert(pair<int, ATBWeekDaysWorktime>(WeekDaysWorktime.pwd_period_day_in_week_id, WeekDaysWorktime));
 | 
			
		||||
                    break;
 | 
			
		||||
                case MemberType::SpecialDaysType:
 | 
			
		||||
                    cfg->SpecialDays.insert(pair<int, ATBSpecialDays>(SpecialDays.ped_id, SpecialDays));
 | 
			
		||||
                    break;
 | 
			
		||||
                case MemberType::PeriodYearType:
 | 
			
		||||
                    cfg->YearPeriod.insert(pair<int, ATBPeriodYear>(YearPeriod.pye_id, YearPeriod));
 | 
			
		||||
                    break;
 | 
			
		||||
                case MemberType::DailyTicketType:
 | 
			
		||||
                    cfg->DailyTicket.insert(pair<int, ATBDailyTicket>(DailyTicket.daily_ticket_id, DailyTicket));
 | 
			
		||||
                    qCritical() << DailyTicket;
 | 
			
		||||
@@ -790,18 +808,136 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json)
 | 
			
		||||
                    qCritical() << TariffCarryOver;
 | 
			
		||||
                    break;
 | 
			
		||||
                default:
 | 
			
		||||
                                        break;
 | 
			
		||||
                                }
 | 
			
		||||
                        }
 | 
			
		||||
                     break;
 | 
			
		||||
                }
 | 
			
		||||
                return true;
 | 
			
		||||
        }
 | 
			
		||||
        catch (...) {
 | 
			
		||||
                printf("%s\n", "General exception has occurred while parsing JSON\n");
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    catch (...) {
 | 
			
		||||
        printf("%s\n", "General exception has occurred while parsing JSON\n");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::optional<QDateTime> Configuration::getInterpolationEnd(QDateTime const &start, int paymentOptionIndex) const {
 | 
			
		||||
    int const pop_id = getPaymentOptions(paymentOptionIndex).pop_id;
 | 
			
		||||
    int const pop_carry_over_option_id = getPaymentOptions(paymentOptionIndex).pop_carry_over_option_id;
 | 
			
		||||
    int const pop_truncate_last_interpolation_step = getPaymentOptions(paymentOptionIndex).pop_truncate_last_interpolation_step;
 | 
			
		||||
    int const weekDay = start.date().dayOfWeek();
 | 
			
		||||
    //QTime const &carryOverStart = TariffCarryOverOptions.find(pop_carry_over_option_id)->second.carryover[weekDay].static_start;
 | 
			
		||||
    //QTime const &carryOverEnd = TariffCarryOverOptions.find(pop_carry_over_option_id)->second.carryover[weekDay].static_end;
 | 
			
		||||
    //bool const carry_over_seemless = TariffCarryOverOptions.find(pop_carry_over_option_id)->second.carryover[weekDay].seemless;
 | 
			
		||||
    //bool const carry_over_never = TariffCarryOverOptions.find(pop_carry_over_option_id)->second.carryover[weekDay].never;
 | 
			
		||||
    int const carryOverDuration  = TariffCarryOverOptions.find(pop_carry_over_option_id)->second.carryover[weekDay].duration;
 | 
			
		||||
 | 
			
		||||
    std::optional<QDateTime> value = std::nullopt;
 | 
			
		||||
 | 
			
		||||
    QDateTime interpolationEndTime = start;
 | 
			
		||||
 | 
			
		||||
    int price = 0;
 | 
			
		||||
 | 
			
		||||
    for (auto[itr, rangeEnd] = PaymentRate.equal_range(pop_id); itr != rangeEnd; ++itr) {
 | 
			
		||||
        int const durationId = itr->second.pra_payment_unit_id;
 | 
			
		||||
        // int const price = itr->second.pra_price;
 | 
			
		||||
 | 
			
		||||
        auto search = Duration.find(durationId);
 | 
			
		||||
        if (search != Duration.end()) {
 | 
			
		||||
            ATBDuration duration = search->second;
 | 
			
		||||
 | 
			
		||||
            if (duration.pun_interpolation_id == -1) {
 | 
			
		||||
                // should never happen -> misconfigured tariff-file
 | 
			
		||||
                qCritical() << "(" << __func__ << ":" << __LINE__ << ") ERROR pun_interpolation not set!";
 | 
			
		||||
                qCritical() << "(" << __func__ << ":" << __LINE__ << ") See for instance customer_505/6";
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            std::optional<ATBInterpolation> ipolCheck = getInterpolationType(duration.pun_interpolation_id);
 | 
			
		||||
            if (ipolCheck) {
 | 
			
		||||
                ATBInterpolation interpolation = ipolCheck.value();
 | 
			
		||||
                switch (duration.pun_interpolation_id) {
 | 
			
		||||
                    case static_cast<int>(ATBInterpolation::NO_INTERPOLATION):
 | 
			
		||||
                        //qCritical() << "(" << __func__ << ":" << __LINE__ << ") TODO";
 | 
			
		||||
                    break;
 | 
			
		||||
                    case static_cast<int>(ATBInterpolation::STATIC_WALLCLOCK_TIME_VALUES):
 | 
			
		||||
                        //qCritical() << "(" << __func__ << ":" << __LINE__ << ") TODO";
 | 
			
		||||
                    break;
 | 
			
		||||
                    case static_cast<int>(ATBInterpolation::STATIC_TIMEPOINT_AND_DURATION):
 | 
			
		||||
                        //qCritical() << "(" << __func__ << ":" << __LINE__ << ") TODO";
 | 
			
		||||
                    break;
 | 
			
		||||
                    case static_cast<int>(ATBInterpolation::DYNAMIC_TIMEPOINT_AND_STATIC_DURATION):
 | 
			
		||||
                        //qCritical() << "(" << __func__ << ":" << __LINE__ << ") TODO";
 | 
			
		||||
                    break;
 | 
			
		||||
                    case static_cast<int>(ATBInterpolation::DYNAMIC_ABSTRACT_TIMEPOINT_AND_STATIC_DURATION):
 | 
			
		||||
                        //qCritical() << "(" << __func__ << ":" << __LINE__ << ") TODO";
 | 
			
		||||
                    break;
 | 
			
		||||
                    case static_cast<int>(ATBInterpolation::DYNAMIC_ABSTRACT_TIMEPOINT_AND_STATIC_PRICE): {
 | 
			
		||||
                        interpolation.dynamic_start = start.time();
 | 
			
		||||
                        interpolation.dynamic_start.setHMS(start.time().hour(), start.time().minute(), 0);
 | 
			
		||||
 | 
			
		||||
                        //qCritical() << "(" << __func__ << ":" << __LINE__ << ")               interpol start:" << interpolation.dynamic_start.toString(Qt::ISODate);
 | 
			
		||||
                        //qCritical() << "(" << __func__ << ":" << __LINE__ << ") computed interpol end so far:" << interpolationEndTime.toString(Qt::ISODate);
 | 
			
		||||
 | 
			
		||||
                        if (interpolation.seemless) {
 | 
			
		||||
                            qCritical() << "(" << __func__ << ":" << __LINE__ << ") TODO";
 | 
			
		||||
                        } else
 | 
			
		||||
                        if (interpolation.never) {
 | 
			
		||||
                            qCritical() << "(" << __func__ << ":" << __LINE__ << ") TODO";
 | 
			
		||||
                        } else {
 | 
			
		||||
                            QDateTime const &s = interpolationEndTime.addSecs(duration.pun_duration * 60);
 | 
			
		||||
                            int const minutesToStaticEnd = s.time().secsTo(interpolation.static_end) / 60;
 | 
			
		||||
 | 
			
		||||
                            //qCritical() << "(" << __func__ << ":" << __LINE__ << ") computed interpol end so far:" << s.toString(Qt::ISODate);
 | 
			
		||||
                            //qCritical() << "(" << __func__ << ":" << __LINE__ << ")          interpol static end:" << interpolation.static_end.toString(Qt::ISODate);
 | 
			
		||||
                            //qCritical() << "(" << __func__ << ":" << __LINE__ << ")        minutes to static end:" << minutesToStaticEnd;
 | 
			
		||||
                            //qCritical() << "(" << __func__ << ":" << __LINE__ << ")                       pun-id:" << duration.pun_id;
 | 
			
		||||
 | 
			
		||||
                            int p = 0;
 | 
			
		||||
                            for (auto[it, rangeEnd] = this->PaymentRate.equal_range(pop_id); it != rangeEnd; ++it) {
 | 
			
		||||
                                if (it->second.pra_payment_unit_id == duration.pun_id) {
 | 
			
		||||
                                    if (minutesToStaticEnd >= 0) {
 | 
			
		||||
                                        // the end of the interpolation for this day must be before a possible carry over interval
 | 
			
		||||
                                        p = it->second.pra_price;
 | 
			
		||||
                                        //qCritical() << "(" << __func__ << ":" << __LINE__ << ")                   next price:" << p;
 | 
			
		||||
                                        price += p;
 | 
			
		||||
                                        interpolationEndTime = s;
 | 
			
		||||
                                    } else {
 | 
			
		||||
                                        if (pop_truncate_last_interpolation_step == false) {
 | 
			
		||||
                                            p = it->second.pra_price;
 | 
			
		||||
                                            //qCritical() << "(" << __func__ << ":" << __LINE__ << ")                   next price:" << p;
 | 
			
		||||
                                            price += p;
 | 
			
		||||
                                            interpolationEndTime = s;
 | 
			
		||||
                                            interpolationEndTime = interpolationEndTime.addSecs(carryOverDuration * 60);
 | 
			
		||||
                                        } else {
 | 
			
		||||
                                            qCritical() << "(" << __func__ << ":" << __LINE__ << ") TODO";
 | 
			
		||||
                                        }
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            //qCritical() << "(" << __func__ << ":" << __LINE__ << ")                        price:" << price;
 | 
			
		||||
 | 
			
		||||
                            if (price >= interpolation.dynamic_until_price) {
 | 
			
		||||
                                qCritical() << "(" << __func__ << ":" << __LINE__ << ")                        price:" << price;
 | 
			
		||||
                                qCritical() << "(" << __func__ << ":" << __LINE__ << ")       computed interpol endr:" << interpolationEndTime.toString(Qt::ISODate);
 | 
			
		||||
                                value = value.value_or(interpolationEndTime);
 | 
			
		||||
                                break;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
                    case static_cast<int>(ATBInterpolation::DYNAMIC_ABSTRACT_TIMEPOINT_AND_STATIC_END_TIME):
 | 
			
		||||
                    break;
 | 
			
		||||
                    default:;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int Configuration::getPaymentOptionIndexIfSpecialDay(QDateTime const &dt) const {
 | 
			
		||||
    if (isSpecialDay(dt)) {
 | 
			
		||||
        int const numOptions = getAllPaymentOptions().size();
 | 
			
		||||
@@ -1043,23 +1179,27 @@ std::optional<ATBPrepaid> Configuration::getPrepaidType(int key) const {
 | 
			
		||||
    return value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::optional<QDateTime> Configuration::adaptStart(QDateTime const &start, int prepaid_option_id) {
 | 
			
		||||
std::optional<QDateTime> Configuration::prepaidStart(QDateTime const &start, int prepaid_option_id) {
 | 
			
		||||
    std::optional<QDateTime> value;
 | 
			
		||||
    QDateTime s = start;
 | 
			
		||||
 | 
			
		||||
    qCritical() << "(" << __func__ << ":" << __LINE__ << ")         prepaid option id:" << prepaid_option_id;
 | 
			
		||||
 | 
			
		||||
    std::optional<ATBPrepaid> prepaid_option = getPrepaidType(prepaid_option_id);
 | 
			
		||||
    if (prepaid_option.has_value()) {
 | 
			
		||||
        ATBPrepaid prepaid = prepaid_option.value();
 | 
			
		||||
        if (prepaid.anytime == true) {
 | 
			
		||||
            int const weekdayId = s.date().dayOfWeek();
 | 
			
		||||
            QTime worktime_from = QTime::fromString(WeekDaysWorktime.find(weekdayId)->second.pwd_time_from.c_str(), Qt::ISODate);
 | 
			
		||||
            QTime worktime_to = QTime::fromString(WeekDaysWorktime.find(weekdayId)->second.pwd_time_to.c_str(), Qt::ISODate);
 | 
			
		||||
            if (s.time() < worktime_from) {
 | 
			
		||||
                s.setTime(worktime_from);
 | 
			
		||||
 | 
			
		||||
        if (prepaid.anytime == false && prepaid.never == false) {
 | 
			
		||||
            // start: 22:00, end: 08:00
 | 
			
		||||
            QTime prepaidStart = TariffPrepaidOptions.find(prepaid_option_id)->second.static_start;
 | 
			
		||||
            QTime prepaidEnd = TariffPrepaidOptions.find(prepaid_option_id)->second.static_end;
 | 
			
		||||
 | 
			
		||||
            if (s.time() >= prepaidStart) {
 | 
			
		||||
                s = s.addDays(1);
 | 
			
		||||
                s.setTime(prepaidEnd);
 | 
			
		||||
            } else
 | 
			
		||||
            if (worktime_to < s.time()) {
 | 
			
		||||
                s = start.addDays(1);
 | 
			
		||||
                s.setTime(worktime_from);
 | 
			
		||||
            if (s.time() < prepaidEnd) {
 | 
			
		||||
                s.setTime(prepaidEnd);
 | 
			
		||||
            }
 | 
			
		||||
            s.setTime(QTime(s.time().hour(), s.time().minute(), 0));
 | 
			
		||||
            value = value.value_or(s);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								library/src/tariff_global_defines.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								library/src/tariff_global_defines.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
#include "tariff_global_defines.h"
 | 
			
		||||
 | 
			
		||||
int DBG_LEVEL = DBG_NOTICE;
 | 
			
		||||
// int DBG_LEVEL = DBG_INFORMATION;
 | 
			
		||||
// int DBG_LEVEL = DBG_DEBUG;
 | 
			
		||||
		Reference in New Issue
	
	Block a user