diff --git a/htdocs/admin/facture_situation.php b/htdocs/admin/facture_situation.php new file mode 100644 index 00000000000..0e62029e8f2 --- /dev/null +++ b/htdocs/admin/facture_situation.php @@ -0,0 +1,228 @@ + + * Copyright (C) 2004-2011 Laurent Destailleur + * Copyright (C) 2005 Eric Seigne + * Copyright (C) 2005-2012 Regis Houssin + * Copyright (C) 2008 Raphael Bertrand (Resultic) + * Copyright (C) 2012-2013 Juanjo Menent + * 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/admin/facture.php + * \ingroup facture + * \brief Page to setup invoice module + */ + +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/invoice.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; + +// Load translation files required by the page +$langs->loadLangs(array('admin', 'errors', 'other', 'bills')); + +if (! $user->admin) accessforbidden(); + +$action = GETPOST('action', 'alpha'); +$value = GETPOST('value', 'alpha'); +$label = GETPOST('label', 'alpha'); +$scandir = GETPOST('scan_dir', 'alpha'); +$type='invoice'; + + +/* + * Actions + */ + +include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; + + + +/* + * View + */ + +$dirmodels=array_merge(array('/'), (array) $conf->modules_parts['models']); + +llxHeader( + "", $langs->trans("BillsSetup"), + 'EN:Invoice_Configuration|FR:Configuration_module_facture|ES:ConfiguracionFactura' +); + +$form=new Form($db); + + +$linkback=''.$langs->trans("BackToModuleList").''; +print load_fiche_titre($langs->trans("BillsSetup"), $linkback, 'title_setup'); + +$head = invoice_admin_prepare_head(); +dol_fiche_head($head, 'situation', $langs->trans("InvoiceSituation"), -1, 'invoice'); + +/* + * Numbering module + */ + +print load_fiche_titre($langs->trans("InvoiceSituation"), '', ''); +$var=0; + +print '
'; +print ''; + +_updateBtn(); + +print ''; + + +_printOnOff('INVOICE_USE_SITUATION', $langs->trans('UseSituationInvoices')); +_printOnOff('INVOICE_USE_SITUATION_CREDIT_NOTE', $langs->trans('UseSituationInvoicesCreditNote')); +_printOnOff('INVOICE_USE_SITUATION_RETAINED_WARRANTY', $langs->trans('Retainedwarranty')); + +$metas = array( + 'type' => 'number', + 'step' => '0.01', + 'min' => 0, + 'max' => 100 +); +_printInputFormPart('INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_PERCENT', $langs->trans('RetainedwarrantyDefaultPercent'), '', $metas); + + + + +// Conditions paiements +$inputCount = empty($inputCount)?1:($inputCount+1); +print ''; +print ''; +print ''; +print ''; + + +print '
'.$langs->trans('PaymentConditionsShortRetainedWarranty').' '; +print ''; +$form->select_conditions_paiements($conf->global->INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID, 'value'.$inputCount, -1, 1); +print '
'; + +_updateBtn(); + +print '
'; + +dol_fiche_end(); + +// End of page +llxFooter(); +$db->close(); + +/** + * Print an update button + * + * @return void + */ +function _updateBtn() +{ + global $langs; + print '
'; + print ''; + print '
'; +} + +/** + * Print a On/Off button + * + * @param string $confkey the conf key + * @param bool $title Title of conf + * @param string $desc Description + * + * @return void + */ +function _printOnOff($confkey, $title = false, $desc = '') +{ + global $var, $bc, $langs; + $var=!$var; + print ''; + print ''.($title?$title:$langs->trans($confkey)); + if (!empty($desc)) { + print '
'.$langs->trans($desc).''; + } + print ''; + print ' '; + print ''; + print ajax_constantonoff($confkey); + print ''; +} + + +/** + * Print a form part + * + * @param string $confkey the conf key + * @param bool $title Title of conf + * @param string $desc Description of + * @param array $metas html meta + * @param string $type type of input textarea or input + * @param bool $help help description + * + * @return void + */ +function _printInputFormPart($confkey, $title = false, $desc = '', $metas = array(), $type = 'input', $help = false) +{ + global $var, $bc, $langs, $conf, $db, $inputCount; + $var=!$var; + $inputCount = empty($inputCount)?1:($inputCount+1); + $form=new Form($db); + + $defaultMetas = array( + 'name' => 'value'.$inputCount + ); + + if ($type!='textarea') { + $defaultMetas['type'] = 'text'; + $defaultMetas['value'] = $conf->global->{$confkey}; + } + + + $metas = array_merge($defaultMetas, $metas); + $metascompil = ''; + foreach ($metas as $key => $values) { + $metascompil .= ' '.$key.'="'.$values.'" '; + } + + print ''; + print ''; + + if (!empty($help)) { + print $form->textwithtooltip(($title?$title:$langs->trans($confkey)), $langs->trans($help), 2, 1, img_help(1, '')); + } else { + print $title?$title:$langs->trans($confkey); + } + + if (!empty($desc)) { + print '
'.$langs->trans($desc).''; + } + + print ''; + print ' '; + print ''; + print ''; + + print ''; + if ($type=='textarea') { + print ''; + } else { + print ''; + } + print ''; +} diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 2f017b485d6..bfa21a9c759 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -309,6 +309,38 @@ if (empty($reshook)) dol_print_error($db, $object->error); } + elseif ($action == 'setretainedwarrantyconditions' && $user->rights->facture->creer) + { + $object->fetch($id); + $object->retained_warranty_fk_cond_reglement = 0; // To clean property + $result = $object->setRetainedWarrantyPaymentTerms(GETPOST('retained_warranty_fk_cond_reglement', 'int')); + if ($result < 0) dol_print_error($db, $object->error); + + $old_rw_date_lim_reglement = $object->retained_warranty_date_limit; + $new_rw_date_lim_reglement = $object->calculate_date_lim_reglement($object->retained_warranty_fk_cond_reglement); + if ($new_rw_date_lim_reglement > $old_rw_date_lim_reglement) $object->retained_warranty_date_limit = $new_rw_date_lim_reglement; + if ($object->retained_warranty_date_limit < $object->date) $object->retained_warranty_date_limit = $object->date; + $result = $object->update($user); + if ($result < 0) dol_print_error($db, $object->error); + } + + elseif ($action == 'setretainedwarranty' && $user->rights->facture->creer) + { + $object->fetch($id); + $result = $object->setRetainedWarranty(GETPOST('retained_warranty', 'float')); + if ($result < 0) + dol_print_error($db, $object->error); + } + + elseif ($action == 'setretainedwarrantydatelimit' && $user->rights->facture->creer) + { + $object->fetch($id); + $result = $object->setRetainedWarrantyDateLimit(GETPOST('retained_warranty_date_limit', 'float')); + if ($result < 0) + dol_print_error($db, $object->error); + } + + // Multicurrency Code elseif ($action == 'setmulticurrencycode' && $usercancreate) { $result = $object->setMulticurrencyCode(GETPOST('multicurrency_code', 'alpha')); @@ -1209,6 +1241,16 @@ if (empty($reshook)) $object->situation_counter = 1; $object->situation_final = 0; $object->situation_cycle_ref = $object->newCycle(); + + + $object->retained_warranty = GETPOST('retained_warranty', 'int'); + $object->retained_warranty_fk_cond_reglement = GETPOST('retained_warranty_fk_cond_reglement', 'int'); + + $retained_warranty_date_limit = GETPOST('retained_warranty_date_limit'); + if(!empty($retained_warranty_date_limit) && $db->jdate($retained_warranty_date_limit)){ + $object->retained_warranty_date_limit = $db->jdate($retained_warranty_date_limit); + } + $object->retained_warranty_date_limit = !empty($object->retained_warranty_date_limit) ? $object->retained_warranty_date_limit : $object->calculate_date_lim_reglement($object->retained_warranty_fk_cond_reglement); } $object->fetch_thirdparty(); @@ -3147,6 +3189,44 @@ if ($action == 'create') $form->select_conditions_paiements(isset($_POST['cond_reglement_id']) ? $_POST['cond_reglement_id'] : $cond_reglement_id, 'cond_reglement_id'); print ''; + if (! empty($conf->global->INVOICE_USE_SITUATION)) + { + if($conf->global->INVOICE_USE_SITUATION_RETAINED_WARRANTY){ + + $rwStyle = 'display:none;'; + if(GETPOST('type', 'int') == Facture::TYPE_SITUATION){ + $rwStyle = ''; + } + + + $retained_warranty = GETPOST('retained_warranty', 'int'); + $retained_warranty = !empty($retained_warranty)?$retained_warranty:$conf->global->INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_PERCENT; + print '' . $langs->trans('RetainedWarranty') . ''; + print '%'; + + // Retained warranty payment term + print '' . $langs->trans('PaymentConditionsShortRetainedWarranty') . ''; + $retained_warranty_fk_cond_reglement = GETPOST('retained_warranty_fk_cond_reglement', 'int'); + $retained_warranty_fk_cond_reglement = !empty($retained_warranty_fk_cond_reglement)? $retained_warranty_fk_cond_reglement : $conf->global->INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID; + $form->select_conditions_paiements($retained_warranty_fk_cond_reglement, 'retained_warranty_fk_cond_reglement', -1, 1); + print ''; + + print ''; + } + } + // Payment mode print '' . $langs->trans('PaymentMode') . ''; $form->select_types_paiements(isset($_POST['mode_reglement_id']) ? $_POST['mode_reglement_id'] : $mode_reglement_id, 'mode_reglement_id', 'CRDT'); @@ -4020,6 +4100,126 @@ elseif ($id > 0 || ! empty($ref)) print ''; } + $displayWarranty = false; + if( ( $object->type == Facture::TYPE_SITUATION && (!empty($object->retained_warranty) || !empty($conf->global->INVOICE_USE_SITUATION_RETAINED_WARRANTY)) ) ) + { + // Check if this situation invoice is 100% for real + if(!empty($object->situation_final) && !empty($object->lines)){ + $displayWarranty = true; + foreach($object->lines as $i => $line){ + if($line->product_type < 2 && $line->situation_percent < 100){ + $displayWarranty = false; + break; + } + } + } + + + + // Retained Warranty + print ''; + print ''; + if ($action != 'editretainedwarranty' && $user->rights->facture->creer){ + print ''; + } + + print '
'; + print $langs->trans('RetainedWarranty'); + print 'id . '">' . img_edit($langs->trans('setretainedwarranty'), 1) . '
'; + print ''; + if ($action == 'editretainedwarranty') + { + print '
'; + print ''; + print ''; + print ''; + print ''; + print '
'; + } + else + { + print price($object->retained_warranty).'%'; + } + print ''; + + // Retained warranty payment term + print ''; + print ''; + if ($action != 'editretainedwarrantypaymentterms' && $user->rights->facture->creer){ + print ''; + } + + print '
'; + print $langs->trans('PaymentConditionsShortRetainedWarranty'); + print 'id . '">' . img_edit($langs->trans('setPaymentConditionsShortRetainedWarranty'), 1) . '
'; + print ''; + $defaultDate = !empty($object->retained_warranty_date_limit)?$object->retained_warranty_date_limit:strtotime('-1 years', $object->date_lim_reglement); + if($object->date > $defaultDate){ + $defaultDate = $object->date; + } + + if ($action == 'editretainedwarrantypaymentterms') + { + //date('Y-m-d',$object->date_lim_reglement) + print '
'; + print ''; + print ''; + $retained_warranty_fk_cond_reglement = GETPOST('retained_warranty_fk_cond_reglement', 'int'); + $retained_warranty_fk_cond_reglement = !empty($retained_warranty_fk_cond_reglement)? $retained_warranty_fk_cond_reglement : $object->retained_warranty_fk_cond_reglement; + $retained_warranty_fk_cond_reglement = !empty($retained_warranty_fk_cond_reglement)? $retained_warranty_fk_cond_reglement : $conf->global->INVOICE_SITUATION_DEFAULT_RETAINED_WARRANTY_COND_ID; + $form->select_conditions_paiements($retained_warranty_fk_cond_reglement, 'retained_warranty_fk_cond_reglement', -1, 1); + print ''; + print '
'; + } + else + { + print $form->form_conditions_reglement($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->retained_warranty_fk_cond_reglement, 'none'); + if(!$displayWarranty){ + print img_picto($langs->trans('RetainedWarrantyNeed100Percent'), 'warning.png', 'class="pictowarning valignmiddle" '); + } + } + print ''; + + + + + if($displayWarranty) + { + // Retained Warranty payment date limit + print ''; + print ''; + if ($action != 'editretainedwarrantydatelimit' && $user->rights->facture->creer){ + print ''; + } + + print '
'; + print $langs->trans('RetainedWarrantyDateLimit'); + print 'id . '">' . img_edit($langs->trans('setretainedwarrantyDateLimit'), 1) . '
'; + print ''; + $defaultDate = !empty($object->retained_warranty_date_limit)?$object->retained_warranty_date_limit:strtotime('-1 years', $object->date_lim_reglement); + if($object->date > $defaultDate){ + $defaultDate = $object->date; + } + + if ($action == 'editretainedwarrantydatelimit') + { + //date('Y-m-d',$object->date_lim_reglement) + print '
'; + print ''; + print ''; + print ''; + print ''; + print '
'; + } + else + { + print dol_print_date($object->retained_warranty_date_limit, 'day'); + } + print ''; + } + } + + // Other attributes $cols = 2; include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php'; @@ -4464,6 +4664,31 @@ elseif ($id > 0 || ! empty($ref)) print ' :'; print '' . price($resteapayeraffiche) . ''; print ' '; + + // Retained warranty : usualy use on construction industry + if(!empty($object->situation_final) && !empty($object->retained_warranty) && $displayWarranty){ + + // Billed - retained warranty + if($object->type == Facture::TYPE_SITUATION) + { + $retainedWarranty = $total_global_ttc * $object->retained_warranty / 100; + } + else + { + // Because one day retained warranty could be used on standard invoices + $retainedWarranty = $object->total_ttc * $object->retained_warranty / 100; + } + + $billedWithRetainedWarranty = $object->total_ttc - $retainedWarranty ; + + print '' . $langs->trans("ToPayOn", dol_print_date($object->date_lim_reglement, 'day')) . ' :' . price($billedWithRetainedWarranty) . ' '; + + // retained warranty + print ''; + print $langs->trans("RetainedWarranty") . ' ('.$object->retained_warranty.'%)'; + print !empty($object->retained_warranty_date_limit)?' '.$langs->trans("ToPayOn", dol_print_date($object->retained_warranty_date_limit, 'day')):''; + print ' :' . price($retainedWarranty) . ' '; + } } else // Credit note { diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index e5b8c0795ed..8136f93b47a 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -206,6 +206,21 @@ class Facture extends CommonInvoice public $oldcopy; + /** + * @var double percentage of retainage + */ + public $retained_warranty; + + /** + * @var int timestamp of date limit of retainage + */ + public $retained_warranty_date_limit; + + /** + * @var int Code in llx_c_paiement + */ + public $retained_warranty_fk_cond_reglement; + /** * Standard invoice */ @@ -472,6 +487,9 @@ class Facture extends CommonInvoice $sql.= ", fk_multicurrency"; $sql.= ", multicurrency_code"; $sql.= ", multicurrency_tx"; + $sql.= ", retained_warranty"; + $sql.= ", retained_warranty_date_limit"; + $sql.= ", retained_warranty_fk_cond_reglement"; $sql.= ")"; $sql.= " VALUES ("; $sql.= "'(PROV)'"; @@ -506,6 +524,10 @@ class Facture extends CommonInvoice $sql.= ", ".(int) $this->fk_multicurrency; $sql.= ", '".$this->db->escape($this->multicurrency_code)."'"; $sql.= ", ".(double) $this->multicurrency_tx; + $sql.= ", ".(empty($this->retained_warranty)?"0":$this->db->escape($this->retained_warranty)); + $sql.= ", ".(!empty($this->retained_warranty_date_limit)?"'".$this->db->idate($this->retained_warranty_date_limit)."'":'NULL'); + $sql.= ", ".(int) $this->retained_warranty_fk_cond_reglement; + $sql.=")"; $resql=$this->db->query($sql); @@ -1336,6 +1358,7 @@ class Facture extends CommonInvoice $sql.= ', f.fk_incoterms, f.location_incoterms'; $sql.= ', f.module_source, f.pos_source'; $sql.= ", i.libelle as label_incoterms"; + $sql.= ", f.retained_warranty as retained_warranty, f.retained_warranty_date_limit as retained_warranty_date_limit, f.retained_warranty_fk_cond_reglement as retained_warranty_fk_cond_reglement"; $sql.= ' FROM '.MAIN_DB_PREFIX.'facture as f'; $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_payment_term as c ON f.fk_cond_reglement = c.rowid'; $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as p ON f.fk_mode_reglement = p.id'; @@ -1405,6 +1428,10 @@ class Facture extends CommonInvoice $this->situation_cycle_ref = $obj->situation_cycle_ref; $this->situation_counter = $obj->situation_counter; $this->situation_final = $obj->situation_final; + $this->retained_warranty = $obj->retained_warranty; + $this->retained_warranty_date_limit = $this->db->jdate($obj->retained_warranty_date_limit); + $this->retained_warranty_fk_cond_reglement = $obj->retained_warranty_fk_cond_reglement; + $this->extraparams = (array) json_decode($obj->extraparams, true); //Incoterms @@ -1648,6 +1675,8 @@ class Facture extends CommonInvoice if (isset($this->note_public)) $this->note_public=trim($this->note_public); if (isset($this->modelpdf)) $this->modelpdf=trim($this->modelpdf); if (isset($this->import_key)) $this->import_key=trim($this->import_key); + if (isset($this->retained_warranty)) $this->retained_warranty = floatval($this->retained_warranty); + // Check parameters // Put here code to add control on parameters values @@ -1688,7 +1717,10 @@ class Facture extends CommonInvoice $sql.= " import_key=".(isset($this->import_key)?"'".$this->db->escape($this->import_key)."'":"null").","; $sql.= " situation_cycle_ref=".(empty($this->situation_cycle_ref)?"null":$this->db->escape($this->situation_cycle_ref)).","; $sql.= " situation_counter=".(empty($this->situation_counter)?"null":$this->db->escape($this->situation_counter)).","; - $sql.= " situation_final=".(empty($this->situation_final)?"0":$this->db->escape($this->situation_final)); + $sql.= " situation_final=".(empty($this->situation_final)?"0":$this->db->escape($this->situation_final)).","; + $sql.= " retained_warranty=".(empty($this->retained_warranty)?"0":$this->db->escape($this->retained_warranty)).","; + $sql.= " retained_warranty_date_limit=".(strval($this->retained_warranty_date_limit)!='' ? "'".$this->db->idate($this->retained_warranty_date_limit)."'" : 'null').","; + $sql.= " retained_warranty_fk_cond_reglement=".(isset($this->retained_warranty_fk_cond_reglement)?intval($this->retained_warranty_fk_cond_reglement):"null"); $sql.= " WHERE rowid=".$this->id; $this->db->begin(); @@ -4374,6 +4406,137 @@ class Facture extends CommonInvoice return $this->date_lim_reglement < ($now - $conf->facture->client->warning_delay); } + + + /** + * @return number or -1 if not available + */ + public function getRetainedWarrantyAmount() + { + if(empty($this->retained_warranty) ){ + return -1; + } + + $retainedWarrantyAmount = 0; + + // Billed - retained warranty + if($this->type == Facture::TYPE_SITUATION) + { + $displayWarranty = true; + // Check if this situation invoice is 100% for real + if(!empty($this->lines)){ + foreach($this->lines as $i => $line){ + if($line->product_type < 2 && $line->situation_percent < 100){ + $displayWarranty = false; + break; + } + } + } + + if($displayWarranty && !empty($this->situation_final)) + { + $this->fetchPreviousNextSituationInvoice(); + $TPreviousIncoice = $this->tab_previous_situation_invoice; + + $total2BillWT = 0; + foreach ($TPreviousIncoice as &$fac){ + $total2BillWT += $fac->total_ttc; + } + $total2BillWT += $this->total_ttc; + + $retainedWarrantyAmount = $total2BillWT * $this->retained_warranty / 100; + } + else{ + return -1; + } + } + else + { + // Because one day retained warranty could be used on standard invoices + $retainedWarrantyAmount = $this->total_ttc * $this->retained_warranty / 100; + } + + return $retainedWarrantyAmount; + } + + /** + * Change the retained warranty + * + * @param float $value value of retained warranty + * @return int >0 if OK, <0 if KO + */ + public function setRetainedWarranty($value) + { + dol_syslog(get_class($this).'::setRetainedWarranty('.$value.')'); + if ($this->statut >= 0) + { + $fieldname = 'retained_warranty'; + $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; + $sql .= ' SET '.$fieldname.' = '.floatval($value); + $sql .= ' WHERE rowid='.$this->id; + + if ($this->db->query($sql)) + { + $this->retained_warranty = floatval($value); + return 1; + } + else + { + dol_syslog(get_class($this).'::setRetainedWarranty Erreur '.$sql.' - '.$this->db->error()); + $this->error=$this->db->error(); + return -1; + } + } + else + { + dol_syslog(get_class($this).'::setRetainedWarranty, status of the object is incompatible'); + $this->error='Status of the object is incompatible '.$this->statut; + return -2; + } + } + + + /** + * Change the retained_warranty_date_limit + * + * @param int $timestamp date limit of retained warranty in timestamp format + * @param string $dateYmd date limit of retained warranty in Y m d format + * @return int >0 if OK, <0 if KO + */ + public function setRetainedWarrantyDateLimit($timestamp, $dateYmd = false) + { + if(!$timestamp && $dateYmd){ + $timestamp = $this->db->jdate($dateYmd); + } + + + dol_syslog(get_class($this).'::setRetainedWarrantyDateLimit('.$timestamp.')'); + if ($this->statut >= 0) + { + $fieldname = 'retained_warranty_date_limit'; + $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; + $sql .= ' SET '.$fieldname.' = '.(strval($timestamp)!='' ? '\'' .$this->db->idate($timestamp).'\'' : 'null' ); + $sql .= ' WHERE rowid='.$this->id; + + if ($this->db->query($sql)) + { + $this->retained_warranty_date_limit = $timestamp; + return 1; + } + else + { + dol_syslog(get_class($this).'::setRetainedWarrantyDateLimit Erreur '.$sql.' - '.$this->db->error()); + $this->error=$this->db->error(); + return -1; + } + } + else + { + dol_syslog(get_class($this).'::setRetainedWarrantyDateLimit, status of the object is incompatible'); + $this->error='Status of the object is incompatible '.$this->statut; + return -2; + } + } } /** diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index 2982246c6d9..eca39ade98c 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -182,6 +182,12 @@ $arrayfields=array( 'f.tms'=>array('label'=>"DateModificationShort", 'checked'=>0, 'position'=>500), 'f.fk_statut'=>array('label'=>"Status", 'checked'=>1, 'position'=>1000), ); + +if($conf->global->INVOICE_USE_SITUATION && $conf->global->INVOICE_USE_SITUATION_RETAINED_WARRANTY) +{ + $arrayfields['f.retained_warranty'] = array('label'=>$langs->trans("RetainedWarranty"), 'checked'=>0); +} + // Extra fields if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) { @@ -373,6 +379,10 @@ $sql.= ' f.localtax1 as total_localtax1, f.localtax2 as total_localtax2,'; $sql.= ' f.datef as df, f.date_lim_reglement as datelimite,'; $sql.= ' f.paye as paye, f.fk_statut,'; $sql.= ' f.datec as date_creation, f.tms as date_update,'; +if($conf->global->INVOICE_USE_SITUATION && $conf->global->INVOICE_USE_SITUATION_RETAINED_WARRANTY) +{ + $sql.= ' f.retained_warranty, f.retained_warranty_date_limit, f.situation_final,f.situation_cycle_ref,f.situation_counter,'; +} $sql.= ' s.rowid as socid, s.nom as name, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta as code_compta_client, s.code_compta_fournisseur,'; $sql.= " typent.code as typent_code,"; $sql.= " state.code_departement as state_code, state.nom as state_name,"; @@ -834,6 +844,13 @@ if ($resql) print ''; print ''; } + + if(! empty($arrayfields['f.retained_warranty']['checked'])) + { + print ''; + print ''; + } + if (! empty($arrayfields['dynamount_payed']['checked'])) { print ''; @@ -899,6 +916,7 @@ if ($resql) if (! empty($arrayfields['f.total_localtax1']['checked'])) print_liste_field_titre($arrayfields['f.total_localtax1']['label'], $_SERVER['PHP_SELF'], 'f.localtax1', '', $param, 'class="right"', $sortfield, $sortorder); if (! empty($arrayfields['f.total_localtax2']['checked'])) print_liste_field_titre($arrayfields['f.total_localtax2']['label'], $_SERVER['PHP_SELF'], 'f.localtax2', '', $param, 'class="right"', $sortfield, $sortorder); if (! empty($arrayfields['f.total_ttc']['checked'])) print_liste_field_titre($arrayfields['f.total_ttc']['label'], $_SERVER['PHP_SELF'], 'f.total_ttc', '', $param, 'class="right"', $sortfield, $sortorder); + if (! empty($arrayfields['f.retained_warranty']['checked'])) print_liste_field_titre($arrayfields['f.retained_warranty']['label'], $_SERVER['PHP_SELF'], '', '', $param, 'align="right"', $sortfield, $sortorder); if (! empty($arrayfields['dynamount_payed']['checked'])) print_liste_field_titre($arrayfields['dynamount_payed']['label'], $_SERVER['PHP_SELF'], '', '', $param, 'class="right"', $sortfield, $sortorder); if (! empty($arrayfields['rtp']['checked'])) print_liste_field_titre($arrayfields['rtp']['label'], $_SERVER['PHP_SELF'], '', '', $param, 'class="right"', $sortfield, $sortorder); // Extra fields @@ -939,7 +957,15 @@ if ($resql) $facturestatic->date_lim_reglement=$db->jdate($obj->datelimite); $facturestatic->note_public=$obj->note_public; $facturestatic->note_private=$obj->note_private; - + if($conf->global->INVOICE_USE_SITUATION && $conf->global->INVOICE_USE_SITUATION_RETAINED_WARRANTY) + { + $facturestatic->retained_warranty=$obj->retained_warranty; + $facturestatic->retained_warranty_date_limit=$obj->retained_warranty_date_limit; + $facturestatic->situation_final=$obj->retained_warranty_date_limit; + $facturestatic->situation_final=$obj->retained_warranty_date_limit; + $facturestatic->situation_cycle_ref=$obj->situation_cycle_ref; + $facturestatic->situation_counter=$obj->situation_counter; + } $thirdpartystatic->id=$obj->socid; $thirdpartystatic->name=$obj->name; $thirdpartystatic->client=$obj->client; @@ -1181,6 +1207,11 @@ if ($resql) $totalarray['totalttc'] += $obj->total_ttc; } + if(! empty($arrayfields['f.retained_warranty']['checked'])) + { + print ''.(! empty($obj->retained_warranty)?price($obj->retained_warranty).'%':' ').''; + } + if (! empty($arrayfields['dynamount_payed']['checked'])) { print ''.(! empty($totalpay)?price($totalpay, 0, $langs):' ').''; // TODO Use a denormalized field diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 67c3f0f9630..28ea7f44f10 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -2053,6 +2053,43 @@ abstract class CommonObject return -2; } } + + /** + * Change the retained warranty payments terms + * + * @param int $id Id of new payment terms + * @return int >0 if OK, <0 if KO + */ + public function setRetainedWarrantyPaymentTerms($id) + { + dol_syslog(get_class($this).'::setRetainedWarrantyPaymentTerms('.$id.')'); + if ($this->statut >= 0 || $this->element == 'societe') + { + $fieldname = 'retained_warranty_fk_cond_reglement'; + + $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; + $sql .= ' SET '.$fieldname.' = '.$id; + $sql .= ' WHERE rowid='.$this->id; + + if ($this->db->query($sql)) + { + $this->retained_warranty_fk_cond_reglement = $id; + return 1; + } + else + { + dol_syslog(get_class($this).'::setRetainedWarrantyPaymentTerms Erreur '.$sql.' - '.$this->db->error()); + $this->error=$this->db->error(); + return -1; + } + } + else + { + dol_syslog(get_class($this).'::setRetainedWarrantyPaymentTerms, status of the object is incompatible'); + $this->error='Status of the object is incompatible '.$this->statut; + return -2; + } + } /** * Define delivery address diff --git a/htdocs/core/lib/invoice.lib.php b/htdocs/core/lib/invoice.lib.php index 9495a13edde..b3d518eb088 100644 --- a/htdocs/core/lib/invoice.lib.php +++ b/htdocs/core/lib/invoice.lib.php @@ -136,7 +136,14 @@ function invoice_admin_prepare_head() $head[$h][1] = $langs->trans("Payments"); $head[$h][2] = 'payment'; $h++; - + + if($conf->global->INVOICE_USE_SITUATION){ + $head[$h][0] = DOL_URL_ROOT.'/admin/facture_situation.php'; + $head[$h][1] = $langs->trans("InvoiceSituation"); + $head[$h][2] = 'situation'; + $h++; + } + // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab diff --git a/htdocs/core/lib/pdf.lib.php b/htdocs/core/lib/pdf.lib.php index c1b5f4c489d..ba42ebd23d8 100644 --- a/htdocs/core/lib/pdf.lib.php +++ b/htdocs/core/lib/pdf.lib.php @@ -2212,3 +2212,49 @@ function pdf_getSizeForImage($realpath) } return array('width'=>$width,'height'=>$height); } + +/** + * Return line total amount discount + * + * @param Object $object Object + * @param int $i Current line number + * @param Translate $outputlangs Object langs for output + * @param int $hidedetails Hide details (0=no, 1=yes, 2=just special lines) + * @return string Return total of line excl tax + */ +function pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, $hidedetails = 0) +{ + global $conf, $hookmanager; + $sign=1; + if (isset($object->type) && $object->type == 2 && ! empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) $sign=-1; + if ($object->lines[$i]->special_code == 3) + { + return $outputlangs->transnoentities("Option"); + } + else + { + + if (is_object($hookmanager)) + { + $special_code = $object->lines[$i]->special_code; + if (! empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line); + + $parameters = array( + 'i'=>$i, + 'outputlangs'=>$outputlangs, + 'hidedetails'=>$hidedetails, + 'special_code'=>$special_code + ); + + $action=''; + + if( $hookmanager->executeHooks('getlinetotalremise', $parameters, $object, $action)>0) + { + return $hookmanager->resPrint; // Note that $action and $object may have been modified by some hooks + } + } + + if (empty($hidedetails) || $hidedetails > 1) return $sign * ( ($object->lines[$i]->subprice * $object->lines[$i]->qty) - $object->lines[$i]->total_ht ); + } + return ''; +} diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index 53929f28e75..acc88a1e96a 100644 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -1347,6 +1347,50 @@ class pdf_crabe extends ModelePDFFactures $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); $pdf->MultiCell($largcol2, $tab2_hl, price($sign * $total_ttc, 0, $outputlangs), $useborder, 'R', 1); + + // Retained warranty + if( !empty($object->situation_final) && ( $object->type == Facture::TYPE_SITUATION && (!empty($object->retained_warranty) ) ) ) + { + $displayWarranty = false; + + // Check if this situation invoice is 100% for real + if(!empty($object->lines)){ + $displayWarranty = true; + foreach($object->lines as $i => $line){ + if($line->product_type < 2 && $line->situation_percent < 100){ + $displayWarranty = false; + break; + } + } + } + + if($displayWarranty){ + $pdf->SetTextColor(40, 40, 40); + $pdf->SetFillColor(255, 255, 255); + + $retainedWarranty = $object->total_ttc * $object->retained_warranty / 100; + $billedWithRetainedWarranty = $object->total_ttc - $retainedWarranty ; + + // Billed - retained warranty + $index++; + $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("ToPayOn", dol_print_date($object->date_lim_reglement, 'day')), $useborder, 'L', 1); + + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($billedWithRetainedWarranty), $useborder, 'R', 1); + + // retained warranty + $index++; + $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); + + $retainedWarrantyToPayOn = $outputlangs->transnoentities("RetainedWarranty") . ' ('.$object->retained_warranty.'%)'; + $retainedWarrantyToPayOn.= !empty($object->retained_warranty_date_limit)?' '.$outputlangs->transnoentities("toPayOn", dol_print_date($object->retained_warranty_date_limit, 'day')):''; + + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $retainedWarrantyToPayOn, $useborder, 'L', 1); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($retainedWarranty), $useborder, 'R', 1); + } + } } } diff --git a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php index b5529c78d8e..26e2b1824d8 100644 --- a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php @@ -1225,13 +1225,172 @@ class pdf_sponge extends ModelePDFFactures $useborder=0; $index = 0; + + + // pourcentage global d'avancement + $percent = 0; + $i=0; + foreach ($object->lines as $line) + { + if(!class_exists('TSubtotal') || !TSubtotal::isModSubtotalLine($line)){ + $percent += $line->situation_percent; + $i++; + } + } + if(!empty($i)){ + $avancementGlobal = $percent/$i; + } + else{ + $avancementGlobal = 0; + } + + $object->fetchPreviousNextSituationInvoice(); + $TPreviousIncoice = $object->tab_previous_situation_invoice; + + $total_a_payer = 0; + $total_a_payer_ttc = 0; + foreach ($TPreviousIncoice as &$fac){ + $total_a_payer += $fac->total_ht; + $total_a_payer_ttc += $fac->total_ttc; + } + $total_a_payer += $object->total_ht; + $total_a_payer_ttc += $object->total_ttc; + + if(!empty($avancementGlobal)){ + $total_a_payer = $total_a_payer * 100 / $avancementGlobal; + $total_a_payer_ttc = $total_a_payer_ttc * 100 / $avancementGlobal; + } + else{ + $total_a_payer = 0; + $total_a_payer_ttc = 0; + } + + $deja_paye = 0; + $i = 1; + if(!empty($TPreviousIncoice)){ + + $pdf->setY($tab2_top); + $posy = $pdf->GetY(); + + + + + foreach ($TPreviousIncoice as &$fac){ + + if($posy > $this->page_hauteur - 4 ) { + $this->_pagefoot($pdf, $object, $outputlangs, 1); + $pdf->addPage(); + $pdf->setY($this->marge_haute); + $posy = $pdf->GetY(); + } + + // cumul TVA précédent + $index++; + $pdf->SetFillColor(255, 255, 255); + $pdf->SetXY($col1x, $posy); + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("PDFSituationTitle", $fac->situation_counter).' '.$outputlangs->transnoentities("TotalHT"), 0, 'L', 1); + + $pdf->SetXY($col2x, $posy); + + $facSign = ''; + if($i>1){ + $facSign = $fac->total_ht>=0?'+':''; + } + + $displayAmount = ' '.$facSign.' '.price($fac->total_ht, 0, $outputlangs); + + $pdf->MultiCell($largcol2, $tab2_hl, $displayAmount, 0, 'R', 1); + + $i++; + $deja_paye += $fac->total_ht; + $posy += $tab2_hl; + + $pdf->setY($posy); + } + + // Display curent total + $pdf->SetFillColor(255, 255, 255); + $pdf->SetXY($col1x, $posy); + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("PDFSituationTitle", $object->situation_counter).' '.$outputlangs->transnoentities("TotalHT"), 0, 'L', 1); + + $pdf->SetXY($col2x, $posy); + $facSign = ''; + if($i>1){ + $facSign = $object->total_ht>=0?'+':''; // gestion d'un cas particulier client + } + + if($fac->type === facture::TYPE_CREDIT_NOTE){ + $facSign = '-'; // les avoirs + } + + + $displayAmount = ' '.$facSign.' '.price($object->total_ht, 0, $outputlangs); + $pdf->MultiCell($largcol2, $tab2_hl, $displayAmount, 0, 'R', 1); + + $posy += $tab2_hl; + + // Display all total + $pdf->SetFont('', '', $default_font_size - 1); + $pdf->SetFillColor(255, 255, 255); + $pdf->SetXY($col1x, $posy); + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("SituationTotalProgress", $avancementGlobal), 0, 'L', 1); + + $pdf->SetXY($col2x, $posy); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_a_payer*$avancementGlobal/100, 0, $outputlangs), 0, 'R', 1); + $pdf->SetFont('', '', $default_font_size - 2); + + $posy += $tab2_hl; + + if($posy > $this->page_hauteur - 4 ) { + $pdf->addPage(); + $pdf->setY($this->marge_haute); + $posy = $pdf->GetY(); + } + + $tab2_top = $posy; + $index=0; + } + + $tab2_top += 3; + + // Get Total HT + $total_ht = ($conf->multicurrency->enabled && $object->mylticurrency_tx != 1 ? $object->multicurrency_total_ht : $object->total_ht); + + // Total remise + $total_line_remise=0; + foreach($object->lines as $i => $line) { + $total_line_remise+= pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, 2); // TODO: add this methode to core/lib/pdf.lib + // Gestion remise sous forme de ligne négative + if($line->total_ht < 0) $total_line_remise += -$line->total_ht; + } + if($total_line_remise > 0) { + if (! empty($conf->global->MAIN_SHOW_AMOUNT_DISCOUNT)) { + $pdf->SetFillColor(255, 255, 255); + $pdf->SetXY($col1x, $tab2_top + $tab2_hl); + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("TotalDiscount"), 0, 'L', 1); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_line_remise, 0, $outputlangs), 0, 'R', 1); + + $index++; + } + // Show total NET before discount + if (! empty($conf->global->MAIN_SHOW_AMOUNT_BEFORE_DISCOUNT)) { + $pdf->SetFillColor(255, 255, 255); + $pdf->SetXY($col1x, $tab2_top + 0); + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("TotalHTBeforeDiscount"), 0, 'L', 1); + $pdf->SetXY($col2x, $tab2_top + 0); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_line_remise + $total_ht, 0, $outputlangs), 0, 'R', 1); + + $index++; + } + } + // Total HT $pdf->SetFillColor(255, 255, 255); - $pdf->SetXY($col1x, $tab2_top + 0); + $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("TotalHT"), 0, 'L', 1); - $total_ht = ($conf->multicurrency->enabled && $object->mylticurrency_tx != 1 ? $object->multicurrency_total_ht : $object->total_ht); - $pdf->SetXY($col2x, $tab2_top + 0); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); $pdf->MultiCell($largcol2, $tab2_hl, price($sign * ($total_ht + (! empty($object->remise)?$object->remise:0)), 0, $outputlangs), 0, 'R', 1); // Show VAT by rates and total @@ -1256,7 +1415,7 @@ class pdf_sponge extends ModelePDFFactures //{ foreach($this->localtax1 as $localtax_type => $localtax_rate) { - if (in_array((string) $localtax_type, array('1','3','5'))) continue; + if (in_array((string) $localtax_type, array('1', '3', '5'))) continue; foreach($localtax_rate as $tvakey => $tvaval) { @@ -1330,7 +1489,14 @@ class pdf_sponge extends ModelePDFFactures } if($sum_pdf_tva!=$object->total_tva) { // apply coef to recover the VAT object amount (the good one) - $coef_fix_tva = $object->total_tva / $sum_pdf_tva; + if(!empty($sum_pdf_tva)) + { + $coef_fix_tva = $object->total_tva / $sum_pdf_tva; + } + else { + $coef_fix_tva = 1; + } + foreach($this->tva as $tvakey => $tvaval) { $this->tva[$tvakey]=$tvaval * $coef_fix_tva; @@ -1427,7 +1593,7 @@ class pdf_sponge extends ModelePDFFactures } } } - //} + // Revenue stamp if (price2num($object->revenuestamp) != 0) @@ -1449,6 +1615,69 @@ class pdf_sponge extends ModelePDFFactures $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); $pdf->MultiCell($largcol2, $tab2_hl, price($sign * $total_ttc, 0, $outputlangs), $useborder, 'R', 1); + + + /*if($object->type == Facture::TYPE_SITUATION) + { + // reste à payer total + $index++; + + $pdf->SetFont('','', $default_font_size - 1); + $pdf->SetFillColor(255,255,255); + $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities('SituationTotalRayToRest'), 0, 'L', 1); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($total_a_payer_ttc-$deja_paye, 0, $outputlangs), 0, 'R', 1); + }*/ + + + // Retained warranty + if( !empty($object->situation_final) && ( $object->type == Facture::TYPE_SITUATION && (!empty($object->retained_warranty) ) ) ) + { + $displayWarranty = false; + + // Check if this situation invoice is 100% for real + if(!empty($object->situation_final)){ + $displayWarranty = true; + } + elseif(!empty($object->lines) && $object->status == Facture::STATUS_DRAFT ){ + // $object->situation_final need validation to be done so this test is need for draft + $displayWarranty = true; + foreach($object->lines as $i => $line){ + if($line->product_type < 2 && $line->situation_percent < 100){ + $displayWarranty = false; + break; + } + } + } + + if($displayWarranty){ + $pdf->SetTextColor(40, 40, 40); + $pdf->SetFillColor(255, 255, 255); + + $retainedWarranty = $total_a_payer_ttc * $object->retained_warranty / 100; + $billedWithRetainedWarranty = $object->total_ttc - $retainedWarranty ; + + // Billed - retained warranty + $index++; + $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("PDFEVOLToPayOn", dol_print_date($object->date_lim_reglement, 'day')), $useborder, 'L', 1); + + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($billedWithRetainedWarranty), $useborder, 'R', 1); + + // retained warranty + $index++; + $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); + + $retainedWarrantyToPayOn = $outputlangs->transnoentities("PDFEVOLRetainedWarranty") . ' ('.$object->retained_warranty.'%)'; + $retainedWarrantyToPayOn.= !empty($object->retained_warranty_date_limit)?' '.$outputlangs->transnoentities("PDFEVOLtoPayOn", dol_print_date($object->retained_warranty_date_limit, 'day')):''; + + $pdf->MultiCell($col2x-$col1x, $tab2_hl, $retainedWarrantyToPayOn, $useborder, 'L', 1); + $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); + $pdf->MultiCell($largcol2, $tab2_hl, price($retainedWarranty), $useborder, 'R', 1); + } + } } } @@ -1456,7 +1685,7 @@ class pdf_sponge extends ModelePDFFactures $creditnoteamount=$object->getSumCreditNotesUsed(($conf->multicurrency->enabled && $object->multicurrency_tx != 1) ? 1 : 0); $depositsamount=$object->getSumDepositsUsed(($conf->multicurrency->enabled && $object->multicurrency_tx != 1) ? 1 : 0); - //print "x".$creditnoteamount."-".$depositsamount;exit; + $resteapayer = price2num($total_ttc - $deja_regle - $creditnoteamount - $depositsamount, 'MT'); if ($object->paye) $resteapayer=0; @@ -1509,6 +1738,20 @@ class pdf_sponge extends ModelePDFFactures return ($tab2_top + ($tab2_hl * $index)); } + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Return list of active generation modules + * + * @param DoliDB $db Database handler + * @param integer $maxfilenamelength Max length of value to show + * @return array List of templates + */ + public static function liste_modeles($db, $maxfilenamelength = 0) + { + // phpcs:enable + return parent::liste_modeles($db, $maxfilenamelength); // TODO: Change the autogenerated stub + } + /** * Show table for lines * diff --git a/htdocs/install/mysql/migration/8.0.0-9.0.0.sql b/htdocs/install/mysql/migration/8.0.0-9.0.0.sql index f639db56ab5..6e38e8cff5b 100644 --- a/htdocs/install/mysql/migration/8.0.0-9.0.0.sql +++ b/htdocs/install/mysql/migration/8.0.0-9.0.0.sql @@ -286,6 +286,11 @@ DELETE from llx_accounting_account where rowid in (select minid from tmp_llx_acc --update llx_expensereport_det set fk_code_ventilation = maxid WHERE fk_code_ventilation = minid; +ALTER TABLE llx_facture ADD COLUMN retained_warranty real DEFAULT NULL after situation_final; +ALTER TABLE llx_facture ADD COLUMN retained_warranty_date_limit date DEFAULT NULL after retained_warranty; +ALTER TABLE llx_facture ADD COLUMN retained_warranty_fk_cond_reglement integer DEFAULT NULL after retained_warranty_date_limit; + + ALTER TABLE llx_accounting_account DROP INDEX uk_accounting_account; ALTER TABLE llx_accounting_account ADD UNIQUE INDEX uk_accounting_account (account_number, entity, fk_pcg_version); diff --git a/htdocs/install/mysql/tables/llx_facture.sql b/htdocs/install/mysql/tables/llx_facture.sql index 8e9ceb48d04..742c63d0a6e 100644 --- a/htdocs/install/mysql/tables/llx_facture.sql +++ b/htdocs/install/mysql/tables/llx_facture.sql @@ -88,6 +88,10 @@ create table llx_facture situation_counter smallint, -- situation counter situation_final smallint, -- is the situation final ? + retained_warranty real DEFAULT NULL, -- % of retained warranty + retained_warranty_date_limit date DEFAULT NULL, + retained_warranty_fk_cond_reglement integer DEFAULT NULL, -- payment condition of retained warranty + import_key varchar(14), extraparams varchar(255), -- for other parameters with json format diff --git a/htdocs/langs/en_US/bills.lang b/htdocs/langs/en_US/bills.lang index 4b67ced59c9..5f4a9ff0bba 100644 --- a/htdocs/langs/en_US/bills.lang +++ b/htdocs/langs/en_US/bills.lang @@ -214,6 +214,20 @@ ShowInvoiceReplace=Show replacing invoice ShowInvoiceAvoir=Show credit note ShowInvoiceDeposit=Show down payment invoice ShowInvoiceSituation=Show situation invoice +UseSituationInvoices=Allow situation invoice +UseSituationInvoicesCreditNote=Allow situation invoice credit note +Retainedwarranty=Retained warranty +RetainedwarrantyDefaultPercent=Retained warranty default percent +ToPayOn=To pay on %s +toPayOn=to pay on %s +RetainedWarranty=Retained Warranty +PaymentConditionsShortRetainedWarranty=Retained warranty payment terms +DefaultPaymentConditionsRetainedWarranty=Default retained warranty payment terms +setPaymentConditionsShortRetainedWarranty=Set retained warranty payment terms +setretainedwarranty=Set retained warranty +setretainedwarrantyDateLimit=Set retained warranty date limit +RetainedWarrantyDateLimit=Retained warranty date limit +RetainedWarrantyNeed100Percent=The situation invoice need to be at 100%% progress to be displayed on PDF ShowPayment=Show payment AlreadyPaid=Already paid AlreadyPaidBack=Already paid back @@ -552,4 +566,4 @@ AutoFillDateFromShort=Set start date AutoFillDateTo=Set end date for service line with next invoice date AutoFillDateToShort=Set end date MaxNumberOfGenerationReached=Max number of gen. reached -BILL_DELETEInDolibarr=Invoice deleted \ No newline at end of file +BILL_DELETEInDolibarr=Invoice deleted diff --git a/test/phpunit/FactureTest.php b/test/phpunit/FactureTest.php index 3c066380b09..443d77e2382 100644 --- a/test/phpunit/FactureTest.php +++ b/test/phpunit/FactureTest.php @@ -232,7 +232,8 @@ class FactureTest extends PHPUnit\Framework\TestCase 'newref','oldref','id','lines','client','thirdparty','brouillon','user_author','date_creation','date_validation','datem','date_modification', 'ref','statut','paye','specimen','ref','actiontypecode','actionmsg2','actionmsg','mode_reglement','cond_reglement', 'cond_reglement_doc','situation_cycle_ref','situation_counter','situation_final','multicurrency_total_ht','multicurrency_total_tva', - 'multicurrency_total_ttc','fk_multicurrency','multicurrency_code','multicurrency_tx' + 'multicurrency_total_ttc','fk_multicurrency','multicurrency_code','multicurrency_tx', + 'retained_warranty' ,'retained_warranty_date_limit', 'retained_warranty_fk_cond_reglement' ) ); $this->assertEquals($arraywithdiff, array()); // Actual, Expected