Merge branch 'xorg/1.0.2/master' into xorg/master
authorStéphane Jacob <sj@m4x.org>
Mon, 3 Jan 2011 12:30:33 +0000 (13:30 +0100)
committerStéphane Jacob <sj@m4x.org>
Mon, 3 Jan 2011 12:30:33 +0000 (13:30 +0100)
1  2 
ChangeLog
modules/payment.php

diff --combined ChangeLog
+++ b/ChangeLog
@@@ -1,7 -1,4 +1,7 @@@
  ================================================================================
 +VERSION 1.1.0                                                         XX XX XXXX
 +
 +================================================================================
  VERSION 1.0.2                                                         XX XX XXXX
  
  Bug/Wish:
@@@ -12,6 -9,9 +12,9 @@@
      * Core:
          - #1355: Mode with propagation of the skinning mode                -FRU
  
+     * Payments:
+         - #1318: Fixes PHP errors in PayPal payments                       -JAC
      * Profile:
          - #1340: Allows secretaries and admin to fully edit profiles' name -JAC
          - #1354: Do not notify death to a deceased user                    -JAC
diff --combined modules/payment.php
@@@ -55,23 -55,23 +55,23 @@@ function paypal_erreur($text, $send=tru
  function luhn($nombre) {
      $s = strrev($nombre);
      $sum = 0;
 -    for ($i = 0; $i < strlen($s); $i++) {
 +    for ($i = 0; $i < strlen($s); ++$i) {
      $dgt = $s{$i};
 -        $sum += ($i % 2) ? (2*$dgt) % 9 : $dgt;
 +        $sum += ($i % 2) ? (2 * $dgt) % 9 : $dgt;
      }
      return $sum % 10;
  }
  
  /* calcule la clé d'acceptation a partir de 5 champs */
 -function cle_accept($d1,$d2,$d3,$d4,$d5)
 +function cle_accept($d1, $d2, $d3, $d4, $d5)
  {
 -    $m1 = luhn($d1.$d5);
 -    $m2 = luhn($d2.$d5);
 -    $m3 = luhn($d3.$d5);
 -    $m4 = luhn($d4.$d5);
 +    $m1 = luhn($d1 . $d5);
 +    $m2 = luhn($d2 . $d5);
 +    $m3 = luhn($d3 . $d5);
 +    $m4 = luhn($d4 . $d5);
      $n = $m1 + $m2 + $m3 + $m4;
 -    $alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
 -    return $alpha{$n-1}.$m1.$m2.$m3.$m4;
 +    $alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
 +    return $alpha{$n-1} . $m1 . $m2 . $m3 . $m4;
  }
  
  /* decode the comment */
@@@ -88,16 -88,16 +88,16 @@@ function comment_decode($comment) 
  function check_rib($rib)
  {
      if(strlen($rib) != 23) return false;
 -    
 +
      // extract fields
      $rib = strtr(strtoupper($rib),'ABCDEFGHIJKLMNOPQRSTUVWXYZ','12345678912345678923456789');
      $bank    = substr($rib,0,5);
      $counter = substr($rib,5,5);
      $account = substr($rib,10,11);
      $key     = substr($rib,21,2);
 -    
 +
      // check
 -    return 0 == fmod(89 * $bank + 15 * $counter + 3 * $account + $key, 97);
 +    return (0 == fmod(89 * $bank + 15 * $counter + 3 * $account + $key, 97));
  }
  
  class PaymentModule extends PLModule
      function handlers()
      {
          return array(
 -            'payment'                    => $this->make_hook('payment',       AUTH_MDP,    'payment'),
 -            'payment/cyber_return'       => $this->make_hook('cyber_return',  AUTH_PUBLIC, 'user', NO_HTTPS),
 -            'payment/cyber2_return'      => $this->make_hook('cyber2_return', AUTH_PUBLIC, 'user', NO_HTTPS),
 -            'payment/paypal_return'      => $this->make_hook('paypal_return', AUTH_PUBLIC, 'user', NO_HTTPS),
 -            '%grp/paiement'              => $this->make_hook('xnet_payment',  AUTH_MDP),
 -            '%grp/payment'               => $this->make_hook('xnet_payment',  AUTH_MDP),
 -            '%grp/payment/cyber_return'  => $this->make_hook('cyber_return',  AUTH_PUBLIC, 'user', NO_HTTPS),
 -            '%grp/payment/cyber2_return' => $this->make_hook('cyber2_return', AUTH_PUBLIC, 'user', NO_HTTPS),
 -            '%grp/payment/paypal_return' => $this->make_hook('paypal_return', AUTH_PUBLIC, 'user', NO_HTTPS),
 -            'admin/payments'             => $this->make_hook('admin',         AUTH_MDP,    'admin'),
 -            'admin/payments/methods'     => $this->make_hook('adm_methods',   AUTH_MDP,    'admin'),
 -            'admin/payments/transactions'=> $this->make_hook('adm_transactions', AUTH_MDP, 'admin'),
 -            'admin/reconcile'            => $this->make_hook('adm_reconcile', AUTH_MDP,    'admin'),
 -            'admin/reconcile/importlogs' => $this->make_hook('adm_importlogs', AUTH_MDP,    'admin'),
 -            'admin/reconcile/transfers'  => $this->make_hook('adm_transfers', AUTH_MDP,    'admin'),
 -            'admin/reconcile/bankaccounts'=> $this->make_hook('adm_bankaccounts', AUTH_MDP, 'admin'),
 +            'payment'                      => $this->make_hook('payment',          AUTH_MDP,    'payment'),
 +            'payment/cyber_return'         => $this->make_hook('cyber_return',     AUTH_PUBLIC, 'user', NO_HTTPS),
 +            'payment/cyber2_return'        => $this->make_hook('cyber2_return',    AUTH_PUBLIC, 'user', NO_HTTPS),
 +            'payment/paypal_return'        => $this->make_hook('paypal_return',    AUTH_PUBLIC, 'user', NO_HTTPS),
 +            '%grp/paiement'                => $this->make_hook('xnet_payment',     AUTH_MDP),
 +            '%grp/payment'                 => $this->make_hook('xnet_payment',     AUTH_MDP),
 +            '%grp/payment/cyber_return'    => $this->make_hook('cyber_return',     AUTH_PUBLIC, 'user', NO_HTTPS),
 +            '%grp/payment/cyber2_return'   => $this->make_hook('cyber2_return',    AUTH_PUBLIC, 'user', NO_HTTPS),
 +            '%grp/payment/paypal_return'   => $this->make_hook('paypal_return',    AUTH_PUBLIC, 'user', NO_HTTPS),
 +            'admin/payments'               => $this->make_hook('admin',            AUTH_MDP,    'admin'),
 +            'admin/payments/methods'       => $this->make_hook('adm_methods',      AUTH_MDP,    'admin'),
 +            'admin/payments/transactions'  => $this->make_hook('adm_transactions', AUTH_MDP,    'admin'),
 +            'admin/reconcile'              => $this->make_hook('adm_reconcile',    AUTH_MDP,    'admin'),
 +            'admin/reconcile/importlogs'   => $this->make_hook('adm_importlogs',   AUTH_MDP,    'admin'),
 +            'admin/reconcile/transfers'    => $this->make_hook('adm_transfers',    AUTH_MDP,    'admin'),
 +            'admin/reconcile/bankaccounts' => $this->make_hook('adm_bankaccounts', AUTH_MDP,    'admin'),
          );
      }
  
              if (!$globals->asso('id')) {
                  return PL_NOT_FOUND;
              }
 -            $res = XDB::query("SELECT asso_id
 -                                 FROM payments
 -                                WHERE asso_id = {?} AND id = {?}",
 +            $res = XDB::query('SELECT  asso_id
 +                                 FROM  payments
 +                                WHERE  asso_id = {?} AND id = {?}',
                                $globals->asso('id'), $ref);
              if (!$res->numRows()) {
                  return PL_FORBIDDEN;
              $page->trigError($e);
          }
  
 -        if ($op=='submit') {
 +        if ($op == 'submit') {
              $pay->init($val, $meth);
              $pay->prepareform($pay);
          } else {
 -            $res = XDB::iterator("SELECT  timestamp, amount
 +            $res = XDB::iterator('SELECT  timestamp, amount
                                      FROM  payment_transactions
                                     WHERE  uid = {?} AND ref = {?}
 -                                ORDER BY  timestamp DESC",
 +                                ORDER BY  timestamp DESC',
                                   S::v('uid', -1), $ref);
  
 -            if ($res->total()) $page->assign('transactions', $res);
 +            if ($res->total()) {
 +                $page->assign('transactions', $res);
 +            }
          }
  
 -        $val = floor($val).".".substr(floor(($val - floor($val))*100+100),1);
 -        $page->assign('montant',$val);
 -        $page->assign('comment',Env::v('comment'));
 +        $val = floor($val) . '.' . substr(floor(($val - floor($val)) * 100 + 100), 1);
 +        $page->assign('montant', $val);
 +        $page->assign('comment', Env::v('comment'));
  
          $page->assign('meth', $meth);
 -        $page->assign('pay',  $pay);
 +        $page->assign('pay', $pay);
          $page->assign('evtlink', $pay->event());
+         $page->assign('sex', S::user()->isFemale());
      }
  
      function handler_cyber_return(&$page, $uid = null)
          }
  
          echo ($ref = $matches[1]);
 -        $res = XDB::query("SELECT  mail, text, confirmation
 +        $res = XDB::query('SELECT  mail, text, confirmation
                               FROM  payments
 -                            WHERE  id={?}", $ref);
 +                            WHERE  id = {?}', $ref);
          if (!list($conf_mail, $conf_title, $conf_text) = $res->fetchOneRow()) {
              cb_erreur("référence de commande inconnue");
          }
          }
  
          /* on fait l'insertion en base de donnees */
 -        XDB::execute("INSERT INTO  payment_transactions (id, uid, ref, fullref, amount, pkey, comment)
 -                           VALUES  ({?}, {?}, {?}, {?}, {?}, {?}, {?})",
 +        XDB::execute('INSERT INTO  payment_transactions (id, uid, ref, fullref, amount, pkey, comment)
 +                           VALUES  ({?}, {?}, {?}, {?}, {?}, {?}, {?})',
                       $champ901, $user->id(), $ref, $champ200, $montant, $champ905, Env::v('comment'));
  
          // We check if it is an Xnet payment and then update the related ML.
          /* on vérifie la signature */
          $vads_params = array();
          foreach($_REQUEST as $key => $value)
 -            if(substr($key,0,5) == "vads_")
 +            if(substr($key,0,5) == 'vads_') {
                  $vads_params[$key] = $value;
 +            }
          ksort($vads_params);
 -        $signature = sha1(join('+',$vads_params).'+'.$globals->money->cyperplus_key);
 +        $signature = sha1(join('+', $vads_params) . '+' . $globals->money->cyperplus_key);
          //if($signature != Env::v('signature')) {
          //    cb_erreur("signature invalide");
          //}
          }
  
          $ref = $matches[1];
 -        $res = XDB::query("SELECT  mail, text, confirmation
 +        $res = XDB::query('SELECT  mail, text, confirmation
                               FROM  payments
 -                            WHERE  id={?}", $ref);
 +                            WHERE  id={?}', $ref);
          if ($res->numRows() != 1) {
              cb_erreur("référence de commande inconnue");
          }
          list($conf_mail, $conf_title, $conf_text) = $res->fetchOneRow();
  
          /* on extrait le montant */
 -        if (Env::v('vads_currency') != "978") {
 +        if (Env::v('vads_currency') != '978') {
              cb_erreur("monnaie autre que l'euro");
          }
          $amount = ((float)Env::i('vads_amount')) / 100;
          $montant = sprintf("%.02f EUR", $amount);
  
          /* on extrait le code de retour */
 -        if (Env::v('vads_result') != "00") {
 -            cb_erreur("erreur lors du paiement : ?? (".Env::v('vads_result').")");
 +        if (Env::v('vads_result') != '00') {
 +            cb_erreur('erreur lors du paiement : ?? (' . Env::v('vads_result') . ')');
          }
  
          /* on fait l'insertion en base de donnees */
 -        XDB::execute("INSERT INTO  payment_transactions (id, uid, ref, fullref, amount, pkey, comment)
 -                           VALUES  ({?}, {?}, {?}, {?}, {?}, {?}, {?})",
 -                     Env::v('vads_trans_date'), $user->id(), $ref, Env::v('vads_order_id'), $montant, "", Env::v('vads_order_info'));
 +        XDB::execute('INSERT INTO  payment_transactions (id, uid, ref, fullref, amount, pkey, comment)
 +                           VALUES  ({?}, {?}, {?}, {?}, {?}, {?}, {?})',
 +                     Env::v('vads_trans_date'), $user->id(), $ref, Env::v('vads_order_id'), $montant, '', Env::v('vads_order_info'));
          echo "Paiement stored.\n";
  
          // We check if it is an Xnet payment and then update the related ML.
          /* code retour */
          $status = Env::s('st');
          /* raison */
 -        $reason = ($status == 'Pending')? Env::s('pending_reason'): Env::s('reason_code');
 +        $reason = ($status == 'Pending') ? Env::s('pending_reason') : Env::s('reason_code');
          /* reference complete de la commande */
          $fullref = Env::s('cm');
          /* montant de la transaction */
  
          /* on extrait le code de retour */
          if ($status != "Completed") {
 -            if ($status)
 +            if ($status) {
                  paypal_erreur("erreur lors du paiement : $status - $reason");
 -            else
 +            } else {
                  paypal_erreur("Paiement annulé", false);
 +            }
          }
  
          /* on extrait les informations sur l'utilisateur */
          }
  
          $ref = $matches[1];
 -        $res = XDB::query("SELECT  mail, text, confirmation
 +        $res = XDB::query('SELECT  mail, text, confirmation
                               FROM  payments
 -                            WHERE  id = {?}", $ref);
 -        if (!list($conf_mail,$conf_title,$conf_text) = $res->fetchOneRow()) {
 -            paypal_erreur("référence de commande inconnue");
 +                            WHERE  id = {?}', $ref);
 +        if (!list($conf_mail, $conf_title, $conf_text) = $res->fetchOneRow()) {
 +            paypal_erreur('référence de commande inconnue');
          }
  
          /* on fait l'insertion en base de donnees */
                    WHERE  asso_id = {?} AND NOT FIND_IN_SET('old', flags)
                 ORDER BY  id DESC", $globals->asso('id'));
          $tit = $res->fetchAllAssoc();
 -        $page->assign('titres', $tit);
 -
 +        $page->assign('titles', $tit);
  
 -        // TODO: replug sort.
          $trans = array();
          $event = array();
 +        if (may_update()) {
 +            static $orders = array('timestamp' => 'p', 'directory_name' => 'a', 'promo' => 'pd', 'comment' => 'p', 'amount' => 'p');
 +
 +            if (Get::has('order_id') && Get::has('order') && array_key_exists(Get::v('order'), $orders)) {
 +                $order_id = Get::i('order_id');
 +                $order = Get::v('order');
 +                $ordering = ' ORDER BY ' . $orders[$order] . '.' . $order;
 +                if (Get::has('order_inv') && Get::i('order_inv') == 1) {
 +                    $ordering .= ' DESC';
 +                    $page->assign('order_inv', 0);
 +                } else {
 +                    $page->assign('order_inv', 1);
 +                }
 +                $page->assign('order_id', $order_id);
 +                $page->assign('order', $order);
 +                $page->assign('anchor', 'legend_' . $order_id);
 +            } else {
 +                $order_id = false;
 +                $ordering = '';
 +                $page->assign('order', false);
 +            }
 +        } else {
 +            $ordering = '';
 +            $page->assign('order', false);
 +        }
          foreach($tit as $foo) {
              $pid = $foo['id'];
              if (may_update()) {
 -                $res = XDB::query('SELECT  t.uid, timestamp AS `date`, t.comment, amount
 -                                     FROM  payment_transactions AS t
 -                                    WHERE  t.ref = {?}', $pid);
 +                $res = XDB::query('SELECT  p.uid, IF(p.timestamp = \'0000-00-00\', 0, p.timestamp) AS date, p.comment, p.amount
 +                                     FROM  payment_transactions AS p
 +                               INNER JOIN  accounts             AS a  ON (a.uid = p.uid)
 +                                LEFT JOIN  account_profiles     AS ap ON (ap.uid = p.uid AND FIND_IN_SET(\'owner\', ap.perms))
 +                                LEFT JOIN  profile_display      AS pd ON (ap.pid = pd.pid)
 +                                    WHERE  p.ref = {?}' . (($order_id == $pid) ? $ordering : ''),
 +                                  $pid);
                  $trans[$pid] = User::getBulkUsersWithUIDs($res->fetchAllAssoc(), 'uid', 'user');
                  $sum = 0;
                  foreach ($trans[$pid] as $i => $t) {
                      $sum += strtr(substr($t['amount'], 0, strpos($t['amount'], 'EUR')), ',', '.');
                      $trans[$pid][$i]['amount'] = str_replace('EUR', '€', $t['amount']);
                  }
 -                $trans[$pid][] = array('nom' => 'somme totale',
 -                                       'amount' => strtr($sum, '.', ',').' €');
 +                $trans[$pid][] = array('limit'  =>  true,
 +                                       'amount' => strtr($sum, '.', ',') . ' €');
              }
 -            $res = XDB::iterRow("SELECT e.eid, e.short_name, e.intitule, ep.nb, ei.montant, ep.paid
 -                                   FROM group_events AS e
 -                              LEFT JOIN group_event_participants AS ep ON (ep.eid = e.eid AND ep.uid = {?})
 -                             INNER JOIN group_event_items AS ei ON (ep.eid = ei.eid AND ep.item_id = ei.item_id)
 -                                  WHERE e.paiement_id = {?}",
 -                                 S::v('uid'), $pid);
 +            $res = XDB::iterRow("SELECT  e.eid, e.short_name, e.intitule, ep.nb, ei.montant, ep.paid
 +                                   FROM  group_events             AS e
 +                              LEFT JOIN  group_event_participants AS ep ON (ep.eid = e.eid AND ep.uid = {?})
 +                             INNER JOIN  group_event_items        AS ei ON (ep.eid = ei.eid AND ep.item_id = ei.item_id)
 +                                  WHERE  e.paiement_id = {?}",
 +                                S::v('uid'), $pid);
              $event[$pid] = array();
              $event[$pid]['paid'] = 0;
              if ($res->total()) {
                      $event[$pid]['paid']      = $paid;
                  }
              }
 -            $res = XDB::query("SELECT amount
 -                                 FROM payment_transactions AS t
 -                                WHERE ref = {?} AND uid = {?}", $pid, S::v('uid'));
 +            $res = XDB::query('SELECT  amount
 +                                 FROM  payment_transactions
 +                                WHERE  id = {?} AND uid = {?}', $pid, S::v('uid'));
              $montants = $res->fetchColumn();
  
              foreach ($montants as $m) {
          $table_editor->add_sort_field('flags');
          $table_editor->add_sort_field('id', true, true);
          $table_editor->on_delete("UPDATE payments SET flags = 'old' WHERE id = {?}", "Le paiement a été archivé");
 -        $table_editor->describe('text','intitulé',true);
 -        $table_editor->describe('url','site web',false);
 -        $table_editor->describe('amount_def','montant par défaut',false);
 -        $table_editor->describe('amount_min','montant minimum',false);
 -        $table_editor->describe('amount_max','montant maximum',false);
 -        $table_editor->describe('mail','email contact',true);
 -        $table_editor->describe('confirmation','message confirmation',false);
 +        $table_editor->describe('text', 'intitulé', true);
 +        $table_editor->describe('url', 'site web', false);
 +        $table_editor->describe('amount_def', 'montant par défaut', false);
 +        $table_editor->describe('amount_min', 'montant minimum', false);
 +        $table_editor->describe('amount_max', 'montant maximum', false);
 +        $table_editor->describe('mail', 'email contact', true);
 +        $table_editor->describe('confirmation', 'message confirmation', false);
  
          // adds a column with the start date of the linked event if there is one
 -        $table_editor->add_option_table('group_events','group_events.paiement_id = t.id');
 +        $table_editor->add_option_table('group_events', 'group_events.paiement_id = t.id');
          $table_editor->add_option_field('group_events.debut', 'related_event', 'évènement', 'timestamp');
  
          $table_editor->apply($page, $action, $id);
      }
 -    
 +
      function handler_adm_transactions(&$page, $payment_id = null, $action = "list", $id = null) {
          // show transactions. FIXME: should not be modifiable
          $page->setTitle('Administration - Paiements - Transactions');
          $page->assign('title', "Liste des transactions pour le paiement {$payment_id}");
 -        
 +
          if ($payment_id == null)
              $page->trigError("Aucun ID de paiement fourni.");
 -        
 +
          $table_editor = new PLTableEditor("admin/transactions/{$payment_id}",'payment_transactions','id');
          $table_editor->set_where_clause(XDB::format('ref = {?}', $payment_id));
          $table_editor->apply($page, 'list', $id); // only the 'list' action is allowed
 -        $page->assign("readonly","readonly");     // don't show modification features
 +        $page->assign('readonly', 'readonly');     // don't show modification features
      }
 -    
 -    function handler_adm_bankaccounts(&$page, $action = "list", $id = null) {
 +
 +    function handler_adm_bankaccounts(&$page, $action = 'list', $id = null) {
          // managment of bank account used for money transfert
          $page->setTitle('Administration - Paiements - RIBs');
          $page->assign('title', "Liste des RIBs");
 -        
 -        $table_editor = new PLTableEditor("admin/payments/bankaccounts",'payment_bankaccounts','id');
 -        $table_editor->describe('asso_id','ID du groupe',false);
 -        $table_editor->describe('owner','titulaire',true);
 -        $table_editor->add_option_table('groups','groups.id = t.asso_id');
 +
 +        $table_editor = new PLTableEditor('admin/payments/bankaccounts', 'payment_bankaccounts', 'id');
 +        $table_editor->describe('asso_id', 'ID du groupe', false);
 +        $table_editor->describe('owner', 'titulaire', true);
 +        $table_editor->add_option_table('groups', 'groups.id = t.asso_id');
          $table_editor->add_option_field('groups.diminutif', 'group_name', 'groupe', 'varchar','account');
 -        
 +
          // check RIB key
 -        if ($action == "update" && Post::has("account") && !check_rib(Post::v("account"))) {
 +        if ($action == 'update' && Post::has('account') && !check_rib(Post::v('account'))) {
              $page->trigError("Le RIB n'est pas valide");
 -            $table_editor->apply($page, "edit", $id);
 +            $table_editor->apply($page, 'edit', $id);
              return;
          }
 -        
 +
          $table_editor->apply($page, $action, $id);
      }
 -    
 -    function handler_adm_methods(&$page, $action = "list", $id = null) {
 +
 +    function handler_adm_methods(&$page, $action = 'list', $id = null) {
          // show and edit payment methods
          $page->setTitle('Administration - Paiements - Méthodes');
 -        $page->assign('title', "Méthodes de paiement");
 -        $table_editor = new PLTableEditor("admin/payments/methods",'payment_methods','id');
 +        $page->assign('title', 'Méthodes de paiement');
 +        $table_editor = new PLTableEditor('admin/payments/methods', 'payment_methods', 'id');
          $table_editor->apply($page, $action, $id);
      }
  
          $page->changeTpl('payment/reconcile.tpl');
          $page->assign('step', $step);
          $list = true;
 -        
 +
          // actions
          if ($step == 'delete' && $param != null) {
              S::assert_xsrf_token();
 -            XDB::execute("DELETE FROM payment_reconcilations WHERE id={?}", $param);
 +            XDB::execute('DELETE FROM payment_reconcilations WHERE id = {?}', $param);
              // FIXME: hardcoding !!!
 -            XDB::execute("UPDATE payment_transactions SET recon_id=NULL,commission=NULL WHERE recon_id={?} AND method_id=2", $param);
 -            XDB::execute("UPDATE payment_transactions SET recon_id=NULL WHERE recon_id={?} AND method_id=1", $param);
 -            $page->trigSuccess("L'entrée ".$param." a été supprimée.");
 -        
 +            XDB::execute('UPDATE payment_transactions SET recon_id = NULL,commission = NULL WHERE recon_id = {?} AND method_id = 2', $param);
 +            XDB::execute('UPDATE payment_transactions SET recon_id = NULL WHERE recon_id = {?} AND method_id = 1', $param);
 +            $page->trigSuccess("L'entrée " . $param . ' a été supprimée.');
 +
          } elseif ($step == 'edit') {
              $page->trigError("L'édition n'est pas implémentée.");
 -            
 +
          } elseif ($step == 'step5') {
              $page->trigSuccess("La réconciliation est terminée. Il est maintenant nécessaire de générer les virements.");
 -        
 +
          }
 -        
 +
          if($list) {
              // show list of reconciliations, with a "add" button
 -            $page->assign('title', "Réconciliation - Liste");
 +            $page->assign('title', 'Réconciliation - Liste');
              $page->assign('step', 'list');
 -            
 +
              $recongps = array();
 -    
 +
              $res = XDB::query("SELECT  r.id, short_name AS method, period_start, period_end, status,
                                         payment_count, sum_amounts, sum_commissions
                                   FROM  payment_reconcilations AS r
 -                            LEFT JOIN  payment_methods AS m ON r.method_id=m.id
 +                            LEFT JOIN  payment_methods        AS m ON (r.method_id = m.id)
                                  WHERE  recongroup_id IS NULL
                               ORDER BY  period_end DESC, period_start DESC");
              foreach ($res->fetchAllAssoc() as $recon)
                  $recongps[] = array('recons' => array($recon), 'transfers' => array());
 -            
 +
              $res = XDB::query("SELECT  recongroup_id AS id
                                   FROM  payment_reconcilations
                               GROUP BY  recongroup_id
                  $res = XDB::query("SELECT  r.id, short_name AS method, period_start, period_end, status,
                                             payment_count, sum_amounts, sum_commissions
                                       FROM  payment_reconcilations AS r
 -                                LEFT JOIN  payment_methods AS m ON r.method_id=m.id
 -                                    WHERE  recongroup_id={?}
 +                                LEFT JOIN  payment_methods        AS m ON (r.method_id = m.id)
 +                                    WHERE  recongroup_id = {?}
                                   ORDER BY  period_end DESC, period_start DESC",
                                    $recongp['id']);
                  $recongp['recons'] = $res->fetchAllAssoc();
  
 -                $res = XDB::query("SELECT  id, payment_id, amount, account_id, message, date
 +                $res = XDB::query('SELECT  id, payment_id, amount, account_id, message, date
                                       FROM  payment_transfers
 -                                    WHERE  recongroup_id={?}",
 +                                    WHERE  recongroup_id = {?}',
                                    $recongp['id']);
                  $recongp['transfers'] = $res->fetchAllAssoc();
 -                        
 +
                  $recongps[] = $recongp;
              }
              $page->assign_by_ref('recongps', $recongps);
          }
      }
 -    
 +
      function handler_adm_importlogs(&$page, $step, $param = null) {
          $page->setTitle('Administration - Paiements - Réconciliations');
          $page->changeTpl('payment/reconcile.tpl');
          $page->assign('step', $step);
 -        
 +
          if (isset($_SESSION['paymentrecon_data'])) {
              // create temporary table with imported data
 -            XDB::execute("CREATE TEMPORARY TABLE payment_tmp (
 +            XDB::execute('CREATE TEMPORARY TABLE payment_tmp (
                              reference VARCHAR(255) PRIMARY KEY,
                              date DATE,
                              amount DECIMAL(9,2),
                              commission DECIMAL(9,2)
 -                          )");
 +                          )');
              foreach ($_SESSION['paymentrecon_data'] as $i)
 -                XDB::execute("INSERT INTO payment_tmp VALUES ({?},{?},{?},{?})",
 +                XDB::execute('INSERT INTO payment_tmp VALUES ({?}, {?}, {?}, {?})',
                                $i['reference'], $i['date'], $i['amount'], $i['commission']);
          }
 -        
 +
          if ($step == 'step1') {
 -            $page->assign('title', "Étape 1");
 +            $page->assign('title', 'Étape 1');
              unset($_SESSION['paymentrecon_method']);
              unset($_SESSION['paymentrecon_data']);
              unset($_SESSION['paymentrecon_id']);
 -                
 +
              // was a payment method choosen ?
              if ($param != null) {
                  $_SESSION['paymentrecon_method'] = (int)$param;
 -                pl_redirect("admin/reconcile/importlogs/step2");
 +                pl_redirect('admin/reconcile/importlogs/step2');
  
              } else {
              // ask to choose a payment method
 -                $res = XDB::query("SELECT id, text FROM payment_methods");
 +                $res = XDB::query('SELECT id, text FROM payment_methods');
                  $page->assign('methods', $res->fetchAllAssoc());
              }
  
          } elseif ( $step == 'step2' ) {
 -            $page->assign('title', "Étape 2");
 -            
 +            $page->assign('title', 'Étape 2');
 +
              // import logs formated in CVS
 -            $fields = array('date','reference','amount','commission');
 +            $fields = array('date', 'reference', 'amount', 'commission');
              $importer = new PaymentLogsImporter();
              $importer->apply($page, 'admin/reconcile/importlogs/step2', $fields);
 -            
 +
              // if import is finished
              $result = $importer->get_result();
              if($result != null) {
                  $_SESSION['paymentrecon_data'] = $result;
 -                pl_redirect("admin/reconcile/importlogs/step3");
 +                pl_redirect('admin/reconcile/importlogs/step3');
              }
 -            
 +
          } elseif ($step == 'step3' ) {
 -            $page->assign('title', "Étape 3");
 -            
 +            $page->assign('title', 'Étape 3');
 +
              // compute reconcilation summary data
 -            $res = XDB::query("SELECT  MIN(date) AS period_start, MAX(date) AS period_end,
 +            $res = XDB::query('SELECT  MIN(date) AS period_start, MAX(date) AS period_end,
                                         count(*) AS payment_count, SUM(amount) AS sum_amounts,
                                         SUM(commission) AS sum_commissions
 -                                 FROM  payment_tmp");
 +                                 FROM  payment_tmp');
              $recon = $res->fetchOneAssoc();
              $recon['method_id'] = $_SESSION['paymentrecon_method'];
 -            
 +
              // create reconciliation item in database
              if(Post::has('next')) {
                  S::assert_xsrf_token();
 -                
 +
                  // get parameters
 -                $recon['period_start'] = preg_replace('/([0-9]{1,2})\/([0-9]{1,2})\/([0-9]{4})/','\3-\2-\1',Post::v('period_start'));
 -                $recon['period_end']   = preg_replace('/([0-9]{1,2})\/([0-9]{1,2})\/([0-9]{4})/','\3-\2-\1',Post::v('period_end'));
 +                $recon['period_start'] = preg_replace('/([0-9]{1,2})\/([0-9]{1,2})\/([0-9]{4})/', '\3-\2-\1', Post::v('period_start'));
 +                $recon['period_end']   = preg_replace('/([0-9]{1,2})\/([0-9]{1,2})\/([0-9]{4})/', '\3-\2-\1', Post::v('period_end'));
                      // FIXME: save checks to be done at next step
 -                
 +
                  // Create reconcilation item in database
                      // FIXME: check if period doesn't overlap with others for the same method_id
 -                XDB::execute("INSERT INTO  payment_reconcilations (method_id, period_start, period_end,
 +                XDB::execute('INSERT INTO  payment_reconcilations (method_id, period_start, period_end,
                                                                     payment_count, sum_amounts, sum_commissions)
 -                                   VALUES  ({?}, {?}, {?}, {?}, {?}, {?})",
 +                                   VALUES  ({?}, {?}, {?}, {?}, {?}, {?})',
                               $recon['method_id'], $recon['period_start'], $recon['period_end'],
                               $recon['payment_count'], $recon['sum_amounts'], $recon['sum_commissions']);
                  $_SESSION['paymentrecon_id'] = XDB::insertId();
 -                
 +
                  // reconcile simple cases (trans.commission n'est modifié que s'il vaut NULL)
                  XDB::execute("UPDATE  payment_transactions AS trans, payment_tmp AS tmp
 -                                 SET  trans.recon_id={?}, trans.commission=tmp.commission
 -                               WHERE  trans.fullref=tmp.reference
 -                                      AND trans.amount=tmp.amount AND DATE(trans.ts_confirmed)=tmp.date
 -                                      AND (trans.commission IS NULL OR trans.commission=tmp.commission)
 -                                      AND method_id={?} AND recon_id IS NULL AND status='confirmed'",
 +                                 SET  trans.recon_id = {?}, trans.commission=tmp.commission
 +                               WHERE  trans.fullref = tmp.reference
 +                                      AND trans.amount = tmp.amount AND DATE(trans.ts_confirmed) = tmp.date
 +                                      AND (trans.commission IS NULL OR trans.commission = tmp.commission)
 +                                      AND method_id = {?} AND recon_id IS NULL AND status = 'confirmed'",
                               $_SESSION['paymentrecon_id'], $recon['method_id']);
 -                
 -                pl_redirect("admin/reconcile/importlogs/step4");                
 -                
 +
 +                pl_redirect("admin/reconcile/importlogs/step4");
 +
              // show summary of the imported data + ask form start/end of reconcilation period
              } else {
                  $recon['period_start'] = preg_replace('/([0-9]{4})-([0-9]{2})-([0-9]{2})/', '\3/\2/\1', $recon['period_start']);
              }
  
          } elseif ($step == 'step4' ) {
 -            $page->assign('title', "Étape 4");
 -            
 +            $page->assign('title', 'Étape 4');
 +
              // get reconcilation summary informations
 -            $res = XDB::query("SELECT * FROM payment_reconcilations WHERE id={?}", $_SESSION['paymentrecon_id']);
 +            $res = XDB::query('SELECT * FROM payment_reconcilations WHERE id = {?}', $_SESSION['paymentrecon_id']);
              $recon = $res->fetchOneAssoc();
              $page->assign('recon', $recon);
  
              if (Post::has('force')) {
                  S::assert_xsrf_token();
                  foreach (Post::v('force') as $id => $value) {
 -                    XDB::execute("UPDATE  payment_transactions AS trans, payment_tmp AS tmp
 -                                     SET  trans.recon_id={?}, trans.commission=tmp.commission
 -                                   WHERE  trans.id={?} AND trans.fullref=tmp.reference",
 +                    XDB::execute('UPDATE  payment_transactions AS trans, payment_tmp AS tmp
 +                                     SET  trans.recon_id = {?}, trans.commission = tmp.commission
 +                                   WHERE  trans.id = {?} AND trans.fullref = tmp.reference',
                                   $_SESSION['paymentrecon_id'], $id);
                  }
 -                $page->trigSuccess('La réconciliation a été forcée pour '.count(Post::v('force')).' transaction(s).');
 -                
 +                $page->trigSuccess('La réconciliation a été forcée pour ' . count(Post::v('force')) . ' transaction(s).');
 +
              } elseif (Post::has('next')) {
 -                if (strlen($recon['comments'])<3) {
 -                    $page->trigError("Le commentaire doit contenir au moins 3 caractères.");
 +                if (strlen($recon['comments'])< 3 ) {
 +                    $page->trigError('Le commentaire doit contenir au moins 3 caractères.');
                  } else {
 -                    XDB::execute("UPDATE payment_reconcilations SET status='transfering' WHERE id={?}", $_SESSION['paymentrecon_id']);
 +                    XDB::execute("UPDATE payment_reconcilations SET status = 'transfering' WHERE id = {?}", $_SESSION['paymentrecon_id']);
                      pl_redirect('admin/reconcile/step5');
                  }
 -                
 +
              } elseif (Post::has('savecomments')) {
                  S::assert_xsrf_token();
                  $recon['comments'] = Post::v('comments');
                  $page->assign('recon', $recon);
 -                XDB::execute("UPDATE payment_reconcilations SET comments={?} WHERE id={?}", $recon['comments'], $_SESSION['paymentrecon_id']);
 +                XDB::execute('UPDATE payment_reconcilations SET comments = {?} WHERE id = {?}', $recon['comments'], $_SESSION['paymentrecon_id']);
                  $page->trigSuccess('Les commentaires ont été enregistrés.');
              }
 -            
 +
              // reconcilation results - ok
 -            $res = XDB::query("SELECT  count(*),SUM(amount),SUM(commission)
 -                                 FROM  payment_transactions WHERE recon_id={?}",
 +            $res = XDB::query('SELECT  count(*), SUM(amount), SUM(commission)
 +                                 FROM  payment_transactions
 +                                WHERE recon_id = {?}',
                                $recon['id']);
 -            list($ok_count,$ok_sum_amounts,$ok_sum_coms) = $res->fetchOneRow();
 +            list($ok_count, $ok_sum_amounts, $ok_sum_coms) = $res->fetchOneRow();
              $page->assign('ok_count', $ok_count);
 -            
 +
              // reconcilation results - ref exists, but some data differs
 -            $res = XDB::query("SELECT  id, fullref, method_id, ts_confirmed, trans.amount, trans.commission, status, recon_id,
 +            $res = XDB::query('SELECT  id, fullref, method_id, ts_confirmed, trans.amount, trans.commission, status, recon_id,
                                         reference, date, tmp.amount as amount2, tmp.commission as commission2
                                   FROM  payment_transactions AS trans
 -                           INNER JOIN  payment_tmp AS tmp ON trans.fullref=tmp.reference
 -                                WHERE  trans.recon_id IS NULL OR trans.recon_id != {?}",
 +                           INNER JOIN  payment_tmp          AS tmp ON (trans.fullref = tmp.reference)
 +                                WHERE  trans.recon_id IS NULL OR trans.recon_id != {?}',
                                $recon['id']);
              $differs = $res->fetchAllAssoc();
              $page->assign_by_ref('differs', $differs);
              $page->assign('differ_count', count($differs));
 -            
 +
              // reconcilation results - ref doesn't exists in database
 -            $res = XDB::query("SELECT  tmp.*
 -                                 FROM  payment_tmp AS tmp
 -                            LEFT JOIN  payment_transactions AS trans ON trans.fullref=tmp.reference
 -                                WHERE  trans.fullref IS NULL");
 +            $res = XDB::query('SELECT  tmp.*
 +                                 FROM  payment_tmp          AS tmp
 +                            LEFT JOIN  payment_transactions AS trans ON (trans.fullref = tmp.reference)
 +                                WHERE  trans.fullref IS NULL');
              $only_import = $res->fetchAllAssoc();
              $page->assign_by_ref('only_import', $only_import);
              $page->assign('onlyim_count', count($only_import));
 -            
 +
              // reconcilation results - exists in database but not in import
 -            $res = XDB::query("SELECT  trans.*
 +            $res = XDB::query('SELECT  trans.*
                                   FROM  payment_transactions AS trans
 -                            LEFT JOIN  payment_tmp AS tmp ON trans.fullref=tmp.reference
 -                                WHERE  {?}<=DATE(trans.ts_confirmed) AND DATE(trans.ts_confirmed)<={?}
 -                                       AND tmp.reference IS NULL AND method_id={?}",
 +                            LEFT JOIN  payment_tmp          AS tmp ON (trans.fullref = tmp.reference)
 +                                WHERE  {?} <= DATE(trans.ts_confirmed) AND DATE(trans.ts_confirmed) <= {?}
 +                                       AND tmp.reference IS NULL AND method_id = {?}',
                                $recon['period_start'], $recon['period_end'], $recon['method_id']);
              $only_database = $res->fetchAllAssoc();
              $page->assign_by_ref('only_database', $only_database);
              $page->assign('onlydb_count', count($only_database));
          }
      }
 -    
 +
      function handler_adm_transfers(&$page, $action = null, $id = null) {
          // list/log all bank transfers and link them to individual transactions
 -        
 +
          if (Post::has('generate')) {
              $recon_ids = array_keys(Post::v('recon_id'));
 -            
 +
              // generate a new reconcilation group ID
              $res = XDB::query("SELECT MAX(recongroup_id)+1 FROM payment_reconcilations");
              $recongp_id = $res->fetchOneCell();
              if ($recongp_id == null) $recongp_id = 1;
 -            
 +
              // add reconcilations to group
                  // FIXME: should check if reconcilations are in good status
 -            XDB::execute("UPDATE payment_reconcilations SET recongroup_id={?}, status='closed'
 -                          WHERE id IN {?}",
 -                          $recongp_id, $recon_ids);
 -            
 +            XDB::execute("UPDATE  payment_reconcilations
 +                             SET  recongroup_id = {?}, status = 'closed'
 +                           WHERE  id IN {?}",
 +                         $recongp_id, $recon_ids);
 +
              // create transfers
 -            XDB::execute("INSERT INTO  payment_transfers
 +            XDB::execute('INSERT INTO  payment_transfers
                                 SELECT  NULL, {?}, t.ref, SUM(t.amount+t.commission), NULL, p.text, NULL
                                   FROM  payment_transactions AS t
 -                            LEFT JOIN  payments AS p ON t.ref = p.id
 -                            LEFT JOIN  groups AS g ON p.asso_id = g.id
 +                            LEFT JOIN  payments             AS p ON (t.ref = p.id)
 +                            LEFT JOIN  groups               AS g ON (p.asso_id = g.id)
                                  WHERE  t.recon_id IN {?}
 -                             GROUP BY  t.ref",
 -                              $recongp_id, $recon_ids);
 -            
 +                             GROUP BY  t.ref',
 +                         $recongp_id, $recon_ids);
 +
              //$res = XDB::query("SELECT * FROM  payment_reconcilations WHERE id IN {?}", $recon_ids);
              //$recons = $res->fetchAllAssoc();
 -            
 -            $page->trigSuccess("Les virements ont été générés pour ".count($recon_ids)." réconciliations.");
 +
 +            $page->trigSuccess('Les virements ont été générés pour ' . count($recon_ids) . ' réconciliations.');
              $this->handler_adm_reconcile($page);
 -            
 -        } elseif ($action == "delgroup") {
 +
 +        } elseif ($action == 'delgroup') {
              S::assert_xsrf_token();
 -            XDB::execute("UPDATE payment_reconcilations SET status='transfering', recongroup_id=NULL WHERE recongroup_id={?}", $id);
 -            XDB::execute("DELETE FROM payment_transfers WHERE recongroup_id={?} AND date IS NULL", $id);
 -            
 +            XDB::execute("UPDATE  payment_reconcilations
 +                             SET  status = 'transfering', recongroup_id = NULL
 +                           WHERE  recongroup_id = {?}", $id);
 +            XDB::execute("DELETE FROM  payment_transfers
 +                                WHERE  recongroup_id = {?} AND date IS NULL", $id);
 +
              $page->trigSuccess("Les virements non réalisés ont été supprimé du groupe ".$id.".");
              $this->handler_adm_reconcile($page);
 -            
 +
          } elseif ($action == "confirm") {
              S::assert_xsrf_token();
 -            XDB::execute("UPDATE payment_transfers SET date=NOW() WHERE id={?}", $id);
 -            
 -            $page->trigSuccess("Virement ".$id." confirmé.");
 +            XDB::execute('UPDATE  payment_transfers
 +                             SET  date = NOW()
 +                           WHERE  id = {?}', $id);
 +
 +            $page->trigSuccess('Virement ' . $id . ' confirmé.');
              $this->handler_adm_reconcile($page);
 -            
 +
          } else {
 -            pl_redirect("admin/reconcile");
 +            pl_redirect('admin/reconcile');
          }
      }
  }
  
  class PaymentLogsImporter extends CSVImporter {
      protected $result;
 -    
 +
      public function __construct() {
          parent::__construct('');
 -        $this->registerFunction('systempay_commission', 'Compute BPLC commission', array($this,"compute_systempay_commission"));
 -        $this->registerFunction('payment_id', 'Autocompute payment ID', array($this,"compute_payment_id"));
 +        $this->registerFunction('systempay_commission', 'Compute BPLC commission', array($this, 'compute_systempay_commission'));
 +        $this->registerFunction('payment_id', 'Autocompute payment ID', array($this, 'compute_payment_id'));
          //$this->forceValue('payment_id','func_payment_id');
      }
 -    
 +
      public function run($action = null, $insert_relation = null, $update_relation = null) {
          $this->result = array();
          foreach ($this->data as $line) {
              $a = $this->makeAssoc($line, $insert_relation);
 -            $a['date'] = preg_replace('/([0-9]{2})\/([0-9]{2})\/([0-9]{4}).*/','\3-\2-\1', $a['date']);
 -            $a['amount'] = str_replace(',','.',$a['amount']);
 -            $a['commission'] = str_replace(',','.',$a['commission']);
 +            $a['date'] = preg_replace('/([0-9]{2})\/([0-9]{2})\/([0-9]{4}).*/', '\3-\2-\1', $a['date']);
 +            $a['amount'] = str_replace(',', '.', $a['amount']);
 +            $a['commission'] = str_replace(',', '.', $a['commission']);
              $this->result[] = $a;
          }
      }
 -    
 +
      public function get_result() {
          return $this->result;
      }
 -    
 +
      static public function compute_systempay_commission($line, $key, $relation) {
 -        static $EEE_countries = array('France','Allemagne','Autriche','Belgique','Bulgarie','Chypre',
 -            'Danemark','Espagne','Estonie','Finlande','Grèce','Hongrie','Irlande','Islande','Italie',
 -            'Lettonie','Liechtenstein','Lituanie','Luxembourg','Malte','Norvège','Pays-Bas','Pologne',
 -            'Portugal','Roumanie','Royaume-Uni','Slovaquie','Slovénie','Suède','République Tchèque');
 -        
 -        if($key!='commission' || !array_key_exists('carte',$line)) return null;
 +        static $EEE_countries = array(
 +            'France', 'Allemagne', 'Autriche', 'Belgique', 'Bulgarie', 'Chypre',
 +            'Danemark', 'Espagne', 'Estonie', 'Finlande', 'Grèce', 'Hongrie', 'Irlande', 'Islande', 'Italie',
 +            'Lettonie', 'Liechtenstein', 'Lituanie', 'Luxembourg', 'Malte', 'Norvège', 'Pays-Bas', 'Pologne',
 +            'Portugal', 'Roumanie', 'Royaume-Uni', 'Slovaquie', 'Slovénie', 'Suède', 'République Tchèque'
 +        );
 +
 +        if($key!='commission' || !array_key_exists('carte', $line)) {
 +            return null;
 +        }
          $amount = self::getValue($line, 'amount', $relation['amount']);
 -        if (in_array($line['pays carte'],$EEE_countries))
 -            return -0.20 - round($amount*0.005, 2);
 -        else
 -            return -0.20 - round($amount*0.005, 2) - 0.76;
 +        if (in_array($line['pays carte'], $EEE_countries)) {
 +            return -0.20 - round($amount * 0.005, 2);
 +        } else {
 +            return -0.20 - round($amount * 0.005, 2) - 0.76;
 +        }
      }
  
      static public function compute_payment_id($line, $key, $relation) {
 -        if ($key != 'payment_id') return null;
 +        if ($key != 'payment_id') {
 +            return null;
 +        }
          $reference = self::getValue($line, 'reference', $relation['reference']);
 -        if (ereg('-([0-9]+)$', $reference, $matches))
 +        if (ereg('-([0-9]+)$', $reference, $matches)) {
              return $matches[1];
 -        else
 +        } else {
              return null;
 +        }
      }
  }