]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/store/postgresql/postgresql_store_tariffs.cpp
Added DIR_TRAFF_RES, refactored DIR_TRAFF.
[stg.git] / projects / stargazer / plugins / store / postgresql / postgresql_store_tariffs.cpp
1 /*
2  *    This program is free software; you can redistribute it and/or modify
3  *    it under the terms of the GNU General Public License as published by
4  *    the Free Software Foundation; either version 2 of the License, or
5  *    (at your option) any later version.
6  *
7  *    This program is distributed in the hope that it will be useful,
8  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *    GNU General Public License for more details.
11  *
12  *    You should have received a copy of the GNU General Public License
13  *    along with this program; if not, write to the Free Software
14  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  */
16
17 /*
18  *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
19  */
20
21 /*
22  *  Tariffs manipulation methods
23  *
24  *  $Revision: 1.2 $
25  *  $Date: 2009/06/09 12:32:40 $
26  *
27  */
28
29 #include <string>
30 #include <vector>
31 #include <sstream>
32 #include <cmath>
33
34 #include <libpq-fe.h>
35
36 #include "postgresql_store.h"
37 #include "stg/locker.h"
38
39 //-----------------------------------------------------------------------------
40 int POSTGRESQL_STORE::GetTariffsList(std::vector<std::string> * tariffsList) const
41 {
42 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
43
44 if (PQstatus(connection) != CONNECTION_OK)
45     {
46     printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
47     if (Reset())
48         {
49         strError = "Connection lost";
50         printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): '%s'\n", strError.c_str());
51         return -1;
52         }
53     }
54
55 PGresult * result;
56
57 if (StartTransaction())
58     {
59     printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Failed to start transaction'\n");
60     return -1;
61     }
62
63 result = PQexec(connection, "SELECT name FROM tb_tariffs");
64
65 if (PQresultStatus(result) != PGRES_TUPLES_OK)
66     {
67     strError = PQresultErrorMessage(result);
68     PQclear(result);
69     printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): '%s'\n", strError.c_str());
70     if (RollbackTransaction())
71         {
72         printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Failed to rollback transaction'\n");
73         }
74     return -1;
75     }
76
77 int tuples = PQntuples(result);
78
79 for (int i = 0; i < tuples; ++i)
80     {
81     tariffsList->push_back(PQgetvalue(result, i, 0));
82     }
83
84 PQclear(result);
85
86 if (CommitTransaction())
87     {
88     printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Failed to commit transaction'\n");
89     return -1;
90     }
91
92 return 0;
93 }
94
95 //-----------------------------------------------------------------------------
96 int POSTGRESQL_STORE::AddTariff(const std::string & name) const
97 {
98 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
99
100 if (PQstatus(connection) != CONNECTION_OK)
101     {
102     printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
103     if (Reset())
104         {
105         strError = "Connection lost";
106         printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): '%s'\n", strError.c_str());
107         return -1;
108         }
109     }
110
111 PGresult * result;
112
113 if (StartTransaction())
114     {
115     printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to start transaction'\n");
116     return -1;
117     }
118
119 std::string ename = name;
120
121 if (EscapeString(ename))
122     {
123     printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to escape name'\n");
124     if (RollbackTransaction())
125         {
126         printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to rollback transaction'\n");
127         }
128     return -1;
129     }
130
131 std::ostringstream query;
132 query << "SELECT sp_add_tariff('" << ename << "', " << DIR_NUM << ")";
133
134 result = PQexec(connection, query.str().c_str());
135
136 if (PQresultStatus(result) != PGRES_TUPLES_OK)
137     {
138     strError = PQresultErrorMessage(result);
139     PQclear(result);
140     printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): '%s'\n", strError.c_str());
141     if (RollbackTransaction())
142         {
143         printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to rollback transaction'\n");
144         }
145     return -1;
146     }
147
148 PQclear(result);
149
150 if (CommitTransaction())
151     {
152     printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to commit transaction'\n");
153     return -1;
154     }
155
156 return 0;
157 }
158 //-----------------------------------------------------------------------------
159 int POSTGRESQL_STORE::DelTariff(const std::string & name) const
160 {
161 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
162
163 if (PQstatus(connection) != CONNECTION_OK)
164     {
165     printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
166     if (Reset())
167         {
168         strError = "Connection lost";
169         printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): '%s'\n", strError.c_str());
170         return -1;
171         }
172     }
173
174 PGresult * result;
175
176 if (StartTransaction())
177     {
178     printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Failed to start transaction'\n");
179     return -1;
180     }
181
182 std::string ename = name;
183
184 if (EscapeString(ename))
185     {
186     printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to escape name'\n");
187     if (RollbackTransaction())
188         {
189         printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to rollback transaction'\n");
190         }
191     return -1;
192     }
193
194 std::ostringstream query;
195 query << "DELETE FROM tb_tariffs WHERE name = '" << ename << "'";
196
197 result = PQexec(connection, query.str().c_str());
198
199 if (PQresultStatus(result) != PGRES_COMMAND_OK)
200     {
201     strError = PQresultErrorMessage(result);
202     PQclear(result);
203     printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): '%s'\n", strError.c_str());
204     if (RollbackTransaction())
205         {
206         printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Failed to rollback transaction'\n");
207         }
208     return -1;
209     }
210
211 PQclear(result);
212
213 if (CommitTransaction())
214     {
215     printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Failed to commit transaction'\n");
216     return -1;
217     }
218
219 return 0;
220 }
221 //-----------------------------------------------------------------------------
222 int POSTGRESQL_STORE::SaveTariff(const TARIFF_DATA & td,
223                                  const std::string & tariffName) const
224 {
225 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
226
227 if (PQstatus(connection) != CONNECTION_OK)
228     {
229     printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
230     if (Reset())
231         {
232         strError = "Connection lost";
233         printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
234         return -1;
235         }
236     }
237
238 PGresult * result;
239
240 if (StartTransaction())
241     {
242     printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to start transaction'\n");
243     return -1;
244     }
245
246 std::string ename = tariffName;
247
248 if (EscapeString(ename))
249     {
250     printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to escape name'\n");
251     if (RollbackTransaction())
252         {
253         printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
254         }
255     return -1;
256     }
257
258 int32_t id, i;
259 double pda, pdb, pna, pnb;
260 int threshold;
261
262     {
263     std::ostringstream query;
264     query << "SELECT pk_tariff FROM tb_tariffs WHERE name = '" << ename << "'";
265
266     result = PQexec(connection, query.str().c_str());
267     }
268
269 if (PQresultStatus(result) != PGRES_TUPLES_OK)
270     {
271     strError = PQresultErrorMessage(result);
272     PQclear(result);
273     printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
274     if (RollbackTransaction())
275         {
276         printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
277         }
278     return -1;
279     }
280
281 int tuples = PQntuples(result);
282
283 if (tuples != 1)
284     {
285     strError = "Failed to fetch tariff ID";
286     printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
287     PQclear(result);
288     if (RollbackTransaction())
289         {
290         printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
291         }
292     return -1;
293     }
294
295     {
296     std::stringstream tuple;
297     tuple << PQgetvalue(result, 0, 0);
298
299     PQclear(result);
300
301     tuple >> id;
302     }
303
304     {
305     std::ostringstream query;
306     query << "UPDATE tb_tariffs SET \
307                   fee = " << td.tariffConf.fee << ", \
308                   free = " << td.tariffConf.free << ", \
309                   passive_cost = " << td.tariffConf.passiveCost << ", \
310                   traff_type = " << td.tariffConf.traffType << " \
311               WHERE pk_tariff = " << id;
312
313     result = PQexec(connection, query.str().c_str());
314     }
315
316 if (PQresultStatus(result) != PGRES_COMMAND_OK)
317     {
318     strError = PQresultErrorMessage(result);
319     PQclear(result);
320     printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
321     if (RollbackTransaction())
322         {
323         printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
324         }
325     return -1;
326     }
327
328 PQclear(result);
329
330 for(i = 0; i < DIR_NUM; i++)
331     {
332
333     pda = td.dirPrice[i].priceDayA * 1024 * 1024;
334     pdb = td.dirPrice[i].priceDayB * 1024 * 1024;
335
336     if (td.dirPrice[i].singlePrice)
337         {
338         pna = pda;
339         pnb = pdb;
340         }
341     else
342         {
343         pna = td.dirPrice[i].priceNightA * 1024 * 1024;
344         pnb = td.dirPrice[i].priceNightB * 1024 * 1024;
345         }
346
347     if (td.dirPrice[i].noDiscount)
348         {
349         threshold = 0xffFFffFF;
350         }
351     else
352         {
353         threshold = td.dirPrice[i].threshold;
354         }
355
356         {
357         std::ostringstream query;
358         query << "UPDATE tb_tariffs_params SET \
359                       price_day_a = " << pda << ", \
360                       price_day_b = " << pdb << ", \
361                       price_night_a = " << pna << ", \
362                       price_night_b = " << pnb << ", \
363                       threshold = " << threshold << ", \
364                       time_day_begins = CAST('" << td.dirPrice[i].hDay
365                                                 << ":"
366                                                 << td.dirPrice[i].mDay << "' AS TIME), \
367                       time_day_ends = CAST('" << td.dirPrice[i].hNight
368                                               << ":"
369                                               << td.dirPrice[i].mNight << "' AS TIME) \
370                  WHERE fk_tariff = " << id << " AND dir_num = " << i;
371
372         result = PQexec(connection, query.str().c_str());
373         }
374
375     if (PQresultStatus(result) != PGRES_COMMAND_OK)
376         {
377         strError = PQresultErrorMessage(result);
378         PQclear(result);
379         printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
380         if (RollbackTransaction())
381             {
382             printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
383             }
384         return -1;
385         }
386
387     PQclear(result);
388     }
389
390 if (CommitTransaction())
391     {
392     printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to commit transaction'\n");
393     return -1;
394     }
395
396 return 0;
397 }
398 //-----------------------------------------------------------------------------
399 int POSTGRESQL_STORE::RestoreTariff(TARIFF_DATA * td,
400                                   const std::string & tariffName) const
401 {
402 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
403
404 if (PQstatus(connection) != CONNECTION_OK)
405     {
406     printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
407     if (Reset())
408         {
409         strError = "Connection lost";
410         printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): '%s'\n", strError.c_str());
411         return -1;
412         }
413     }
414
415 PGresult * result;
416
417 if (StartTransaction())
418     {
419     printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to start transaction'\n");
420     return -1;
421     }
422
423 std::string ename = tariffName;
424
425 if (EscapeString(ename))
426     {
427     printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to escape name'\n");
428     if (RollbackTransaction())
429         {
430         printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
431         }
432     return -1;
433     }
434
435 td->tariffConf.name = tariffName;
436
437 std::ostringstream query;
438 query << "SELECT pk_tariff, \
439                  fee, \
440                  free, \
441                  passive_cost, \
442                  traff_type \
443           FROM tb_tariffs WHERE name = '" << ename << "'";
444
445 result = PQexec(connection, query.str().c_str());
446
447 if (PQresultStatus(result) != PGRES_TUPLES_OK)
448     {
449     strError = PQresultErrorMessage(result);
450     PQclear(result);
451     printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): '%s'\n", strError.c_str());
452     if (RollbackTransaction())
453         {
454         printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
455         }
456     return -1;
457     }
458
459 int tuples = PQntuples(result);
460
461 if (tuples != 1)
462     {
463     strError = "Failed to fetch tariff data";
464     printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
465     PQclear(result);
466     if (RollbackTransaction())
467         {
468         printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
469         }
470     return -1;
471     }
472
473 int id;
474
475     {
476     std::stringstream tuple;
477     tuple << PQgetvalue(result, 0, 0) << " ";
478     tuple << PQgetvalue(result, 0, 1) << " ";
479     tuple << PQgetvalue(result, 0, 2) << " ";
480     tuple << PQgetvalue(result, 0, 3) << " ";
481     tuple << PQgetvalue(result, 0, 4) << " ";
482
483     tuple >> id;
484     tuple >> td->tariffConf.fee;
485     tuple >> td->tariffConf.free;
486     tuple >> td->tariffConf.passiveCost;
487     tuple >> td->tariffConf.traffType;
488     }
489
490 PQclear(result);
491
492 query.str("");
493 query << "SELECT dir_num, \
494                  price_day_a, \
495                  price_day_b, \
496                  price_night_a, \
497                  price_night_b, \
498                  threshold, \
499                  EXTRACT(hour FROM time_day_begins), \
500                  EXTRACT(minute FROM time_day_begins), \
501                  EXTRACT(hour FROM time_day_ends), \
502                  EXTRACT(minute FROM time_day_ends) \
503           FROM tb_tariffs_params \
504           WHERE fk_tariff = " << id;
505
506 result = PQexec(connection, query.str().c_str());
507
508 if (PQresultStatus(result) != PGRES_TUPLES_OK)
509     {
510     strError = PQresultErrorMessage(result);
511     PQclear(result);
512     printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): '%s'\n", strError.c_str());
513     if (RollbackTransaction())
514         {
515         printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
516         }
517     return -1;
518     }
519
520 tuples = PQntuples(result);
521
522 if (tuples != DIR_NUM)
523     {
524     printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Tariff params count and DIR_NUM does not feet (wanted %d, actually %d)'\n", DIR_NUM, tuples);
525     }
526
527 for (int i = 0; i < std::min(tuples, DIR_NUM); ++i)
528     {
529     int dir;
530
531         {
532         std::stringstream tuple;
533         tuple << PQgetvalue(result, i, 0) << " ";
534         tuple << PQgetvalue(result, i, 1) << " ";
535         tuple << PQgetvalue(result, i, 2) << " ";
536         tuple << PQgetvalue(result, i, 3) << " ";
537         tuple << PQgetvalue(result, i, 4) << " ";
538         tuple << PQgetvalue(result, i, 5) << " ";
539         tuple << PQgetvalue(result, i, 6) << " ";
540         tuple << PQgetvalue(result, i, 7) << " ";
541         tuple << PQgetvalue(result, i, 8) << " ";
542         tuple << PQgetvalue(result, i, 9) << " ";
543
544         tuple >> dir;
545         tuple >> td->dirPrice[dir].priceDayA;
546         td->dirPrice[dir].priceDayA /= 1024 * 1024;
547         tuple >> td->dirPrice[dir].priceDayB;
548         td->dirPrice[dir].priceDayB /= 1024 * 1024;
549         tuple >> td->dirPrice[dir].priceNightA;
550         td->dirPrice[dir].priceNightA /= 1024 * 1024;
551         tuple >> td->dirPrice[dir].priceNightB;
552         td->dirPrice[dir].priceNightB /= 1024 * 1024;
553         tuple >> td->dirPrice[dir].threshold;
554         tuple >> td->dirPrice[dir].hDay;
555         tuple >> td->dirPrice[dir].mDay;
556         tuple >> td->dirPrice[dir].hNight;
557         tuple >> td->dirPrice[dir].mNight;
558         }
559
560     if (std::fabs(td->dirPrice[dir].priceDayA - td->dirPrice[dir].priceNightA) > 1.0e-3 &&
561         std::fabs(td->dirPrice[dir].priceDayB - td->dirPrice[dir].priceNightB) > 1.0e-3)
562         {
563         td->dirPrice[dir].singlePrice = true;
564         }
565     else
566         {
567         td->dirPrice[dir].singlePrice = false;
568         }
569     if (td->dirPrice[dir].threshold == (int)0xffFFffFF)
570         {
571         td->dirPrice[dir].noDiscount = true;
572         }
573     else
574         {
575
576         td->dirPrice[dir].noDiscount = false;
577         }
578
579     }
580
581 PQclear(result);
582
583 if (CommitTransaction())
584     {
585     printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to commit transaction'\n");
586     return -1;
587     }
588
589 return 0;
590 }
591 //-----------------------------------------------------------------------------
592