api.ddt.php 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104
  1. <?php
  2. /**
  3. * Automatic user tariff migration aka Dooms Day Tariffs class
  4. */
  5. class DoomsDayTariffs {
  6. /**
  7. * Contains system alter config as key=>value
  8. */
  9. protected $altCfg = array();
  10. /**
  11. * Contains available DDT options aka tariffs as id=>data
  12. *
  13. * @var array
  14. */
  15. protected $allOptions = array();
  16. /**
  17. * Contains available system tariffs as tariffname=>tariffdata
  18. *
  19. * @var array
  20. */
  21. protected $allTariffs = array();
  22. /**
  23. * Contains available system tariffs as tariffname=>tariffname
  24. *
  25. * @var array
  26. */
  27. protected $allTariffNames = array();
  28. /**
  29. * Contains default periods descriptions as period=>periodname
  30. *
  31. * @var array
  32. */
  33. protected $periods = array();
  34. /**
  35. * Contains all available users data as login=>userdata
  36. *
  37. * @var array
  38. */
  39. protected $allUserData = array();
  40. /**
  41. * Contains all of available ddt users history data
  42. *
  43. * @var array
  44. */
  45. protected $allDDTUsers = array();
  46. /**
  47. * System message helper object placeholder
  48. *
  49. * @var object
  50. */
  51. protected $messages = '';
  52. /**
  53. * DealWith it object instance placeholder
  54. *
  55. * @var object
  56. */
  57. protected $dealwithit = '';
  58. /**
  59. * Contains currently scheduled dealwithit tasks for tariff changes as id=>taskdata
  60. *
  61. * @var array
  62. */
  63. protected $allTasks = array();
  64. /**
  65. * Mapped from DDT_ENDPREVDAYS option
  66. *
  67. * @var int
  68. */
  69. protected $prevDaysOffset = 0;
  70. /**
  71. * Users/history database abstraction layer
  72. *
  73. * @var object
  74. */
  75. protected $usersDb = '';
  76. /**
  77. * Tariff options database abstraction layer
  78. *
  79. * @var object
  80. */
  81. protected $optionsDb = '';
  82. /**
  83. * Charge tariffs database abstraction layer
  84. *
  85. * @var object
  86. */
  87. protected $chargeOptsDb = '';
  88. /**
  89. * Charges history database absctraction layer
  90. *
  91. * @var object
  92. */
  93. protected $chargeHistDb = '';
  94. /**
  95. * Registered users log database abstraction layer
  96. *
  97. * @var object
  98. */
  99. protected $userRegDb = '';
  100. /**
  101. * Contains all charge opts as id=>data
  102. *
  103. * @var array
  104. */
  105. protected $allChargeOpts = array();
  106. /**
  107. * Contains all tariff charge rules as tariff=>ruleData
  108. *
  109. * @var array
  110. */
  111. protected $allTariffChargeRules = array();
  112. /**
  113. * Contains full charges history as id=>data
  114. *
  115. * @var array
  116. */
  117. protected $fullChargeHist = array();
  118. /**
  119. * Default control module URL
  120. */
  121. const URL_ME = '?module=ddt';
  122. /**
  123. * Default history report URL
  124. */
  125. const URL_HIST = '?module=ddt&history=true';
  126. /**
  127. * Forced charges history URL
  128. */
  129. const URL_CH_HIST = '&mode=fch';
  130. /**
  131. * Default user profile link URL
  132. */
  133. const URL_PROFILE = '?module=userprofile&username=';
  134. /**
  135. * Default deal with it search url
  136. */
  137. const URL_DWI = '?module=pl_dealwithit&username=';
  138. /**
  139. * Other predefined stuff
  140. */
  141. const PID = 'DDT';
  142. const TABLE_USERS = 'ddt_users';
  143. const TABLE_OPTIONS = 'ddt_options';
  144. const TABLE_CHARGESHIST = 'ddt_charges';
  145. const TABLE_CHARGEOPTS = 'ddt_chargeopts';
  146. const TABLE_USERREG = 'userreg';
  147. const ROUTE_CH_DELETE = 'deletechargeruleid';
  148. const ROUTE_CH_HISTAJX = 'forcedchargehistoryajax';
  149. const PROUTE_CH_CREATE = 'newchargetariffcreation';
  150. const PROUTE_CH_TARIFF = 'newchargetariff';
  151. const PROUTE_CH_UDAY = 'newchargeuntilday';
  152. const PROUTE_CH_FEE = 'newchargefeeflag';
  153. const PROUTE_CH_ABS = 'newchargeabsolute';
  154. const PROUTE_CH_CREDITDAYS = 'newchargecreditdays';
  155. /**
  156. * Creates new DoomsDay instance
  157. *
  158. * @param bool $fast
  159. */
  160. public function __construct($fast = false) {
  161. $this->initMessages();
  162. $this->loadConfigs();
  163. $this->initDbs();
  164. $this->loadOptionsDDT();
  165. $this->loadChargeOptions();
  166. $this->setOptions();
  167. $this->initDealWithIt();
  168. if (!$fast) {
  169. //full data set load
  170. $this->loadTariffs();
  171. $this->loadUsersDDT();
  172. $this->loadUserData();
  173. }
  174. }
  175. /**
  176. * Inits default system message helper object into protected prop
  177. *
  178. * @return void
  179. */
  180. protected function initMessages() {
  181. $this->messages = new UbillingMessageHelper();
  182. }
  183. /**
  184. * Preloads some required configs for further usage
  185. *
  186. * @global object $ubillingConfig
  187. *
  188. * @return void
  189. */
  190. protected function loadConfigs() {
  191. global $ubillingConfig;
  192. $this->altCfg = $ubillingConfig->getAlter();
  193. if (isset($this->altCfg['DDT_ENDPREVDAYS'])) {
  194. if (!empty($this->altCfg['DDT_ENDPREVDAYS']) and is_numeric($this->altCfg['DDT_ENDPREVDAYS'])) {
  195. $this->prevDaysOffset = $this->altCfg['DDT_ENDPREVDAYS'];
  196. }
  197. }
  198. }
  199. /**
  200. * Inits all requuired database abstraction layers
  201. *
  202. * @return void
  203. */
  204. protected function initDbs() {
  205. $this->usersDb = new NyanORM(self::TABLE_USERS);
  206. $this->optionsDb = new NyanORM(self::TABLE_OPTIONS);
  207. $this->chargeHistDb = new NyanORM(self::TABLE_CHARGESHIST);
  208. $this->chargeOptsDb = new NyanORM(self::TABLE_CHARGEOPTS);
  209. $this->userRegDb = new NyanORM(self::TABLE_USERREG);
  210. }
  211. /**
  212. * Inits dealwithit protected property
  213. *
  214. * @return void
  215. */
  216. protected function initDealWithIt() {
  217. $this->dealwithit = new DealWithIt();
  218. $tmpTasks = $this->dealwithit->getAvailableTasks();
  219. if (!empty($tmpTasks)) {
  220. foreach ($tmpTasks as $io => $each) {
  221. if ($each['action'] == 'tariffchange') {
  222. $this->allTasks[$each['id']] = $each;
  223. }
  224. }
  225. }
  226. }
  227. /**
  228. * Loads existing doomsday tariffs
  229. *
  230. * @return void
  231. */
  232. protected function loadOptionsDDT() {
  233. $this->allOptions = $this->optionsDb->getAll('id');
  234. }
  235. /**
  236. * Loads direct charge options
  237. *
  238. * @return void
  239. */
  240. protected function loadChargeOptions() {
  241. $this->allChargeOpts = $this->chargeOptsDb->getAll('id');
  242. if (!empty($this->allChargeOpts)) {
  243. foreach ($this->allChargeOpts as $io => $each) {
  244. $this->allTariffChargeRules[$each['tariff']] = $each;
  245. }
  246. }
  247. }
  248. /**
  249. * Sets default periods id-s and their localized names
  250. *
  251. * @return void
  252. */
  253. protected function setOptions() {
  254. $this->periods['month'] = __('Month');
  255. $this->periods['day'] = __('Day');
  256. }
  257. /**
  258. * Loads all users data into protected prop
  259. *
  260. * @return void
  261. */
  262. protected function loadUserData() {
  263. $this->allUserData = zb_UserGetAllStargazerDataAssoc();
  264. }
  265. /**
  266. * Loads existing DDT users database
  267. *
  268. * @return void
  269. */
  270. protected function loadUsersDDT() {
  271. $this->allDDTUsers = $this->usersDb->getAll('id');
  272. }
  273. /**
  274. * Loads available system tariffs into protected prop for further usage
  275. *
  276. * @return void
  277. */
  278. protected function loadTariffs() {
  279. $this->allTariffs = zb_TariffGetAllData();
  280. if (!empty($this->allTariffs)) {
  281. foreach ($this->allTariffs as $tariffName => $tariffData) {
  282. $this->allTariffNames[$tariffName] = $tariffName;
  283. }
  284. }
  285. }
  286. /**
  287. * Renders default DDT tariff creation form
  288. *
  289. * @return string
  290. */
  291. public function renderCreateForm() {
  292. $result = '';
  293. if (!empty($this->allTariffNames)) {
  294. $tariffsNewAvail = $this->allTariffNames;
  295. $currentTariffsDDT = $this->getCurrentTariffsDDT();
  296. $currentTariffsCharge = $this->getCurrentChargeTariffs();
  297. if (!empty($currentTariffsDDT)) {
  298. foreach ($currentTariffsDDT as $io => $each) {
  299. unset($tariffsNewAvail[$io]);
  300. }
  301. }
  302. if (!empty($currentTariffsCharge)) {
  303. foreach ($currentTariffsCharge as $io => $each) {
  304. unset($tariffsNewAvail[$io]);
  305. }
  306. }
  307. if (!empty($tariffsNewAvail)) {
  308. $inputs = wf_HiddenInput('createnewddtsignal', 'true');
  309. $inputs .= wf_Selector('createnewddttariff', $tariffsNewAvail, __('Tariff'), '', true);
  310. $inputs .= wf_Selector('createnewddtperiod', $this->periods, __('Period'), '', true);
  311. $inputs .= wf_TextInput('createnewddtduration', __('Duration'), '1', true, 4, 'digits');
  312. $inputs .= wf_CheckInput('createnewddtstartnow', __('Take into account the current period'), true, false);
  313. $inputs .= wf_CheckInput('createnewddtchargefee', __('Charge current tariff fee'), true, false);
  314. $inputs .= wf_TextInput('createnewddtchargeuntilday', __('Charge current tariff fee if day less then'), '1', true, 2, 'digits');
  315. $inputs .= wf_CheckInput('createnewddtsetcredit', __('Set a user credit if the money is not enough to use the service now'), true, false);
  316. $inputs .= wf_Selector('createnewddttariffmove', $this->allTariffNames, __('Move to tariff after ending of periods'), '', true);
  317. $inputs .= wf_delimiter(0);
  318. $inputs .= wf_Submit(__('Create'));
  319. $result .= wf_Form('', 'POST', $inputs, 'glamour');
  320. } else {
  321. $result .= $this->messages->getStyledMessage(__('You already planned doomsday for all of available tariffs'), 'success');
  322. }
  323. } else {
  324. $result .= $this->messages->getStyledMessage(__('No existing tariffs available at all'), 'error');
  325. }
  326. return ($result);
  327. }
  328. /**
  329. * Catches DDT Tariff creation request and creates it into database
  330. *
  331. * @return void/string on error
  332. */
  333. public function createTariffDDT() {
  334. $result = '';
  335. if (ubRouting::checkPost(array('createnewddtsignal', 'createnewddttariff', 'createnewddtperiod', 'createnewddtduration', 'createnewddttariffmove'))) {
  336. $newTariff = ubRouting::post('createnewddttariff');
  337. $newTariff_f = ubRouting::filters($newTariff, 'mres');
  338. $newTariffMove = ubRouting::post('createnewddttariffmove');
  339. $newTariffMove_f = ubRouting::filters($newTariffMove, 'mres');
  340. $newPeriod = ubRouting::post('createnewddtperiod', 'vf');
  341. $newDuration = ubRouting::post('createnewddtduration', 'int');
  342. $newStartNow = (ubRouting::checkPost('createnewddtstartnow')) ? 1 : 0;
  343. $newChargeFee = (ubRouting::checkPost('createnewddtchargefee')) ? 1 : 0;
  344. $newChargeDay = ubRouting::post('createnewddtchargeuntilday', 'int');
  345. $newSetCredit = (ubRouting::checkPost('createnewddtsetcredit')) ? 1 : 0;
  346. $currentTariffsDDT = $this->getCurrentTariffsDDT();
  347. $currentTariffsCharge = $this->getCurrentChargeTariffs();
  348. if ($newTariff != $newTariffMove) {
  349. if (!empty($newDuration)) {
  350. if (!isset($currentTariffsDDT[$newTariff]) and !isset($currentTariffsCharge[$newTariff])) {
  351. $this->optionsDb->data('tariffname', $newTariff_f);
  352. $this->optionsDb->data('period', $newPeriod);
  353. $this->optionsDb->data('startnow', $newStartNow);
  354. $this->optionsDb->data('duration', $newDuration);
  355. $this->optionsDb->data('chargefee', $newChargeFee);
  356. $this->optionsDb->data('chargeuntilday', $newChargeDay);
  357. $this->optionsDb->data('setcredit', $newSetCredit);
  358. $this->optionsDb->data('tariffmove', $newTariffMove_f);
  359. $this->optionsDb->create();
  360. $newId = $this->optionsDb->getLastId();
  361. log_register('DDT CREATE [' . $newId . '] TARIFF `' . $newTariff . '` MOVE ON `' . $newTariffMove . '` IN ' . $newDuration . ' `' . $newPeriod . '`');
  362. } else {
  363. $result = __('You already have doomsday assigned for tariff') . ' ' . $newTariff;
  364. log_register('DDT CREATE FAIL DUPLICATE TARIFF `' . $newTariff . '`');
  365. }
  366. } else {
  367. $result = __('Duration cannot be empty');
  368. log_register('DDT CREATE FAIL EMPTY DURATION');
  369. }
  370. } else {
  371. $result = __('Tariffs must be different');
  372. log_register('DDT CREATE FAIL SAME TARIFFS `' . $newTariff . '`');
  373. }
  374. }
  375. return ($result);
  376. }
  377. /**
  378. * Deletes some doomsday tariff by its ID
  379. *
  380. * @param int $tariffId
  381. *
  382. * @return void/string on error
  383. */
  384. public function deleteTariffDDT($tariffId) {
  385. $result = '';
  386. $tariffId = ubRouting::filters($tariffId, 'int');
  387. if (isset($this->allOptions[$tariffId])) {
  388. $tariffData = $this->allOptions[$tariffId];
  389. $this->optionsDb->where('id', '=', $tariffId);
  390. $this->optionsDb->delete();
  391. log_register('DDT DELETE [' . $tariffId . '] TARIFF `' . $tariffData['tariffname'] . '`');
  392. } else {
  393. $result .= __('Tariff') . ' ' . $tariffId . ' ' . __('Not exists');
  394. log_register('DDT DELETE FAIL [' . $tariffId . '] NOT_EXISTS');
  395. }
  396. return ($result);
  397. }
  398. /**
  399. * Returns list of available ddt tariffs as tariffname=>options
  400. *
  401. * @return array
  402. */
  403. public function getCurrentTariffsDDT() {
  404. $result = array();
  405. if (!empty($this->allOptions)) {
  406. foreach ($this->allOptions as $io => $each) {
  407. $result[$each['tariffname']] = $each;
  408. }
  409. }
  410. return ($result);
  411. }
  412. /**
  413. * Returns list of available charge tariffs as tariffname=>options
  414. *
  415. * @return array
  416. */
  417. public function getCurrentChargeTariffs() {
  418. $result = array();
  419. $result = $this->allTariffChargeRules;
  420. return ($result);
  421. }
  422. /**
  423. * Returns some tariff price
  424. *
  425. * @param string $tariffName
  426. *
  427. * @return float
  428. */
  429. protected function getTariffFee($tariffName) {
  430. $result = 0;
  431. if (isset($this->allTariffs[$tariffName])) {
  432. $result = $this->allTariffs[$tariffName]['Fee'];
  433. }
  434. return ($result);
  435. }
  436. /**
  437. * Renders available DDT tariffs list with some controls
  438. *
  439. * @return string
  440. */
  441. public function renderTariffsList() {
  442. $result = '';
  443. if (!empty($this->allOptions)) {
  444. $cells = wf_TableCell(__('ID'));
  445. $cells .= wf_TableCell(__('Tariff'));
  446. $cells .= wf_TableCell(__('Fee'));
  447. $cells .= wf_TableCell(__('Period'));
  448. $cells .= wf_TableCell(__('Start at this period'));
  449. $cells .= wf_TableCell(__('Duration'));
  450. $cells .= wf_TableCell(__('Charge fee'));
  451. $cells .= wf_TableCell(__('Charge until day'));
  452. $cells .= wf_TableCell(__('Set credit'));
  453. $cells .= wf_TableCell(__('New tariff'));
  454. $cells .= wf_TableCell(__('Fee'));
  455. $cells .= wf_TableCell(__('Actions'));
  456. $rows = wf_TableRow($cells, 'row1');
  457. foreach ($this->allOptions as $io => $each) {
  458. $cells = wf_TableCell($each['id']);
  459. $cells .= wf_TableCell($each['tariffname']);
  460. $cells .= wf_TableCell($this->getTariffFee($each['tariffname']));
  461. $cells .= wf_TableCell($this->periods[$each['period']]);
  462. $cells .= wf_TableCell(web_bool_led($each['startnow']));
  463. $cells .= wf_TableCell($each['duration']);
  464. $cells .= wf_TableCell(web_bool_led($each['chargefee']));
  465. $cells .= wf_TableCell($each['chargeuntilday']);
  466. $cells .= wf_TableCell(web_bool_led($each['setcredit']));
  467. $cells .= wf_TableCell($each['tariffmove']);
  468. $cells .= wf_TableCell($this->getTariffFee($each['tariffmove']));
  469. $deleteUrl = self::URL_ME . '&deleteddtariff=' . $each['id'];
  470. $cancelUrl = self::URL_ME;
  471. $alertLabel = __('Delete') . ' ' . __('Doomsday tariff') . ' ' . $each['tariffname'] . '? ' . $this->messages->getDeleteAlert();
  472. $actLinks = wf_ConfirmDialog($deleteUrl, web_delete_icon(), $alertLabel, '', $cancelUrl, __('Delete'));
  473. $cells .= wf_TableCell($actLinks);
  474. $rows .= wf_TableRow($cells, 'row5');
  475. }
  476. $result .= wf_TableBody($rows, '100%', 0, 'sortable');
  477. } else {
  478. $result .= $this->messages->getStyledMessage(__('There is nothing to watch') . '.', 'info');
  479. }
  480. $result .= wf_delimiter();
  481. $result .= wf_modalAuto(web_icon_create() . ' ' . __('Create new doomsday tariff'), __('Create new doomsday tariff'), $this->renderCreateForm(), 'ubButton');
  482. return ($result);
  483. }
  484. /**
  485. * Checks is user have some tariff moving tasks created already
  486. *
  487. * @param string $userLogin
  488. *
  489. * @return bool
  490. */
  491. protected function isTaskCreated($userLogin) {
  492. $result = false;
  493. if (!empty($this->allTasks)) {
  494. foreach ($this->allTasks as $io => $each) {
  495. if ($each['login'] == $userLogin and $each['action'] == 'tariffchange') {
  496. $result = true;
  497. }
  498. }
  499. }
  500. return ($result);
  501. }
  502. /**
  503. * Checks is user have some tariff moving tasks created already and return task data.
  504. *
  505. * @param string $userLogin
  506. *
  507. * @return array
  508. */
  509. public function getTaskCreated($userLogin) {
  510. $result = array();
  511. if (!empty($this->allTasks)) {
  512. foreach ($this->allTasks as $io => $each) {
  513. if ($each['login'] == $userLogin and $each['action'] == 'tariffchange') {
  514. $result = $each;
  515. }
  516. }
  517. }
  518. return ($result);
  519. }
  520. /**
  521. * Logs first user appear for some DDT tariff
  522. *
  523. * @param string $login
  524. * @param string $userTariff
  525. * @param string $targetDate
  526. * @param string $nextTariff
  527. * @param int $dwiid
  528. *
  529. * @return void
  530. */
  531. protected function logSchedule($login, $userTariff, $targetDate, $nextTariff, $dwiid) {
  532. $curDateTime = curdatetime();
  533. $this->usersDb->data('login', $login);
  534. $this->usersDb->data('active', '1');
  535. $this->usersDb->data('startdate', $curDateTime);
  536. $this->usersDb->data('curtariff', $userTariff);
  537. $this->usersDb->data('enddate', $targetDate);
  538. $this->usersDb->data('nexttariff', $nextTariff);
  539. $this->usersDb->data('dwiid', $dwiid);
  540. $this->usersDb->create();
  541. }
  542. /**
  543. * Runs DDT tariffs periodic processing
  544. *
  545. * @global object $billing
  546. *
  547. * @return void
  548. */
  549. public function runProcessing() {
  550. global $billing;
  551. if (!empty($this->allOptions)) {
  552. if (!empty($this->allUserData)) {
  553. $ddtTariffs = $this->getCurrentTariffsDDT();
  554. foreach ($this->allUserData as $eachUserLogin => $eachUserData) {
  555. $currentUserTariff = $eachUserData['Tariff'];
  556. if (isset($ddtTariffs[$currentUserTariff])) {
  557. //yep, this is DDT user
  558. if (!$this->isTaskCreated($eachUserLogin)) {
  559. //no existing move task
  560. $currentTariffOptions = $ddtTariffs[$currentUserTariff];
  561. $tariffPeriod = $currentTariffOptions['period'];
  562. $tariffDuration = $currentTariffOptions['duration'];
  563. $moveTariff = $currentTariffOptions['tariffmove'];
  564. $currentDate = curdate();
  565. $currentDayNum = date("j");
  566. $targetDate = '';
  567. if ($tariffPeriod == 'month') {
  568. if ($currentTariffOptions['startnow']) {
  569. $tariffDuration = $tariffDuration - 1;
  570. }
  571. $targetDate = date('Y-m-t', strtotime("+" . $tariffDuration . " months", strtotime($currentDate)));
  572. //optional "before end of month" date offset
  573. if ($this->prevDaysOffset) {
  574. $targetDate = date('Y-m-d', strtotime("-" . $this->prevDaysOffset . " days", strtotime($targetDate)));
  575. }
  576. }
  577. if ($tariffPeriod == 'day') {
  578. if ($currentTariffOptions['startnow']) {
  579. $tariffDuration = $tariffDuration - 1;
  580. }
  581. $targetDate = date('Y-m-d', strtotime("+" . $tariffDuration . " days", strtotime($currentDate)));
  582. }
  583. if (!empty($targetDate)) {
  584. //creating scheduled task for move
  585. $newDwiid = $this->dealwithit->createTask($targetDate, $eachUserLogin, 'tariffchange', $moveTariff, __('Doomsday tariff') . ': ' . $currentTariffOptions['tariffname']);
  586. //writing some history
  587. $this->logSchedule($eachUserLogin, $currentUserTariff, $targetDate, $moveTariff, $newDwiid);
  588. //charge some fee if required
  589. if ($currentTariffOptions['chargefee']) {
  590. if ($currentTariffOptions['chargeuntilday']) {
  591. if ($currentTariffOptions['chargeuntilday'] >= $currentDayNum) {
  592. $nativeTariffData = $this->allTariffs[$currentUserTariff];
  593. $nativeTariffFee = $nativeTariffData['Fee'];
  594. $nativeTariffPeriod = (isset($nativeTariffData['period'])) ? $nativeTariffData['period'] : 'month';
  595. log_register('DDT FEE CHARGE (' . $eachUserLogin . ') TARIFF `' . $currentUserTariff . '` ON -' . $nativeTariffFee);
  596. zb_CashAdd($eachUserLogin, '-' . $nativeTariffFee, 'correct', 1, 'DDT: ' . $currentUserTariff);
  597. //setting credit if required
  598. if ($currentTariffOptions['setcredit']) {
  599. $currentUserBalance = $eachUserData['Cash'];
  600. $nextUserBalance = $currentUserBalance - $nativeTariffFee;
  601. if ($nextUserBalance < '-' . $eachUserData['Credit']) {
  602. $newUserCredit = abs($nextUserBalance);
  603. //set credit
  604. $billing->setcredit($eachUserLogin, $newUserCredit);
  605. log_register('DDT CHANGE Credit (' . $eachUserLogin . ') ON ' . $newUserCredit);
  606. //set credit expire date
  607. if ($tariffPeriod == 'month') {
  608. $tariffExpireDate = date('Y-m-t');
  609. }
  610. if ($tariffPeriod == 'day') {
  611. $tariffExpireDate = date('Y-m-d', strtotime("+3 days", strtotime($currentDate)));
  612. }
  613. $billing->setcreditexpire($eachUserLogin, $tariffExpireDate);
  614. log_register('DDT CHANGE CreditExpire (' . $eachUserLogin . ') ON ' . $tariffExpireDate);
  615. }
  616. }
  617. }
  618. }
  619. }
  620. }
  621. }
  622. }
  623. }
  624. } else {
  625. log_register('DDT RUN FAIL NO_USERS');
  626. }
  627. } else {
  628. log_register('DDT RUN FAIL NO_TARIFFS');
  629. }
  630. }
  631. /**
  632. * Renders module controls
  633. *
  634. * @return string
  635. */
  636. public function renderControls() {
  637. $result = '';
  638. if (cfr('DDTCONF')) {
  639. $result .= wf_Link(self::URL_ME, web_icon_extended() . ' ' . __('Configuration'), false, 'ubButton');
  640. }
  641. $result .= wf_Link(self::URL_HIST, wf_img('skins/icon_calendar.gif') . ' ' . __('Doomsday tariffs history'), false, 'ubButton');
  642. $result .= wf_Link(self::URL_HIST . self::URL_CH_HIST, wf_img('skins/icon_dollar_16.gif') . ' ' . __('Forced charges history'), false, 'ubButton');
  643. return ($result);
  644. }
  645. /**
  646. * Renders history report container
  647. *
  648. * @param string $userLogin
  649. *
  650. * @return string
  651. */
  652. public function renderHistoryContainer($userLogin = '') {
  653. $result = '';
  654. if (!empty($this->allDDTUsers)) {
  655. $opts = '"order": [[ 1, "desc" ]]';
  656. $ajaxUrl = self::URL_HIST . '&ajax=true';
  657. $userControls = '';
  658. if ($userLogin) {
  659. $ajaxUrl .= '&username=' . $userLogin;
  660. $userControls = wf_delimiter(0) . web_UserControls($userLogin);
  661. }
  662. $columns = array('User', 'Date', 'Tariff', 'End date', 'New tariff', 'Deal with it');
  663. $result .= wf_JqDtLoader($columns, $ajaxUrl, false, __('Users'), 100, $opts);
  664. $result .= $userControls;
  665. } else {
  666. $result .= $this->messages->getStyledMessage(__('There is nothing to watch'), 'warning');
  667. }
  668. return ($result);
  669. }
  670. /**
  671. * Renders DDT history report json data
  672. *
  673. * @return void
  674. */
  675. public function getHistoryAjax() {
  676. $json = new wf_JqDtHelper();
  677. $loginFilter = ubRouting::get('username');
  678. if (!empty($this->allDDTUsers)) {
  679. $userFullData = zb_UserGetAllDataCache();
  680. foreach ($this->allDDTUsers as $io => $each) {
  681. $userLink = isset($userFullData[$each['login']]) ? wf_Link(self::URL_PROFILE . $each['login'], web_profile_icon() . ' ' . $userFullData[$each['login']]['fulladress']) : $each['login'];
  682. $data[] = $userLink;
  683. $data[] = $each['startdate'];
  684. $data[] = $each['curtariff'];
  685. $data[] = $each['enddate'];
  686. $data[] = $each['nexttariff'];
  687. $dwiLink = wf_Link(self::URL_DWI . $each['login'], $each['dwiid']);
  688. $data[] = $dwiLink;
  689. if (empty($loginFilter)) {
  690. $json->addRow($data);
  691. } else {
  692. if ($each['login'] == $loginFilter) {
  693. $json->addRow($data);
  694. }
  695. }
  696. unset($data);
  697. }
  698. }
  699. $json->getJson();
  700. }
  701. /**
  702. * Render available tariffs charge opts here
  703. *
  704. * @return void
  705. */
  706. public function renderChargeOpsList() {
  707. $result = '';
  708. if (!empty($this->allChargeOpts)) {
  709. $cells = wf_TableCell(__('ID'));
  710. $cells .= wf_TableCell(__('Tariff'));
  711. $cells .= wf_TableCell(__('Fee'));
  712. $cells .= wf_TableCell(__('Charge until day'));
  713. $cells .= wf_TableCell(__('Charge fee'));
  714. $cells .= wf_TableCell(__('Additional amount'));
  715. $cells .= wf_TableCell(__('Credit days'));
  716. $cells .= wf_TableCell(__('Actions'));
  717. $rows = wf_TableRow($cells, 'row1');
  718. foreach ($this->allChargeOpts as $io => $each) {
  719. $tariffFee = $this->getTariffFee($each['tariff']);
  720. $cells = wf_TableCell($each['id']);
  721. $cells .= wf_TableCell($each['tariff']);
  722. $cells .= wf_TableCell($tariffFee);
  723. $udayLabel = ($each['untilday']) ? $each['untilday'] : __('Any');
  724. $cells .= wf_TableCell($udayLabel);
  725. $cells .= wf_TableCell(web_bool_led($each['chargefee']));
  726. $absLabel = ($each['absolute']) ? $each['absolute'] : __('No');
  727. $cells .= wf_TableCell($absLabel);
  728. $credLabel = ($each['creditdays']) ? $each['creditdays'] : __('No');
  729. $cells .= wf_TableCell($credLabel);
  730. $deleteUrl = self::URL_ME . '&' . self::ROUTE_CH_DELETE . '=' . $each['id'];
  731. $cancelUrl = self::URL_ME;
  732. $alertLabel = __('Delete') . ' ' . __('rule for') . ' ' . $each['tariff'] . '? ' . $this->messages->getDeleteAlert();
  733. $actLinks = wf_ConfirmDialog($deleteUrl, web_delete_icon(), $alertLabel, '', $cancelUrl, __('Delete'));
  734. $cells .= wf_TableCell($actLinks);
  735. $rows .= wf_TableRow($cells, 'row5');
  736. }
  737. $result .= wf_TableBody($rows, '100%', 0, 'sortable');
  738. } else {
  739. $result .= $this->messages->getStyledMessage(__('Nothing to show'), 'info');
  740. }
  741. $result .= wf_delimiter(0);
  742. $result .= wf_modalAuto(wf_img('skins/icon_dollar_16.gif') . ' ' . __('Create new forced charge rule'), __('Create new forced charge rule'), $this->renderChargeOptsCreateForm(), 'ubButton');
  743. return ($result);
  744. }
  745. /**
  746. * Renders charge opts rule creation form
  747. *
  748. * @return void
  749. */
  750. public function renderChargeOptsCreateForm() {
  751. $result = '';
  752. $tariffParams = array();
  753. $dayParams = array();
  754. $currentTariffsDDT = $this->getCurrentTariffsDDT();
  755. $currentTariffsCharge = $this->getCurrentChargeTariffs();
  756. if (!empty($this->allTariffNames)) {
  757. foreach ($this->allTariffNames as $io => $each) {
  758. if (!isset($currentTariffsDDT[$each]) and !isset($currentTariffsCharge[$each])) {
  759. $tariffParams[$each] = $each;
  760. }
  761. }
  762. }
  763. $dayParams[0] = __('Any');
  764. for ($i = 1; $i <= 31; $i++) {
  765. $dayParams[$i] = $i;
  766. }
  767. if (!empty($tariffParams)) {
  768. $inputs = wf_HiddenInput(self::PROUTE_CH_CREATE, 'true');
  769. $inputs .= wf_Selector(self::PROUTE_CH_TARIFF, $tariffParams, __('Tariff'), '', true);
  770. $inputs .= wf_Selector(self::PROUTE_CH_UDAY, $dayParams, __('Charge current tariff fee if day less then'), '', true);
  771. $inputs .= wf_CheckInput(self::PROUTE_CH_FEE, __('Charge current tariff fee'), true, true);
  772. $inputs .= wf_TextInput(self::PROUTE_CH_ABS, __('Also additionally withdraw the following amount'), '', true, 4, 'digits');
  773. $inputs .= wf_TextInput(self::PROUTE_CH_CREDITDAYS, __('Set a credit, for so many days'), '', true, 4, 'digits');
  774. $inputs .= wf_delimiter(0);
  775. $inputs .= wf_Submit(__('Create'));
  776. $result .= wf_Form('', 'POST', $inputs, 'glamour');
  777. } else {
  778. $result .= $this->messages->getStyledMessage(__('Something went wrong'), 'error');
  779. }
  780. return ($result);
  781. }
  782. /**
  783. * Creates new forsed charge rule database record
  784. *
  785. * @return void|string on error
  786. */
  787. public function createChargeRule() {
  788. $result = '';
  789. if (ubRouting::checkPost(array(self::PROUTE_CH_CREATE, self::PROUTE_CH_TARIFF))) {
  790. $newTariff = ubRouting::post(self::PROUTE_CH_TARIFF);
  791. $newTariff_f = ubRouting::filters($newTariff, 'mres');
  792. $uDay = ubRouting::post(self::PROUTE_CH_UDAY, 'int');
  793. $feeFlag = (ubRouting::checkPost(self::PROUTE_CH_FEE)) ? 1 : 0;
  794. $absValue = (ubRouting::checkPost(self::PROUTE_CH_ABS)) ? ubRouting::post(self::PROUTE_CH_ABS, 'int') : 0;
  795. $creditDays = (ubRouting::checkPost(self::PROUTE_CH_CREDITDAYS)) ? ubRouting::post(self::PROUTE_CH_CREDITDAYS, 'int') : 0;
  796. $currentTariffsDDT = $this->getCurrentTariffsDDT();
  797. $currentTariffsCharge = $this->getCurrentChargeTariffs();
  798. if (!isset($currentTariffsDDT[$newTariff]) and !isset($currentTariffsCharge[$newTariff])) {
  799. $this->chargeOptsDb->data('tariff', $newTariff_f);
  800. $this->chargeOptsDb->data('untilday', $uDay);
  801. $this->chargeOptsDb->data('chargefee', $feeFlag);
  802. $this->chargeOptsDb->data('absolute', $absValue);
  803. $this->chargeOptsDb->data('creditdays', $creditDays);
  804. $this->chargeOptsDb->create();
  805. $newId = $this->chargeOptsDb->getLastId();
  806. log_register('DDT CHARGE CREATE [' . $newId . '] TARIFF `' . $newTariff . '`');
  807. } else {
  808. $result = __('You already have doomsday assigned for tariff') . ' ' . $newTariff;
  809. log_register('DDT CHARGE CREATE FAIL DUPLICATE TARIFF `' . $newTariff . '`');
  810. }
  811. return ($result);
  812. }
  813. }
  814. /**
  815. * Deletes some tariff charge rule by its ID
  816. *
  817. * @param int $tariffId
  818. *
  819. * @return void/string on error
  820. */
  821. public function deleteChargeRule($ruleId) {
  822. $result = '';
  823. $ruleId = ubRouting::filters($ruleId, 'int');
  824. if (isset($this->allChargeOpts[$ruleId])) {
  825. $ruleData = $this->allChargeOpts[$ruleId];
  826. $this->chargeOptsDb->where('id', '=', $ruleId);
  827. $this->chargeOptsDb->delete();
  828. log_register('DDT DELETE [' . $ruleId . '] TARIFF `' . $ruleData['tariff'] . '`');
  829. } else {
  830. $result .= __('Forced tariffs charge') . ' [' . $ruleId . '] ' . __('Not exists');
  831. log_register('DDT CHARGE DELETE FAIL [' . $ruleId . '] NOT_EXISTS');
  832. }
  833. return ($result);
  834. }
  835. /**
  836. * Returns array of users charged today as login=>histData
  837. *
  838. * @return array
  839. */
  840. protected function getTodayChargedUsers() {
  841. $result = array();
  842. $curDay = curdate();
  843. $this->chargeHistDb->where('chargedate', '=', $curDay);
  844. $result = $this->chargeHistDb->getAll('login');
  845. return ($result);
  846. }
  847. /**
  848. * Returns array of users registered today as login=>regData
  849. *
  850. * @return array
  851. */
  852. protected function getUsersRegisteredToday() {
  853. $result = array();
  854. $curDay = curdate();
  855. $this->userRegDb->where('date', 'LIKE', $curDay . '%');
  856. $result = $this->userRegDb->getAll('login');
  857. return ($result);
  858. }
  859. /**
  860. * Creates new history record for some user forsed tariff charge
  861. *
  862. * @param string $login
  863. * @param string $chargeDate
  864. * @param string $tariff
  865. * @param foat $summ
  866. *
  867. * @return void
  868. */
  869. protected function logCharge($login, $chargeDate, $tariff, $summ) {
  870. $login = ubRouting::filters($login, 'login');
  871. $chargeDate = ubRouting::filters($chargeDate, 'mres');
  872. $tariff = ubRouting::filters($tariff, 'mres');
  873. $summ = ubRouting::filters($summ, 'mres');
  874. $this->chargeHistDb->data('login', $login);
  875. $this->chargeHistDb->data('chargedate', $chargeDate);
  876. $this->chargeHistDb->data('tariff', $tariff);
  877. $this->chargeHistDb->data('summ', $summ);
  878. $this->chargeHistDb->create();
  879. }
  880. /**
  881. * Performs forced tariffs charge ruleset processing
  882. *
  883. * @return void
  884. */
  885. public function runChargeRules() {
  886. global $billing;
  887. if (!empty($this->allTariffChargeRules)) {
  888. $todayUsers = $this->getUsersRegisteredToday();
  889. if (!empty($todayUsers)) {
  890. $chargedUsers = $this->getTodayChargedUsers();
  891. $chargeTariffs = $this->getCurrentChargeTariffs();
  892. foreach ($todayUsers as $eachUserLogin => $regData) {
  893. $eachUserData = $this->allUserData[$eachUserLogin];
  894. $currentUserTariff = $eachUserData['Tariff'];
  895. if (isset($chargeTariffs[$currentUserTariff])) {
  896. //yep, this this tariff have charge rule
  897. if (!isset($chargedUsers[$eachUserLogin])) {
  898. //not charged today yet
  899. $chargeRuleData = $chargeTariffs[$currentUserTariff];
  900. $chargeUntilDay = $chargeRuleData['untilday'] ? $chargeRuleData['untilday'] : 0;
  901. $chargeAllowed = ($chargeUntilDay == 0) ? true : false;
  902. $absValue = $chargeRuleData['absolute'];
  903. $feeFlag = ($chargeRuleData['chargefee']) ? true : false;
  904. $creditDays = ($chargeRuleData['creditdays']) ? $chargeRuleData['creditdays'] : 0;
  905. $currentDate = curdate();
  906. $currentDayNum = date("j");
  907. if (!$chargeAllowed) {
  908. if ($currentDayNum <= $chargeUntilDay) {
  909. $chargeAllowed = true;
  910. }
  911. }
  912. $nativeTariffData = $this->allTariffs[$currentUserTariff];
  913. $nativeTariffFee = $nativeTariffData['Fee'];
  914. $nativeTariffPeriod = (isset($nativeTariffData['period'])) ? $nativeTariffData['period'] : 'month';
  915. $currentUserBalance = $eachUserData['Cash'];
  916. $expectedUserBalance = $currentUserBalance;
  917. $chargeFeeAmount = 0;
  918. //is nowdays valid for charging this tariff?
  919. if ($chargeAllowed) {
  920. //native tariff fee charge?
  921. if ($feeFlag) {
  922. $expectedUserBalance = $expectedUserBalance - $nativeTariffFee;
  923. $chargeFeeAmount += $nativeTariffFee;
  924. }
  925. //charge absolute value
  926. if ($absValue) {
  927. $expectedUserBalance = $expectedUserBalance - $absValue;
  928. $chargeFeeAmount += $absValue;
  929. }
  930. //is any credit required?
  931. if ($expectedUserBalance < 0) {
  932. if ($creditDays) {
  933. $newUserCredit = abs($expectedUserBalance);
  934. //set some credit
  935. $billing->setcredit($eachUserLogin, $newUserCredit);
  936. log_register('DDT CHANGE Credit (' . $eachUserLogin . ') ON ' . $newUserCredit);
  937. //and expire date
  938. $tariffExpireDate = date('Y-m-d', strtotime("+" . $creditDays . " days", strtotime($currentDate)));
  939. $billing->setcreditexpire($eachUserLogin, $tariffExpireDate);
  940. log_register('DDT CHANGE CreditExpire (' . $eachUserLogin . ') ON ' . $tariffExpireDate);
  941. }
  942. }
  943. //charging from user
  944. log_register('DDT FORCED CHARGE (' . $eachUserLogin . ') TARIFF `' . $currentUserTariff . '` ON -' . $chargeFeeAmount);
  945. $chargeComment = 'DDT: ' . $currentUserTariff;
  946. zb_CashAdd($eachUserLogin, '-' . $chargeFeeAmount, 'correct', 1, $chargeComment);
  947. $this->logCharge($eachUserLogin, $currentDate, $currentUserTariff, $chargeFeeAmount);
  948. $chargedUsers[$eachUserLogin] = array(); //preventing multiple charge this user
  949. }
  950. }
  951. }
  952. }
  953. }
  954. }
  955. }
  956. /**
  957. * Renders forced charges history report container
  958. *
  959. * @return string
  960. */
  961. public function renderChargesHistoryContainer() {
  962. $result = '';
  963. if (!empty($this->allDDTUsers)) {
  964. $opts = '"order": [[ 1, "desc" ]]';
  965. $ajaxUrl = self::URL_ME . '&' . self::ROUTE_CH_HISTAJX . '=true';
  966. $columns = array('User', 'Date', 'Tariff', 'Sum');
  967. $result .= wf_JqDtLoader($columns, $ajaxUrl, false, __('Users'), 100, $opts);
  968. } else {
  969. $result .= $this->messages->getStyledMessage(__('There is nothing to watch'), 'warning');
  970. }
  971. return ($result);
  972. }
  973. /**
  974. * Renders DDT history report json data
  975. *
  976. * @return void
  977. */
  978. public function getChargesHistoryAjax() {
  979. $json = new wf_JqDtHelper();
  980. $allChargesHistory = $this->chargeHistDb->getAll();
  981. if (!empty($allChargesHistory)) {
  982. $userFullData = zb_UserGetAllDataCache();
  983. foreach ($allChargesHistory as $io => $each) {
  984. $userLink = isset($userFullData[$each['login']]) ? wf_Link(self::URL_PROFILE . $each['login'], web_profile_icon() . ' ' . $userFullData[$each['login']]['fulladress']) : $each['login'];
  985. $data[] = $userLink;
  986. $data[] = $each['chargedate'];
  987. $data[] = $each['tariff'];
  988. $data[] = $each['summ'];
  989. $json->addRow($data);
  990. unset($data);
  991. }
  992. }
  993. $json->getJson();
  994. }
  995. }