Compare commits
	
		
			42 Commits
		
	
	
		
			2.1.0
			...
			neuhauser-
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						
						
							
						
						16ccb706da
	
				 | 
					
					
						|||
| 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 | 
@@ -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) {
 | 
			
		||||
@@ -162,6 +198,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 +211,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
 | 
			
		||||
@@ -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,6 +76,49 @@ int CALCULATE_LIBRARY_API get_minimal_parkingprice(Configuration *cfg, PERMIT_TY
 | 
			
		||||
    return minPrice;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
@@ -91,7 +134,7 @@ int CALCULATE_LIBRARY_API get_maximal_parkingprice(Configuration *cfg, PERMIT_TY
 | 
			
		||||
            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);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -352,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;
 | 
			
		||||
@@ -391,7 +435,7 @@ CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket(
 | 
			
		||||
                        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));
 | 
			
		||||
 
 | 
			
		||||
@@ -181,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;
 | 
			
		||||
@@ -229,137 +236,340 @@ 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();
 | 
			
		||||
 | 
			
		||||
            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) {
 | 
			
		||||
                weekDayWorkTimeRanges.append(itr->second); // working with vector is easier
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            int weekDayWorkTimeIndex = 0;
 | 
			
		||||
            bool moveToNextTimeRange = false;
 | 
			
		||||
 | 
			
		||||
            // time ranges for Neuhauser-Kirchdorf (743): 30, 5, 5, ... 5
 | 
			
		||||
            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);
 | 
			
		||||
            while (timeRangeIt != cfg->TimeRange.cend()) { // ; ++timeRangeIt) {
 | 
			
		||||
 | 
			
		||||
                for (WTIterator itr = p.first; itr != p.second; ++itr) {
 | 
			
		||||
                    ++range;
 | 
			
		||||
                if (weekDayWorkTimeIndex >= weekDayWorkTimeRanges.size()) {
 | 
			
		||||
 | 
			
		||||
                    QTime const &from = Utilities::WeekDaysWorkTimeFrom(itr);
 | 
			
		||||
                    QTime const &to = Utilities::WeekDaysWorkTimeUntil(itr);
 | 
			
		||||
#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();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                    Q_ASSERT_X(from < to, __func__, "MISCONFIGURED WORK-TIMES");
 | 
			
		||||
                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
 | 
			
		||||
 | 
			
		||||
                    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;
 | 
			
		||||
                Q_ASSERT_X(from < to, __func__, "MISCONFIGURED WORK-TIMES");
 | 
			
		||||
 | 
			
		||||
                            if (range == 1) {
 | 
			
		||||
                                start_datetime = current;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                if (current.time() >= to) {
 | 
			
		||||
                    ++weekDayWorkTimeIndex;
 | 
			
		||||
 | 
			
		||||
                    while (timeRangeIt != cfg->TimeRange.cend()) {
 | 
			
		||||
                        ATBTimeRange timeRange = timeRangeIt->second;
 | 
			
		||||
#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) {
 | 
			
		||||
                        lastCurrent = current;
 | 
			
		||||
                        current.setTime(from); // move current forward (range==1),
 | 
			
		||||
                                               // as prepaid is set
 | 
			
		||||
                        uint const minutesMoved = lastCurrent.secsTo(current) / 60;
 | 
			
		||||
                        durationMinutesBrutto += minutesMoved;
 | 
			
		||||
 | 
			
		||||
                        timeRange.computeQTimes(current.time());
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                        qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                    << "lastCurrent" << lastCurrent.toString(Qt::ISODate)
 | 
			
		||||
                                    << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                                    << "minutesMoved" << minutesMoved
 | 
			
		||||
                                    << "durationMinutesBrutto" << durationMinutesBrutto;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                        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) {
 | 
			
		||||
                                        durationMinutes -= minsToCarryOver;
 | 
			
		||||
                                        durationMinutesNetto += minsToCarryOver;
 | 
			
		||||
                                        durationMinutesBrutto += minsToCarryOver;
 | 
			
		||||
                                        current = current.addSecs(minsToCarryOver*60);
 | 
			
		||||
                                        minsToCarryOver = 0;
 | 
			
		||||
                                    } else {
 | 
			
		||||
                                        if (price >= cost) {
 | 
			
		||||
                                            end_datetime = current;
 | 
			
		||||
                                            return end_datetime.toString(Qt::ISODate).toStdString();
 | 
			
		||||
                                        }
 | 
			
		||||
 | 
			
		||||
                                        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);
 | 
			
		||||
                            int const minsUsed = lastCurrent.secsTo(current) / 60;
 | 
			
		||||
 | 
			
		||||
                            // mod duration: possibly discard some minutes in
 | 
			
		||||
                            // the next time-range
 | 
			
		||||
                            minsToCarryOver = (durationMinutes - minsUsed) % duration;
 | 
			
		||||
 | 
			
		||||
                            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;
 | 
			
		||||
                        if (weekDayWorkTimeIndex == 0) {
 | 
			
		||||
                            start_datetime = current;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                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 _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;
 | 
			
		||||
 | 
			
		||||
                    minsToCarryOver = 0;
 | 
			
		||||
 | 
			
		||||
#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;
 | 
			
		||||
 | 
			
		||||
                            current = current.addSecs(duration * 60);
 | 
			
		||||
 | 
			
		||||
                            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 _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();
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (moveToNextTimeRange) {
 | 
			
		||||
                        if (++timeRangeIt != cfg->TimeRange.cend()) {
 | 
			
		||||
                            continue;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    // 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);
 | 
			
		||||
                    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
 | 
			
		||||
                    if (duration >= minsUsed) {
 | 
			
		||||
                        minsToCarryOver = duration - minsUsed;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    durationMinutes -= minsUsed;
 | 
			
		||||
                    durationMinutesNetto += minsUsed;
 | 
			
		||||
                    durationMinutesBrutto += minsUsed;
 | 
			
		||||
 | 
			
		||||
#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;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
#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 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();
 | 
			
		||||
    }
 | 
			
		||||
@@ -371,6 +581,7 @@ std::string Calculator::GetDurationFromCost(Configuration* cfg,
 | 
			
		||||
    // TODO: im fehlerfall
 | 
			
		||||
    return t.getValidUntil().toString(Qt::ISODate).toStdString();
 | 
			
		||||
}
 | 
			
		||||
#undef _DEBUG_
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
@@ -494,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;
 | 
			
		||||
            }
 | 
			
		||||
@@ -518,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;
 | 
			
		||||
@@ -567,120 +787,309 @@ 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();
 | 
			
		||||
 | 
			
		||||
            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) {
 | 
			
		||||
                weekDayWorkTimeRanges.append(itr->second); // working with vector is easier
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            int weekDayWorkTimeIndex = 0;
 | 
			
		||||
            bool moveToNextTimeRange = false;
 | 
			
		||||
 | 
			
		||||
            // time ranges for Neuhauser-Kirchdorf (743): 30, 5, 5, ... 5
 | 
			
		||||
            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);
 | 
			
		||||
            while (timeRangeIt != cfg->TimeRange.cend()) { // ; ++timeRangeIt) {
 | 
			
		||||
 | 
			
		||||
                for (WTIterator itr = p.first; itr != p.second; ++itr) {
 | 
			
		||||
                    ++range;
 | 
			
		||||
                if (weekDayWorkTimeIndex >= weekDayWorkTimeRanges.size()) {
 | 
			
		||||
 | 
			
		||||
                    QTime const &from = Utilities::WeekDaysWorkTimeFrom(itr);
 | 
			
		||||
                    QTime const &to = Utilities::WeekDaysWorkTimeUntil(itr);
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                    qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                << "weekDayWorkTimeIndex" << weekDayWorkTimeIndex
 | 
			
		||||
                                << "weekDayWorkTimeRanges.size()" << weekDayWorkTimeRanges.size();
 | 
			
		||||
#endif
 | 
			
		||||
                    end_datetime = current;
 | 
			
		||||
                    return price;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                    Q_ASSERT_X(from < to, __func__, "MISCONFIGURED WORK-TIMES");
 | 
			
		||||
                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 (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 _DEBUG_==1
 | 
			
		||||
                qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                            << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                            << "from" << from.toString(Qt::ISODate)
 | 
			
		||||
                            << "to" << to.toString(Qt::ISODate);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                            if (range == 1) {
 | 
			
		||||
                                start_datetime = current;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                Q_ASSERT_X(from < to, __func__, "MISCONFIGURED WORK-TIMES");
 | 
			
		||||
 | 
			
		||||
                    while (timeRangeIt != cfg->TimeRange.cend()) {
 | 
			
		||||
                        ATBTimeRange timeRange = timeRangeIt->second;
 | 
			
		||||
                if (current.time() >= to) {
 | 
			
		||||
                    ++weekDayWorkTimeIndex;
 | 
			
		||||
 | 
			
		||||
                        timeRange.computeQTimes(current.time());
 | 
			
		||||
#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) {
 | 
			
		||||
                        lastCurrent = current;
 | 
			
		||||
                        current.setTime(from); // move current forward (range==1),
 | 
			
		||||
                                               // as prepaid is set
 | 
			
		||||
                        uint const minutesMoved = lastCurrent.secsTo(current) / 60;
 | 
			
		||||
                        durationMinutesBrutto += minutesMoved;
 | 
			
		||||
 | 
			
		||||
                        int duration = timeRange.time_range_to_in_minutes_from_start -
 | 
			
		||||
                                       timeRange.time_range_from_in_minutes_from_start;
 | 
			
		||||
#if _DEBUG_==1
 | 
			
		||||
                        qCritical() << "(" << __func__ << ":" << __LINE__ << ")"
 | 
			
		||||
                                    << "lastCurrent" << lastCurrent.toString(Qt::ISODate)
 | 
			
		||||
                                    << "current" << current.toString(Qt::ISODate)
 | 
			
		||||
                                    << "minutesMoved" << minutesMoved
 | 
			
		||||
                                    << "durationMinutesBrutto" << durationMinutesBrutto;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
                        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;
 | 
			
		||||
 | 
			
		||||
                                        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;
 | 
			
		||||
                        if (weekDayWorkTimeIndex == 0) {
 | 
			
		||||
                            start_datetime = current;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                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 _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;
 | 
			
		||||
 | 
			
		||||
                    minsToCarryOver = 0;
 | 
			
		||||
 | 
			
		||||
#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;
 | 
			
		||||
                            durationMinutesNetto += duration;
 | 
			
		||||
                            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;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (moveToNextTimeRange) {
 | 
			
		||||
                        if (++timeRangeIt != cfg->TimeRange.cend()) {
 | 
			
		||||
                            continue;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    // 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);
 | 
			
		||||
                    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
 | 
			
		||||
                    if (duration >= minsUsed) {
 | 
			
		||||
                        minsToCarryOver = duration - minsUsed;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    durationMinutes -= minsUsed;
 | 
			
		||||
                    durationMinutesNetto += minsUsed;
 | 
			
		||||
                    durationMinutesBrutto += minsUsed;
 | 
			
		||||
 | 
			
		||||
#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;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
#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;
 | 
			
		||||
    }
 | 
			
		||||
@@ -1327,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) {
 | 
			
		||||
@@ -1419,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;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1122
									
								
								main/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										1122
									
								
								main/main.cpp
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user