1 | <?php
|
---|
2 |
|
---|
3 | class PageFinanceManage extends Page
|
---|
4 | {
|
---|
5 | function __construct(System $System)
|
---|
6 | {
|
---|
7 | parent::__construct($System);
|
---|
8 | $this->Title = 'Správa financí';
|
---|
9 | $this->ParentClass = 'PageFinance';
|
---|
10 | }
|
---|
11 |
|
---|
12 | function Show(): string
|
---|
13 | {
|
---|
14 | $Output = '';
|
---|
15 | if (!ModuleUser::Cast($this->System->GetModule('User'))->User->CheckPermission('Finance', 'Manage'))
|
---|
16 | return 'Nemáte oprávnění';
|
---|
17 |
|
---|
18 | if (array_key_exists('Operation', $_GET)) $Operation = $_GET['Operation'];
|
---|
19 | else $Operation = '';
|
---|
20 | switch ($Operation)
|
---|
21 | {
|
---|
22 | case 'Recalculate':
|
---|
23 | $Output .= ModuleFinance::Cast($this->System->GetModule('Finance'))->Finance->RecalculateMemberPayment();
|
---|
24 | break;
|
---|
25 | case 'ShowMonthlyPayment':
|
---|
26 | $Output = $this->ShowMonthlyPayment();
|
---|
27 | break;
|
---|
28 | case 'ProcessMonthlyPayment':
|
---|
29 | $Output = $this->ProcessMonthlyPayment();
|
---|
30 | break;
|
---|
31 | case 'GenerateBills':
|
---|
32 | $Output = $this->GenerateBills();
|
---|
33 | break;
|
---|
34 | case 'RegenerateInvoice':
|
---|
35 | $Output = $this->GenerateInvoice('AND (Id='.$_GET['i'].')');
|
---|
36 | break;
|
---|
37 | case 'RegenerateOperation':
|
---|
38 | $Output = $this->GenerateOperation('AND (Id='.$_GET['i'].')');
|
---|
39 | break;
|
---|
40 | case 'SendPaymentEmail':
|
---|
41 | $Output = $this->SendPaymentEmail($_GET['i']);
|
---|
42 | break;
|
---|
43 | default:
|
---|
44 | //$Output .= '<a href="?Operation=Recalculate">Přepočet financí</a><br />';
|
---|
45 | $Output .= '<a href="?Operation=ShowMonthlyPayment">Měsíční vyúčtování</a><br />';
|
---|
46 | $Output .= '<a href="'.$this->System->Link('/finance/zivnost/').'">Živnost</a><br />';
|
---|
47 | $Output .= '<a href="?Operation=GenerateBills">Generovat chybějící doklady</a><br />';
|
---|
48 | $Output .= '<a href="'.$this->System->Link('/finance/import/').'">Import plateb</a><br />';
|
---|
49 | }
|
---|
50 | return $Output;
|
---|
51 | }
|
---|
52 |
|
---|
53 | /* Get first day and last day of given billing period. Periods are aligned with year start/end. */
|
---|
54 | function GetBillingPeriod(int $Period): array
|
---|
55 | {
|
---|
56 | $Time = time();
|
---|
57 | $Year = date('Y', $Time);
|
---|
58 |
|
---|
59 | $MonthCount = ModuleFinance::Cast($this->System->GetModule('Finance'))->Finance->BillingPeriods[$Period]['MonthCount'];
|
---|
60 | if ($MonthCount <= 0) return array('From' => NULL, 'To' => NULL, 'MonthCount' => 0);
|
---|
61 | $MonthCurrent = date('n', $Time);
|
---|
62 |
|
---|
63 | /* Get start and end of aligned period */
|
---|
64 | $MonthFrom = floor(($MonthCurrent - 1) / $MonthCount) * $MonthCount + 1;
|
---|
65 | $MonthTo = $MonthFrom + $MonthCount - 1;
|
---|
66 |
|
---|
67 | /* Use period from current month to end month so months before current month are cut out */
|
---|
68 | $MonthCount = $MonthTo - $MonthCurrent + 1;
|
---|
69 | $MonthFrom = $MonthCurrent;
|
---|
70 |
|
---|
71 | /* Get first and last day of period */
|
---|
72 | $PeriodFrom = mktime(0, 0, 0, $MonthFrom, 1, $Year);
|
---|
73 | $PeriodTo = mktime(0, 0, 0, $MonthTo, date('t', mktime(0, 0, 0, $MonthTo, 1, $Year)), $Year);
|
---|
74 |
|
---|
75 | return array('From' => $PeriodFrom, 'To' => $PeriodTo, 'MonthCount' => $MonthCount);
|
---|
76 | }
|
---|
77 |
|
---|
78 | function ShowMonthlyPayment(): string
|
---|
79 | {
|
---|
80 | if (!ModuleUser::Cast($this->System->GetModule('User'))->User->CheckPermission('Finance', 'Manage')) return 'Nemáte oprávnění';
|
---|
81 | $SQL = 'SELECT `Member`.*, `MemberPayment`.`MonthlyTotal` AS `Monthly`, '.
|
---|
82 | '`MemberPayment`.`Cash` AS `Cash`, '.
|
---|
83 | '(SELECT GROUP_CONCAT(`Service`.`Name`) FROM `ServiceCustomerRel` LEFT JOIN `Service` '.
|
---|
84 | 'ON `Service`.`Id`=`ServiceCustomerRel`.`Service` WHERE `ServiceCustomerRel`.`Customer`=`Member`.`Id` AND '.
|
---|
85 | '`ServiceCustomerRel`.`ChangeAction` IS NULL) AS `ServicesNextMonth`, '.
|
---|
86 | 'UNIX_TIMESTAMP(`Member`.`BillingPeriodLastDate`) AS `LastDate`, `Subject`.`Name` AS `SubjectName`, '.
|
---|
87 | '`FinanceBillingPeriod`.`Name` AS `BillingPeriodName` '.
|
---|
88 | 'FROM `MemberPayment` JOIN `Member` ON `Member`.`Id`=`MemberPayment`.`Member` JOIN `Subject` '.
|
---|
89 | 'ON `Subject`.`Id`=`Member`.`Subject` LEFT JOIN `FinanceBillingPeriod` ON '.
|
---|
90 | '`FinanceBillingPeriod`.`Id`=`Member`.`BillingPeriod` WHERE (`Member`.`Blocked` = 0)'.
|
---|
91 | 'AND (`Member`.`BillingPeriod` > 1) AND (`MemberPayment`.`MonthlyTotal` != 0)';
|
---|
92 |
|
---|
93 | $DbResult = $this->Database->query('SELECT COUNT(*) FROM ('.$SQL.') AS T');
|
---|
94 | $DbRow = $DbResult->fetch_row();
|
---|
95 | $PageList = GetPageList('MonthlyPayment', $DbRow[0]);
|
---|
96 |
|
---|
97 | $Output = $PageList['Output'];
|
---|
98 | $Output .= '<table class="WideTable" style="font-size: small;">';
|
---|
99 |
|
---|
100 | $TableColumns = array(
|
---|
101 | array('Name' => 'SubjectName', 'Title' => 'Jméno'),
|
---|
102 | array('Name' => 'Monthly', 'Title' => 'Platba'),
|
---|
103 | array('Name' => 'Cash', 'Title' => 'Kredit'),
|
---|
104 | array('Name' => 'LastDate', 'Title' => 'Poslední fakturace'),
|
---|
105 | array('Name' => 'ServicesNextMonth', 'Title' => 'Služby'),
|
---|
106 | array('Name' => 'BillingPeriodName', 'Title' => 'Perioda'),
|
---|
107 | );
|
---|
108 | $Order = GetOrderTableHeader('MonthlyPayment', $TableColumns, 'SubjectName', 0);
|
---|
109 | $Output .= $Order['Output'];
|
---|
110 |
|
---|
111 | $Query = $SQL.' '.$Order['SQL'].$PageList['SQLLimit'];
|
---|
112 |
|
---|
113 | $DbResult = $this->Database->query($Query);
|
---|
114 | while ($Row = $DbResult->fetch_assoc())
|
---|
115 | {
|
---|
116 | $Output .= '<tr>'.
|
---|
117 | '<td>'.$Row['SubjectName'].'</td>'.
|
---|
118 | '<td>'.$Row['Monthly'].'</td>'.
|
---|
119 | '<td>'.$Row['Cash'].'</td>'.
|
---|
120 | '<td>'.date('j.n.Y', $Row['LastDate']).'</td>'.
|
---|
121 | '<td>'.$Row['ServicesNextMonth'].'</td>'.
|
---|
122 | '<td>'.$Row['BillingPeriodName'].'</td>'.
|
---|
123 | '</tr>';
|
---|
124 | }
|
---|
125 | $Output .= '</table>';
|
---|
126 | $Output .= $PageList['Output'];
|
---|
127 | $Output .= '<a href="?Operation=ProcessMonthlyPayment">Generovat faktury</a>';
|
---|
128 | return $Output;
|
---|
129 | }
|
---|
130 |
|
---|
131 | function InsertInvoice(string $Subject, string $TimeCreation, string $TimeDue, array $Items,
|
---|
132 | array $Group, float $PeriodFrom, float $PeriodTo): string
|
---|
133 | {
|
---|
134 | global $LastInsertTime;
|
---|
135 |
|
---|
136 | $Finance = ModuleFinance::Cast($this->System->GetModule('Finance'))->Finance;
|
---|
137 |
|
---|
138 | $Year = date('Y', $TimeCreation);
|
---|
139 | $BillCode = ModuleDocument::Cast($this->System->GetModule('Document'))->GetNextDocumentLineNumberId($Group['DocumentLine'], $Year);
|
---|
140 | $SumValue = 0;
|
---|
141 | foreach ($Items as $Item) {
|
---|
142 | $SumValue = $SumValue + $Item['Price'] * $Item['Quantity'];
|
---|
143 | }
|
---|
144 | $SumValue = round($SumValue, $Finance->Rounding);
|
---|
145 | $this->Database->insert('FinanceInvoice', array(
|
---|
146 | 'Subject' => $Subject, 'Time' => TimeToMysqlDateTime($TimeCreation),
|
---|
147 | 'TimeDue' => TimeToMysqlDateTime($TimeDue), 'Value' => $SumValue * $Group['ValueSign'],
|
---|
148 | 'BillCode' => $BillCode,
|
---|
149 | 'PeriodFrom' => TimeToMysqlDate($PeriodFrom), 'PeriodTo' => TimeToMysqlDate($PeriodTo),
|
---|
150 | 'Generate' => 1, 'Group' => $Group['Id']));
|
---|
151 | $InvoiceId = $this->Database->insert_id;
|
---|
152 | foreach ($Items as $Item)
|
---|
153 | $this->Database->insert('FinanceInvoiceItem', array('FinanceInvoice' => $InvoiceId,
|
---|
154 | 'Description' => $Item['Description'], 'Price' => $Item['Price'],
|
---|
155 | 'Quantity' => $Item['Quantity'], 'VAT' => $Item['VAT']));
|
---|
156 | //$LastInsertTime = $Time;
|
---|
157 | //$this->CheckAdvancesAndLiabilities($Subject);
|
---|
158 | return $InvoiceId;
|
---|
159 | }
|
---|
160 |
|
---|
161 | function ProduceInvoices(): string
|
---|
162 | {
|
---|
163 | $Output = '';
|
---|
164 |
|
---|
165 | // Produce accounting items
|
---|
166 | $DbResult = $this->Database->query('SELECT `Member`.*, `MemberPayment`.`MonthlyTotal` AS `MonthlyTotal`, '.
|
---|
167 | 'UNIX_TIMESTAMP(`Member`.`BillingPeriodLastDate`) AS `BillingPeriodLastUnixTime`, `Subject`.`Name` AS `SubjectName`,'.
|
---|
168 | '`MemberPayment`.`MonthlyPlus` AS `MonthlyPlus` '.
|
---|
169 | 'FROM `MemberPayment` JOIN `Member` ON `Member`.`Id`=`MemberPayment`.`Member` '.
|
---|
170 | 'JOIN `Subject` ON `Subject`.`Id`=`Member`.`Subject`');
|
---|
171 | while ($Member = $DbResult->fetch_assoc())
|
---|
172 | {
|
---|
173 | $Output .= $Member['SubjectName'].': ';
|
---|
174 | $Period = $this->GetBillingPeriod($Member['BillingPeriod']);
|
---|
175 |
|
---|
176 | // Check if need to produce new invoice for customer
|
---|
177 | if (($Period['MonthCount'] > 0) and ($Member['Blocked'] == 0) and
|
---|
178 | ($Period['From'] > $Member['BillingPeriodLastUnixTime']))
|
---|
179 | {
|
---|
180 | $InvoiceItems = array();
|
---|
181 | $MonthlyTotal = 0;
|
---|
182 | $DbResult2 = $this->Database->query('SELECT `Service`.* '.
|
---|
183 | 'FROM `ServiceCustomerRel` LEFT JOIN `Service` '.
|
---|
184 | 'ON `Service`.`Id`=`ServiceCustomerRel`.`Service` '.
|
---|
185 | 'WHERE (`ServiceCustomerRel`.`Customer`='.
|
---|
186 | $Member['Id'].') AND (`ServiceCustomerRel`.`ChangeAction` IS NULL) ');
|
---|
187 | while ($Service = $DbResult2->fetch_assoc())
|
---|
188 | {
|
---|
189 | $InvoiceItems[] = array('Description' => $Service['Name'], 'Price' => $Service['Price'],
|
---|
190 | 'Quantity' => $Period['MonthCount'], 'VAT' => ModuleFinance::Cast($this->System->GetModule('Finance'))->Finance->GetVATByType($Service['VAT']));
|
---|
191 | $MonthlyTotal += $Service['Price'];
|
---|
192 | }
|
---|
193 | $PayPerPeriod = $MonthlyTotal * $Period['MonthCount'];
|
---|
194 | // We can't produce negative invoice except storno invoice.
|
---|
195 | // TODO: In case of negative invoice it is not sufficient to reverse invoicing direction
|
---|
196 | // Other subject should invoice only positive items. Negative items should be somehow removed.
|
---|
197 | if ($MonthlyTotal >= 0)
|
---|
198 | {
|
---|
199 | $InvoiceGroupId = INVOICE_GROUP_OUT;
|
---|
200 | } else
|
---|
201 | {
|
---|
202 | $InvoiceGroupId = INVOICE_GROUP_IN;
|
---|
203 | }
|
---|
204 |
|
---|
205 | // Load invoice group
|
---|
206 | $FinanceGroup = ModuleFinance::Cast($this->System->GetModule('Finance'))->Finance->GetFinanceGroupById($InvoiceGroupId, 'FinanceInvoiceGroup');
|
---|
207 | foreach ($InvoiceItems as $Index => $Item)
|
---|
208 | {
|
---|
209 | $InvoiceItems[$Index]['Price'] = $Item['Price'] * $FinanceGroup['ValueSign'];
|
---|
210 | }
|
---|
211 |
|
---|
212 | if ($PayPerPeriod != 0)
|
---|
213 | {
|
---|
214 | $TimePeriodText = date('j.n.Y', $Period['From']).' - '.date('j.n.Y', $Period['To']);
|
---|
215 | $Output .= $TimePeriodText.': '.$MonthlyTotal.' * '.$Period['MonthCount'].' = '.$PayPerPeriod;
|
---|
216 | $this->InsertInvoice($Member['Subject'], time(), time() + 3600 * 24 * INVOICE_DUE_DAYS,
|
---|
217 | $InvoiceItems, $FinanceGroup, $Period['From'], $Period['To']);
|
---|
218 |
|
---|
219 | $Output .= $this->SendPaymentEmail($Member['Id']);
|
---|
220 | }
|
---|
221 | // Update last billing day
|
---|
222 | $this->Database->update('Member', '`Id`='.$Member['Id'],
|
---|
223 | array('BillingPeriodLastDate' => TimeToMysqlDateTime($Period['To'])));
|
---|
224 | }
|
---|
225 | $Output .= "\n";
|
---|
226 | }
|
---|
227 | return $Output;
|
---|
228 | }
|
---|
229 |
|
---|
230 | function TableUpdateChanges(string $Table): void
|
---|
231 | {
|
---|
232 | $Time = time();
|
---|
233 | $DbResult = $this->Database->select($Table, '*', '(`ChangeAction` IS NOT NULL) AND '.
|
---|
234 | '(`ChangeTime` <= "'.TimeToMysqlDateTime($Time).'") ORDER BY `ChangeTime` ASC');
|
---|
235 | while ($Service = $DbResult->fetch_assoc())
|
---|
236 | {
|
---|
237 | if ($Service['ChangeAction'] == 'add')
|
---|
238 | {
|
---|
239 | unset($Service['Id']);
|
---|
240 | unset($Service['ChangeReplaceId']);
|
---|
241 | unset($Service['ChangeAction']);
|
---|
242 | unset($Service['ChangeTime']);
|
---|
243 | $this->Database->insert($Table, $Service);
|
---|
244 | } else
|
---|
245 | if ($Service['ChangeAction'] == 'modify')
|
---|
246 | {
|
---|
247 | unset($Service['Id']);
|
---|
248 | unset($Service['ChangeAction']);
|
---|
249 | $ReplaceId = $Service['ChangeReplaceId'];
|
---|
250 | unset($Service['ChangeReplaceId']);
|
---|
251 | unset($Service['ChangeTime']);
|
---|
252 | $this->Database->update($Table, '`Id`='.$ReplaceId, $Service);
|
---|
253 | } else
|
---|
254 | if ($Service['ChangeAction'] == 'delete')
|
---|
255 | {
|
---|
256 | $this->Database->delete($Table, '`Id`='.$Service['ReplaceId']);
|
---|
257 | }
|
---|
258 | }
|
---|
259 | $this->Database->delete($Table, '(`ChangeAction` IS NOT NULL) AND (`ChangeTime` <= "'.TimeToMysqlDateTime($Time).'")');
|
---|
260 | }
|
---|
261 |
|
---|
262 | function ProcessTableUpdates(): string
|
---|
263 | {
|
---|
264 | // Update customers
|
---|
265 | $Output = 'Měním zákazníky...'."\n";
|
---|
266 | $this->TableUpdateChanges('Member');
|
---|
267 |
|
---|
268 | // Update finance charge
|
---|
269 | $Output = 'Měním aktuální parametry sítě...'."\n";
|
---|
270 | $this->TableUpdateChanges('FinanceCharge');
|
---|
271 |
|
---|
272 | // Update services
|
---|
273 | $Output .= 'Aktualizuji služby....'."\n";
|
---|
274 | $this->TableUpdateChanges('Service');
|
---|
275 |
|
---|
276 | // Update customer service selections
|
---|
277 | $Output .= 'Aktualizuji výběr služeb zákazníků....'."\n";
|
---|
278 | $this->TableUpdateChanges('ServiceCustomerRel');
|
---|
279 |
|
---|
280 | return $Output;
|
---|
281 | }
|
---|
282 |
|
---|
283 | function ProcessMonthlyPayment(): string
|
---|
284 | {
|
---|
285 | if (!ModuleUser::Cast($this->System->GetModule('User'))->User->CheckPermission('Finance', 'Manage')) return 'Nemáte oprávnění';
|
---|
286 | $Output = '';
|
---|
287 |
|
---|
288 | $Output .= $this->ProcessTableUpdates();
|
---|
289 |
|
---|
290 | $Finance = &ModuleFinance::Cast($this->System->GetModule('Finance'))->Finance;
|
---|
291 | $Finance->LoadMonthParameters(0);
|
---|
292 |
|
---|
293 | // Načti poslední měsíční přehled a nastavení
|
---|
294 | $DbResult = $this->Database->select('FinanceMonthlyOverall', '*', '1 ORDER BY `Date` DESC LIMIT 1');
|
---|
295 | $Overall = $DbResult->fetch_array();
|
---|
296 |
|
---|
297 | $Output .= 'Datum: '.date('j.n.Y')."\n";
|
---|
298 |
|
---|
299 | $DateParts = explode('-', $Overall['Date']);
|
---|
300 | $MonthLast = $DateParts[1];
|
---|
301 | $YearLast = $DateParts[0];
|
---|
302 | $MonthCurrent = date('m') + 0;
|
---|
303 | $YearCurrent = date('Y') + 0;
|
---|
304 |
|
---|
305 | $Output .= $Finance->RecalculateMemberPayment();
|
---|
306 |
|
---|
307 | $DbResult = $this->Database->query('SELECT SUM(`Cash`) FROM `MemberPayment`');
|
---|
308 | $Row = $DbResult->fetch_row();
|
---|
309 | $TotalMemberCash = $Row[0];
|
---|
310 | $Output .= 'Stav pokladny: Členové('.round($TotalMemberCash).')'."\n";
|
---|
311 |
|
---|
312 | $DbResult = $this->Database->query('SELECT SUM(`Product`.`Consumption`) AS `Consumption` FROM `StockSerialNumber` '.
|
---|
313 | 'JOIN `Product` ON `StockSerialNumber`.`Product` = `Product`.`Id` WHERE (`StockSerialNumber`.`TimeElimination` IS NULL) ');
|
---|
314 | $Row = $DbResult->fetch_row();
|
---|
315 | $TotalConsumption = $Row[0];
|
---|
316 | $TotalConsumptionCost = $Finance->W2Kc($TotalConsumption);
|
---|
317 |
|
---|
318 | $SpravaCelkem = $Finance->Sprava * $Finance->SpravaUsers;
|
---|
319 | $Output .= 'Kontrola placení (Zaplaceno-Sprava-Internet): '.$Finance->TotalPaid.'-'.$SpravaCelkem.'-'.$Finance->Internet.'='.($Finance->TotalPaid - $SpravaCelkem - $Finance->Internet)."\n";
|
---|
320 |
|
---|
321 | // Zkontrolovat odečtení měsíčního poplatku
|
---|
322 | $Output .= 'Kontrola odečtení poplatků: Poslední měsíc-'.$MonthLast.' Aktuální měsíc-'.$MonthCurrent."\n";
|
---|
323 | if (($MonthCurrent != $MonthLast) or ($YearCurrent != $YearLast))
|
---|
324 | {
|
---|
325 | $Output .= 'Odečítám pravidelný poplatek...'."\n";
|
---|
326 | $Output .= $this->ProduceInvoices();
|
---|
327 |
|
---|
328 | $Output .= 'Přidávám měsíční přehled...'."\n";
|
---|
329 | $DbResult = $this->Database->query('SELECT * FROM `FinanceCharge` WHERE (`ChangeAction` IS NULL) LIMIT 1');
|
---|
330 | $Charge = $DbResult->fetch_assoc();
|
---|
331 | $this->Database->insert('FinanceMonthlyOverall', array('Date' => 'NOW()',
|
---|
332 | 'Money' => $Finance->Internet, 'kWh' => $Finance->kWh,
|
---|
333 | 'Administration' => $Finance->Sprava, 'AdministrationTotal' => $SpravaCelkem,
|
---|
334 | 'ConsumptionTotal' => $TotalConsumptionCost, 'TotalPaid' => $Finance->TotalPaid,
|
---|
335 | 'BaseTariffPrice' => $Charge['BaseTariffPrice'],
|
---|
336 | 'TopTariffPrice' => $Charge['TopTariffPrice'], 'MemberCount' => $Finance->InternetUsers));
|
---|
337 |
|
---|
338 | $Finance->RecalculateMemberPayment();
|
---|
339 |
|
---|
340 | // Restart traffic shaping
|
---|
341 | //$this->Database->update('NetworkConfiguration', 'Id = 3', array('Changed' => 1));
|
---|
342 | //flush();
|
---|
343 | //$this->GenerateBills();
|
---|
344 | ModuleLog::Cast($this->System->GetModule('Log'))->NewRecord('Finance', 'ProcessMonthlyPayment', $Output);
|
---|
345 | }
|
---|
346 | $Output = str_replace("\n", '<br/>', $Output);
|
---|
347 | return $Output;
|
---|
348 | }
|
---|
349 |
|
---|
350 | function SendPaymentEmail(string $MemberId, string $FileId = ''): string
|
---|
351 | {
|
---|
352 | $Finance = &ModuleFinance::Cast($this->System->GetModule('Finance'))->Finance;
|
---|
353 | $Finance->LoadMonthParameters(0);
|
---|
354 |
|
---|
355 | if (!ModuleUser::Cast($this->System->GetModule('User'))->User->CheckPermission('Finance', 'Manage')) return 'Nemáte oprávnění';
|
---|
356 | global $Config;
|
---|
357 |
|
---|
358 | $DbResult = $this->Database->select('Member', '*', '`Id`='.$MemberId);
|
---|
359 | $Member = $DbResult->fetch_assoc();
|
---|
360 |
|
---|
361 | $DbResult = $this->Database->select('MemberPayment', '*', '`Member`='.$MemberId);
|
---|
362 | $MemberPayment = $DbResult->fetch_assoc();
|
---|
363 |
|
---|
364 | $DbResult = $this->Database->select('Subject', 'Name', '`Id`='.$Member['Subject']);
|
---|
365 | $Subject = $DbResult->fetch_assoc();
|
---|
366 |
|
---|
367 | $DbResult = $this->Database->select('User', '*', '`Id`='.$Member['ResponsibleUser']);
|
---|
368 | $User = $DbResult->fetch_assoc();
|
---|
369 |
|
---|
370 | $DbResult = $this->Database->select('Subject', '*', '`Id`='.$Config['Finance']['MainSubjectId']);
|
---|
371 | $MainSubject = $DbResult->fetch_assoc();
|
---|
372 |
|
---|
373 | $DbResult = $this->Database->select('Company', '*', '`Id`='.$Config['Finance']['MainCompanyId']);
|
---|
374 | $MainCompany = $DbResult->fetch_assoc();
|
---|
375 |
|
---|
376 | $Period = $this->GetBillingPeriod($Member['BillingPeriod']);
|
---|
377 |
|
---|
378 | $DbResult = $this->Database->query('SELECT `FinanceBankAccount`.*, '.
|
---|
379 | 'CONCAT(`FinanceBankAccount`.`Number`, "/", `FinanceBank`.`Code`) AS `NumberFull` FROM `FinanceBankAccount` '.
|
---|
380 | 'JOIN `FinanceBank` ON `FinanceBank`.`Id`=`FinanceBankAccount`.`Bank` '.
|
---|
381 | 'WHERE (`FinanceBankAccount`.`Subject`='.$Config['Finance']['MainSubjectId'].') '.
|
---|
382 | 'AND (`FinanceBankAccount`.`Use`=1)');
|
---|
383 | $MainSubjectAccount = $DbResult->fetch_assoc();
|
---|
384 |
|
---|
385 | if ($User['Email'] != '')
|
---|
386 | {
|
---|
387 | $Title = 'Pravidelné vyúčtování služeb '.$MainCompany['Name'];
|
---|
388 | $Content = 'Dobrý den,<br/><br/>'.
|
---|
389 | 'Zasíláme vyúčtování klienta <strong>'.$Subject['Name'].'</strong> zastoupeného uživatelem <strong>'.
|
---|
390 | $User['Name'].'</strong> ke dni <strong>'.Core::Cast($this->System)->HumanDate(time()).'</strong>.<br/><br/>'."\n".
|
---|
391 | 'Vaše aktuální služby: ';
|
---|
392 | $DbResult = $this->Database->query('SELECT GROUP_CONCAT(`Service`.`Name`) AS `Name` FROM `ServiceCustomerRel` LEFT JOIN `Service` '.
|
---|
393 | 'ON `Service`.`Id`=`ServiceCustomerRel`.`Service` WHERE (`ServiceCustomerRel`.`Customer`='.$Member['Id'].') '.
|
---|
394 | 'AND (`ServiceCustomerRel`.`ChangeAction` IS NULL)');
|
---|
395 | $Service = $DbResult->fetch_assoc();
|
---|
396 | $Content .= '<strong>'.$Service['Name'].'</strong><br />'."\n".
|
---|
397 | 'Vaše platební období: <strong>'.ModuleFinance::Cast($this->System->GetModule('Finance'))->Finance->BillingPeriods[$Member['BillingPeriod']]['Name'].'</strong><br />'."\n".
|
---|
398 | 'Pravidelná platba za období: <strong>'.($MemberPayment['MonthlyTotal'] * $Period['MonthCount']).' Kč</strong><br />'."\n".
|
---|
399 | 'Bankovní účet: <strong>'.$MainSubjectAccount['NumberFull'].'</strong><br/>'."\n".
|
---|
400 | 'Variabilní symbol: <strong>'.$Member['Subject'].'</strong><br/>'."\n".
|
---|
401 | 'Stav vašeho účtu: <strong>'.($MemberPayment['Cash'] - $MemberPayment['MonthlyTotal'] * $Period['MonthCount']).' Kč</strong><br /><br />'."\n";
|
---|
402 | $Content .= 'Nové finanční operace:<br/>'.
|
---|
403 | '<table style="margin-left: auto; margin-right: auto; border-style: solid; border-width: 1px; border-collapse: collapse;">'.
|
---|
404 | '<tr><th style="border-style: solid; border-width: 1px; padding: 1px 5px 1px 5px; text-align: center; font-weight: bold;">Čas</th>'.
|
---|
405 | '<th style="border-style: solid; border-width: 1px; padding: 1px 5px 1px 5px; text-align: center; font-weight: bold;">Popis</th>'.
|
---|
406 | '<th style="border-style: solid; border-width: 1px; padding: 1px 5px 1px 5px; text-align: center; font-weight: bold;">Částka [Kč]</th></tr>'."\n";
|
---|
407 | if ($Member['PaymentEmailTime'] <> 'NULL')
|
---|
408 | {
|
---|
409 | $Where = ' WHERE (`T1`.`Time` > "'.$Member['PaymentEmailTime'].'")';
|
---|
410 | } else
|
---|
411 | {
|
---|
412 | $Where = '';
|
---|
413 | }
|
---|
414 | $DbResult = $this->Database->query('SELECT T1.* FROM ((SELECT `Text`, `Time`, `Value`, `File` FROM `FinanceOperation` WHERE (`Subject`='.$Member['Subject'].')) UNION ALL '.
|
---|
415 | '(SELECT (SELECT GROUP_CONCAT(`Description` SEPARATOR ", ") FROM `FinanceInvoiceItem` '.
|
---|
416 | 'WHERE `FinanceInvoiceItem`.`FinanceInvoice` = `FinanceInvoice`.`Id`) AS `Text`, '.
|
---|
417 | '`Time`, -`Value`, `File` FROM `FinanceInvoice` WHERE (`Subject`='.$Member['Subject'].')) ORDER BY `Time` DESC) AS `T1`'.$Where);
|
---|
418 | while ($DbRow = $DbResult->fetch_assoc())
|
---|
419 | {
|
---|
420 | $Text = $DbRow['Text'];
|
---|
421 | $Content .= '<tr><td style="border-style: solid; border-width: 1px; padding: 1px 5px 1px 5px; text-align: center;">'.HumanDate($DbRow['Time']).'</td>'.
|
---|
422 | '<td style="border-style: solid; border-width: 1px; padding: 1px 5px 1px 5px; text-align: center;">'.$Text.'</td>'.
|
---|
423 | '<td style="border-style: solid; border-width: 1px; padding: 1px 5px 1px 5px; text-align: center;">'.$DbRow['Value'].'</td></tr>'."\n";
|
---|
424 | }
|
---|
425 | $Content .= '</table><br />'."\n".
|
---|
426 | 'Pro aktuální informace, prohlížení elektronických dokladů a možnost změny údajů se prosím přihlaste na stránkách '.
|
---|
427 | '<a href="https://'.$Config['Web']['Host'].$Config['Web']['RootFolder'].'">https://'.
|
---|
428 | $Config['Web']['Host'].$Config['Web']['RootFolder'].'</a>.<br/><br/>'."\n";
|
---|
429 |
|
---|
430 | $Content .= '<br/>Tento email je generován automaticky. V případě zjištění nesrovnalostí prosím napište zpět.';
|
---|
431 |
|
---|
432 | $Content .= '<br/><br/>S pozdravem,<br/>'.$MainCompany['Name'].'<br/><a href="'.$MainSubject['WWW'].'">'.
|
---|
433 | str_replace(array('https:', '/'), '', $MainSubject['WWW']).'</a>';
|
---|
434 |
|
---|
435 | ModuleEmailQueue::Cast($this->System->GetModule('EmailQueue'))->AddItem($User['Name'].' <'.$User['Email'].'>', $Title, $Content,
|
---|
436 | $Config['Web']['Admin'].' <'.$Config['Web']['AdminEmail'].'>');
|
---|
437 | $this->Database->update('Member', 'Id='.$Member['Id'], array('PaymentEmailTime' => 'NOW()'));
|
---|
438 | $Output = '';
|
---|
439 | } else $Output = 'Uživatel '.$User['Name'].' nemá email.';
|
---|
440 | return $Output;
|
---|
441 | }
|
---|
442 |
|
---|
443 | function GenerateInvoice(string $Where): string
|
---|
444 | {
|
---|
445 | $DirectoryId = ModuleFinance::Cast($this->System->GetModule('Finance'))->Finance->DirectoryId;
|
---|
446 | $Output = '';
|
---|
447 | $DbResult = $this->Database->query('SELECT * FROM `FinanceInvoice` WHERE (`BillCode` <> "") '.
|
---|
448 | 'AND (`Value` != 0) AND (`Generate` = 1)'.$Where);
|
---|
449 | while ($Row = $DbResult->fetch_assoc())
|
---|
450 | {
|
---|
451 | if ($Row['File'] == null)
|
---|
452 | {
|
---|
453 | $this->Database->insert('File', array('Name' => '', 'Size' => 0, 'Directory' => $DirectoryId, 'Time' => 'NOW()',
|
---|
454 | 'Hash' => 'SHA1(CONCAT(Id,Name,Size,Time))'));
|
---|
455 | $FileId = $this->Database->insert_id;
|
---|
456 | } else $FileId = $Row['File'];
|
---|
457 | $FileName = 'doklad-'.$FileId.'.pdf';
|
---|
458 | $Bill = new BillInvoice($this->System);
|
---|
459 | $Bill->InvoiceId = $Row['Id'];
|
---|
460 | $FullFileName = ModuleFile::Cast($this->System->GetModule('File'))->File->GetDir($DirectoryId).$FileName;
|
---|
461 | $Bill->SaveToFile($FullFileName);
|
---|
462 | if (file_exists($FullFileName))
|
---|
463 | {
|
---|
464 | $this->Database->update('File', 'Id='.$FileId, array('Name' => $FileName, 'Size' => filesize($FullFileName), 'Hash' => 'SHA1(CONCAT(Id,Name,Size,Time))'));
|
---|
465 | $this->Database->update('FinanceInvoice', 'Id='.$Row['Id'], array('File' => $FileId));
|
---|
466 | $Output .= 'Faktura '.$Row['Id'].' vygenerována do souboru '.$FileName.'<br/>'."\n";
|
---|
467 | } else $Output .= 'Soubor "'.$FullFileName.'" se nepodařilo uložit.';
|
---|
468 | }
|
---|
469 | return $Output;
|
---|
470 | }
|
---|
471 |
|
---|
472 | function GenerateOperation(string $Where): string
|
---|
473 | {
|
---|
474 | $DirectoryId = ModuleFinance::Cast($this->System->GetModule('Finance'))->Finance->DirectoryId;
|
---|
475 | $Output = '';
|
---|
476 | $DbResult = $this->Database->query('SELECT * FROM `FinanceOperation` WHERE (`BillCode` <> "") '.
|
---|
477 | 'AND (`Value` != 0) AND (`Generate` = 1)'.$Where);
|
---|
478 | while ($Row = $DbResult->fetch_assoc())
|
---|
479 | {
|
---|
480 | if ($Row['File'] == null)
|
---|
481 | {
|
---|
482 | $DbResult2 = $this->Database->insert('File', array('Name' => '', 'Size' => 0,
|
---|
483 | 'Directory' => $DirectoryId, 'Time' => 'NOW()', 'Hash' => 'SHA1(CONCAT(Id,Name,Size,Time))'));
|
---|
484 | $FileId = $this->Database->insert_id;
|
---|
485 | } else $FileId = $Row['File'];
|
---|
486 | $FileName = 'doklad2-'.$FileId.'.pdf';
|
---|
487 | $Bill = new BillOperation($this->System);
|
---|
488 | $Bill->OperationId = $Row['Id'];
|
---|
489 | $FullFileName = ModuleFile::Cast($this->System->GetModule('File'))->File->GetDir($DirectoryId).$FileName;
|
---|
490 | $Bill->SaveToFile($FullFileName);
|
---|
491 | if (file_exists($FullFileName))
|
---|
492 | {
|
---|
493 | $this->Database->update('File', 'Id='.$FileId, array('Name' => $FileName, 'Size' => filesize($FullFileName), 'Hash' => 'SHA1(CONCAT(Id,Name,Size,Time))'));
|
---|
494 | $this->Database->update('FinanceOperation', 'Id='.$Row['Id'], array('File' => $FileId));
|
---|
495 | $Output .= 'Doklad pro platbu '.$Row['Id'].' vygenerován do souboru '.$FileName.'<br/>'."\n";
|
---|
496 | } else $Output .= 'Soubor "'.$FullFileName.'" se nepodařilo uložit.';
|
---|
497 | }
|
---|
498 | return $Output;
|
---|
499 | }
|
---|
500 |
|
---|
501 | function GenerateBills(): string
|
---|
502 | {
|
---|
503 | $Output = '';
|
---|
504 | // Generate PDF files for new invoices and operations
|
---|
505 | $Output .= $this->GenerateInvoice(' AND (`File` IS NULL)');
|
---|
506 | $Output .= $this->GenerateOperation(' AND (`File` IS NULL)');
|
---|
507 | return $Output;
|
---|
508 | }
|
---|
509 | }
|
---|