$bugfixes
[memberdb.git] / include / directdebit.php
1 <?php
2
3 use MemberDB\Config\Config;
4
5 function action_directdebit()
6 {
7     $config = Config::getInstance();
8     $bank = $config->get('bank');
9
10     $debittype = array(
11         1 => 'DTAUS',
12         2 => 'FRST',
13         3 => 'RCUR'
14     );
15
16     $members = db_get_members();
17     if (empty($members)) {
18         return;
19     }
20
21     $debits = array();
22     $cash_payments = array();
23     foreach ($members as $member) {
24         if (empty($member['directdebit'])) {
25             // Barzahler
26             $open = bcsub(fees_sum_for_member($member['id'], time()),
27                 bcadd(finance_get_paid_fees_for_member($member['id']),
28                     finance_get_paid_fees_for_member($member['id'], true)));
29             if (bccomp($open, 0) != 1) {
30                 continue;
31             }
32             $cash_payments[] = array(
33                 'member_id'     => $member['id'],
34                 'member_number' => $member['number'],
35                 'nickname'      => $member['nickname'],
36                 'amount'        => $open
37             );
38             continue;
39         }
40         $info = fee_next_directdebit_for_member($member['id'], time());
41         if (empty($info)) {
42             continue;
43         }
44         $debits[] = array(
45             'member_id'        => $member['id'],
46             'member_number'    => $member['number'],
47             'nickname'         => $member['nickname'],
48             'accountholder'    => $member['accountholder'],
49             'accountnumber'    => $member['accountnumber'],
50             'bankcode'         => $member['bankcode'],
51             //          'bankname'         => $member['bankname'],
52             'amount'           => $info['value'],
53             'amountcent'       => '' . (int)round(bcmul($info['value'], 100)),
54             'purpose'          => $info['info'],
55             'ddmandatesigdate' => $member['ddmandatesigdate'],
56             'debittype'        => $debittype[$member['directdebit']],
57         );
58     }
59
60     js_modal_windows();
61     js_get_master_key();
62     ?>
63     <noscript>
64         <p class="error">
65             <strong>Achtung:</strong> Ohne JavaScript geht hier gar nichts. Bitte aktivieren!
66         </p>
67     </noscript>
68     <?php if (!empty($cash_payments)) : ?>
69     <h2>Barzahler</h2>
70     <table>
71         <tr>
72             <th>Mitgliedsnummer</th>
73             <th>Nickname</th>
74             <th style="text-align: right;">Betrag</th>
75             <th></th>
76         </tr>
77         <?php foreach ($cash_payments as $payment) : ?>
78             <tr>
79                 <td><a href="<?php echo html_escape(link_to('fees',
80                         array('member_id' => $payment['member_id']))) ?>"><?php echo html_escape($payment['member_number']) ?></a>
81                 </td>
82                 <td><?php echo html_escape($payment['nickname']) ?></td>
83                 <td style="text-align: right;"><?php echo html_escape(format_money($payment['amount'])) ?></td>
84                 <td>
85                     <form action="<?php echo link_to('create_earning') ?>" method="post" class="clearfix">
86                         <?php echo html_hidden_field('date', format_date(time())) ?>
87                         <?php echo html_hidden_field('type', 'fee') ?>
88                         <?php echo html_hidden_field('status', 'paid') ?>
89                         <?php echo html_hidden_field('value', format_money($payment['amount'])) ?>
90                         <?php echo html_hidden_field('member_id', $payment['member_id']) ?>
91                         <?php echo html_hidden_field('description', '') ?>
92                         <?php echo html_hidden_field('account', 'cash') ?>
93                         <input class="submit" type="submit" name="submit" value="Einnahme verbuchen"/>
94                     </form>
95                 </td>
96             </tr>
97         <?php endforeach ?>
98     </table>
99 <?php endif ?>
100
101     <h2>Bankeinzug</h2>
102     <table>
103         <tr>
104             <th>Mitgliedsnummer</th>
105             <th>Nickname</th>
106             <th>Verwendungszweck</th>
107             <th>Einzugstyp</th>
108             <th style="text-align: right;">Betrag</th>
109         </tr>
110         <?php $total = 0; ?>
111         <?php foreach ($debits as $debit) : ?>
112             <tr>
113                 <td><a href="<?php echo html_escape(link_to('fees',
114                         array('member_id' => $debit['member_id']))) ?>"><?php echo html_escape($debit['member_number']) ?></a>
115                 </td>
116                 <td><?php echo html_escape($debit['nickname']) ?></td>
117                 <td><?php echo html_escape($debit['purpose']) ?></td>
118                 <td><?php echo html_escape($debit['debittype']) ?></td>
119                 <td style="text-align: right;"><?php echo html_escape(format_money($debit['amount'])) ?></td>
120             </tr>
121             <?php $total = bcadd($total, $debit['amount']); ?>
122         <?php endforeach ?>
123         <tr class="total">
124             <td>Gesamt</td>
125             <td></td>
126             <td></td>
127             <td></td>
128             <td style="text-align: right;"><?php echo html_escape(format_money($total)) ?></td>
129         </tr>
130     </table>
131
132     <?php echo html_list_box('Dateiformat', 'directdebittype', array('dtaus' => 'DTAUS', 'pain' => 'PAIN'), 'pain'); ?>
133     <input class="submit" type="button" name="btn_directdebit" value="Datei erzeugen" onclick="ask_for_password()"
134            id="btn_directdebit"/>
135     <br/>
136     <br/>
137     <form action="<?php echo link_to('create_earnings') ?>" method="post" class="clearfix">
138         <?php $count = 0; ?>
139         <?php foreach ($debits as $debit) : ?>
140             <?php echo html_hidden_field(sprintf('earnings[%d][date]', $count), format_date(time())) ?>
141             <?php echo html_hidden_field(sprintf('earnings[%d][type]', $count), 'fee') ?>
142             <?php echo html_hidden_field(sprintf('earnings[%d][status]', $count), 'paid') ?>
143             <?php echo html_hidden_field(sprintf('earnings[%d][value]', $count), $debit['amount']) ?>
144             <?php echo html_hidden_field(sprintf('earnings[%d][member_id]', $count), $debit['member_id']) ?>
145             <?php echo html_hidden_field(sprintf('earnings[%d][description]', $count), $debit['purpose']) ?>
146             <?php $count++; ?>
147         <?php endforeach ?>
148         <input class="submit" type="submit" name="btn_create_earnings" value="Einnahmen verbuchen"/>
149     </form>
150     <hr/>
151     <form action="<?php echo link_to('export_ibanhin') ?>" method="POST" class="clearfix">
152         <input class="submit" type="submit" name="btn_export_ibanhin" value="IBAN-hin Export"/>
153     </form>
154
155     <div id="password_popup" class="modal_window">
156         <fieldset>
157             <legend>Passwortabfrage</legend>
158             <?php echo html_password_field('Passwort', 'password') ?>
159             <input class="submit" type="button" name="btn_generate_directdebit" value="Datei erzeugen"
160                    onclick="generate_directdebit()"/>
161             <input class="submit" type="button" name="btn_cancel" value="Abbrechen"
162                    onclick="cancel_ask_for_password()"/>
163         </fieldset>
164     </div>
165     <div id="directdebit_popup" class="modal_window">
166         <fieldset>
167             <legend>DTAUS / SEPA PAIN FRST</legend>
168             <textarea id="directdebit_content" style="width: 100%" rows="15" readonly="readonly"></textarea>
169             <legend>SEPA PAIN RCUR</legend>
170             <textarea id="directdebit_content2" style="width: 100%" rows="15" readonly="readonly"></textarea>
171             <input class="submit" type="button" name="btn_directdebit_close" value="Schließen"
172                    onclick="directdebit_close()"/>
173         </fieldset>
174     </div>
175
176     <script type="text/javascript">
177         var debits = new Array(
178             <?php echo join(",\n", array_map('json_encode', $debits)) ?>
179         );
180
181         $(document).ready(function () {
182             $('#password').keypress(function (event) {
183                 if (event.keyCode == '13') {
184                     generate_directdebit();
185                 }
186             });
187             $('#btn_directdebit').focus();
188         });
189
190         function ask_for_password() {
191             modal_window_show($("#password_popup"));
192             $("#password").focus();
193             return;
194         }
195
196         function cancel_ask_for_password() {
197             modal_window_hide();
198             $("#btn_directdebit").focus();
199             return;
200         }
201
202         function generate_directdebit() {
203             var password = $('#password').val();
204             var directdebitcontent = "";
205             var directdebitcontent2 = "Wird nur bei SEPA verwendet.";
206             $("#password").val('');
207
208             // We pass a closure so that get_master_key may defer execution
209             get_master_key(password, function (masterkey) {
210
211                 modal_window_replace($("#directdebit_popup"));
212
213                 switch ($('#directdebittype').val()) {
214                     case "dtaus":
215                         if (!DTAUS.setAccountFileSender('<?php echo dtaus_string($bank['holder']); ?>', '<?php echo $bank['code']; ?>', '<?php echo $bank['number']; ?>')) {
216                             $('#directdebit_content').val(DTAUS.errormsg);
217                             return;
218                         }
219
220                         for (var i = 0; i < debits.length; i++) {
221
222                             if (debits[i]['debittype'] != 'DTAUS') {
223                                 continue;
224                             }
225
226                             var accountholder = debits[i]['accountholder'];
227                             var accountnumber = debits[i]['accountnumber'];
228                             var bankcode = debits[i]['bankcode'];
229
230                             // Encrypt/Decrypt data using AES with masterkey
231                             if (accountholder != "") accountholder = Crypto.charenc.UTF8.bytesToString(Crypto.AES.decrypt(accountholder, masterkey));
232                             if (accountnumber != "") accountnumber = Crypto.charenc.UTF8.bytesToString(Crypto.AES.decrypt(accountnumber, masterkey));
233                             if (bankcode != "") bankcode = Crypto.charenc.UTF8.bytesToString(Crypto.AES.decrypt(bankcode, masterkey));
234
235                             accountholder = DTAUS.prepareString(accountholder);
236
237                             if (!DTAUS.addExchange(accountholder, bankcode, accountnumber, '', debits[i]['amountcent'], debits[i]['purpose'])) {
238                                 $('#directdebit_content').val('Mitglied ' + debits[i]['member_number'] + ' ' + accountholder + '\n' + DTAUS.errormsg);
239                                 return;
240                             }
241                         }
242                         directdebitcontent = DTAUS.getFileContent();
243                         break;
244
245                     case "pain":
246                         // datejs.com MAGIC
247                         var jetzt = new Date.today();
248                         var collectiondate = new Date.parse('<?php echo $config->get('direct_debit')['day']; ?>');
249                         if (jetzt.getDate() > <?php echo $config->get('direct_debit')['day']; ?>) {
250                             collectiondate = collectiondate.add(1).month();
251                         }
252
253                         if (!SEPACORE.init(collectiondate, '<?php echo $bank['creditor_id']; ?>', '<?php echo $bank['holder']; ?>', '<?php echo $bank['iban']; ?>', '<?php echo $bank['bic']; ?>')) {
254                         $('#directdebit_content').val(DTAUS.errormsg);
255                         return;
256                 }
257
258                 for (var i = 0; i < debits.length; i++) {
259
260                     if (debits[i]['debittype'] != 'FRST' && debits[i]['debittype'] != 'RCUR') {
261                         continue;
262                     }
263
264                     var accountholder = debits[i]['accountholder'];
265                     var accountnumber = debits[i]['accountnumber'];
266                     var bankcode = debits[i]['bankcode'];
267
268                     // Encrypt/Decrypt data using AES with masterkey
269                     if (accountholder != "") accountholder = Crypto.charenc.UTF8.bytesToString(Crypto.AES.decrypt(accountholder, masterkey));
270                     if (accountnumber != "") accountnumber = Crypto.charenc.UTF8.bytesToString(Crypto.AES.decrypt(accountnumber, masterkey));
271                     if (bankcode != "") bankcode = Crypto.charenc.UTF8.bytesToString(Crypto.AES.decrypt(bankcode, masterkey));
272
273                     // Mandatsreferenz '/V1/M:n/'; z.B. /V:1/M:2/
274                     var mandateref = '/V:1/M:' + debits[i]['member_number'] + '/';
275                     var e2eid = '/V:1/E2E:' + parseInt(SEPACORE.creationdate.getTime() / 1000) + '/S:' + debits[i]['debittype'][0] + '/I:' + i + '/';
276                     if (!SEPACORE.addDDTx(debits[i]['debittype'], accountholder, accountnumber, bankcode, mandateref, debits[i]['ddmandatesigdate'].substring(0, 10), debits[i]['amountcent'], debits[i]['purpose'], e2eid)) {
277                         $('#directdebit_content').val('Mitglied ' + debits[i]['member_number'] + ' ' + accountholder + '\n' + SEPACORE.errormsg);
278                         return;
279                     }
280                 }
281
282                 directdebitcontent = SEPACORE.getXMLContent('FRST');
283                 directdebitcontent2 = SEPACORE.getXMLContent('RCUR');
284
285                 if (SEPACORE.errormsg.lenght > 0) {
286                     $('#directdebit_content').val(SEPACORE.errormsg);
287                     return;
288                 }
289             }
290             $('#directdebit_content').val(directdebitcontent);
291             $('#directdebit_content2').val(directdebitcontent2);
292             $('#directdebit_content').focus();
293             $('#directdebit_content').select();
294         }
295
296         )
297         }
298
299         function directdebit_close() {
300             modal_window_hide();
301             $("#directdebit_content").val('');
302             $("#directdebit_content2").val('');
303         }
304     </script>
305     <?php
306 }
307
308 // borrowed from PEARs Payment_DTA
309 function dtaus_string($string)
310 {
311     if (strlen($string) == 0) {
312         return '';
313     }
314     $special_chars = array(
315         'á' => 'a',
316         'à' => 'a',
317         'ä' => 'ae',
318         'â' => 'a',
319         'ã' => 'a',
320         'å' => 'a',
321         'æ' => 'ae',
322         'ā' => 'a',
323         'ă' => 'a',
324         'ą' => 'a',
325         'ȁ' => 'a',
326         'ȃ' => 'a',
327         'Á' => 'A',
328         'À' => 'A',
329         'Ä' => 'Ae',
330         'Â' => 'A',
331         'Ã' => 'A',
332         'Å' => 'A',
333         'Æ' => 'AE',
334         'Ā' => 'A',
335         'Ă' => 'A',
336         'Ą' => 'A',
337         'Ȁ' => 'A',
338         'Ȃ' => 'A',
339         'ç' => 'c',
340         'ć' => 'c',
341         'ĉ' => 'c',
342         'ċ' => 'c',
343         'č' => 'c',
344         'Ç' => 'C',
345         'Ć' => 'C',
346         'Ĉ' => 'C',
347         'Ċ' => 'C',
348         'Č' => 'C',
349         'ď' => 'd',
350         'đ' => 'd',
351         'Ď' => 'D',
352         'Đ' => 'D',
353         'é' => 'e',
354         'è' => 'e',
355         'ê' => 'e',
356         'ë' => 'e',
357         'ē' => 'e',
358         'ĕ' => 'e',
359         'ė' => 'e',
360         'ę' => 'e',
361         'ě' => 'e',
362         'ȅ' => 'e',
363         'ȇ' => 'e',
364         'É' => 'E',
365         'È' => 'E',
366         'Ê' => 'E',
367         'Ë' => 'E',
368         'Ē' => 'E',
369         'Ĕ' => 'E',
370         'Ė' => 'E',
371         'Ę' => 'E',
372         'Ě' => 'E',
373         'Ȅ' => 'E',
374         'Ȇ' => 'E',
375         'ĝ' => 'g',
376         'ğ' => 'g',
377         'ġ' => 'g',
378         'ģ' => 'g',
379         'Ĝ' => 'G',
380         'Ğ' => 'G',
381         'Ġ' => 'G',
382         'Ģ' => 'G',
383         'ĥ' => 'h',
384         'ħ' => 'h',
385         'Ĥ' => 'H',
386         'Ħ' => 'H',
387         'ì' => 'i',
388         'î' => 'i',
389         'ï' => 'i',
390         'ĩ' => 'i',
391         'ī' => 'i',
392         'ĭ' => 'i',
393         'į' => 'i',
394         'ı' => 'i',
395         'ij' => 'ij',
396         'ȉ' => 'i',
397         'ȋ' => 'i',
398         'Í' => 'I',
399         'Ì' => 'I',
400         'Î' => 'I',
401         'Ï' => 'I',
402         'Ĩ' => 'I',
403         'Ī' => 'I',
404         'Ĭ' => 'I',
405         'Į' => 'I',
406         'İ' => 'I',
407         'IJ' => 'IJ',
408         'Ȉ' => 'I',
409         'Ȋ' => 'I',
410         'ĵ' => 'j',
411         'Ĵ' => 'J',
412         'ķ' => 'k',
413         'Ķ' => 'K',
414         'ĺ' => 'l',
415         'ļ' => 'l',
416         'ľ' => 'l',
417         'ŀ' => 'l',
418         'ł' => 'l',
419         'Ĺ' => 'L',
420         'Ļ' => 'L',
421         'Ľ' => 'L',
422         'Ŀ' => 'L',
423         'Ł' => 'L',
424         'ñ' => 'n',
425         'ń' => 'n',
426         'ņ' => 'n',
427         'ň' => 'n',
428         'ʼn' => 'n',
429         'Ñ' => 'N',
430         'Ń' => 'N',
431         'Ņ' => 'N',
432         'Ň' => 'N',
433         'ó' => 'o',
434         'ò' => 'o',
435         'ö' => 'oe',
436         'ô' => 'o',
437         'õ' => 'o',
438         'ø' => 'o',
439         'ō' => 'o',
440         'ŏ' => 'o',
441         'ő' => 'o',
442         'œ' => 'oe',
443         'ȍ' => 'o',
444         'ȏ' => 'o',
445         'Ó' => 'O',
446         'Ò' => 'O',
447         'Ö' => 'Oe',
448         'Ô' => 'O',
449         'Õ' => 'O',
450         'Ø' => 'O',
451         'Ō' => 'O',
452         'Ŏ' => 'O',
453         'Ő' => 'O',
454         'Œ' => 'OE',
455         'Ȍ' => 'O',
456         'Ȏ' => 'O',
457         'ŕ' => 'r',
458         'ř' => 'r',
459         'ȑ' => 'r',
460         'ȓ' => 'r',
461         'Ŕ' => 'R',
462         'Ř' => 'R',
463         'Ȑ' => 'R',
464         'Ȓ' => 'R',
465         'ß' => 'ss',
466         'ś' => 's',
467         'ŝ' => 's',
468         'ş' => 's',
469         'š' => 's',
470         'ș' => 's',
471         'Ś' => 'S',
472         'Ŝ' => 'S',
473         'Ş' => 'S',
474         'Š' => 'S',
475         'Ș' => 'S',
476         'ţ' => 't',
477         'ť' => 't',
478         'ŧ' => 't',
479         'ț' => 't',
480         'Ţ' => 'T',
481         'Ť' => 'T',
482         'Ŧ' => 'T',
483         'Ț' => 'T',
484         'ú' => 'u',
485         'ù' => 'u',
486         'ü' => 'ue',
487         'û' => 'u',
488         'ũ' => 'u',
489         'ū' => 'u',
490         'ŭ' => 'u',
491         'ů' => 'u',
492         'ű' => 'u',
493         'ų' => 'u',
494         'ȕ' => 'u',
495         'ȗ' => 'u',
496         'Ú' => 'U',
497         'Ù' => 'U',
498         'Ü' => 'Ue',
499         'Û' => 'U',
500         'Ũ' => 'U',
501         'Ū' => 'U',
502         'Ŭ' => 'U',
503         'Ů' => 'U',
504         'Ű' => 'U',
505         'Ų' => 'U',
506         'Ȕ' => 'U',
507         'Ȗ' => 'U',
508         'ŵ' => 'w',
509         'Ŵ' => 'W',
510         'ý' => 'y',
511         'ÿ' => 'y',
512         'ŷ' => 'y',
513         'Ý' => 'Y',
514         'Ÿ' => 'Y',
515         'Ŷ' => 'Y',
516         'ź' => 'z',
517         'ż' => 'z',
518         'ž' => 'z',
519         'Ź' => 'Z',
520         'Ż' => 'Z',
521         'Ž' => 'Z',
522     );
523
524     $result = strtr($string, $special_chars);   // replace known special chars
525     $result = strtoupper($result);                  // upper case
526     // make sure every special char is replaced by one space, not two or three
527     $result = mb_convert_encoding($result, 'ASCII', 'UTF-8');
528     $result = preg_replace('/[^A-Z0-9 \.,&\-\/\+\*\$%]/', ' ', $result);
529
530     return $result;
531 }