class TARIFF {
public:
+ enum CHANGE_POLICY { ALLOW = 0, TO_CHEAP, TO_EXPENSIVE, DENY };
+
enum PERIOD { DAY = 0, MONTH };
enum TRAFF_TYPE { TRAFF_UP = 0, TRAFF_DOWN, TRAFF_UP_DOWN, TRAFF_MAX };
+ static std::string ChangePolicyToString(CHANGE_POLICY changePolicy);
+ static CHANGE_POLICY StringToChangePolicy(const std::string& value);
+
static std::string PeriodToString(PERIOD period);
static PERIOD StringToPeriod(const std::string& value);
virtual double GetFee() const = 0;
virtual double GetFree() const = 0;
virtual PERIOD GetPeriod() const = 0;
+ virtual CHANGE_POLICY GetChangePolicy() const = 0;
virtual const std::string & GetName() const = 0;
virtual void SetName(const std::string & name) = 0;
virtual const TARIFF_DATA & GetTariffData() const = 0;
};
+inline
+std::string TARIFF::ChangePolicyToString(TARIFF::CHANGE_POLICY changePolicy)
+{
+switch (changePolicy)
+ {
+ case ALLOW: return "allow";
+ case TO_CHEAP: return "to_cheap";
+ case TO_EXPENSIVE: return "to_expensive";
+ case DENY: return "deny";
+ }
+return "allow"; // Classic behaviour.
+}
+
+inline
+TARIFF::CHANGE_POLICY TARIFF::StringToChangePolicy(const std::string& value)
+{
+if (strcasecmp(value.c_str(), "to_cheap") == 0)
+ return TO_CHEAP;
+if (strcasecmp(value.c_str(), "to_expensive") == 0)
+ return TO_EXPENSIVE;
+if (strcasecmp(value.c_str(), "deny") == 0)
+ return DENY;
+return ALLOW; // Classic behaviour.
+}
+
inline
std::string TARIFF::PeriodToString(TARIFF::PERIOD period)
{
double passiveCost;
std::string name;
TARIFF::PERIOD period;
+ TARIFF::CHANGE_POLICY changePolicy;
TARIFF_CONF()
: fee(0),
traffType(TARIFF::TRAFF_UP_DOWN),
passiveCost(0),
name(),
- period(TARIFF::MONTH)
+ period(TARIFF::MONTH),
+ changePolicy(TARIFF::ALLOW)
{}
TARIFF_CONF(const std::string & n)
traffType(TARIFF::TRAFF_UP_DOWN),
passiveCost(0),
name(n),
- period(TARIFF::MONTH)
+ period(TARIFF::MONTH),
+ changePolicy(TARIFF::ALLOW)
{}
};
//-----------------------------------------------------------------------------
traffType(),
passiveCost(),
name(),
- period()
+ period(),
+ changePolicy()
{}
TARIFF_CONF_RES & operator=(const TARIFF_CONF & tc)
passiveCost = tc.passiveCost;
name = tc.name;
period = tc.period;
+ changePolicy = tc.changePolicy;
return *this;
}
passiveCost.maybeSet(tc.passiveCost);
traffType.maybeSet(tc.traffType);
period.maybeSet(tc.period);
+ changePolicy.maybeSet(tc.changePolicy);
return tc;
}
RESETABLE<double> passiveCost;
RESETABLE<std::string> name;
RESETABLE<TARIFF::PERIOD> period;
+ RESETABLE<TARIFF::CHANGE_POLICY> changePolicy;
};
//-----------------------------------------------------------------------------
struct TARIFF_DATA
return dash ? std::string(level * 4 - 2, ' ') + "- " : std::string(level * 4, ' ');
}
+std::string ChangePolicyToString(TARIFF::CHANGE_POLICY changePolicy)
+{
+switch (changePolicy)
+ {
+ case TARIFF::ALLOW: return "allow";
+ case TARIFF::TO_CHEAP: return "to_cheap";
+ case TARIFF::TO_EXPENSIVE: return "to_expensive";
+ case TARIFF::DENY: return "deny";
+ }
+return "unknown";
+}
+
std::string PeriodToString(TARIFF::PERIOD period)
{
switch (period)
throw SGCONF::ACTION::ERROR("Period should be 'daily' or 'monthly'. Got: '" + value + "'");
}
+void ConvChangePolicy(const std::string & value, RESETABLE<TARIFF::CHANGE_POLICY> & res)
+{
+std::string lowered = ToLower(value);
+if (lowered == "allow")
+ res = TARIFF::ALLOW;
+else if (lowered == "to_cheap")
+ res = TARIFF::TO_CHEAP;
+else if (lowered == "to_expensive")
+ res = TARIFF::TO_EXPENSIVE;
+else if (lowered == "deny")
+ res = TARIFF::DENY;
+else
+ throw SGCONF::ACTION::ERROR("Change policy should be 'allow', 'to_cheap', 'to_expensive' or 'deny'. Got: '" + value + "'");
+}
+
void ConvTraffType(const std::string & value, RESETABLE<TARIFF::TRAFF_TYPE> & res)
{
std::string lowered = ToLower(value);
<< Indent(level) << "free mb: " << conf.free << "\n"
<< Indent(level) << "passive cost: " << conf.passiveCost << "\n"
<< Indent(level) << "traff type: " << TraffTypeToString(conf.traffType) << "\n"
- << Indent(level) << "period: " << PeriodToString(conf.period) << "\n";
+ << Indent(level) << "period: " << PeriodToString(conf.period) << "\n"
+ << Indent(level) << "change policy: " << ChangePolicyToString(conf.changePolicy) << "\n";
}
void PrintTariff(const STG::GET_TARIFF::INFO & info, size_t level = 0)
params.push_back(SGCONF::API_ACTION::PARAM("passive-cost", "<cost>", "\tpassive cost"));
params.push_back(SGCONF::API_ACTION::PARAM("traff-type", "<type>", "\ttraffic type (up, down, up+down, max)"));
params.push_back(SGCONF::API_ACTION::PARAM("period", "<period>", "\ttarification period (daily, monthly)"));
+params.push_back(SGCONF::API_ACTION::PARAM("change-policy", "<policy>", "tariff change policy (allow, to_cheap, to_expensive, deny)"));
params.push_back(SGCONF::API_ACTION::PARAM("times", "<hh:mm-hh:mm, ...>", "coma-separated day time-spans for each direction"));
params.push_back(SGCONF::API_ACTION::PARAM("day-prices", "<price/price, ...>", "coma-separated day prices for each direction"));
params.push_back(SGCONF::API_ACTION::PARAM("night-prices", "<price/price, ...>", "coma-separated night prices for each direction"));
SGCONF::MaybeSet(options, "passive-cost", conf.tariffConf.passiveCost);
SGCONF::MaybeSet(options, "traff-type", conf.tariffConf.traffType, ConvTraffType);
SGCONF::MaybeSet(options, "period", conf.tariffConf.period, ConvPeriod);
+SGCONF::MaybeSet(options, "change-policy", conf.tariffConf.changePolicy, ConvChangePolicy);
SGCONF::MaybeSet(options, "times", conf.dirPrice, ConvTimes);
SGCONF::MaybeSet(options, "day-prices", conf.dirPrice, ConvDayPrices);
SGCONF::MaybeSet(options, "night-prices", conf.dirPrice, ConvNightPrices);
SGCONF::MaybeSet(options, "passive-cost", conf.tariffConf.passiveCost);
SGCONF::MaybeSet(options, "traff-type", conf.tariffConf.traffType, ConvTraffType);
SGCONF::MaybeSet(options, "period", conf.tariffConf.period, ConvPeriod);
+SGCONF::MaybeSet(options, "change-policy", conf.tariffConf.changePolicy, ConvChangePolicy);
SGCONF::MaybeSet(options, "times", conf.dirPrice, ConvTimes);
SGCONF::MaybeSet(options, "day-prices", conf.dirPrice, ConvDayPrices);
SGCONF::MaybeSet(options, "night-prices", conf.dirPrice, ConvNightPrices);
--- /dev/null
+/*
+ * DB migration from v02 to v03 (postgres)
+ */
+BEGIN;
+
+CREATE DOMAIN DM_TARIFF_CHANGE_POLICY AS TEXT NOT NULL
+ CONSTRAINT valid_value CHECK (VALUE IN ('allow', 'to_cheap', 'to_expensive', 'deny'));
+
+ALTER TABLE tb_tariffs ADD change_policy DM_TARIFF_CHANGE_POLICY DEFAULT 'allow';
+
+UPDATE tb_info SET version = 8;
+
+COMMIT;
--- /dev/null
+/*
+ * DB migration from v02 to v03 (firebird)
+ */
+
+CREATE DOMAIN DM_TARIFF_CHANGE_POLICY AS VARCHAR(32) NOT NULL
+ CHECK (VALUE IN ('allow', 'to_cheap', 'to_expensive', 'deny'));
+
+ALTER TABLE tb_tariffs ADD change_policy DM_TARIFF_CHANGE_POLICY DEFAULT 'allow';
+
+UPDATE tb_info SET version = 2;
structVal["passivecost"] = xmlrpc_c::value_double(data.tariffConf.passiveCost);
structVal["traffType"] = xmlrpc_c::value_int(data.tariffConf.traffType);
structVal["period"] = xmlrpc_c::value_string(TARIFF::PeriodToString(data.tariffConf.period));
+structVal["changePolicy"] = xmlrpc_c::value_string(TARIFF::ChangePolicyToString(data.tariffConf.changePolicy));
std::vector<xmlrpc_c::value> prices(DIR_NUM);
data.tariffConf.period = TARIFF::StringToPeriod(xmlrpc_c::value_string(it->second));
}
+if ((it = structVal.find("changePolicy")) != structVal.end())
+ {
+ data.tariffConf.changePolicy = TARIFF::StringToChangePolicy(xmlrpc_c::value_string(it->second));
+ }
+
if ((it = structVal.find("dirprices")) != structVal.end())
{
std::vector<xmlrpc_c::value> prices(
"<Free value=\"" + x2str(it->tariffConf.free) + "\"/>" +
"<TraffType value=\"" + TARIFF::TraffTypeToString(it->tariffConf.traffType) + "\"/>" +
"<Period value=\"" + TARIFF::PeriodToString(it->tariffConf.period) + "\"/>" +
+ "<ChangePolicy value=\"" + TARIFF::ChangePolicyToString(it->tariffConf.changePolicy) + "\"/>" +
"</tariff>";
}
td.tariffConf.period = TARIFF::StringToPeriod(attr[1]);
return 0;
}
+
+ if (strcasecmp(el, "ChangePolicy") == 0)
+ {
+ td.tariffConf.changePolicy = TARIFF::StringToChangePolicy(attr[1]);
+ return 0;
+ }
}
return -1;
}
td->tariffConf.period = TARIFF::MONTH;
else
td->tariffConf.period = TARIFF::StringToPeriod(str);
+
+if (conf.ReadString("ChangePolicy", &str, "allow") < 0)
+ td->tariffConf.changePolicy = TARIFF::ALLOW;
+else
+ td->tariffConf.changePolicy = TARIFF::StringToChangePolicy(str);
return 0;
}
//-----------------------------------------------------------------------------
cf.WriteDouble("Free", td.tariffConf.free);
cf.WriteString("TraffType", TARIFF::TraffTypeToString(td.tariffConf.traffType));
cf.WriteString("Period", TARIFF::PeriodToString(td.tariffConf.period));
+ cf.WriteString("ChangePolicy", TARIFF::ChangePolicyToString(td.tariffConf.changePolicy));
}
return 0;
int32_t id;
st->Get(1, id);
st->Close();
- if (schemaVersion > 0)
+ if (schemaVersion == 1)
{
st->Prepare("update tb_tariffs set \
fee = ?, \
st->Set(5, TARIFF::PeriodToString(td.tariffConf.period));
st->Set(6, id);
}
+ else if (schemaVersion > 1)
+ {
+ st->Prepare("update tb_tariffs set \
+ fee = ?, \
+ free = ?, \
+ passive_cost = ?, \
+ traff_type = ?, \
+ period = ?, \
+ change_policy = ? \
+ where pk_tariff = ?");
+ st->Set(1, td.tariffConf.fee);
+ st->Set(2, td.tariffConf.free);
+ st->Set(3, td.tariffConf.passiveCost);
+ st->Set(4, td.tariffConf.traffType);
+ st->Set(5, TARIFF::PeriodToString(td.tariffConf.period));
+ st->Set(6, TARIFF::ChangePolicyToString(td.tariffConf.changePolicy));
+ st->Set(7, id);
+ }
else
{
st->Prepare("update tb_tariffs set \
td->tariffConf.traffType = TARIFF::IntToTraffType(Get<int>(st, 6));
if (schemaVersion > 0)
td->tariffConf.period = TARIFF::StringToPeriod(Get<std::string>(st, 7));
+ if (schemaVersion > 1)
+ td->tariffConf.changePolicy = TARIFF::StringToChangePolicy(Get<std::string>(st, 8));
st->Close();
st->Prepare("select * from tb_tariffs_params where fk_tariff = ?");
st->Set(1, id);
res += "PassiveCost DOUBLE DEFAULT 0.0, Fee DOUBLE DEFAULT 0.0,"
"Free DOUBLE DEFAULT 0.0, TraffType VARCHAR(10) DEFAULT '',"
- "period VARCHAR(32) NOT NULL DEFAULT 'month')";
+ "period VARCHAR(32) NOT NULL DEFAULT 'month',"
+ "change_policy VARCHAR(32) NOT NULL DEFAULT 'allow')";
if(MysqlQuery(res.c_str(),sock))
{
res += "PassiveCost=0.0, Fee=10.0, Free=0,"\
"SinglePrice0=1, SinglePrice1=1,PriceDayA1=0.75,PriceDayB1=0.75,"\
- "PriceNightA0=1.0,PriceNightB0=1.0,TraffType='up+down',period='month'";
+ "PriceNightA0=1.0,PriceNightB0=1.0,TraffType='up+down',period='month',"\
+ "change_policy='allow'";
if(MysqlQuery(res.c_str(),sock))
{
mysql_close(sock);
return -1;
}
- schemaVersion = 1;
+ schemaVersion = 2;
}
//users-----------------------------------------------------------------------
schemaVersion = 1;
logger("MYSQL_STORE: Updated DB schema to version %d", schemaVersion);
}
+
+if (schemaVersion < 2)
+ {
+ if (MysqlQuery("ALTER TABLE tariffs ADD change_policy VARCHAR(32) NOT NULL DEFAULT 'allow'", sock))
+ {
+ errorStr = "Couldn't update tariffs table to version 2. With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+ if (MysqlQuery("UPDATE info SET version = 2", sock))
+ {
+ errorStr = "Couldn't update DB schema version to 2. With error:\n";
+ errorStr += mysql_error(sock);
+ mysql_close(sock);
+ return -1;
+ }
+ schemaVersion = 2;
+ logger("MYSQL_STORE: Updated DB schema to version %d", schemaVersion);
+ }
return 0;
}
//-----------------------------------------------------------------------------
td->tariffConf.period = TARIFF::MONTH;
}
+if (schemaVersion > 1)
+{
+ str = row[6+8*DIR_NUM];
+ param = "ChangePolicy";
+
+ if (str.length() == 0)
+ {
+ mysql_free_result(res);
+ errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+ mysql_close(sock);
+ return -1;
+ }
+
+ td->tariffConf.changePolicy = TARIFF::StringToChangePolicy(str);
+ }
+else
+ {
+ td->tariffConf.changePolicy = TARIFF::ALLOW;
+ }
+
mysql_free_result(res);
mysql_close(sock);
return 0;
if (schemaVersion > 0)
res += ", Period='" + TARIFF::PeriodToString(td.tariffConf.period) + "'";
+if (schemaVersion > 1)
+ res += ", change_policy='" + TARIFF::ChangePolicyToString(td.tariffConf.changePolicy) + "'";
+
strprintf(¶m, " WHERE name='%s' LIMIT 1", tariffName.c_str());
res += param;
if (version > 6)
query << ", period = '" << TARIFF::PeriodToString(td.tariffConf.period) << "'";
+ if (version > 7)
+ query << ", change_policy = '" << TARIFF::ChangePolicyToString(td.tariffConf.changePolicy) << "'";
+
query << " WHERE pk_tariff = " << id;
result = PQexec(connection, query.str().c_str());
if (version > 6)
query << ", period";
+if (version > 7)
+ query << ", change_policy";
+
query << " FROM tb_tariffs WHERE name = '" << ename << "'";
result = PQexec(connection, query.str().c_str());
if (version > 6)
td->tariffConf.period = TARIFF::StringToPeriod(PQgetvalue(result, 0, 5));
+if (version > 7)
+ td->tariffConf.changePolicy = TARIFF::StringToChangePolicy(PQgetvalue(result, 0, 6));
+
PQclear(result);
query.str("");
double GetFee() const { return tariffData.tariffConf.fee; }
double GetFree() const { return tariffData.tariffConf.free; }
PERIOD GetPeriod() const { return tariffData.tariffConf.period; }
+ CHANGE_POLICY GetChangePolicy() const { return tariffData.tariffConf.changePolicy; }
void Print() const;
case TARIFF::MONTH: stream << "<period value=\"month\"/>"; break;
}
+if (!data.tariffConf.changePolicy.empty())
+ switch (data.tariffConf.changePolicy.data())
+ {
+ case TARIFF::ALLOW: stream << "<changePolicy value=\"allow\"/>"; break;
+ case TARIFF::TO_CHEAP: stream << "<changePolicy value=\"to_cheap\"/>"; break;
+ case TARIFF::TO_EXPENSIVE: stream << "<changePolicy value=\"to_expensive\"/>"; break;
+ case TARIFF::DENY: stream << "<changePolicy value=\"deny\"/>"; break;
+ }
+
for (size_t i = 0; i < DIR_NUM; ++i)
if (!data.dirPrice[i].hDay.empty() &&
!data.dirPrice[i].mDay.empty() &&
return true;
}
+template <typename T>
+bool GetChangePolicy(const char ** attr, T & value, const std::string & attrName)
+{
+if (!CheckValue(attr, attrName))
+ return false;
+std::string type(attr[1]);
+if (type == "allow")
+ value = TARIFF::ALLOW;
+else if (type == "to_cheap")
+ value = TARIFF::TO_CHEAP;
+else if (type == "to_expensive")
+ value = TARIFF::TO_EXPENSIVE;
+else if (type == "deny")
+ value = TARIFF::DENY;
+else
+ return false;
+return true;
+}
+
template <typename A, typename T>
bool GetSlashedValue(const char ** attr, A & array, T A::value_type:: * field)
{
AddParser(propertyParsers, "free", info.tariffConf.free);
AddParser(propertyParsers, "traffType", info.tariffConf.traffType, GetTraffType);
AddParser(propertyParsers, "period", info.tariffConf.period, GetPeriod);
+ AddParser(propertyParsers, "changePolicy", info.tariffConf.changePolicy, GetChangePolicy);
for (size_t i = 0; i < DIR_NUM; ++i)
AddParser(propertyParsers, "time" + unsigned2str(i), info.dirPrice[i], GetTimeSpan);
AddAOSParser(propertyParsers, "priceDayA", info.dirPrice, &DIRPRICE_DATA::priceDayA, GetSlashedValue);