VoIPAmsImport.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. <?php
  2. Lib::loadClass('RouteBase');
  3. Lib::loadClass('ProcesHelper');
  4. class Route_UrlAction_VoIPAmsImport extends RouteBase {
  5. private $fields = [
  6. "Data początkowa" => [
  7. "name" => "date",
  8. "regex" => "/^[[:digit:]]{4}(-[[:digit:]]{2}){2} [[:digit:]]{2}(:[[:digit:]]{2}){2}$/",
  9. "sqlType" => "datetime",
  10. ],
  11. "Numer abonenta" => [
  12. "name" => "number",
  13. "regex" => "/^[[:digit:]]{11}$/",
  14. "sqlType" => "varchar(11)",
  15. ],
  16. "Koszt netto" => [
  17. "name" => "cost",
  18. "regex" => "/^[[:digit:]]+,[[:digit:]]{2}$/",
  19. "sqlType" => "decimal(10,2)",
  20. "replace" => [
  21. "from" => ",",
  22. "to" => ".",
  23. ],
  24. ],
  25. ];
  26. public function handleAuth() {
  27. if (!User::logged()) {
  28. throw new HttpException('Unauthorized', 401);
  29. }
  30. }
  31. private function parseCsv($file) {
  32. if (!file_exists($file)) Throw new Exception("CSV file error #1 - File not found.");
  33. $csv = array_map(function ($line) {
  34. return str_getcsv(trim($line), ";");
  35. }, file($file));
  36. array_walk($csv, function(&$a) use ($csv) {
  37. if (count($csv[0]) != count($a)) throw new Exception("CSV file error #2 - Wrong fields count.");
  38. $a = array_combine($csv[0], $a);
  39. });
  40. array_shift($csv);
  41. $csv = array_filter($csv, function($a) {
  42. //if (($a['TG wych.'] == '-1') || (!$a['TG wych.'])) return false;
  43. if ($a['Koszt netto'] == '0,00') return false;
  44. return true;
  45. });
  46. array_walk($csv, function(&$a) {
  47. $result = [];
  48. foreach ($this->fields as $k => $v) {
  49. if (!isset($a[$k])) throw new Exception("CSV file error #3 - Field \"{$k}\" not found.");
  50. if (!preg_match($v["regex"], $a[$k])) throw new Exception("CSV file error #4 - Bad value of \"{$k}\" ({$a[$k]}).");
  51. if (isset($v["replace"])) $result[$v["name"]] = str_replace($v["replace"]["from"], $v["replace"]["to"], $a[$k]);
  52. else $result[$v["name"]] = $a[$k];
  53. }
  54. $a = $result;
  55. });
  56. return array_values($csv);
  57. }
  58. private function importCsv() {
  59. if (!isset($_FILES['csv'])) throw new Exception("Błąd formularza");
  60. if ($_FILES['csv']['type'] != "text/csv") throw new Exception("Błędny plik CSV");
  61. $csv = $this->parseCsv($_FILES['csv']['tmp_name']);
  62. $csvPost = base64_encode(gzcompress(json_encode($csv)));
  63. $_SESSION['VoIPAmsImportReady'] = true;
  64. ?>
  65. <div class="container" style="margin-top:20px">
  66. <form class="form-horizontal" method="post" enctype="multipart/form-data">
  67. <legend>
  68. Znalezione rekordy billingowe do zafakurowania
  69. </legend>
  70. <div class="col-sm-offset-2 col-sm-8">
  71. <div style="text-align:center;">
  72. <input type="hidden" name="csv" value="<?=$csvPost?>"/>
  73. <button type="submit" class="btn btn-primary" name="action" value="doImportCsv">Importuj</button>
  74. </div>
  75. <hr/>
  76. <table class="table table-bordered table-hover table-striped">
  77. <thead>
  78. <tr style="text-align:center; background-color:lightgray"><td width="19%">Lp.</td><td>Data połączenia</td><td>Numer klienta</td><td>Koszt netto połączenia</td></tr>
  79. </thead>
  80. <tbody>
  81. <?php
  82. foreach ($csv as $i => $v) {
  83. echo "<tr><td>" . ($i + 1) . "</td>";
  84. foreach ($this->fields as $field) echo "<td> " . $v[$field["name"]] . "</td>";
  85. echo "</tr>\n";
  86. }
  87. ?>
  88. </tbody>
  89. </table>
  90. </div>
  91. </form>
  92. </div>
  93. <?php
  94. }
  95. private function doQuery($query) {
  96. try {
  97. return DB::getPDO()->query($query);
  98. } catch (Exception $e) {
  99. throw new Exception("Wystąpił problem z zapytaniem SQL: {$query}<br/>{$e->getMessage()}");
  100. }
  101. }
  102. private function doImportCsv() {
  103. if (!isset($_SESSION['VoIPAmsImportReady'])) throw new Exception("Błąd formularza");
  104. unset($_SESSION['VoIPAmsImportReady']);
  105. $csv = json_decode(gzuncompress(base64_decode(V::get('csv','',$_POST))), true);
  106. if (!$csv) throw new Exception("Błąd formularza");
  107. $createColumns = []; $keys = []; $columns = [];
  108. foreach ($this->fields as $field) {
  109. $createColumns[] = "`{$field['name']}` {$field['sqlType']} NOT NULL";
  110. $keys[] = "KEY `{$field['name']}` (`{$field['name']}`)";
  111. $columns[] = $field['name'];
  112. }
  113. $queries = [];
  114. $queries[] = "create temporary table `tmp_VoIPAmsImport` (" . implode(", ", array_merge($createColumns, $keys)) . ")";
  115. foreach ($csv as $v) {
  116. $values = [];
  117. foreach ($this->fields as $field) $values["`{$field['name']}`"] = "'{$v[$field['name']]}'";
  118. $queries[] = "insert into `tmp_VoIPAmsImport` (" . implode(", ", array_keys($values)) . ") values (" . implode(", ", $values) . ")";
  119. }
  120. $queries[] = <<<EOT
  121. create temporary table `tmp_VoIPAmsImport2`
  122. select sesa.ID_SERVICES, sesa.ID_BILLING_USERS, '16' as TYPE, DATE_FORMAT(tmp.`date`,'%Y-%m') as VALUE1, sum(round(tmp.`cost`,2)) as VALUE2,
  123. '1' as NODE_ID, NULL as EXTERNAL_ID,'0' as TAB_UPDATE_STAT, 'ZAIMPORTOWANO PRZEZ VoIPAmsImport' as TAB_UPDATE_INFO
  124. from `tmp_VoIPAmsImport` tmp left join SES_VOIP_A sesa on sesa.S_ALIAS=tmp.number
  125. where sesa.ID_SERVICES IS NOT NULL
  126. group by sesa.ID_SERVICES, VALUE1
  127. having VALUE2>0
  128. EOT;
  129. foreach ($queries as $query) $this->doQuery($query);
  130. $result = DB::getPDO()->fetchFirst("select count(*) as `count`, sum(VALUE2) as `sum` from `tmp_VoIPAmsImport2`");
  131. $sumFromCsv = DB::getPDO()->fetchValue("select sum(`cost`) from `tmp_VoIPAmsImport`");
  132. $query = <<<EOT
  133. insert into SES_VOIP_C (ID_SERVICES, ID_BILLING_USERS, TYPE, VALUE1, VALUE2, NODE_ID, EXTERNAL_ID, TAB_UPDATE_STAT, TAB_UPDATE_INFO)
  134. select * from `tmp_VoIPAmsImport2`
  135. EOT;
  136. $this->doQuery($query);
  137. SE_Layout::alert('success', "Z powodzeniem zaimportowano " . count($csv) . " rekordów billingowych ({$result['count']} pozycji do faktur na łączną kwotę {$result['sum']} zł netto; suma wynikająca z pliku CSV - {$sumFromCsv})");
  138. $this->form();
  139. }
  140. private function form() {
  141. ?>
  142. <div class="container" style="margin-top:20px">
  143. <form class="form-horizontal" method="post" enctype="multipart/form-data">
  144. <legend>
  145. Importowanie danych billingowych połączeń telefonicznych z platformy AMS
  146. </legend>
  147. <label class="col-sm-2 control-label">Wgraj plik</label>
  148. <div class="col-sm-10" style="margin-top:3px;">
  149. <input type="hidden" name="action" value="importCsv"/>
  150. <input type="file" name="csv" onchange="javascript:this.form.submit();"/>
  151. </div>
  152. </div>
  153. </form>
  154. </div>
  155. <?php
  156. }
  157. public function defaultAction() {
  158. SE_Layout::gora();
  159. SE_Layout::menu();
  160. try {
  161. $action = V::get('action','',$_POST);
  162. $actions = [
  163. "importCsv",
  164. "doImportCsv"
  165. ];
  166. if (in_array($action, $actions)) $this->$action();
  167. else $this->form();
  168. } catch (Exception $e) {
  169. SE_Layout::alert('danger',$e->getMessage());
  170. $this->form();
  171. }
  172. SE_Layout::dol();
  173. }
  174. }