* Copyright (C) 2004-2014 Laurent Destailleur * Copyright (C) 2005 Marc Barilley / Ocebo * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2007 Franky Van Liedekerke * Copyright (C) 2012 Cédric Salvador * Copyright (C) 2014 Raphaël Doursenaud * Copyright (C) 2014 Teddy Andreotti <125155@supinfo.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * \file htdocs/compta/paiement.php * \ingroup facture * \brief Payment page for customers invoices */ require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; $langs->load('companies'); $langs->load('bills'); $langs->load('banks'); $action = GETPOST('action','alpha'); $confirm = GETPOST('confirm'); $facid = GETPOST('facid','int'); $socname = GETPOST('socname'); $accountid = GETPOST('accountid'); $paymentnum = GETPOST('num_paiement'); $sortfield = GETPOST('sortfield','alpha'); $sortorder = GETPOST('sortorder','alpha'); $page = GETPOST('page','int'); $amounts=array(); $amountsresttopay=array(); $addwarning=0; // Security check $socid=0; if ($user->societe_id > 0) { $socid = $user->societe_id; } $object=new Facture($db); // Load object if ($facid > 0) { $ret=$object->fetch($facid); } // Initialize technical object to manage hooks of paiements. Note that conf->hooks_modules contains array array $hookmanager->initHooks(array('paiementcard','globalcard')); /* * Actions */ $parameters=array('socid'=>$socid); $reshook=$hookmanager->executeHooks('doActions',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); if (empty($reshook)) { if ($action == 'add_paiement' || ($action == 'confirm_paiement' && $confirm=='yes')) { $error = 0; $datepaye = dol_mktime(12, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear')); $paiement_id = 0; $totalpayment = 0; $atleastonepaymentnotnull = 0; // Generate payment array and check if there is payment higher than invoice and payment date before invoice date $tmpinvoice=new Facture($db); foreach ($_POST as $key => $value) { if (substr($key,0,7) == 'amount_') { $cursorfacid = substr($key,7); $amounts[$cursorfacid] = price2num(trim(GETPOST($key))); $totalpayment = $totalpayment + $amounts[$cursorfacid]; if (! empty($amounts[$cursorfacid])) $atleastonepaymentnotnull++; $result=$tmpinvoice->fetch($cursorfacid); if ($result <= 0) dol_print_error($db); $amountsresttopay[$cursorfacid]=price2num($tmpinvoice->total_ttc - $tmpinvoice->getSommePaiement()); if ($amounts[$cursorfacid]) { // Check amount if ($amounts[$cursorfacid] && (abs($amounts[$cursorfacid]) > abs($amountsresttopay[$cursorfacid]))) { $addwarning=1; $formquestion['text'] = img_warning($langs->trans("PaymentHigherThanReminderToPay")).' '.$langs->trans("HelpPaymentHigherThanReminderToPay"); } // Check date if ($datepaye && ($datepaye < $tmpinvoice->date)) { $langs->load("errors"); //$error++; setEventMessage($langs->transnoentities("WarningPaymentDateLowerThanInvoiceDate", dol_print_date($datepaye,'day'), dol_print_date($tmpinvoice->date, 'day'), $tmpinvoice->ref), 'warnings'); } } $formquestion[$i++]=array('type' => 'hidden','name' => $key, 'value' => $_POST[$key]); } } // Check parameters if (! GETPOST('paiementcode')) { setEventMessage($langs->transnoentities('ErrorFieldRequired',$langs->transnoentities('PaymentMode')), 'errors'); $error++; } if (! empty($conf->banque->enabled)) { // If bank module is on, account is required to enter a payment if (GETPOST('accountid') <= 0) { setEventMessage($langs->transnoentities('ErrorFieldRequired',$langs->transnoentities('AccountToCredit')), 'errors'); $error++; } } if (empty($totalpayment) && empty($atleastonepaymentnotnull)) { setEventMessage($langs->transnoentities('ErrorFieldRequired',$langs->trans('PaymentAmount')), 'errors'); $error++; } if (empty($datepaye)) { setEventMessage($langs->transnoentities('ErrorFieldRequired',$langs->transnoentities('Date')), 'errors'); $error++; } } /* * Action add_paiement */ if ($action == 'add_paiement') { if ($error) { $action = 'create'; } // Le reste propre a cette action s'affiche en bas de page. } /* * Action confirm_paiement */ if ($action == 'confirm_paiement' && $confirm == 'yes') { $error=0; $datepaye = dol_mktime(12, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear')); $db->begin(); // Clean parameters amount if payment is for a credit note if (GETPOST('type') == 2) { foreach ($amounts as $key => $value) // How payment is dispatch { $newvalue = price2num($value,'MT'); $amounts[$key] = -$newvalue; } } if (! empty($conf->banque->enabled)) { // Si module bank actif, un compte est obligatoire lors de la saisie d'un paiement if (GETPOST('accountid') <= 0) { setEventMessage($langs->trans('ErrorFieldRequired',$langs->transnoentities('AccountToCredit')), 'errors'); $error++; } } // Creation of payment line $paiement = new Paiement($db); $paiement->datepaye = $datepaye; $paiement->amounts = $amounts; // Array with all payments dispatching $paiement->paiementid = dol_getIdFromCode($db,$_POST['paiementcode'],'c_paiement'); $paiement->num_paiement = $_POST['num_paiement']; $paiement->note = $_POST['comment']; if (! $error) { $paiement_id = $paiement->create($user, (GETPOST('closepaidinvoices')=='on'?1:0)); if ($paiement_id < 0) { setEventMessage($paiement->error, 'errors'); $error++; } } if (! $error) { $label='(CustomerInvoicePayment)'; if (GETPOST('type') == 2) $label='(CustomerInvoicePaymentBack)'; $result=$paiement->addPaymentToBank($user,'payment',$label,GETPOST('accountid'),GETPOST('chqemetteur'),GETPOST('chqbank')); if ($result < 0) { setEventMessage($paiement->error, 'errors'); $error++; } } if (! $error) { $db->commit(); // If payment dispatching on more than one invoice, we keep on summary page, otherwise go on invoice card $invoiceid=0; foreach ($paiement->amounts as $key => $amount) { $facid = $key; if (is_numeric($amount) && $amount <> 0) { if ($invoiceid != 0) $invoiceid=-1; // There is more than one invoice payed by this payment else $invoiceid=$facid; } } if ($invoiceid > 0) $loc = DOL_URL_ROOT.'/compta/facture.php?facid='.$invoiceid; else $loc = DOL_URL_ROOT.'/compta/paiement/card.php?id='.$paiement_id; header('Location: '.$loc); exit; } else { $db->rollback(); } } } /* * View */ llxHeader(); $form=new Form($db); if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paiement') { $facture = new Facture($db); $result=$facture->fetch($facid); if ($result >= 0) { $facture->fetch_thirdparty(); $title=''; if ($facture->type != 2) $title.=$langs->trans("EnterPaymentReceivedFromCustomer"); if ($facture->type == 2) $title.=$langs->trans("EnterPaymentDueToCustomer"); print_fiche_titre($title); // Initialize data for confirmation (this is used because data can be change during confirmation) if ($action == 'add_paiement') { $i=0; $formquestion[$i++]=array('type' => 'hidden','name' => 'facid', 'value' => $facture->id); $formquestion[$i++]=array('type' => 'hidden','name' => 'socid', 'value' => $facture->socid); $formquestion[$i++]=array('type' => 'hidden','name' => 'type', 'value' => $facture->type); } // Invoice with Paypal transaction // TODO add hook possibility (regis) if (! empty($conf->paypalplus->enabled) && $conf->global->PAYPAL_ENABLE_TRANSACTION_MANAGEMENT && ! empty($facture->ref_int)) { if (! empty($conf->global->PAYPAL_BANK_ACCOUNT)) $accountid=$conf->global->PAYPAL_BANK_ACCOUNT; $paymentnum=$facture->ref_int; } // Add realtime total information if ($conf->use_javascript_ajax) { print "\n".''."\n"; } print '
'; print ''; print ''; print ''; print ''; print ''; print ''; dol_fiche_head(); print ''; // Third party print '\n"; // Date payment print ''; print ''; $rowspan=5; // Payment mode print '\n"; print ''; print ''; // Bank account print ''; if (! empty($conf->banque->enabled)) { if ($facture->type != 2) print ''; if ($facture->type == 2) print ''; print ''; } else { print ''; } print "\n"; // Cheque number print ''; print ''; // Check transmitter print ''; print ''; // Bank name print ''; print ''; print '
'.$langs->trans('Company').''.$facture->client->getNomUrl(4)."
'.$langs->trans('Date').''; $datepayment = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']); $datepayment= ($datepayment == '' ? (empty($conf->global->MAIN_AUTOFILL_DATE)?-1:'') : $datepayment); $form->select_date($datepayment,'','','',0,"add_paiement",1,1); print ''.$langs->trans('Comments').'
'.$langs->trans('PaymentMode').''; $form->select_types_paiements((GETPOST('paiementcode')?GETPOST('paiementcode'):$facture->mode_reglement_code),'paiementcode','',2); print "'; print '
'.$langs->trans('AccountToCredit').''.$langs->trans('AccountToDebit').''; $form->select_comptes($accountid,'accountid',0,'',2); print ' 
'.$langs->trans('Numero'); print ' ('.$langs->trans("ChequeOrTransferNumber").')'; print '
'.$langs->trans('CheckTransmitter'); print ' ('.$langs->trans("ChequeMaker").')'; print '
'.$langs->trans('Bank'); print ' ('.$langs->trans("ChequeBank").')'; print '
'; dol_fiche_end(); /* * List of unpaid invoices */ $sql = 'SELECT f.rowid as facid, f.facnumber, f.total_ttc, f.type, '; $sql.= ' f.datef as df'; $sql.= ' FROM '.MAIN_DB_PREFIX.'facture as f'; $sql.= ' WHERE f.entity = '.$conf->entity; $sql.= ' AND f.fk_soc = '.$facture->socid; $sql.= ' AND f.paye = 0'; $sql.= ' AND f.fk_statut = 1'; // Statut=0 => not validated, Statut=2 => canceled if ($facture->type != 2) { $sql .= ' AND type IN (0,1,3,5)'; // Standard invoice, replacement, deposit, situation } else { $sql .= ' AND type = 2'; // If paying back a credit note, we show all credit notes } // Sort invoices by date and serial number: the older one comes first $sql.=' ORDER BY f.datef ASC, f.facnumber ASC'; $resql = $db->query($sql); if ($resql) { $num = $db->num_rows($resql); if ($num > 0) { $sign=1; if ($facture->type == 2) $sign=-1; $arraytitle=$langs->trans('Invoice'); if ($facture->type == 2) $arraytitle=$langs->trans("CreditNotes"); $alreadypayedlabel=$langs->trans('Received'); if ($facture->type == 2) $alreadypayedlabel=$langs->trans("PaidBack"); $remaindertopay=$langs->trans('RemainderToTake'); if ($facture->type == 2) $remaindertopay=$langs->trans("RemainderToPayBack"); $i = 0; //print ''; print '
'; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print "\n"; $var=true; $total=0; $totalrecu=0; $totalrecucreditnote=0; $totalrecudeposits=0; while ($i < $num) { $objp = $db->fetch_object($resql); $var=!$var; $invoice=new Facture($db); $invoice->fetch($objp->facid); $paiement = $invoice->getSommePaiement(); $creditnotes=$invoice->getSumCreditNotesUsed(); $deposits=$invoice->getSumDepositsUsed(); $alreadypayed=price2num($paiement + $creditnotes + $deposits,'MT'); $remaintopay=price2num($invoice->total_ttc - $paiement - $creditnotes - $deposits,'MT'); print ''; print '\n"; // Date print '\n"; // Price print ''; // Received or paid back print ''; // Remain to take or to pay back print ''; //$test= price(price2num($objp->total_ttc - $paiement - $creditnotes - $deposits)); // Amount print '"; // Warning print ''; $parameters=array(); $reshook=$hookmanager->executeHooks('printObjectLine',$parameters,$objp,$action); // Note that $action and $object may have been modified by hook print "\n"; $total+=$objp->total; $total_ttc+=$objp->total_ttc; $totalrecu+=$paiement; $totalrecucreditnote+=$creditnotes; $totalrecudeposits+=$deposits; $i++; } if ($i > 1) { // Print total print ''; print ''; print ''; print ''; print ''; print ''; print ''; print "\n"; } print "
'.$arraytitle.''.$langs->trans('Date').''.$langs->trans('AmountTTC').''.$alreadypayedlabel.''.$remaindertopay.''.$langs->trans('PaymentAmount').' 
'; print $invoice->getNomUrl(1,''); print "'.dol_print_date($db->jdate($objp->df),'day')."'.price($sign * $objp->total_ttc).''.price($sign * $paiement); if ($creditnotes) print '+'.price($creditnotes); if ($deposits) print '+'.price($deposits); print ''.price($sign * $remaintopay).''; // Add remind amount $namef = 'amount_'.$objp->facid; $nameRemain = 'remain_'.$objp->facid; if ($action != 'add_paiement') { if(!empty($conf->global->FAC_AUTO_FILLJS)) print img_picto("Auto fill",'rightarrow', "class='AutoFillAmout' data-rowname='".$namef."' data-value='".($sign * $remaintopay)."'"); print ''; print ''; } else { print ''; print ''; } print "'; //print "xx".$amounts[$invoice->id]."-".$amountsresttopay[$invoice->id]."
"; if ($amounts[$invoice->id] && (abs($amounts[$invoice->id]) > abs($amountsresttopay[$invoice->id]))) { print ' '.img_warning($langs->trans("PaymentHigherThanReminderToPay")); } print '
'.$langs->trans('TotalTTC').''.price($sign * $total_ttc).''.price($sign * $totalrecu); if ($totalrecucreditnote) print '+'.price($totalrecucreditnote); if ($totalrecudeposits) print '+'.price($totalrecudeposits); print ''.price($sign * price2num($total_ttc - $totalrecu - $totalrecucreditnote - $totalrecudeposits,'MT')).' 
"; //print "\n"; } $db->free($resql); } else { dol_print_error($db); } // Bouton Enregistrer if ($action != 'add_paiement') { $checkboxlabel=$langs->trans("ClosePaidInvoicesAutomatically"); if ($facture->type == 2) $checkboxlabel=$langs->trans("ClosePaidCreditNotesAutomatically"); $buttontitle=$langs->trans('ToMakePayment'); if ($facture->type == 2) $buttontitle=$langs->trans('ToMakePaymentBack'); print '
'; print ' '.$checkboxlabel; /*if (! empty($conf->prelevement->enabled)) { $langs->load("withdrawals"); if (! empty($conf->global->WITHDRAW_DISABLE_AUTOCREATE_ONPAYMENTS)) print '
'.$langs->trans("IfInvoiceNeedOnWithdrawPaymentWontBeClosed"); }*/ print '


'; print '
'; } // Form to confirm payment if ($action == 'add_paiement') { $preselectedchoice=$addwarning?'no':'yes'; print '
'; $text=$langs->trans('ConfirmCustomerPayment',$totalpayment,$langs->trans("Currency".$conf->currency)); if (GETPOST('closepaidinvoices')) { $text.='
'.$langs->trans("AllCompletelyPayedInvoiceWillBeClosed"); print ''; } $form->form_confirm($_SERVER['PHP_SELF'].'?facid='.$facture->id.'&socid='.$facture->socid.'&type='.$facture->type,$langs->trans('ReceivedCustomersPayments'),$text,'confirm_paiement',$formquestion,$preselectedchoice); } print "
\n"; } } /** * Show list of payments */ if (! GETPOST('action')) { if ($page == -1) $page = 0 ; $limit = $conf->liste_limit; $offset = $limit * $page ; if (! $sortorder) $sortorder='DESC'; if (! $sortfield) $sortfield='p.datep'; $sql = 'SELECT p.datep as dp, p.amount, f.amount as fa_amount, f.facnumber'; $sql.=', f.rowid as facid, c.libelle as paiement_type, p.num_paiement'; $sql.= ' FROM '.MAIN_DB_PREFIX.'paiement as p, '.MAIN_DB_PREFIX.'facture as f, '.MAIN_DB_PREFIX.'c_paiement as c'; $sql.= ' WHERE p.fk_facture = f.rowid AND p.fk_paiement = c.id'; $sql.= ' AND f.entity = '.$conf->entity; if ($socid) { $sql.= ' AND f.fk_soc = '.$socid; } $sql.= ' ORDER BY '.$sortfield.' '.$sortorder; $sql.= $db->plimit($limit+1, $offset); $resql = $db->query($sql); if ($resql) { $num = $db->num_rows($resql); $i = 0; $var=true; print_barre_liste($langs->trans('Payments'), $page, $_SERVER["PHP_SELF"],'',$sortfield,$sortorder,'',$num); print ''; print ''; print_liste_field_titre($langs->trans('Invoice'),$_SERVER["PHP_SELF"],'facnumber','','','',$sortfield,$sortorder); print_liste_field_titre($langs->trans('Date'),$_SERVER["PHP_SELF"],'dp','','','',$sortfield,$sortorder); print_liste_field_titre($langs->trans('Type'),$_SERVER["PHP_SELF"],'libelle','','','',$sortfield,$sortorder); print_liste_field_titre($langs->trans('Amount'),$_SERVER["PHP_SELF"],'fa_amount','','','align="right"',$sortfield,$sortorder); print_liste_field_titre('',$_SERVER["PHP_SELF"],"",'','','',$sortfield,$sortorder,'maxwidthsearch '); print "\n"; while ($i < min($num,$limit)) { $objp = $db->fetch_object($resql); $var=!$var; print ''; print '\n"; print '\n"; print '\n"; print ''; $parameters=array(); $reshook=$hookmanager->executeHooks('printObjectLine',$parameters,$objp,$action); // Note that $action and $object may have been modified by hook print ''; $i++; } print '
'.$objp->facnumber."'.dol_print_date($db->jdate($objp->dp))."'.$objp->paiement_type.' '.$objp->num_paiement."'.price($objp->amount).' 
'; } } llxFooter(); $db->close();