diff --git a/ChangeLog b/ChangeLog index b0a6fb9eab2..dc680f5a3f0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,7 @@ $Id$ ***** ChangeLog for 3.1 compared to 3.0 ***** For users: +- New: task #10969 : Add checkbox to close automatically invoice to "payed" - New: Can edit note of payment. - New: Login is not mandatory in member module. - New: Reduce a step into supplier order workflow to save time (if user diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index fe87efa7684..8ab2a9c35c2 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -419,10 +419,10 @@ class Facture extends CommonObject /** - * \brief Create a new invoice in database from current invoice - * \param user Object user that ask creation - * \param invertdetail Reverse sign of amounts for lines - * \return int <0 si ko, >0 si ok + * Create a new invoice in database from current invoice + * @param user Object user that ask creation + * @param invertdetail Reverse sign of amounts for lines + * @return int <0 if KO, >0 if OK */ function createFromCurrent($user,$invertdetail=0) { @@ -476,10 +476,10 @@ class Facture extends CommonObject /** - * \brief Load an object from its id and create a new one in database - * \param fromid Id of object to clone - * \param invertdetail Reverse sign of amounts for lines - * \return int New id of clone + * Load an object from its id and create a new one in database + * @param fromid Id of object to clone + * @param invertdetail Reverse sign of amounts for lines + * @return int New id of clone */ function createFromClone($fromid,$invertdetail=0) { @@ -741,8 +741,8 @@ class Facture extends CommonObject /** - * \brief Recupere les lignes de factures dans this->lines - * \return int 1 if OK, < 0 if KO + * Recupere les lignes de factures dans this->lines + * @return int 1 if OK, < 0 if KO */ function fetch_lines() { @@ -1203,11 +1203,11 @@ class Facture extends CommonObject } /** - * \brief Tag la facture comme paye completement (close_code non renseigne) ou partiellement (close_code renseigne) + appel trigger BILL_PAYED - * \param user Objet utilisateur qui modifie - * \param close_code Code renseigne si on classe a payee completement alors que paiement incomplet (cas ecompte par exemple) - * \param close_note Commentaire renseigne si on classe a payee alors que paiement incomplet (cas ecompte par exemple) - * \return int <0 si ok, >0 si ok + * Tag la facture comme paye completement (close_code non renseigne) ou partiellement (close_code renseigne) + appel trigger BILL_PAYED + * @param user Objet utilisateur qui modifie + * @param close_code Code renseigne si on classe a payee completement alors que paiement incomplet (cas escompte par exemple) + * @param close_note Commentaire renseigne si on classe a payee alors que paiement incomplet (cas escompte par exemple) + * @return int <0 si ok, >0 si ok */ function set_paid($user,$close_code='',$close_note='') { @@ -1686,7 +1686,7 @@ class Facture extends CommonObject if (empty($txtva)) $txtva=0; if (empty($txlocaltax1)) $txlocaltax1=0; if (empty($txlocaltax2)) $txlocaltax2=0; - + $remise_percent=price2num($remise_percent); $qty=price2num($qty); $pu_ht=price2num($pu_ht); @@ -2227,7 +2227,7 @@ class Facture extends CommonObject * \param paye Etat paye * \param statut Id statut * \param mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto - * \param alreadypaid Montant deja paye + * \param alreadypaid Montant deja paye * \param type Type facture * \return string Libelle du statut */ diff --git a/htdocs/compta/paiement.php b/htdocs/compta/paiement.php index b825f1dfed7..1bf1b0ec69b 100644 --- a/htdocs/compta/paiement.php +++ b/htdocs/compta/paiement.php @@ -143,49 +143,59 @@ if ($_POST['action'] == 'confirm_paiement' && $_POST['confirm'] == 'yes') $datepaye = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']); + $db->begin(); + + // 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) { - $db->begin(); - - // Creation de la ligne paiement - $paiement = new Paiement($db); - $paiement->datepaye = $datepaye; - $paiement->amounts = $amounts; // Tableau de montant - $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) { - $paiement_id = $paiement->create($user); - if ($paiement_id < 0) - { - $errmsg=$paiement->error; - $error++; - } + $errmsg=$paiement->error; + $error++; } + } - if (! $error) - { - $result=$paiement->addPaymentToBank($user,'payment','(CustomerInvoicePayment)',$_POST['accountid'],$_POST['chqemetteur'],$_POST['chqbank']); - if ($result < 0) + if (! $error) + { + $result=$paiement->addPaymentToBank($user,'payment','(CustomerInvoicePayment)',$_POST['accountid'],$_POST['chqemetteur'],$_POST['chqbank']); + if ($result < 0) + { + $errmsg=$paiement->error; + $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) { - $errmsg=$paiement->error; - $error++; + if ($invoiceid != 0) $invoiceid=-1; // There is more than one invoice payed by this payment + else $invoiceid=$facid; } - } - - if (! $error) - { - $db->commit(); - $loc = DOL_URL_ROOT.'/compta/paiement/fiche.php?id='.$paiement_id; - Header('Location: '.$loc); - exit; - } - else - { - $db->rollback(); - } + } + if ($invoiceid > 0) $loc = DOL_URL_ROOT.'/compta/facture.php?facid='.$invoiceid; + else $loc = DOL_URL_ROOT.'/compta/paiement/fiche.php?id='.$paiement_id; + Header('Location: '.$loc); + exit; + } + else + { + $db->rollback(); } } @@ -197,7 +207,6 @@ if ($_POST['action'] == 'confirm_paiement' && $_POST['confirm'] == 'yes') llxHeader(); $html=new Form($db); -$facturestatic=new Facture($db); if ($_GET['action'] == 'create' || $_POST['action'] == 'confirm_paiement' || $_POST['action'] == 'add_paiement') @@ -256,7 +265,7 @@ if ($_GET['action'] == 'create' || $_POST['action'] == 'confirm_paiement' || $_P print '});'; print ''."\n"; } - + print '
'; print ''; print ''; @@ -264,9 +273,10 @@ if ($_GET['action'] == 'create' || $_POST['action'] == 'confirm_paiement' || $_P print ''; print ''; print ''; - + print ''; + // Third party print '\n"; // Date payment @@ -278,7 +288,7 @@ if ($_GET['action'] == 'create' || $_POST['action'] == 'confirm_paiement' || $_P print ''; print '\n"; print ''; if ($facture->type == 2) print ''; print ''; } else @@ -302,17 +312,18 @@ if ($_GET['action'] == 'create' || $_POST['action'] == 'confirm_paiement' || $_P print ''; - print ''; + print ''; - print ''; - print ''; + print ''; print ''; - print ''; + print ''; print '
'.$langs->trans('Company').''.$facture->client->getNomUrl(4)."
'.$langs->trans('Comments').'
'.$langs->trans('PaymentMode').''; - $html->select_types_paiements(empty($_POST['paiementcode'])?'':$_POST['paiementcode'],'paiementcode','',2); + $html->select_types_paiements(GETPOST('paiementcode'),'paiementcode','',2); print "'; @@ -290,7 +300,7 @@ if ($_GET['action'] == 'create' || $_POST['action'] == 'confirm_paiement' || $_P if ($facture->type != 2) print ''.$langs->trans('AccountToCredit').''.$langs->trans('AccountToDebit').''; - $html->select_comptes(empty($_POST['accountid'])?'':$_POST['accountid'],'accountid',0,'',2); + $html->select_comptes(GETPOST('accountid'),'accountid',0,'',2); print '
'.$langs->trans('Numero'); print ' ('.$langs->trans("ChequeOrTransferNumber").')'; print '
'.$langs->trans('CheckTransmitter'); + // Check transmitter + print '
'.$langs->trans('CheckTransmitter'); print ' ('.$langs->trans("ChequeMaker").')'; print '
'.$langs->trans('Bank'); print ' ('.$langs->trans("ChequeBank").')'; print '
'; @@ -366,17 +377,18 @@ if ($_GET['action'] == 'create' || $_POST['action'] == 'confirm_paiement' || $_P $objp = $db->fetch_object($resql); $var=!$var; - $facturestatic->ref=$objp->facnumber; - $facturestatic->id=$objp->facid; - $facturestatic->type=$objp->type; - - $creditnotes=$facturestatic->getSumCreditNotesUsed(); - $deposits=$facturestatic->getSumDepositsUsed(); + $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 ''; - print $facturestatic->getNomUrl(1,''); + print $invoice->getNomUrl(1,''); print "\n"; // Date @@ -386,14 +398,13 @@ if ($_GET['action'] == 'create' || $_POST['action'] == 'confirm_paiement' || $_P print ''.price($objp->total_ttc).''; // Recu - $paiement = $facturestatic->getSommePaiement(); print ''.price($paiement); if ($creditnotes) print '+'.price($creditnotes); if ($deposits) print '+'.price($deposits); print ''; // Remain to pay - print ''.price(price2num($objp->total_ttc - $paiement - $creditnotes - $deposits,'MT')).''; + print ''.price($remaintopay).''; // Amount print ''; @@ -411,7 +422,7 @@ if ($_GET['action'] == 'create' || $_POST['action'] == 'confirm_paiement' || $_P // Warning print ''; - if ($amounts[$facturestatic->id] && $amounts[$facturestatic->id] > $amountsresttopay[$facturestatic->id]) + if ($amounts[$invoice->id] && $amounts[$invoice->id] > $amountsresttopay[$invoice->id]) { print ' '.img_warning($langs->trans("PaymentHigherThanReminderToPay")); } @@ -457,7 +468,8 @@ if ($_GET['action'] == 'create' || $_POST['action'] == 'confirm_paiement' || $_P if ($_POST["action"] != 'add_paiement') { // print ''; - print '
'; + print '

'.$langs->trans("ClosePaidInvoicesAutomatically"); + print '
'; // print ''; } @@ -476,6 +488,11 @@ if ($_GET['action'] == 'create' || $_POST['action'] == 'confirm_paiement' || $_P print '
'; $text=$langs->trans('ConfirmCustomerPayment',$totalpaiement,$langs->trans("Currency".$conf->monnaie)); + if (GETPOST('closepaidinvoices')) + { + $text.='
'.$langs->trans("AllCompletelyPayedInvoiceWillBeClosed"); + print ''; + } $html->form_confirm($_SERVER['PHP_SELF'].'?facid='.$facture->id.'&socid='.$facture->socid.'&type='.$facture->type,$langs->trans('ReceivedCustomersPayments'),$text,'confirm_paiement',$formquestion,$preselectedchoice); } @@ -485,9 +502,9 @@ if ($_GET['action'] == 'create' || $_POST['action'] == 'confirm_paiement' || $_P /** - * \brief Affichage de la liste des paiements + * Show list of payments */ -if (! $_GET['action'] && ! $_POST['action']) +if (! GETPOST('action')) { if ($page == -1) $page = 0 ; $limit = $conf->liste_limit; diff --git a/htdocs/compta/paiement/class/paiement.class.php b/htdocs/compta/paiement/class/paiement.class.php index 31342f17436..3440378a341 100644 --- a/htdocs/compta/paiement/class/paiement.class.php +++ b/htdocs/compta/paiement/class/paiement.class.php @@ -123,10 +123,11 @@ class Paiement extends CommonObject /** * Create payment of invoices into database. * Use this->amounts to have list of invoices for the payment - * @param user object user - * @return int id of created payment, < 0 if error + * @param user object user + * @param closepaidinvoices 1=Also close payed invoices to paid, 0=Do nothing more + * @return int id of created payment, < 0 if error */ - function create($user) + function create($user,$closepaidinvoices=0) { global $langs,$conf; @@ -159,7 +160,7 @@ class Paiement extends CommonObject { $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.'paiement'); - // Insere liens montants / factures + // Insert links amount / invoices foreach ($this->amounts as $key => $amount) { $facid = $key; @@ -171,7 +172,26 @@ class Paiement extends CommonObject dol_syslog(get_class($this).'::Create Amount line '.$key.' insert paiement_facture sql='.$sql); $resql=$this->db->query($sql); - if (! $resql) + if ($resql) + { + if ($closepaidinvoices) + { + $invoice=new Facture($this->db); + $invoice->fetch($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'); + + if ($remaintopay == 0) + { + $result=$invoice->set_paid($user,'',''); + } + else dol_syslog("Remain to pay for invoice ".$facid." not null. We do nothing."); + } + } + else { $this->error=$this->db->lasterror(); dol_syslog(get_class($this).'::Create insert paiement_facture error='.$this->error, LOG_ERR); diff --git a/htdocs/compta/paiement/fiche.php b/htdocs/compta/paiement/fiche.php index 68883cb500c..2a6381625eb 100644 --- a/htdocs/compta/paiement/fiche.php +++ b/htdocs/compta/paiement/fiche.php @@ -252,28 +252,32 @@ if ($resql) print ''.$langs->trans('Bill').''; print ''.$langs->trans('Company').''; print ''.$langs->trans('ExpectedToPay').''; - print ''.$langs->trans('Status').''; - print ''.$langs->trans('PayedByThisPayment').''; + print ''.$langs->trans('PayedByThisPayment').''; + print ''.$langs->trans('RemainderToPay').''; + print ''.$langs->trans('Status').''; print "\n"; if ($num > 0) { $var=True; - $facturestatic=new Facture($db); - while ($i < $num) { $objp = $db->fetch_object($resql); $var=!$var; print ''; - // Invoice + $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'); + + // Invoice print ''; - $facturestatic->id=$objp->facid; - $facturestatic->ref=$objp->facnumber; - $facturestatic->type=$objp->type; - print $facturestatic->getNomUrl(1); + print $invoice->getNomUrl(1); print "\n"; // Third party @@ -286,11 +290,14 @@ if ($resql) // Expected to pay print ''.price($objp->total_ttc).''; - // Statut - print ''.$facturestatic->LibStatut($objp->paye,$objp->fk_statut,2,1).''; + // Amount payed + print ''.price($objp->amount).''; - // Amount payed - print ''.price($objp->amount).''; + // Remain to pay + print ''.price($remaintopay).''; + + // Status + print ''.$invoice->getLibStatut(5, $alreadypayed).''; print "\n"; if ($objp->paye == 1) // If at least one invoice is paid, disable delete diff --git a/htdocs/langs/en_US/bills.lang b/htdocs/langs/en_US/bills.lang index 2c887a9e43a..a2feda5db1d 100644 --- a/htdocs/langs/en_US/bills.lang +++ b/htdocs/langs/en_US/bills.lang @@ -367,6 +367,7 @@ CantRemovePaymentWithOneInvoicePaid=Can't remove payment since there is at least ExpectedToPay=Expected payment PayedByThisPayment=Payed by this payment ClosePaidInvoicesAutomatically=Classify "Payed" all invoices entierely payed. +AllCompletelyPayedInvoiceWillBeClosed=All invoice with no remain to pay will be automatically closed to status "Payed". ##### Types de contacts ##### TypeContact_facture_internal_SALESREPFOLL=Representative following-up customer invoice TypeContact_facture_external_BILLING=Customer invoice contact diff --git a/htdocs/langs/fr_FR/bills.lang b/htdocs/langs/fr_FR/bills.lang index eab7087078a..02f325911de 100644 --- a/htdocs/langs/fr_FR/bills.lang +++ b/htdocs/langs/fr_FR/bills.lang @@ -366,7 +366,8 @@ DisabledBecausePayments=Non disponible car il existe des paiements CantRemovePaymentWithOneInvoicePaid=Suppression impossible quand il existe au moins une facture classée payée. ExpectedToPay=Paiement attendu PayedByThisPayment=Règlé par ce paiement -ClosePaidInvoicesAutomatically=Classer automatiquement à "Payé" les factures entièrement payés. +ClosePaidInvoicesAutomatically=Classer automatiquement à "Payé" les factures entièrement payées. +AllCompletelyPayedInvoiceWillBeClosed=Toutes les factures avec un reste à payer nul seront automatiquement fermées au statut "Payé". ##### Types de contacts ##### TypeContact_facture_internal_SALESREPFOLL=Responsable suivi facture client TypeContact_facture_external_BILLING=Contact client facturation