Compare commits
	
		
			53 Commits
		
	
	
		
			Neuhauser-
			...
			bad-neuena
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| aba38d2614 | |||
| 57d6b85f52 | |||
| 4f9c0422fc | |||
| a5b95d71b8 | |||
| fcbc8dcdc3 | |||
| ed99bae725 | |||
| 627d14204d | |||
| 
						
						
							
						
						d8a4c4eaa7
	
				 | 
					
					
						|||
| 4f45db4fde | |||
| a744a1ebb3 | |||
| df16bd7f9c | |||
| b751ba339e | |||
| 
						
						
							
						
						588a88455b
	
				 | 
					
					
						|||
| 
						
						
							
						
						92bfdced6a
	
				 | 
					
					
						|||
| 8bbec596c9 | |||
| 87b14ee3f8 | |||
| 3ad2c77467 | |||
| 493d94aaa1 | |||
| 7831329b11 | |||
| abbbd06f93 | |||
| ac6e45a913 | |||
| b741d2e312 | |||
| 6756aa5b88 | |||
| 7845ab8077 | |||
| cc222c298a | |||
| eb645273cc | |||
| bd1bdf8a8c | |||
| 6d18ce4caa | |||
| e980d8c451 | |||
| afb0e20dd2 | |||
| 39ab08a5b7 | |||
| c4c0e2fd77 | |||
| 7a5487aa41 | |||
| a8c1caf611 | |||
| a22145002c | |||
| 7b7dd6d103 | |||
| 1c801f1053 | |||
| 56fc95e33c | |||
| c0f81f174a | |||
| 6ba3963f25 | |||
| 1a350c0aeb | |||
| 15801be88e | |||
| 20e146d3c9 | |||
| 30768c6931 | |||
| 7933c826e6 | |||
| 9d5ddfc328 | |||
| 102607b71f | |||
| 81d515eb7f | |||
| ce61e5d3b2 | |||
| b6a0f5e8af | |||
| e0223b50f9 | |||
| 690267c388 | |||
| 9c19414e5a | 
@@ -18,6 +18,8 @@
 | 
			
		||||
#define CALCULATE_LIBRARY_API
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "tariff_permit_type.h"
 | 
			
		||||
 | 
			
		||||
class Configuration;
 | 
			
		||||
 | 
			
		||||
typedef Configuration parking_tariff_t;
 | 
			
		||||
@@ -39,17 +41,6 @@ struct CALCULATE_LIBRARY_API price_t {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum class PERMIT_TYPE : quint8 {
 | 
			
		||||
    SHORT_TERM_PARKING,
 | 
			
		||||
    DAY_TICKET,
 | 
			
		||||
    SZEGED_START,
 | 
			
		||||
    SZEGED_STOP,
 | 
			
		||||
    DAY_TICKET_ADULT,
 | 
			
		||||
    DAY_TICKET_TEEN,
 | 
			
		||||
    DAY_TICKET_CHILD,
 | 
			
		||||
    INVALID
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct CALCULATE_LIBRARY_API CalcState {
 | 
			
		||||
    enum class State : uint8_t {
 | 
			
		||||
        SUCCESS,
 | 
			
		||||
@@ -93,6 +84,51 @@ struct CALCULATE_LIBRARY_API CalcState {
 | 
			
		||||
        return (m_status == State::SUCCESS);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QString toString() {
 | 
			
		||||
        QString s;
 | 
			
		||||
        switch (m_status) {
 | 
			
		||||
        case State::SUCCESS:
 | 
			
		||||
            s = "SUCCESS";
 | 
			
		||||
            break;
 | 
			
		||||
        case State::ERROR_PARSING_ZONE_NR:
 | 
			
		||||
            s = "ERROR_PARSING_ZONE_NR";
 | 
			
		||||
            break;
 | 
			
		||||
        case State::ERROR_LOADING_TARIFF:
 | 
			
		||||
            s = "ERROR_LOADING_TARIFF";
 | 
			
		||||
            break;
 | 
			
		||||
        case State::ERROR_PARSING_TARIFF:
 | 
			
		||||
            s = "ERROR_PARSING_TARIFF";
 | 
			
		||||
            break;
 | 
			
		||||
        case State::NEGATIVE_PARING_TIME:
 | 
			
		||||
            s = "NEGATIVE_PARKING_TIME";
 | 
			
		||||
           break;
 | 
			
		||||
        case State::ABOVE_MAX_PARKING_TIME:
 | 
			
		||||
            s = "ABOVE_MAX_PARKING_TIME";
 | 
			
		||||
            break;
 | 
			
		||||
        case State::WRONG_PARAM_VALUES:
 | 
			
		||||
            s = "WRONG_PARAM_VALUES";
 | 
			
		||||
            break;
 | 
			
		||||
        case State::BELOW_MIN_PARKING_TIME:
 | 
			
		||||
            s = "BELOW_MIN_PARKING_TIME";
 | 
			
		||||
            break;
 | 
			
		||||
        case State::BELOW_MIN_PARKING_PRICE:
 | 
			
		||||
            s = "BELOW_MIN_PARKING_PRICE";
 | 
			
		||||
            break;
 | 
			
		||||
        case State::OVERPAID:
 | 
			
		||||
            s = "OVERPAID";
 | 
			
		||||
            break;
 | 
			
		||||
        case State::INVALID_START_DATE:
 | 
			
		||||
            s = "INVALID_START_DATE";
 | 
			
		||||
            break;
 | 
			
		||||
        case State::WRONG_ISO_TIME_FORMAT:
 | 
			
		||||
            s = "WRONG_ISO_TIME_FORMAT";
 | 
			
		||||
            break;
 | 
			
		||||
        case State::OUTSIDE_ALLOWED_PARKING_TIME:
 | 
			
		||||
            s = "OUTSIDE_ALLOWED_PARKING_TIME";
 | 
			
		||||
        }
 | 
			
		||||
        return s + ":" + m_desc;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    explicit operator QString () const noexcept {
 | 
			
		||||
        QString s;
 | 
			
		||||
        switch (m_status) {
 | 
			
		||||
@@ -139,6 +175,8 @@ struct CALCULATE_LIBRARY_API CalcState {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    CalcState &set(State s) { m_status = s; return *this; }
 | 
			
		||||
    CalcState &setStatus(State s) { return set(s); }
 | 
			
		||||
    State getStatus() const { return m_status; }
 | 
			
		||||
    CalcState &setDesc(QString s) { m_desc = s; return *this; }
 | 
			
		||||
 | 
			
		||||
    void setAllowedTimeRange(QTime const &from, QTime const &until) {
 | 
			
		||||
@@ -162,6 +200,7 @@ int CALCULATE_LIBRARY_API get_minimal_parkingtime(Configuration *cfg, PERMIT_TYP
 | 
			
		||||
int CALCULATE_LIBRARY_API get_maximal_parkingtime(Configuration *cfg, PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING);
 | 
			
		||||
int CALCULATE_LIBRARY_API get_minimal_parkingprice(Configuration *cfg, PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING);
 | 
			
		||||
int CALCULATE_LIBRARY_API get_maximal_parkingprice(Configuration *cfg, PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING);
 | 
			
		||||
int CALCULATE_LIBRARY_API compute_product_price(Configuration const *cfg, PERMIT_TYPE permitType = PERMIT_TYPE::SHORT_TERM_PARKING);
 | 
			
		||||
 | 
			
		||||
CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(       // deprecated
 | 
			
		||||
                                            parking_tariff_t *tariff,
 | 
			
		||||
@@ -174,7 +213,8 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
 | 
			
		||||
                                            QDateTime &start_parking_time,
 | 
			
		||||
                                            int netto_parking_time,
 | 
			
		||||
                                            QDateTime &end_parking_time,    // return value
 | 
			
		||||
                                            struct price_t *price);         // return value
 | 
			
		||||
                                            struct price_t *price,          // return value
 | 
			
		||||
                                            bool prepaid = true);
 | 
			
		||||
 | 
			
		||||
CalcState CALCULATE_LIBRARY_API compute_duration_for_parking_ticket(        // deprecated
 | 
			
		||||
                                            parking_tariff_t *tariff,
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,7 @@
 | 
			
		||||
#include "tariff_daily_ticket.h"
 | 
			
		||||
#include "time_range_header.h"
 | 
			
		||||
#include "tariff_timestep_config.h"
 | 
			
		||||
#include "tariff_product.h"
 | 
			
		||||
 | 
			
		||||
#include <QVector>
 | 
			
		||||
#include <optional>
 | 
			
		||||
@@ -53,6 +54,7 @@ public:
 | 
			
		||||
    multimap<int, ATBTimeStepConfig> TimeStepConfig;
 | 
			
		||||
    multimap<int, ATBTimeBase> TimeBase;
 | 
			
		||||
    multimap<int, ATBCustomer> Customer;
 | 
			
		||||
    multimap<int, ATBTariffProduct> TariffProduct;
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Parse JSON string
 | 
			
		||||
@@ -69,6 +71,9 @@ public:
 | 
			
		||||
    std::optional<QVector<ATBPaymentRate>> getPaymentRateForKey(int key) const;
 | 
			
		||||
    std::optional<QVector<ATBDailyTicket>> getDailyTicketsForAllKeys() const;
 | 
			
		||||
    std::optional<QVector<ATBDailyTicket>> getDailyTicketsForKey(int key) const;
 | 
			
		||||
    std::optional<QVector<ATBTariffProduct>> getTariffProductForAllKeys() const;
 | 
			
		||||
    std::optional<QVector<ATBTariffProduct>> getTariffProductForProductId(int id) const;
 | 
			
		||||
    std::optional<QVector<ATBTariffProduct>> getTariffProductForProductId(PermitType permitType) const;
 | 
			
		||||
    std::optional<ATBCustomer> getCustomerForType(ATBCustomer::CustomerType customerType);
 | 
			
		||||
    std::optional<ATBWeekDaysWorktime> getWeekDayWorkTime(QTime const &time, Qt::DayOfWeek dayOfWeek);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,8 @@ enum MemberType
 | 
			
		||||
    CustomerType = 0x0B,
 | 
			
		||||
    TimeBaseType = 0x0C,
 | 
			
		||||
    TimeRangeType = 0x0D,
 | 
			
		||||
    TimeStepConfigType = 0x0E
 | 
			
		||||
    TimeStepConfigType = 0x0E,
 | 
			
		||||
    ProductType = 0x0F
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // MEMBER_TYPE_H_INCLUDED
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										133
									
								
								library/include/mobilisis/tariff_permit_type.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								library/include/mobilisis/tariff_permit_type.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,133 @@
 | 
			
		||||
#ifndef TARIFF_PERMIT_TYPE_H_INCLUDED
 | 
			
		||||
#define TARIFF_PERMIT_TYPE_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <QString>
 | 
			
		||||
 | 
			
		||||
enum class PERMIT_TYPE : quint8 {
 | 
			
		||||
    SHORT_TERM_PARKING,
 | 
			
		||||
    DAY_TICKET,
 | 
			
		||||
    SZEGED_START,
 | 
			
		||||
    SZEGED_STOP,
 | 
			
		||||
    DAY_TICKET_ADULT,
 | 
			
		||||
    DAY_TICKET_TEEN,
 | 
			
		||||
    DAY_TICKET_CHILD,
 | 
			
		||||
    FOOD_STAMP,
 | 
			
		||||
    INVALID
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct PermitType {
 | 
			
		||||
    PERMIT_TYPE m_permitType;
 | 
			
		||||
 | 
			
		||||
    PermitType() { m_permitType = PERMIT_TYPE::INVALID; }
 | 
			
		||||
    PermitType(int permitType) {
 | 
			
		||||
        switch(permitType) {
 | 
			
		||||
        case 0:
 | 
			
		||||
            m_permitType = PERMIT_TYPE::SHORT_TERM_PARKING;
 | 
			
		||||
            break;
 | 
			
		||||
        case 1:
 | 
			
		||||
            m_permitType = PERMIT_TYPE::DAY_TICKET;
 | 
			
		||||
            break;
 | 
			
		||||
        case 2:
 | 
			
		||||
            m_permitType = PERMIT_TYPE::SZEGED_START;
 | 
			
		||||
            break;
 | 
			
		||||
        case 3:
 | 
			
		||||
            m_permitType = PERMIT_TYPE::SZEGED_STOP;
 | 
			
		||||
            break;
 | 
			
		||||
        case 4:
 | 
			
		||||
            m_permitType = PERMIT_TYPE::DAY_TICKET_ADULT;
 | 
			
		||||
            break;
 | 
			
		||||
        case 5:
 | 
			
		||||
            m_permitType = PERMIT_TYPE::DAY_TICKET_TEEN;
 | 
			
		||||
            break;
 | 
			
		||||
        case 6:
 | 
			
		||||
            m_permitType = PERMIT_TYPE::DAY_TICKET_CHILD;
 | 
			
		||||
            break;
 | 
			
		||||
        case 7:
 | 
			
		||||
            m_permitType = PERMIT_TYPE::FOOD_STAMP;
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            m_permitType = PERMIT_TYPE::INVALID;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    PermitType(PERMIT_TYPE permitType) : m_permitType(permitType) {}
 | 
			
		||||
 | 
			
		||||
    void set(PERMIT_TYPE p) { m_permitType = p; }
 | 
			
		||||
    PERMIT_TYPE get() const { return m_permitType; }
 | 
			
		||||
 | 
			
		||||
    operator PERMIT_TYPE() const { return m_permitType; }
 | 
			
		||||
 | 
			
		||||
    operator int () const {
 | 
			
		||||
        switch(m_permitType) {
 | 
			
		||||
        case PERMIT_TYPE::SHORT_TERM_PARKING:
 | 
			
		||||
            return 0;
 | 
			
		||||
        case PERMIT_TYPE::DAY_TICKET:
 | 
			
		||||
            return 1;
 | 
			
		||||
        case PERMIT_TYPE::SZEGED_START:
 | 
			
		||||
            return 2;
 | 
			
		||||
        case PERMIT_TYPE::SZEGED_STOP:
 | 
			
		||||
            return 3;
 | 
			
		||||
        case PERMIT_TYPE::DAY_TICKET_ADULT:
 | 
			
		||||
            return 4;
 | 
			
		||||
        case PERMIT_TYPE::DAY_TICKET_CHILD:
 | 
			
		||||
            return 5;
 | 
			
		||||
        case PERMIT_TYPE::DAY_TICKET_TEEN:
 | 
			
		||||
            return 6;
 | 
			
		||||
        case PERMIT_TYPE::FOOD_STAMP:
 | 
			
		||||
            return 7;
 | 
			
		||||
        default:
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        return 7;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    operator QString () {
 | 
			
		||||
        switch(m_permitType) {
 | 
			
		||||
        case PERMIT_TYPE::DAY_TICKET:
 | 
			
		||||
            return QString("DAY_TICKET");
 | 
			
		||||
        case PERMIT_TYPE::DAY_TICKET_ADULT:
 | 
			
		||||
            return QString("DAY_TICKET_ADULT");
 | 
			
		||||
        case PERMIT_TYPE::DAY_TICKET_CHILD:
 | 
			
		||||
            return QString("DAY_TICKET_CHILD");
 | 
			
		||||
        case PERMIT_TYPE::DAY_TICKET_TEEN:
 | 
			
		||||
            return QString("DAY_TICKET_TEEN");
 | 
			
		||||
        case PERMIT_TYPE::SHORT_TERM_PARKING:
 | 
			
		||||
            return QString("SHORT_TERM_PARKING");
 | 
			
		||||
        case PERMIT_TYPE::SZEGED_START:
 | 
			
		||||
            return QString("SZEGED_START");
 | 
			
		||||
        case PERMIT_TYPE::SZEGED_STOP:
 | 
			
		||||
            return QString("SZEGED_STOP");
 | 
			
		||||
        case PERMIT_TYPE::FOOD_STAMP:
 | 
			
		||||
            return QString("FOOD_STAMP");
 | 
			
		||||
        default:
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        return QString("INVALID");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    operator QString () const {
 | 
			
		||||
        switch(m_permitType) {
 | 
			
		||||
        case PERMIT_TYPE::DAY_TICKET:
 | 
			
		||||
            return QString("DAY_TICKET");
 | 
			
		||||
        case PERMIT_TYPE::DAY_TICKET_ADULT:
 | 
			
		||||
            return QString("DAY_TICKET_ADULT");
 | 
			
		||||
        case PERMIT_TYPE::DAY_TICKET_CHILD:
 | 
			
		||||
            return QString("DAY_TICKET_CHILD");
 | 
			
		||||
        case PERMIT_TYPE::DAY_TICKET_TEEN:
 | 
			
		||||
            return QString("DAY_TICKET_TEEN");
 | 
			
		||||
        case PERMIT_TYPE::SHORT_TERM_PARKING:
 | 
			
		||||
            return QString("SHORT_TERM_PARKING");
 | 
			
		||||
        case PERMIT_TYPE::SZEGED_START:
 | 
			
		||||
            return QString("SZEGED_START");
 | 
			
		||||
        case PERMIT_TYPE::SZEGED_STOP:
 | 
			
		||||
            return QString("SZEGED_STOP");
 | 
			
		||||
        case PERMIT_TYPE::FOOD_STAMP:
 | 
			
		||||
            return QString("FOOD_STAMP");
 | 
			
		||||
        default:
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        return QString("INVALID");
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // TARIFF_PERMIT_TYPE_H_INCLUDED
 | 
			
		||||
							
								
								
									
										64
									
								
								library/include/mobilisis/tariff_product.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								library/include/mobilisis/tariff_product.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,64 @@
 | 
			
		||||
#ifndef TARIFF_PRODUCT_H_INCLUDED
 | 
			
		||||
#define TARIFF_PRODUCT_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <QString>
 | 
			
		||||
#include <QDateTime>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QDebugStateSaver>
 | 
			
		||||
 | 
			
		||||
#include "tariff_permit_type.h"
 | 
			
		||||
 | 
			
		||||
struct ATBTariffProduct {
 | 
			
		||||
    PermitType m_tariff_product_id;
 | 
			
		||||
    uint32_t m_tariff_product_price;
 | 
			
		||||
    QString m_tariff_product_name;
 | 
			
		||||
    QTime m_tariff_product_start;
 | 
			
		||||
    QTime m_tariff_product_end;
 | 
			
		||||
    int m_tariff_product_from_in_minutes_from_start;
 | 
			
		||||
    int m_tariff_product_to_in_minutes_from_start;
 | 
			
		||||
 | 
			
		||||
    explicit ATBTariffProduct() = default;
 | 
			
		||||
 | 
			
		||||
    QTime const &getTimeStart() const { return m_tariff_product_start; }
 | 
			
		||||
    QTime const &getTimeEnd() const { return m_tariff_product_end; }
 | 
			
		||||
 | 
			
		||||
    bool computeQTimeStart(QTime const &t) {
 | 
			
		||||
        if (m_tariff_product_from_in_minutes_from_start != -1) {
 | 
			
		||||
            m_tariff_product_start = t.addSecs(m_tariff_product_from_in_minutes_from_start * 60);
 | 
			
		||||
            return m_tariff_product_start.isValid();
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool computeQTimeEnd(QTime const &t) {
 | 
			
		||||
        if (m_tariff_product_to_in_minutes_from_start != -1) {
 | 
			
		||||
            m_tariff_product_end = t.addSecs(m_tariff_product_from_in_minutes_from_start * 60);
 | 
			
		||||
            return m_tariff_product_end.isValid();
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool computeQTimes(QTime const &t) {
 | 
			
		||||
        if (!t.isNull() && t.isValid()) {
 | 
			
		||||
            return computeQTimeStart(t) && computeQTimeEnd(t);
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    friend QDebug operator<<(QDebug debug, ATBTariffProduct const &product) {
 | 
			
		||||
        QDebugStateSaver saver(debug);
 | 
			
		||||
 | 
			
		||||
        debug.nospace()
 | 
			
		||||
            << "                        m_tariff_product_id: " << QString(product.m_tariff_product_id) << "\n"
 | 
			
		||||
            << "                      m_tariff_product_name: " << product.m_tariff_product_name << "\n"
 | 
			
		||||
            << "                     m_tariff_product_price: " << product.m_tariff_product_price << "\n"
 | 
			
		||||
            << "                     m_tariff_product_start: " << product.m_tariff_product_start << "\n"
 | 
			
		||||
            << "                       m_tariff_product_end: " << product.m_tariff_product_end << "\n"
 | 
			
		||||
            << "m_tariff_product_from_in_minutes_from_start: " << product.m_tariff_product_from_in_minutes_from_start << "\n"
 | 
			
		||||
            << "  m_tariff_product_to_in_minutes_from_start: " << product.m_tariff_product_to_in_minutes_from_start << "\n";
 | 
			
		||||
 | 
			
		||||
        return debug;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // TARIFF_PRODUCT_H_INCLUDED
 | 
			
		||||
@@ -90,6 +90,7 @@ namespace Utilities {
 | 
			
		||||
    uint32_t getMinimalParkingPrice(Configuration const *cfg, PaymentMethod methodId);
 | 
			
		||||
    uint32_t getMaximalParkingPrice(Configuration const *cfg, PaymentMethod methodId);
 | 
			
		||||
    uint32_t getFirstDurationStep(Configuration const *cfg, PaymentMethod methodId);
 | 
			
		||||
    uint32_t getTimeRangeStep(Configuration const *cfg, int step, PaymentMethod methodId);
 | 
			
		||||
    BusinessHours getBusinessHours(Configuration const *cfg, PaymentMethod methodId);
 | 
			
		||||
    uint32_t computeWeekDaysPrice(Configuration const *cfg, PaymentMethod id);
 | 
			
		||||
    double computeWeekDaysDurationUnit(Configuration const *cfg, PaymentMethod id);
 | 
			
		||||
 
 | 
			
		||||
@@ -77,7 +77,9 @@ HEADERS += \
 | 
			
		||||
    include/mobilisis/tariff_daily_ticket.h \
 | 
			
		||||
    include/mobilisis/tariff_customer.h \
 | 
			
		||||
    include/mobilisis/tariff_timebase.h \
 | 
			
		||||
    include/mobilisis/tariff_timestep_config.h
 | 
			
		||||
    include/mobilisis/tariff_timestep_config.h \
 | 
			
		||||
    include/mobilisis/tariff_product.h \
 | 
			
		||||
    include/mobilisis/tariff_permit_type.h
 | 
			
		||||
 | 
			
		||||
OTHER_FILES += src/main.cpp \
 | 
			
		||||
    ../tariffs/tariff_korneuburg.json \
 | 
			
		||||
 
 | 
			
		||||
@@ -76,21 +76,69 @@ int CALCULATE_LIBRARY_API get_minimal_parkingprice(Configuration *cfg, PERMIT_TY
 | 
			
		||||
    return minPrice;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int CALCULATE_LIBRARY_API get_maximal_parkingprice(Configuration *cfg, PERMIT_TYPE permitType) {
 | 
			
		||||
    int maxPrice = -1;
 | 
			
		||||
int CALCULATE_LIBRARY_API compute_product_price(Configuration const *cfg, PERMIT_TYPE permitType) {
 | 
			
		||||
 | 
			
		||||
    switch(permitType) {
 | 
			
		||||
    case PERMIT_TYPE::SHORT_TERM_PARKING: { // e.g. szeged (customer_281)
 | 
			
		||||
    } break;
 | 
			
		||||
    case PERMIT_TYPE::DAY_TICKET_CHILD:
 | 
			
		||||
        // [[fallthrough]];
 | 
			
		||||
    case PERMIT_TYPE::DAY_TICKET_TEEN:
 | 
			
		||||
        // [[fallthrough]];
 | 
			
		||||
    case PERMIT_TYPE::FOOD_STAMP:
 | 
			
		||||
        // [[fallthrough]];
 | 
			
		||||
    case PERMIT_TYPE::DAY_TICKET_ADULT: {
 | 
			
		||||
        std::optional<QVector<ATBTariffProduct>> products = cfg->getTariffProductForProductId(permitType);
 | 
			
		||||
        if (products) {
 | 
			
		||||
            QVector<ATBTariffProduct> product = products.value();
 | 
			
		||||
            if (product.size() > 0) {
 | 
			
		||||
                ATBTariffProduct const &p = product[0];
 | 
			
		||||
                return p.m_tariff_product_price;
 | 
			
		||||
#if 0
 | 
			
		||||
                // in case we do not have prepaid-option
 | 
			
		||||
                QTime const ¤tTime = QDateTime::currentDateTime().time();
 | 
			
		||||
 | 
			
		||||
                if (p.m_tariff_product_start <= currentTime && currentTime <= p.m_tariff_product_end) {
 | 
			
		||||
                    return p.m_tariff_product_price;
 | 
			
		||||
                } else {
 | 
			
		||||
                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                << "ERROR currentTime"
 | 
			
		||||
                                << currentTime.toString(Qt::ISODate)
 | 
			
		||||
                                << "INVALID ("
 | 
			
		||||
                                << p.m_tariff_product_start.toString(Qt::ISODate)
 | 
			
		||||
                                << p.m_tariff_product_end.toString(Qt::ISODate) << ")";
 | 
			
		||||
                }
 | 
			
		||||
#endif
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    } break;
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int CALCULATE_LIBRARY_API get_maximal_parkingprice(Configuration *cfg, PERMIT_TYPE permitType) {
 | 
			
		||||
    int maxPrice = -1;
 | 
			
		||||
    static const PaymentMethod paymentMethodId = Utilities::getPaymentMethodId(cfg);
 | 
			
		||||
 | 
			
		||||
    switch(permitType) {
 | 
			
		||||
    case PERMIT_TYPE::SHORT_TERM_PARKING: { // e.g. szeged (customer_281)
 | 
			
		||||
        if (paymentMethodId == PaymentMethod::Progressive || paymentMethodId == PaymentMethod::Steps) {
 | 
			
		||||
            maxPrice = Utilities::getMaximalParkingPrice(cfg, paymentMethodId);
 | 
			
		||||
        } else { // PaymentMethod::Linear -> e.g. szeged
 | 
			
		||||
            int const key = cfg->getPaymentOptions().pop_id;
 | 
			
		||||
            int const maxTime = cfg->getPaymentOptions().pop_max_time; // maxTime is given in minutes
 | 
			
		||||
            std::optional<QVector<ATBPaymentRate>> const &pv = cfg->getPaymentRateForKey(key);
 | 
			
		||||
            if (pv) {
 | 
			
		||||
                QVector<ATBPaymentRate> const &paymentRate = pv.value();
 | 
			
		||||
                if (paymentRate.size() > 0) {
 | 
			
		||||
                int const price = paymentRate.at(0).pra_price; // price is given per hour
 | 
			
		||||
                    int const price = paymentRate.last().pra_price; // price is given per hour
 | 
			
		||||
                    maxPrice = qRound((maxTime * price) / 60.0f);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    } break;
 | 
			
		||||
    case PERMIT_TYPE::DAY_TICKET_ADULT:
 | 
			
		||||
        break;
 | 
			
		||||
@@ -217,7 +265,9 @@ int CALCULATE_LIBRARY_API compute_next_timestep(parking_tariff_t *tariff, int cu
 | 
			
		||||
 | 
			
		||||
    // use tariff with structure as for instance Schnau, Koenigsee:
 | 
			
		||||
    // without given YearPeriod, SpecialDays and SpecialDaysWorktime
 | 
			
		||||
    if (paymentMethodId == PaymentMethod::Steps)
 | 
			
		||||
    if ((paymentMethodId == PaymentMethod::Steps) ||
 | 
			
		||||
        // progressive tariff: e.g. Neuhauser, Kirchdorf (743)
 | 
			
		||||
        (paymentMethodId == PaymentMethod::Progressive))
 | 
			
		||||
    {
 | 
			
		||||
        const QList<int> stepList = Calculator::GetInstance().GetTimeSteps(tariff);
 | 
			
		||||
        qCritical() << "   compute_next_timestep()     timeSteps:" << stepList;
 | 
			
		||||
@@ -345,7 +395,8 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
 | 
			
		||||
        QDateTime &start_parking_time,
 | 
			
		||||
        int netto_parking_time,
 | 
			
		||||
        QDateTime &end_parking_time,
 | 
			
		||||
        struct price_t *price)
 | 
			
		||||
        struct price_t *price,
 | 
			
		||||
        bool prepaid)
 | 
			
		||||
{
 | 
			
		||||
    CalcState calcState;
 | 
			
		||||
    double minMin = tariff->getPaymentOptions().pop_min_time;
 | 
			
		||||
@@ -377,14 +428,23 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
 | 
			
		||||
        return calcState.set(CalcState::State::SUCCESS);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    double cost = -1;
 | 
			
		||||
    if (start_parking_time.isValid()) {
 | 
			
		||||
        double cost = Calculator::GetInstance().GetCostFromDuration(
 | 
			
		||||
        if (tariff->getPaymentOptions().pop_payment_method_id == PaymentMethod::Steps) {
 | 
			
		||||
            calcState = Calculator::GetInstance().isParkingAllowed(tariff, start_parking_time);
 | 
			
		||||
            if (calcState.getStatus() == CalcState::State::OUTSIDE_ALLOWED_PARKING_TIME) {
 | 
			
		||||
                return calcState;
 | 
			
		||||
            }
 | 
			
		||||
            cost = Calculator::GetInstance().GetCostFromDuration(tariff, start_parking_time, netto_parking_time);
 | 
			
		||||
        } else {
 | 
			
		||||
            cost = Calculator::GetInstance().GetCostFromDuration(
 | 
			
		||||
                        tariff,
 | 
			
		||||
                        tariff->getPaymentOptions().pop_payment_method_id,
 | 
			
		||||
                        start_parking_time,         // starting time
 | 
			
		||||
                        end_parking_time,           // return value: end time
 | 
			
		||||
                        netto_parking_time,         // minutes, netto
 | 
			
		||||
                        false, true);
 | 
			
		||||
                        false, prepaid);
 | 
			
		||||
        }
 | 
			
		||||
        double minCost = tariff->getPaymentOptions().pop_min_price;
 | 
			
		||||
        if (cost < minCost) {
 | 
			
		||||
            calcState.setDesc(QString("minCost=%1, cost=%2").arg(minCost, cost));
 | 
			
		||||
@@ -394,8 +454,10 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
 | 
			
		||||
        // DEBUG
 | 
			
		||||
        qCritical() << "               -> calculated cost (price->netto) =  " << cost;
 | 
			
		||||
 | 
			
		||||
        price->brutto = price->vat = price->vat_percentage = 0;
 | 
			
		||||
        price->units = cost;
 | 
			
		||||
        price->netto = cost;
 | 
			
		||||
 | 
			
		||||
    } else {
 | 
			
		||||
        return calcState.set(CalcState::State::INVALID_START_DATE);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -157,6 +157,17 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
 | 
			
		||||
 | 
			
		||||
        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)");
 | 
			
		||||
@@ -170,6 +181,13 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
 | 
			
		||||
        int durationMinutes = Utilities::getMaximalParkingTime(cfg, paymentMethodId);
 | 
			
		||||
        int durationMinutesBrutto = 0;
 | 
			
		||||
 | 
			
		||||
#ifdef _DEBUG_
 | 
			
		||||
#undef _DEBUG_
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//#define _DEBUG_ 1
 | 
			
		||||
#define _DEBUG_ 0
 | 
			
		||||
 | 
			
		||||
        QDateTime current = start;
 | 
			
		||||
 | 
			
		||||
        int days = 7;
 | 
			
		||||
@@ -218,26 +236,61 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
 | 
			
		||||
        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) {
 | 
			
		||||
            QVector<ATBWeekDaysWorktime> weekDayWorkTimeRanges;
 | 
			
		||||
 | 
			
		||||
            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;
 | 
			
		||||
                weekDayWorkTimeRanges.append(itr->second); // working with vector is easier
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
                    QTime const &from = Utilities::WeekDaysWorkTimeFrom(itr);
 | 
			
		||||
                    QTime const &to = Utilities::WeekDaysWorkTimeUntil(itr);
 | 
			
		||||
            int weekDayWorkTimeIndex = 0;
 | 
			
		||||
            bool moveToNextTimeRange = false;
 | 
			
		||||
 | 
			
		||||
            // time ranges for Neuhauser-Kirchdorf (743): 30, 5, 5, ... 5
 | 
			
		||||
            auto timeRangeIt = cfg->TimeRange.cbegin();
 | 
			
		||||
            while (timeRangeIt != cfg->TimeRange.cend()) { // ; ++timeRangeIt) {
 | 
			
		||||
 | 
			
		||||
                if (weekDayWorkTimeIndex >= weekDayWorkTimeRanges.size()) {
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                << "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
 | 
			
		||||
                                << "weekDayWorkTimeRanges.size()" << weekDayWorkTimeRanges.size()
 | 
			
		||||
                                << "price" << price;
 | 
			
		||||
#endif
 | 
			
		||||
                    end_datetime = current;
 | 
			
		||||
                    return end_datetime.toString(Qt::ISODate).toStdString();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                QTime const &from = QTime::fromString(weekDayWorkTimeRanges[weekDayWorkTimeIndex].pwd_time_from.c_str(), Qt::ISODate);
 | 
			
		||||
                QTime const &to = QTime::fromString(weekDayWorkTimeRanges[weekDayWorkTimeIndex].pwd_time_to.c_str(), Qt::ISODate);
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                            << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                            << "from" << from.toString(Qt::ISODate)
 | 
			
		||||
                            << "to" << to.toString(Qt::ISODate);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                Q_ASSERT_X(from < to, __func__, "MISCONFIGURED WORK-TIMES");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                if (current.time() >= to) {
 | 
			
		||||
                        continue; // try to use next available work-time
 | 
			
		||||
                    ++weekDayWorkTimeIndex;
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                << "try to use next available work-time with"
 | 
			
		||||
                                << "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
 | 
			
		||||
                                << "price" << price;
 | 
			
		||||
#endif
 | 
			
		||||
                    // time range is not affected
 | 
			
		||||
                    continue;
 | 
			
		||||
                } else
 | 
			
		||||
                if (current.time() <= from) {
 | 
			
		||||
                    if (prepaid) {
 | 
			
		||||
@@ -247,13 +300,20 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
 | 
			
		||||
                        uint const minutesMoved = lastCurrent.secsTo(current) / 60;
 | 
			
		||||
                        durationMinutesBrutto += minutesMoved;
 | 
			
		||||
 | 
			
		||||
                            if (range == 1) {
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                        qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                    << "lastCurrent" << lastCurrent.toString(Qt::ISODate)
 | 
			
		||||
                                    << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                                    << "minutesMoved" << minutesMoved
 | 
			
		||||
                                    << "durationMinutesBrutto" << durationMinutesBrutto;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                        if (weekDayWorkTimeIndex == 0) {
 | 
			
		||||
                            start_datetime = current;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                    while (timeRangeIt != cfg->TimeRange.cend()) {
 | 
			
		||||
                ATBTimeRange timeRange = timeRangeIt->second;
 | 
			
		||||
 | 
			
		||||
                timeRange.computeQTimes(current.time());
 | 
			
		||||
@@ -261,24 +321,73 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
 | 
			
		||||
                int duration = timeRange.time_range_to_in_minutes_from_start -
 | 
			
		||||
                               timeRange.time_range_from_in_minutes_from_start;
 | 
			
		||||
 | 
			
		||||
                        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) {
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                            << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                            << "duration" << duration
 | 
			
		||||
                            << "minsUsed" << minsUsed
 | 
			
		||||
                            << "minsToCarryOver" << minsToCarryOver
 | 
			
		||||
                            << "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
 | 
			
		||||
                            << "price" << price;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                if (minsToCarryOver > 0) {  // the price for this time range
 | 
			
		||||
                                            // has been is paid already
 | 
			
		||||
                    Q_ASSERT_X(weekDayWorkTimeIndex > 0, __func__, "WRONG-WORK-TIME");
 | 
			
		||||
 | 
			
		||||
                    current = current.addSecs(minsToCarryOver*60);
 | 
			
		||||
 | 
			
		||||
                    durationMinutes -= minsToCarryOver;
 | 
			
		||||
                    durationMinutesNetto += minsToCarryOver;
 | 
			
		||||
                    durationMinutesBrutto += minsToCarryOver;
 | 
			
		||||
                                        current = current.addSecs(minsToCarryOver*60);
 | 
			
		||||
 | 
			
		||||
                    minsToCarryOver = 0;
 | 
			
		||||
                                    } else {
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                                << "duration" << duration
 | 
			
		||||
                                << "durationMinutes" << durationMinutes
 | 
			
		||||
                                << "durationMinutesNetto" << durationMinutesNetto
 | 
			
		||||
                                << "durationMinutesBrutto" << durationMinutesBrutto
 | 
			
		||||
                                << "price" << price;
 | 
			
		||||
#endif
 | 
			
		||||
                    if (price >= cost) {
 | 
			
		||||
                        end_datetime = current;
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                        qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                    << "end_datetime" << end_datetime.toString(Qt::ISODate)
 | 
			
		||||
                                    << "price" << price;
 | 
			
		||||
#endif
 | 
			
		||||
                        return end_datetime.toString(Qt::ISODate).toStdString();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (current.addSecs(duration * 60).time() <= to) {
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                                << "current.addSecs(" << duration * 60 << ")" << current.addSecs(duration*60).time().toString(Qt::ISODate)
 | 
			
		||||
                                << "duration" << duration
 | 
			
		||||
                                << "to" << to.toString(Qt::ISODate)
 | 
			
		||||
                                << "minsUsed" << minsUsed
 | 
			
		||||
                                << "minsToCarryOver" << minsToCarryOver
 | 
			
		||||
                                << "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
 | 
			
		||||
                                << "durationMinutes" << durationMinutes;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                    moveToNextTimeRange = false;
 | 
			
		||||
                    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;
 | 
			
		||||
@@ -287,58 +396,180 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
 | 
			
		||||
 | 
			
		||||
                            if (price >= cost) {
 | 
			
		||||
                                end_datetime = current;
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                        qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                    << "end_datetime" << end_datetime.toString(Qt::ISODate)
 | 
			
		||||
                                    << "price" << price;
 | 
			
		||||
#endif
 | 
			
		||||
                                return end_datetime.toString(Qt::ISODate).toStdString();
 | 
			
		||||
                            }
 | 
			
		||||
                                    }
 | 
			
		||||
 | 
			
		||||
                            // price has been updated; use next time range
 | 
			
		||||
                            moveToNextTimeRange = true;
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                            if (durationMinutes <= 0) {
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                                << "duration" << duration
 | 
			
		||||
                                << "to" << to.toString(Qt::ISODate)
 | 
			
		||||
                                << "price" << price
 | 
			
		||||
                                << "minsToCarryOver" << minsToCarryOver
 | 
			
		||||
                                << "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
 | 
			
		||||
                                << "durationMinutes" << durationMinutes
 | 
			
		||||
                                << "durationMinutesNetto" << durationMinutesNetto
 | 
			
		||||
                                << "durationMinutesBrutto" << durationMinutesBrutto;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                    if (price >= cost) {
 | 
			
		||||
                        end_datetime = current;
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                        qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                    << "end_datetime" << end_datetime.toString(Qt::ISODate)
 | 
			
		||||
                                    << "price" << price;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                        return end_datetime.toString(Qt::ISODate).toStdString();
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                            ++timeRangeIt;
 | 
			
		||||
                    if (moveToNextTimeRange) {
 | 
			
		||||
                        if (++timeRangeIt != cfg->TimeRange.cend()) {
 | 
			
		||||
                            continue;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                        } else {
 | 
			
		||||
                    // havin a new time range means that we always have a new
 | 
			
		||||
                    // work-time-range
 | 
			
		||||
                    // ++timeRangeIt;
 | 
			
		||||
 | 
			
		||||
                } else { // current.addSecs(duration * 60).time() > to
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                                << "current.addSecs(" << duration * 60 << ")" << current.addSecs(duration*60).time().toString(Qt::ISODate)
 | 
			
		||||
                                << "duration" << duration
 | 
			
		||||
                                << ", to:" << to.toString(Qt::ISODate);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                    lastCurrent = current;
 | 
			
		||||
                    current.setTime(to);
 | 
			
		||||
                            int const minsLeft = lastCurrent.secsTo(current) / 60;
 | 
			
		||||
                    minsUsed = lastCurrent.secsTo(current) / 60;
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                << "lastCurrent" << lastCurrent.toString(Qt::ISODate)
 | 
			
		||||
                                << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                                << "duration" << duration
 | 
			
		||||
                                << "to" << to.toString(Qt::ISODate)
 | 
			
		||||
                                << "minsUsed" << minsUsed
 | 
			
		||||
                                << "minsToCarryOver" << minsToCarryOver
 | 
			
		||||
                                << "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
 | 
			
		||||
                                << "durationMinutes" << durationMinutes;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                    // mod duration: possibly discard some minutes in
 | 
			
		||||
                    // the next time-range
 | 
			
		||||
                            minsToCarryOver = (durationMinutes - minsLeft) % duration;
 | 
			
		||||
                    if (duration >= minsUsed) {
 | 
			
		||||
                        minsToCarryOver = duration - minsUsed;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                            durationMinutes -= minsLeft;
 | 
			
		||||
                            durationMinutesNetto += minsLeft;
 | 
			
		||||
                            durationMinutesBrutto += minsLeft;
 | 
			
		||||
                    durationMinutes -= minsUsed;
 | 
			
		||||
                    durationMinutesNetto += minsUsed;
 | 
			
		||||
                    durationMinutesBrutto += minsUsed;
 | 
			
		||||
 | 
			
		||||
                            if (minsLeft > 0) {
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                << "lastCurrent" << lastCurrent.toString(Qt::ISODate)
 | 
			
		||||
                                << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                                << "duration" << duration
 | 
			
		||||
                                << "to" << to.toString(Qt::ISODate)
 | 
			
		||||
                                << "minsUsed" << minsUsed
 | 
			
		||||
                                << "minsToCarryOver" << minsToCarryOver
 | 
			
		||||
                                << "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
 | 
			
		||||
                                << "durationMinutes" << durationMinutes
 | 
			
		||||
                                << "price" << price;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                    moveToNextTimeRange = false;
 | 
			
		||||
 | 
			
		||||
                    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;
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                                << "end_datetime" << end_datetime.toString(Qt::ISODate)
 | 
			
		||||
                                                << "price" << price;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                                    // return end_datetime.toString(Qt::ISODate).toStdString();
 | 
			
		||||
                                }
 | 
			
		||||
 | 
			
		||||
                                // price has been updated; use next time range
 | 
			
		||||
                                moveToNextTimeRange = true;
 | 
			
		||||
                                break;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                                << "duration" << duration
 | 
			
		||||
                                << "minsUsed" << minsUsed
 | 
			
		||||
                                << "durationMinutes" << durationMinutes
 | 
			
		||||
                                << "moveToNextTimeRange" << moveToNextTimeRange
 | 
			
		||||
                                << "price" << price;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                    if (moveToNextTimeRange) {
 | 
			
		||||
                        if (++timeRangeIt != cfg->TimeRange.cend()) {
 | 
			
		||||
                            continue;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                end_datetime = start.addSecs(durationMinutesBrutto * 60);
 | 
			
		||||
                        // no valid time range left
 | 
			
		||||
                        end_datetime = current;
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                        qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                    << "end_datetime" << end_datetime.toString(Qt::ISODate)
 | 
			
		||||
                                    << "price" << price;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                        return end_datetime.toString(Qt::ISODate).toStdString();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                end_datetime = start.addSecs(durationMinutesBrutto * 60);
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                            << "start" << start.toString(Qt::ISODate)
 | 
			
		||||
                            << "end_datetime" << end_datetime.toString(Qt::ISODate)
 | 
			
		||||
                            << "final price" << std::max(price, minParkingPrice);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                return end_datetime.toString(Qt::ISODate).toStdString();
 | 
			
		||||
            } // while (timeRangeIt != cfg->TimeRange.cend()) {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                            << "INVALID END TIME";
 | 
			
		||||
#endif
 | 
			
		||||
        end_datetime = QDateTime();
 | 
			
		||||
        return end_datetime.toString(Qt::ISODate).toStdString();
 | 
			
		||||
    }
 | 
			
		||||
@@ -350,6 +581,7 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
 | 
			
		||||
    // TODO: im fehlerfall
 | 
			
		||||
    return t.getValidUntil().toString(Qt::ISODate).toStdString();
 | 
			
		||||
}
 | 
			
		||||
#undef _DEBUG_
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
@@ -473,9 +705,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;
 | 
			
		||||
            }
 | 
			
		||||
@@ -497,6 +731,13 @@ double Calculator::GetCostFromDuration(Configuration* cfg,
 | 
			
		||||
        int weekdayIdLast = -1;
 | 
			
		||||
        int durationMinutesBrutto = 0;
 | 
			
		||||
 | 
			
		||||
#ifdef _DEBUG_
 | 
			
		||||
#undef _DEBUG_
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//#define _DEBUG_ 1
 | 
			
		||||
#define _DEBUG_ 0
 | 
			
		||||
 | 
			
		||||
        QDateTime current = start;
 | 
			
		||||
 | 
			
		||||
        int days = 7;
 | 
			
		||||
@@ -527,6 +768,7 @@ double Calculator::GetCostFromDuration(Configuration* cfg,
 | 
			
		||||
 | 
			
		||||
            if (current.time() >= to) {
 | 
			
		||||
                if (carryOverNotSet) {
 | 
			
		||||
                    end_datetime = start;
 | 
			
		||||
                    return 0;
 | 
			
		||||
                } else {
 | 
			
		||||
                    QDateTime const dt = start;
 | 
			
		||||
@@ -545,26 +787,60 @@ double Calculator::GetCostFromDuration(Configuration* cfg,
 | 
			
		||||
        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) {
 | 
			
		||||
            QVector<ATBWeekDaysWorktime> weekDayWorkTimeRanges;
 | 
			
		||||
 | 
			
		||||
            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;
 | 
			
		||||
                weekDayWorkTimeRanges.append(itr->second); // working with vector is easier
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
                    QTime const &from = Utilities::WeekDaysWorkTimeFrom(itr);
 | 
			
		||||
                    QTime const &to = Utilities::WeekDaysWorkTimeUntil(itr);
 | 
			
		||||
            int weekDayWorkTimeIndex = 0;
 | 
			
		||||
            bool moveToNextTimeRange = false;
 | 
			
		||||
 | 
			
		||||
            // time ranges for Neuhauser-Kirchdorf (743): 30, 5, 5, ... 5
 | 
			
		||||
            auto timeRangeIt = cfg->TimeRange.cbegin();
 | 
			
		||||
            while (timeRangeIt != cfg->TimeRange.cend()) { // ; ++timeRangeIt) {
 | 
			
		||||
 | 
			
		||||
                if (weekDayWorkTimeIndex >= weekDayWorkTimeRanges.size()) {
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                << "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
 | 
			
		||||
                                << "weekDayWorkTimeRanges.size()" << weekDayWorkTimeRanges.size();
 | 
			
		||||
#endif
 | 
			
		||||
                    end_datetime = current;
 | 
			
		||||
                    return price;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                QTime const &from = QTime::fromString(weekDayWorkTimeRanges[weekDayWorkTimeIndex].pwd_time_from.c_str(), Qt::ISODate);
 | 
			
		||||
                QTime const &to = QTime::fromString(weekDayWorkTimeRanges[weekDayWorkTimeIndex].pwd_time_to.c_str(), Qt::ISODate);
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                            << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                            << "from" << from.toString(Qt::ISODate)
 | 
			
		||||
                            << "to" << to.toString(Qt::ISODate);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                Q_ASSERT_X(from < to, __func__, "MISCONFIGURED WORK-TIMES");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                if (current.time() >= to) {
 | 
			
		||||
                        continue; // try to use next available work-time
 | 
			
		||||
                    ++weekDayWorkTimeIndex;
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                << "try to use next available work-time with"
 | 
			
		||||
                                << "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
 | 
			
		||||
                                << "price" << price;
 | 
			
		||||
#endif
 | 
			
		||||
                    // time range is not affected
 | 
			
		||||
                    continue;
 | 
			
		||||
                } else
 | 
			
		||||
                if (current.time() <= from) {
 | 
			
		||||
                    if (prepaid) {
 | 
			
		||||
@@ -574,13 +850,20 @@ double Calculator::GetCostFromDuration(Configuration* cfg,
 | 
			
		||||
                        uint const minutesMoved = lastCurrent.secsTo(current) / 60;
 | 
			
		||||
                        durationMinutesBrutto += minutesMoved;
 | 
			
		||||
 | 
			
		||||
                            if (range == 1) {
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                        qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                    << "lastCurrent" << lastCurrent.toString(Qt::ISODate)
 | 
			
		||||
                                    << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                                    << "minutesMoved" << minutesMoved
 | 
			
		||||
                                    << "durationMinutesBrutto" << durationMinutesBrutto;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                        if (weekDayWorkTimeIndex == 0) {
 | 
			
		||||
                            start_datetime = current;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                    while (timeRangeIt != cfg->TimeRange.cend()) {
 | 
			
		||||
                ATBTimeRange timeRange = timeRangeIt->second;
 | 
			
		||||
 | 
			
		||||
                timeRange.computeQTimes(current.time());
 | 
			
		||||
@@ -588,18 +871,67 @@ double Calculator::GetCostFromDuration(Configuration* cfg,
 | 
			
		||||
                int duration = timeRange.time_range_to_in_minutes_from_start -
 | 
			
		||||
                               timeRange.time_range_from_in_minutes_from_start;
 | 
			
		||||
 | 
			
		||||
                        if (current.addSecs(duration * 60).time() <= to) {
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                            << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                            << "duration" << duration
 | 
			
		||||
                            << "minsUsed" << minsUsed
 | 
			
		||||
                            << "minsToCarryOver" << minsToCarryOver
 | 
			
		||||
                            << "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
 | 
			
		||||
                            << "price" << price;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                if (minsToCarryOver > 0) {  // the price for this time range
 | 
			
		||||
                                            // has been is paid already
 | 
			
		||||
                    Q_ASSERT_X(weekDayWorkTimeIndex > 0, __func__, "WRONG-WORK-TIME");
 | 
			
		||||
 | 
			
		||||
                    current = current.addSecs(minsToCarryOver*60);
 | 
			
		||||
 | 
			
		||||
                            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;
 | 
			
		||||
                                    } else {
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                                << "duration" << duration
 | 
			
		||||
                                << "durationMinutes" << durationMinutes
 | 
			
		||||
                                << "durationMinutesNetto" << durationMinutesNetto
 | 
			
		||||
                                << "durationMinutesBrutto" << durationMinutesBrutto;
 | 
			
		||||
#endif
 | 
			
		||||
                    if (durationMinutes <= 0) {
 | 
			
		||||
                        end_datetime = current;
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                        qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                    << "end_datetime" << end_datetime.toString(Qt::ISODate)
 | 
			
		||||
                                    << "price" << price;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                        return price;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (current.addSecs(duration * 60).time() <= to) {
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                                << "current.addSecs(" << duration * 60 << ")" << current.addSecs(duration*60).time().toString(Qt::ISODate)
 | 
			
		||||
                                << "duration" << duration
 | 
			
		||||
                                << "to" << to.toString(Qt::ISODate)
 | 
			
		||||
                                << "minsUsed" << minsUsed
 | 
			
		||||
                                << "minsToCarryOver" << minsToCarryOver
 | 
			
		||||
                                << "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
 | 
			
		||||
                                << "durationMinutes" << durationMinutes;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                    moveToNextTimeRange = false;
 | 
			
		||||
                    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;
 | 
			
		||||
@@ -607,52 +939,157 @@ double Calculator::GetCostFromDuration(Configuration* cfg,
 | 
			
		||||
                            durationMinutesBrutto += duration;
 | 
			
		||||
 | 
			
		||||
                            current = current.addSecs(duration * 60);
 | 
			
		||||
                                    }
 | 
			
		||||
 | 
			
		||||
                            // price has been updated; use next time range
 | 
			
		||||
                            moveToNextTimeRange = true;
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                                << "duration" << duration
 | 
			
		||||
                                << "to" << to.toString(Qt::ISODate)
 | 
			
		||||
                                << "price" << price
 | 
			
		||||
                                << "minsToCarryOver" << minsToCarryOver
 | 
			
		||||
                                << "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
 | 
			
		||||
                                << "durationMinutes" << durationMinutes
 | 
			
		||||
                                << "durationMinutesNetto" << durationMinutesNetto
 | 
			
		||||
                                << "durationMinutesBrutto" << durationMinutesBrutto;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                    if (durationMinutes <= 0) {
 | 
			
		||||
                        end_datetime = current;
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                << "end_datetime" << end_datetime.toString(Qt::ISODate)
 | 
			
		||||
                                << "price" << price;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                        return price;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                            ++timeRangeIt;
 | 
			
		||||
                    if (moveToNextTimeRange) {
 | 
			
		||||
                        if (++timeRangeIt != cfg->TimeRange.cend()) {
 | 
			
		||||
                            continue;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                        } else {
 | 
			
		||||
                    // havin a new time range means that we always have a new
 | 
			
		||||
                    // work-time-range
 | 
			
		||||
                    // ++timeRangeIt;
 | 
			
		||||
 | 
			
		||||
                } else { // current.addSecs(duration * 60).time() > to
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                                << "current.addSecs(" << duration * 60 << ")" << current.addSecs(duration*60).time().toString(Qt::ISODate)
 | 
			
		||||
                                << "duration" << duration
 | 
			
		||||
                                << ", to:" << to.toString(Qt::ISODate);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                    lastCurrent = current;
 | 
			
		||||
                    current.setTime(to);
 | 
			
		||||
                            int const minsLeft = lastCurrent.secsTo(current) / 60;
 | 
			
		||||
                    minsUsed = lastCurrent.secsTo(current) / 60;
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                << "lastCurrent" << lastCurrent.toString(Qt::ISODate)
 | 
			
		||||
                                << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                                << "duration" << duration
 | 
			
		||||
                                << "to" << to.toString(Qt::ISODate)
 | 
			
		||||
                                << "minsUsed" << minsUsed
 | 
			
		||||
                                << "minsToCarryOver" << minsToCarryOver
 | 
			
		||||
                                << "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
 | 
			
		||||
                                << "durationMinutes" << durationMinutes;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                    // mod duration: possibly discard some minutes in
 | 
			
		||||
                    // the next time-range
 | 
			
		||||
                            minsToCarryOver = (durationMinutes - minsLeft) % duration;
 | 
			
		||||
                    if (duration >= minsUsed) {
 | 
			
		||||
                        minsToCarryOver = duration - minsUsed;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                            durationMinutes -= minsLeft;
 | 
			
		||||
                            durationMinutesNetto += minsLeft;
 | 
			
		||||
                            durationMinutesBrutto += minsLeft;
 | 
			
		||||
                    durationMinutes -= minsUsed;
 | 
			
		||||
                    durationMinutesNetto += minsUsed;
 | 
			
		||||
                    durationMinutesBrutto += minsUsed;
 | 
			
		||||
 | 
			
		||||
                            if (minsLeft > 0) {
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                << "lastCurrent" << lastCurrent.toString(Qt::ISODate)
 | 
			
		||||
                                << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                                << "duration" << duration
 | 
			
		||||
                                << "to" << to.toString(Qt::ISODate)
 | 
			
		||||
                                << "minsUsed" << minsUsed
 | 
			
		||||
                                << "minsToCarryOver" << minsToCarryOver
 | 
			
		||||
                                << "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
 | 
			
		||||
                                << "durationMinutes" << durationMinutes
 | 
			
		||||
                                << "price" << price;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                    moveToNextTimeRange = false;
 | 
			
		||||
 | 
			
		||||
                    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;
 | 
			
		||||
 | 
			
		||||
                                // price has been updated; use next time range
 | 
			
		||||
                                moveToNextTimeRange = true;
 | 
			
		||||
                                break;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                            break;
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                                << "duration" << duration
 | 
			
		||||
                                << "minsUsed" << minsUsed
 | 
			
		||||
                                << "durationMinutes" << durationMinutes
 | 
			
		||||
                                << "moveToNextTimeRange" << moveToNextTimeRange
 | 
			
		||||
                                << "price" << price;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                    if (moveToNextTimeRange) {
 | 
			
		||||
                        if (++timeRangeIt != cfg->TimeRange.cend()) {
 | 
			
		||||
                            continue;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        // no valid time range left
 | 
			
		||||
                        end_datetime = current;
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                        qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                    << "end_datetime" << end_datetime.toString(Qt::ISODate)
 | 
			
		||||
                                    << "price" << price;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                        return price;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                end_datetime = start.addSecs(durationMinutesBrutto * 60);
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                            << "start" << start.toString(Qt::ISODate)
 | 
			
		||||
                            << "end_datetime" << end_datetime.toString(Qt::ISODate)
 | 
			
		||||
                            << "final price" << std::max(price, minParkingPrice);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                return std::max(price, minParkingPrice);
 | 
			
		||||
            }
 | 
			
		||||
            } // while (timeRangeIt != cfg->TimeRange.cend()) {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                            << "INVALID END TIME";
 | 
			
		||||
#endif
 | 
			
		||||
        end_datetime = QDateTime();
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
@@ -1145,6 +1582,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;
 | 
			
		||||
@@ -1152,6 +1591,13 @@ 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";
 | 
			
		||||
 | 
			
		||||
        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) {
 | 
			
		||||
@@ -1210,6 +1656,7 @@ QList<int> Calculator::GetTimeSteps(Configuration *cfg) const {
 | 
			
		||||
            } else { // if (pop_carry_over) {
 | 
			
		||||
                // TODO
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        qCritical() << __PRETTY_FUNCTION__ << "payment option time step config:" << "TimeStepConfig::STATIC";
 | 
			
		||||
 | 
			
		||||
@@ -1289,6 +1736,9 @@ Calculator::GetDailyTicketPrice(Configuration* cfg,
 | 
			
		||||
        if (dailyTickets) {
 | 
			
		||||
            QVector<ATBDailyTicket> const tickets = dailyTickets.value();
 | 
			
		||||
            switch (permitType) {
 | 
			
		||||
                case PERMIT_TYPE::FOOD_STAMP: {
 | 
			
		||||
                    // TODO
 | 
			
		||||
                } break;
 | 
			
		||||
                case PERMIT_TYPE::DAY_TICKET_ADULT: {
 | 
			
		||||
                    std::optional<ATBCustomer> c = cfg->getCustomerForType(ATBCustomer::CustomerType::ADULT);
 | 
			
		||||
                    if (c) {
 | 
			
		||||
@@ -1381,6 +1831,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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@
 | 
			
		||||
#include "tariff_timebase.h"
 | 
			
		||||
#include "time_range_header.h"
 | 
			
		||||
#include "tariff_timestep_config.h"
 | 
			
		||||
#include "tariff_permit_type.h"
 | 
			
		||||
 | 
			
		||||
#include <QString>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
@@ -24,6 +25,7 @@ MemberType Configuration::IdentifyJsonMember(const char* member_name)
 | 
			
		||||
    if (strcmp(member_name, "Customer") == 0) return MemberType::CustomerType;
 | 
			
		||||
    if (strcmp(member_name, "TimeRange") == 0) return MemberType::TimeRangeType;
 | 
			
		||||
    if (strcmp(member_name, "TimeStepConfig") == 0) return MemberType::TimeStepConfigType;
 | 
			
		||||
    if (strcmp(member_name, "Product") == 0) return MemberType::ProductType;
 | 
			
		||||
    else return MemberType::UnknownType;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -93,6 +95,7 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json)
 | 
			
		||||
        ATBCustomer Customer;
 | 
			
		||||
        ATBTimeRange TimeRange;
 | 
			
		||||
        ATBTimeStepConfig TimeStepConfig;
 | 
			
		||||
        ATBTariffProduct TariffProduct;
 | 
			
		||||
 | 
			
		||||
        MemberType mb_type = MemberType::UnknownType;
 | 
			
		||||
        this->currentPaymentOptions.clear();
 | 
			
		||||
@@ -157,6 +160,50 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json)
 | 
			
		||||
					{
 | 
			
		||||
					case MemberType::UnknownType:
 | 
			
		||||
						break;
 | 
			
		||||
                    case MemberType::ProductType: {
 | 
			
		||||
                        if (QString(inner_obj_name) == QString("tariff_product_id")) {
 | 
			
		||||
                            if (k->value.IsInt()) {
 | 
			
		||||
                                int const x = k->value.GetInt();
 | 
			
		||||
                                TariffProduct.m_tariff_product_id = PermitType(x);
 | 
			
		||||
                            }
 | 
			
		||||
                        } else
 | 
			
		||||
                        if (QString(inner_obj_name) == QString("tariff_product_price")) {
 | 
			
		||||
                            if (k->value.IsInt()) {
 | 
			
		||||
                                int const x = k->value.GetInt();
 | 
			
		||||
                                TariffProduct.m_tariff_product_price = x;
 | 
			
		||||
                            }
 | 
			
		||||
                        } else
 | 
			
		||||
                        if (QString(inner_obj_name) == QString("tariff_product_name")) {
 | 
			
		||||
                            if (k->value.IsString()) {
 | 
			
		||||
                                std::string const &s = k->value.GetString();
 | 
			
		||||
                                TariffProduct.m_tariff_product_name = QString::fromStdString(s);
 | 
			
		||||
                            }
 | 
			
		||||
                        } else
 | 
			
		||||
                        if (QString(inner_obj_name) == QString("tariff_product_start")) {
 | 
			
		||||
                            if (k->value.IsString()) {
 | 
			
		||||
                                std::string const &s = k->value.GetString();
 | 
			
		||||
                                TariffProduct.m_tariff_product_start = QTime::fromString(QString::fromStdString(s), Qt::ISODate);
 | 
			
		||||
                            }
 | 
			
		||||
                        } else
 | 
			
		||||
                        if (QString(inner_obj_name) == QString("tariff_product_end")) {
 | 
			
		||||
                            if (k->value.IsString()) {
 | 
			
		||||
                                std::string const &s = k->value.GetString();
 | 
			
		||||
                                TariffProduct.m_tariff_product_end = QTime::fromString(QString::fromStdString(s), Qt::ISODate);
 | 
			
		||||
                            }
 | 
			
		||||
                        } else
 | 
			
		||||
                        if (QString(inner_obj_name) == QString("tariff_product_from_in_minutes_from_start")) {
 | 
			
		||||
                            if (k->value.IsInt()) {
 | 
			
		||||
                                int const x = k->value.GetInt();
 | 
			
		||||
                                TariffProduct.m_tariff_product_from_in_minutes_from_start = x;
 | 
			
		||||
                            }
 | 
			
		||||
                        } else
 | 
			
		||||
                        if (QString(inner_obj_name) == QString("tariff_product_to_in_minutes_from_start")) {
 | 
			
		||||
                            if (k->value.IsInt()) {
 | 
			
		||||
                                int const x = k->value.GetInt();
 | 
			
		||||
                                TariffProduct.m_tariff_product_to_in_minutes_from_start = x;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    } break;
 | 
			
		||||
                    case MemberType::TimeRangeType:
 | 
			
		||||
                        if (QString(inner_obj_name) == QString("time_range_id")) {
 | 
			
		||||
                            if (k->value.IsInt()) {
 | 
			
		||||
@@ -479,6 +526,9 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json)
 | 
			
		||||
                    cfg->TimeStepConfig.insert(pair<int, ATBTimeStepConfig>(TimeStepConfig.tsconfig_id, TimeStepConfig));
 | 
			
		||||
                    // qCritical() << TimeStepConfig;
 | 
			
		||||
                    break;
 | 
			
		||||
                case MemberType::ProductType:
 | 
			
		||||
                    cfg->TariffProduct.insert(pair<int, ATBTariffProduct>(TariffProduct.m_tariff_product_id, TariffProduct));
 | 
			
		||||
                    qCritical() << TariffProduct;
 | 
			
		||||
                default:
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
@@ -492,6 +542,7 @@ bool Configuration::ParseJson(Configuration* cfg, const char* json)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ATBPaymentOption const &Configuration::getPaymentOptions() const {
 | 
			
		||||
    Q_ASSERT(!this->currentPaymentOptions.isEmpty());
 | 
			
		||||
    return this->currentPaymentOptions.at(0);
 | 
			
		||||
@@ -510,6 +561,48 @@ QVector<ATBPaymentOption> &Configuration::getAllPaymentOptions() {
 | 
			
		||||
    return this->currentPaymentOptions;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::optional<QVector<ATBTariffProduct>>
 | 
			
		||||
Configuration::getTariffProductForAllKeys() const {
 | 
			
		||||
    QVector<ATBTariffProduct> products;
 | 
			
		||||
    std::optional<QVector<ATBTariffProduct>> value;
 | 
			
		||||
 | 
			
		||||
    products.clear();
 | 
			
		||||
 | 
			
		||||
    for (std::multimap<int, ATBTariffProduct>::const_iterator it = this->TariffProduct.cbegin();
 | 
			
		||||
        it != this->TariffProduct.cend(); ++it) {
 | 
			
		||||
        products.append(it->second);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (products.size() > 0) {
 | 
			
		||||
        value = value.value_or(products);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::optional<QVector<ATBTariffProduct>>
 | 
			
		||||
Configuration::getTariffProductForProductId(PermitType permitType) const {
 | 
			
		||||
    QVector<ATBTariffProduct> products;
 | 
			
		||||
    std::optional<QVector<ATBTariffProduct>> value;
 | 
			
		||||
 | 
			
		||||
    products.clear();
 | 
			
		||||
 | 
			
		||||
    for (auto[it, rangeEnd] = this->TariffProduct.equal_range(permitType); it != rangeEnd; ++it) {
 | 
			
		||||
        products.append(it->second);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (products.size() > 0) {
 | 
			
		||||
        value = value.value_or(products);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::optional<QVector<ATBTariffProduct>>
 | 
			
		||||
Configuration::getTariffProductForProductId(int id) const {
 | 
			
		||||
    return getTariffProductForProductId(PermitType(id));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::optional<QVector<ATBDailyTicket>>
 | 
			
		||||
Configuration::getDailyTicketsForAllKeys() const {
 | 
			
		||||
    QVector<ATBDailyTicket> tickets;
 | 
			
		||||
 
 | 
			
		||||
@@ -397,6 +397,14 @@ uint32_t Utilities::getMaximalParkingPrice(Configuration const *cfg, PaymentMeth
 | 
			
		||||
    return std::max((int)cfg->PaymentOption.find(methodId)->second.pop_max_price, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t Utilities::getTimeRangeStep(Configuration const *cfg, int step, PaymentMethod methodId) {
 | 
			
		||||
    if (methodId == PaymentMethod::Progressive) {
 | 
			
		||||
        return std::max((int)cfg->TimeRange.find(step)->second.time_range_to_in_minutes_from_start, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t Utilities::getFirstDurationStep(Configuration const *cfg, PaymentMethod methodId) {
 | 
			
		||||
 | 
			
		||||
    int const popId = cfg->PaymentOption.find(methodId)->second.pop_id;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1277
									
								
								main/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										1277
									
								
								main/main.cpp
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user