diff --git a/htdocs/admin/fckeditor.php b/htdocs/admin/fckeditor.php index d046d206fbf..c2c49eb4943 100644 --- a/htdocs/admin/fckeditor.php +++ b/htdocs/admin/fckeditor.php @@ -1,7 +1,8 @@ * Copyright (C) 2005-2012 Regis Houssin - * Copyright (C) 2012-20113 Juanjo Menent + * Copyright (C) 2012-2013 Juanjo Menent + * Copyright (C) 2019 Christophe Battarel * * 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 @@ -49,7 +50,8 @@ $modules = array( 'DETAILS' => 'FCKeditorForProductDetails', 'USERSIGN' => 'FCKeditorForUserSignature', 'MAILING' => 'FCKeditorForMailing', -'MAIL' => 'FCKeditorForMail' +'MAIL' => 'FCKeditorForMail', +'TICKET' => 'FCKeditorForTicket' ); // Conditions pour que l'option soit proposee $conditions = array( @@ -58,7 +60,8 @@ $conditions = array( 'DETAILS' => (! empty($conf->facture->enabled) || ! empty($conf->propal->enabled) || ! empty($conf->commande->enabled) || ! empty($conf->supplier_proposal->enabled) || ! empty($conf->fournisseur->enabled)), 'USERSIGN' => 1, 'MAILING' => ! empty($conf->mailing->enabled), -'MAIL' => (! empty($conf->facture->enabled) || ! empty($conf->propal->enabled) || ! empty($conf->commande->enabled)) +'MAIL' => (! empty($conf->facture->enabled) || ! empty($conf->propal->enabled) || ! empty($conf->commande->enabled)), +'TICKET' => ! empty($conf->ticket->enabled) ); // Picto $picto = array( @@ -67,7 +70,8 @@ $picto = array( 'DETAILS' => 'product', 'USERSIGN' => 'user', 'MAILING' => 'email', -'MAIL' => 'email' +'MAIL' => 'email', +'TICKET' => 'ticket' ); diff --git a/htdocs/bookmarks/bookmarks.lib.php b/htdocs/bookmarks/bookmarks.lib.php index 5ce2f782d39..1e54cc816fd 100644 --- a/htdocs/bookmarks/bookmarks.lib.php +++ b/htdocs/bookmarks/bookmarks.lib.php @@ -150,3 +150,140 @@ function printBookmarksList($aDb, $aLangs) return $ret; } + + + +/** + * Add area with bookmarks in top menu + * + * @param DoliDb $aDb Database handler + * @param Translate $aLangs Object lang + * @return string + */ +function printDropdownBookmarksList($aDb, $aLangs) +{ + global $conf, $user; + + $db = $aDb; + $langs = $aLangs; + + require_once DOL_DOCUMENT_ROOT.'/bookmarks/class/bookmark.class.php'; + if (! isset($conf->global->BOOKMARKS_SHOW_IN_MENU)) $conf->global->BOOKMARKS_SHOW_IN_MENU=5; + + $langs->load("bookmarks"); + + $url= $_SERVER["PHP_SELF"]; + + if (! empty($_SERVER["QUERY_STRING"])) + { + $url.=(dol_escape_htmltag($_SERVER["QUERY_STRING"])?'?'.dol_escape_htmltag($_SERVER["QUERY_STRING"]):''); + } + else + { + global $sortfield,$sortorder; + $tmpurl=''; + // No urlencode, all param $url will be urlencoded later + if ($sortfield) $tmpurl.=($tmpurl?'&':'').'sortfield='.$sortfield; + if ($sortorder) $tmpurl.=($tmpurl?'&':'').'sortorder='.$sortorder; + if (is_array($_POST)) + { + foreach($_POST as $key => $val) + { + if (preg_match('/^search_/', $key) && $val != '') $tmpurl.=($tmpurl?'&':'').$key.'='.$val; + } + } + $url.=($tmpurl?'?'.$tmpurl:''); + } + + $searchForm = ''."\n"; + $searchForm.= '
'; + $searchForm.= ''; + $searchForm.= '
'; + + // Url to list bookmark + $listbtn = ''; + $listbtn.= ' '.$langs->trans('Bookmarks').''; + + // Url to go on create new bookmark page + $newbtn = ''; + if (! empty($user->rights->bookmark->creer)) + { + //$urltoadd=DOL_URL_ROOT.'/bookmarks/card.php?action=create&urlsource='.urlencode($url).'&url='.urlencode($url); + $urltoadd=DOL_URL_ROOT.'/bookmarks/card.php?action=create&url='.urlencode($url); + $newbtn.= ''; + $newbtn.= ' '.dol_escape_htmltag($langs->trans('AddThisPageToBookmarks')).''; + } + + + $bookmarkList=''; + + $html= ''; + if (! empty($conf->global->BOOKMARKS_SHOW_IN_MENU)) { + $html.= ' + + + '; + } + + $html.= ' + + + '; + + $html.= ' + + + '; + + if (! empty($conf->global->BOOKMARKS_SHOW_IN_MENU)) { + $html .= ''; + } + + return $html; +} diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index b97ffc5fd28..ba5d2f37293 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -242,7 +242,7 @@ class FormTicket } include_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php'; $uselocalbrowser = true; - $doleditor = new DolEditor('message', $msg, '100%', 230, $toolbarname, 'In', true, $uselocalbrowser); + $doleditor = new DolEditor('message', $msg, '100%', 230, $toolbarname, 'In', true, $uselocalbrowser, $conf->global->FCKEDITOR_ENABLE_TICKET); $doleditor->Create(); print ''; diff --git a/htdocs/core/class/translate.class.php b/htdocs/core/class/translate.class.php index 8f9dc32901d..3780ab35b06 100644 --- a/htdocs/core/class/translate.class.php +++ b/htdocs/core/class/translate.class.php @@ -781,6 +781,8 @@ class Translate if (preg_match('/^[a-z]+_[A-Z]+/i', $dir)) { $this->load("languages"); + + if (! empty($conf->global->MAIN_LANGUAGES_ALLOWED) && ! in_array($dir, explode(',', $conf->global->MAIN_LANGUAGES_ALLOWED)) ) continue; if ($usecode == 2) { diff --git a/htdocs/core/lib/pdf.lib.php b/htdocs/core/lib/pdf.lib.php index 72a44d9267e..d16fc569961 100644 --- a/htdocs/core/lib/pdf.lib.php +++ b/htdocs/core/lib/pdf.lib.php @@ -935,6 +935,11 @@ function pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_ { $line1.=($line1?" ":"").$fromcompany->town; } + // Country + if ($fromcompany->country) + { + $line1.=($line1?", ":"").$fromcompany->country; + } // Phone if ($fromcompany->phone) { diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index ff60f7fe638..dbf56429086 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -958,7 +958,7 @@ function print_left_eldy_menu($db, $menu_array_before, $menu_array_after, &$tabM $newmenu->add("/fichinter/index.php?leftmenu=ficheinter", $langs->trans("Interventions"), 0, $user->rights->ficheinter->lire, '', $mainmenu, 'ficheinter', 2200); $newmenu->add("/fichinter/card.php?action=create&leftmenu=ficheinter", $langs->trans("NewIntervention"), 1, $user->rights->ficheinter->creer, '', '', '', 201); $newmenu->add("/fichinter/list.php?leftmenu=ficheinter", $langs->trans("List"), 1, $user->rights->ficheinter->lire, '', '', '', 202); - if ($conf->global->MAIN_FEATURES_LEVEL >= 2) $newmenu->add("/fichinter/card-rec.php?leftmenu=ficheinter", $langs->trans("ModelList"), 1, $user->rights->ficheinter->lire, '', '', '', 203); + if ($conf->global->MAIN_FEATURES_LEVEL >= 2) $newmenu->add("/fichinter/card-rec.php?leftmenu=ficheinter", $langs->trans("ListOfTemplates"), 1, $user->rights->ficheinter->lire, '', '', '', 203); $newmenu->add("/fichinter/stats/index.php?leftmenu=ficheinter", $langs->trans("Statistics"), 1, $user->rights->fournisseur->commande->lire); } } diff --git a/htdocs/fichinter/card-rec.php b/htdocs/fichinter/card-rec.php index a80df96fe50..5c4b74a04e6 100644 --- a/htdocs/fichinter/card-rec.php +++ b/htdocs/fichinter/card-rec.php @@ -164,8 +164,9 @@ if ($action == 'add') { $newinter->fk_projet=$object->fk_projet; $newinter->fk_project=$object->fk_projet; $newinter->fk_contrat=$object->fk_contrat; - } else + } else { $newinter->socid=GETPOST("socid"); + } $newinter->entity=$object->entity; $newinter->duree=$object->duree; @@ -184,8 +185,9 @@ if ($action == 'add') { if ($newfichinterid > 0) { // Now we add line of details - foreach ($object->lines as $ficheinterligne) - $newinter->addline($user, $newfichinterid, $ficheinterligne->desc, "", $ficheinterligne->duree, ''); + foreach ($object->lines as $line) { + $newinter->addline($user, $newfichinterid, $line->desc, '', $line->duree, ''); + } // on update le nombre d'inter crée à partir du modèle $object->updateNbGenDone(); @@ -197,7 +199,7 @@ if ($action == 'add') { $action=''; } } elseif ($action == 'delete' && $user->rights->ficheinter->supprimer) { - // delete modele + // delete modele $object->fetch($id); $object->delete(); $id = 0 ; @@ -210,13 +212,10 @@ if ($action == 'add') { } elseif ($action == 'setdate_when' && $user->rights->ficheinter->creer) { // Set next date of execution $object->fetch($id); -$date = dol_mktime( - GETPOST('date_whenhour'), GETPOST('date_whenmin'), 0, - GETPOST('date_whenmonth'), GETPOST('date_whenday'), GETPOST('date_whenyear') - ); + $date = dol_mktime(GETPOST('date_whenhour'), GETPOST('date_whenmin'), 0, GETPOST('date_whenmonth'), GETPOST('date_whenday'), GETPOST('date_whenyear')); if (!empty($date)) $object->setNextDate($date); } elseif ($action == 'setnb_gen_max' && $user->rights->ficheinter->creer) { -// Set max period + // Set max period $object->fetch($id); $object->setMaxPeriod(GETPOST('nb_gen_max', 'int')); } @@ -230,17 +229,16 @@ llxHeader('', $langs->trans("RepeatableInterventional"), 'ch-fichinter.html#s-fa $form = new Form($db); $companystatic = new Societe($db); -if (! empty($conf->contrat->enabled)) +if (! empty($conf->contrat->enabled)) { $contratstatic = new Contrat($db); -if (! empty($conf->projet->enabled)) +} +if (! empty($conf->projet->enabled)) { $projectstatic = new Project($db); +} $now = dol_now(); $tmparray=dol_getdate($now); -$today = dol_mktime( - 23, 59, 59, - $tmparray['mon'], $tmparray['mday'], $tmparray['year'] -); // Today is last second of current day +$today = dol_mktime(23, 59, 59, $tmparray['mon'], $tmparray['mday'], $tmparray['year']); // Today is last second of current day @@ -248,13 +246,13 @@ $today = dol_mktime( * Create mode */ if ($action == 'create') { - print load_fiche_titre($langs->trans("CreateRepeatableIntervention"), '', 'commercial'); + print load_fiche_titre($langs->trans("CreateRepeatableIntervention"), '', 'fichinter'); $object = new Fichinter($db); // Source invoice //$object = new Managementfichinter($db); // Source invoice if ($object->fetch($id, $ref) > 0) { - print '
'; + print ''; print ''; print ''; print ''; @@ -273,7 +271,7 @@ if ($action == 'create') { print ''.$langs->trans("Customer").''; print $form->select_company($object->thirdparty->id, 'socid', '', 0, 1); -// .$object->thirdparty->getNomUrl(1,'customer'). + //.$object->thirdparty->getNomUrl(1,'customer'). print ''; print $langs->trans("Comment"); print ''; @@ -295,10 +293,7 @@ if ($action == 'create') { if (empty($conf->global->FICHINTER_DISABLE_DETAILS)) { // Duration print ''.$langs->trans("TotalDuration").''; -print ''.convertSecondToTime( - $object->duration, 'all', - $conf->global->MAIN_DURATION_OF_WORKDAY - ).''; + print ''.convertSecondToTime($object->duration, 'all', $conf->global->MAIN_DURATION_OF_WORKDAY).''; print ''; } @@ -308,10 +303,7 @@ print ''.convertSecondToTime( print "".$langs->trans("Project").""; $projectid = GETPOST('projectid')?GETPOST('projectid'):$object->fk_project; -$numprojet = $formproject->select_projects( - $object->thirdparty->id, $projectid, 'projectid', - 0, 0, 1, 0, 0, 0, 0, '', 0, 0, '' - ); + $numprojet = $formproject->select_projects($object->thirdparty->id, $projectid, 'projectid', 0, 0, 1, 0, 0, 0, 0, '', 0, 0, ''); print '   '; @@ -342,26 +334,21 @@ $numprojet = $formproject->select_projects( print ''; print $form->textwithpicto($langs->trans("Frequency"), $langs->transnoentitiesnoconv('toolTipFrequency')); print ""; - print " "; -print $form->selectarray( - 'unit_frequency', - array('d'=>$langs->trans('Day'), 'm'=>$langs->trans('Month'), 'y'=>$langs->trans('Year')), - (GETPOST('unit_frequency')?GETPOST('unit_frequency'):'m') - ); + print ' '; + print $form->selectarray('unit_frequency', array('d'=>$langs->trans('Day'), 'm'=>$langs->trans('Month'), 'y'=>$langs->trans('Year')), (GETPOST('unit_frequency')?GETPOST('unit_frequency'):'m')); print ""; // First date of execution for cron print "".$langs->trans('NextDateToExecution').""; - if ($date_next_execution != "") -$date_next_execution = (GETPOST('remonth') ? dol_mktime( - 12, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear') - ) : -1); + if ($date_next_execution != "") { + $date_next_execution = (GETPOST('remonth') ? dol_mktime(12, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear')) : -1); + } print $form->selectDate($date_next_execution, '', 1, 1, '', "add", 1, 1); print ""; // Number max of generation print "".$langs->trans("MaxPeriodNumber").""; - print ''; + print ''; print ""; print ""; @@ -369,29 +356,31 @@ $date_next_execution = (GETPOST('remonth') ? dol_mktime( print '
'; $title = $langs->trans("ProductsAndServices"); - if (empty($conf->service->enabled)) + if (empty($conf->service->enabled)) { $title = $langs->trans("Products"); - elseif (empty($conf->product->enabled)) + } elseif (empty($conf->product->enabled)) { $title = $langs->trans("Services"); + } print load_fiche_titre($title, '', ''); /* - * Invoice lines + * Fichinter lines */ print ''; print ''; @@ -436,8 +426,9 @@ $date_next_execution = (GETPOST('remonth') ? dol_mktime( print ''; print "\n"; } - else - dol_print_error('', "Error, no invoice ".$object->id); + else { + dol_print_error('', "Error, no fichinter ".$object->id); + } } elseif ($action == 'selsocforcreatefrommodel') { print load_fiche_titre($langs->trans("CreateRepeatableIntervention"), '', 'commercial'); dol_fiche_head(''); @@ -492,32 +483,25 @@ $date_next_execution = (GETPOST('remonth') ? dol_mktime( $morehtmlref.=img_edit($langs->transnoentitiesnoconv('SetProject')).' : '; } if ($action == 'classify') { - - $morehtmlref.=''; - $morehtmlref.=''; - $morehtmlref.=''; - $morehtmlref.=$formproject->select_projects( - $object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1 - ); - $morehtmlref.=''; - $morehtmlref.=''; + $morehtmlref.= ''; + $morehtmlref.= ''; + $morehtmlref.= ''; + $morehtmlref.= $formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref.= ''; + $morehtmlref.= ''; } else { - $morehtmlref.=$form->form_project( - $_SERVER['PHP_SELF'].'?id='.$object->id, - $object->socid, $object->fk_project, - 'none', 0, 0, 0, 1 - ); + $morehtmlref.= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); } } else { if (! empty($object->fk_project)) { $proj = new Project($db); $proj->fetch($object->fk_project); - $morehtmlref.='trans('ShowProject').'">'; - $morehtmlref.=$proj->ref; - $morehtmlref.=''; + $morehtmlref.= 'trans('ShowProject').'">'; + $morehtmlref.= $proj->ref; + $morehtmlref.= ''; } else { - $morehtmlref.=''; + $morehtmlref.= ''; } } } @@ -605,12 +589,8 @@ $date_next_execution = (GETPOST('remonth') ? dol_mktime( print ''; print '
'; - $sql = 'SELECT l.*'; + $sql = 'SELECT l.rowid, l.description, l.duree'; $sql.= " FROM ".MAIN_DB_PREFIX."fichinterdet as l"; $sql.= " WHERE l.fk_fichinter= ".$object->id; - $sql.= " AND l.fk_product is null "; + //$sql.= " AND l.fk_product is null "; $sql.= " ORDER BY l.rang"; $result = $db->query($sql); if ($result) { $num = $db->num_rows($result); - $i = 0; $total = 0; + $i = 0; + $total = 0; echo ''; if ($num) { @@ -413,15 +402,16 @@ $date_next_execution = (GETPOST('remonth') ? dol_mktime( print $text.' '.nl2br($objp->description); - // Qty + // Duration print ''; print ""; $i++; } $db->free($result); - } else + } else { print $db->error(); + } print "
'.convertSecondToTime($objp->duree).'
"; print '
'; print ''; print ''; print '
'; - print " "; - print $form->selectarray( - 'unit_frequency', - array('d'=>$langs->trans('Day'), 'm'=>$langs->trans('Month'), 'y'=>$langs->trans('Year')), - ($object->unit_frequency?$object->unit_frequency:'m') - ); + print ' '; + print $form->selectarray('unit_frequency', array('d'=>$langs->trans('Day'), 'm'=>$langs->trans('Month'), 'y'=>$langs->trans('Year')), ($object->unit_frequency?$object->unit_frequency:'m')); print '
'; @@ -625,19 +605,13 @@ $date_next_execution = (GETPOST('remonth') ? dol_mktime( // Date when print ''; if ( $user->rights->ficheinter->creer && ($action == 'date_when' || $object->frequency > 0)) { - print $form->editfieldkey( - $langs->trans("NextDateToExecution"), 'date_when', $object->date_when, - $object, $user->rights->facture->creer, 'day' - ); + print $form->editfieldkey($langs->trans("NextDateToExecution"), 'date_when', $object->date_when, $object, $user->rights->facture->creer, 'day'); } else { print $langs->trans("NextDateToExecution"); } print ''; if ($action == 'date_when' || $object->frequency > 0) { - print $form->editfieldval( - $langs->trans("NextDateToExecution"), 'date_when', $object->date_when, - $object, $user->rights->facture->creer, 'day' - ); + print $form->editfieldval($langs->trans("NextDateToExecution"), 'date_when', $object->date_when, $object, $user->rights->facture->creer, 'day'); } print ''; print ''; @@ -645,19 +619,13 @@ $date_next_execution = (GETPOST('remonth') ? dol_mktime( // Max period / Rest period print ''; if ($user->rights->ficheinter->creer && ($action == 'nb_gen_max' || $object->frequency > 0)) { - print $form->editfieldkey( - $langs->trans("MaxPeriodNumber"), 'nb_gen_max', $object->nb_gen_max, - $object, $user->rights->facture->creer - ); + print $form->editfieldkey($langs->trans("MaxPeriodNumber"), 'nb_gen_max', $object->nb_gen_max, $object, $user->rights->facture->creer); } else print $langs->trans("MaxPeriodNumber"); print ''; if ($action == 'nb_gen_max' || $object->frequency > 0) { - print $form->editfieldval( - $langs->trans("MaxPeriodNumber"), 'nb_gen_max', $object->nb_gen_max?$object->nb_gen_max:'', - $object, $user->rights->facture->creer - ); + print $form->editfieldval($langs->trans("MaxPeriodNumber"), 'nb_gen_max', $object->nb_gen_max?$object->nb_gen_max:'', $object, $user->rights->facture->creer); } else print ''; @@ -671,10 +639,7 @@ $date_next_execution = (GETPOST('remonth') ? dol_mktime( if ($object->frequency > 0) { print '
'; if (empty($conf->cron->enabled)) { - $txtinfoadmin=$langs->trans( - "EnableAndSetupModuleCron", - $langs->transnoentitiesnoconv("Module2300Name") - ); + $txtinfoadmin = $langs->trans("EnableAndSetupModuleCron", $langs->transnoentitiesnoconv("Module2300Name")); print info_admin($txtinfoadmin); } print '
'; @@ -709,10 +674,11 @@ $date_next_execution = (GETPOST('remonth') ? dol_mktime( */ $title = $langs->trans("ProductsAndServices"); - if (empty($conf->service->enabled)) + if (empty($conf->service->enabled)) { $title = $langs->trans("Products"); - elseif (empty($conf->product->enabled)) + } elseif (empty($conf->product->enabled)) { $title = $langs->trans("Services"); + } print load_fiche_titre($title); @@ -850,8 +816,9 @@ $date_next_execution = (GETPOST('remonth') ? dol_mktime( $companystatic->id=$objp->socid; $companystatic->name=$objp->name; print ''.$companystatic->getNomUrl(1, 'customer').''; - } else + } else { print ''.$langs->trans("None").''; + } if (! empty($conf->contrat->enabled)) { print ''; @@ -916,13 +883,15 @@ $date_next_execution = (GETPOST('remonth') ? dol_mktime( $i++; } } - } else - print ''.$langs->trans("NoneF").''; + } else { + print ''.$langs->trans("NoneF").''; + } print ""; $db->free($resql); - } else + } else { dol_print_error($db); + } } } llxFooter(); diff --git a/htdocs/fichinter/card.php b/htdocs/fichinter/card.php index afbf55c409e..6943b5335f7 100644 --- a/htdocs/fichinter/card.php +++ b/htdocs/fichinter/card.php @@ -1645,11 +1645,10 @@ elseif ($id > 0 || ! empty($ref)) else print ''; } - // create intervention model - if ($conf->global->MAIN_FEATURE_LEVEL >=2 && $object->statut == Fichinter::STATUS_DRAFT && $user->rights->ficheinter->creer && (count($object->lines) > 0)) { + // create intervention model + if ($conf->global->MAIN_FEATURES_LEVEL >=2 && $object->statut == Fichinter::STATUS_DRAFT && $user->rights->ficheinter->creer && (count($object->lines) > 0)) { print '
'; - // This feature is not yet implemented - print ''.$langs->trans("ChangeIntoRepeatableIntervention").''; + print ''.$langs->trans("ChangeIntoRepeatableIntervention").''; print '
'; } diff --git a/htdocs/fichinter/class/fichinterrec.class.php b/htdocs/fichinter/class/fichinterrec.class.php new file mode 100644 index 00000000000..4fabf64be49 --- /dev/null +++ b/htdocs/fichinter/class/fichinterrec.class.php @@ -0,0 +1,814 @@ + + * Copyright (C) 2004-2015 Laurent Destailleur + * Copyright (C) 2009-2012 Regis Houssin + * Copyright (C) 2010-2011 Juanjo Menent + * Copyright (C) 2012 Cedric Salvador + * Copyright (C) 2013 Florian Henry + * Copyright (C) 2015 Marcos García + * Copyright (C) 2016-2018 Charlie Benke + * + * 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 fichinterrec/class/fichinter-rec.class.php + * \ingroup facture + * \brief Fichier de la classe des factures recurentes + */ + +require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php'; +require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; +require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php'; + + +/** + * Classe de gestion des factures recurrentes/Modeles + */ +class FichinterRec extends Fichinter +{ + public $element = 'fichinterrec'; + public $table_element = 'fichinter_rec'; + public $table_element_line = 'fichinter_rec'; + public $fk_element = 'fk_fichinter'; + public $picto = 'intervention'; + + public $title; + public $number; + public $date; + public $amount; + public $remise; + public $tva; + public $total; + public $db_table; + public $propalid; + + public $date_last_gen; + public $date_when; + public $nb_gen_done; + public $nb_gen_max; + + public $rang; + public $special_code; + + public $usenewprice = 0; + + /** + * Constructor + * + * @param DoliDB $db Database handler + */ + public function __construct($db) + { + $this->db = $db; + + //status dans l'ordre de l'intervention + $this->statuts[0]='Draft'; + $this->statuts[1]='Closed'; + + $this->statuts_short[0]='Draft'; + $this->statuts_short[1]='Closed'; + + $this->statuts_logo[0]='statut0'; + $this->statuts_logo[1]='statut1'; + } + + /** + * Returns the label status + * + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto + * @return string Label + */ + public function getLibStatut($mode = 0) + { + return $this->LibStatut($this->statut, $mode); + } + + + /** + * Create a predefined fichinter + * + * @param User $user User object + * @param int $notrigger no trigger + * @return int <0 if KO, id of fichinter if OK + */ + public function create($user, $notrigger = 0) + { + global $conf; + + $error=0; + $now=dol_now(); + + // Clean parameters + $this->title = trim($this->title); + $this->description = trim($this->description); + + + $this->db->begin(); + + // Load fichinter model + $fichintsrc = new Fichinter($this->db); + + $result = $fichintsrc->fetch($this->id_origin); + $result = $fichintsrc->fetch_lines(1); // to get all lines + + + if ($result > 0) { + // On positionne en mode brouillon la facture + $this->brouillon = 1; + + $sql = "INSERT INTO ".MAIN_DB_PREFIX."fichinter_rec ("; + $sql.= "titre"; + $sql.= ", fk_soc"; + $sql.= ", entity"; + $sql.= ", datec"; + $sql.= ", duree"; + $sql.= ", description"; + $sql.= ", note_private"; + $sql.= ", note_public"; + $sql.= ", fk_user_author"; + $sql.= ", fk_projet"; + $sql.= ", fk_contrat"; + $sql.= ", modelpdf"; + + $sql.= ", frequency"; + $sql.= ", unit_frequency"; + $sql.= ", date_when"; + $sql.= ", date_last_gen"; + $sql.= ", nb_gen_done"; + $sql.= ", nb_gen_max"; + // $sql.= ", auto_validate"; + + $sql.= ") VALUES ("; + $sql.= "'".$this->db->escape($this->title)."'"; + $sql.= ", ".($this->socid >0 ? $this->socid : 'null'); + $sql.= ", ".$conf->entity; + $sql.= ", '".$this->db->idate($now)."'"; + $sql.= ", ".(!empty($fichintsrc->duree)?$fichintsrc->duree:'0'); + $sql.= ", ".(!empty($this->description)?("'".$this->db->escape($this->description)."'"):"null"); + $sql.= ", ".(!empty($fichintsrc->note_private)?("'".$this->db->escape($fichintsrc->note_private)."'"):"null"); + $sql.= ", ".(!empty($fichintsrc->note_public)?("'".$this->db->escape($fichintsrc->note_public)."'"):"null"); + $sql.= ", '".$user->id."'"; + // si c'est la même société on conserve les liens vers le projet et le contrat + if ($this->socid == $fichintsrc->socid) { + $sql.= ", ".(! empty($fichintsrc->fk_project)?$fichintsrc->fk_project:"null"); + $sql.= ", ".(! empty($fichintsrc->fk_contrat)?$fichintsrc->fk_contrat:"null"); + } else { + $sql.= ", null, null"; + } + + $sql.= ", ".(! empty($fichintsrc->modelpdf)?"'".$this->db->escape($fichintsrc->modelpdf)."'":"''"); + + // récurrence + $sql.= ", ".(! empty($this->frequency)?$this->frequency:"null"); + $sql.= ", '".$this->db->escape($this->unit_frequency)."'"; + $sql.= ", ".(!empty($this->date_when)?"'".$this->db->idate($this->date_when)."'":'null'); + $sql.= ", ".(!empty($this->date_last_gen)?"'".$this->db->idate($this->date_last_gen)."'":'null'); + $sql.= ", 0"; // we start à 0 + $sql.= ", ".$this->nb_gen_max; + // $sql.= ", ".$this->auto_validate; + $sql.= ")"; + + if ($this->db->query($sql)) { + $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element); + + /* + * Lines + */ + $num=count($fichintsrc->lines); + for ($i = 0; $i < $num; $i++) { + //$result=$fichintlignesrc->fetch($fichintsrc->lines[$i]->id); + + //var_dump($fichintsrc->lines[$i]); + $result_insert = $this->addline( + $fichintsrc->lines[$i]->desc, + $fichintsrc->lines[$i]->duration, + $fichintsrc->lines[$i]->datei, + $fichintsrc->lines[$i]->rang, + $fichintsrc->lines[$i]->subprice, + $fichintsrc->lines[$i]->qty, + $fichintsrc->lines[$i]->tva_tx, + $fichintsrc->lines[$i]->fk_product, + $fichintsrc->lines[$i]->remise_percent, + 'HT', + 0, + '', + 0, + $fichintsrc->lines[$i]->product_type, + $fichintsrc->lines[$i]->special_code, + $fichintsrc->lines[$i]->label, + $fichintsrc->lines[$i]->fk_unit + ); + + if ($result_insert < 0) + $error++; + } + + if ($error) + $this->db->rollback(); + else { + $this->db->commit(); + return $this->id; + } + } else { + $this->error=$this->db->error().' sql='.$sql; + $this->db->rollback(); + return -2; + } + } else { + $this->db->rollback(); + return -1; + } + } + + + /** + * Recupere l'objet facture et ses lignes de factures + * + * @param int $rowid Id of object to load + * @param string $ref Reference of fichinter + * @param string $ref_ext External reference of fichinter + * @param int $ref_int Internal reference of other object + * @return int >0 if OK, <0 if KO, 0 if not found + */ + public function fetch($rowid = 0, $ref = '', $ref_ext = '', $ref_int = '') + { + $sql = 'SELECT f.titre, f.fk_soc'; + $sql.= ', f.datec, f.duree, f.fk_projet, f.fk_contrat, f.description'; + $sql.= ', f.note_private, f.note_public, f.fk_user_author'; + $sql.= ', f.frequency, f.unit_frequency, f.date_when, f.date_last_gen, f.nb_gen_done, f.nb_gen_max, f.auto_validate'; + $sql.= ', f.note_private, f.note_public, f.fk_user_author'; + + $sql.= ' FROM '.MAIN_DB_PREFIX.'fichinter_rec as f'; + if ($rowid >0 ) $sql.= ' WHERE f.rowid='.$rowid; + elseif ($ref) $sql.= " WHERE f.titre='".$this->db->escape($ref)."'"; + + /* This field are not used for template fichinter + if ($ref_ext) $sql.= " AND f.ref_ext='".$this->db->escape($ref_ext)."'"; + if ($ref_int) $sql.= " AND f.ref_int='".$this->db->escape($ref_int)."'"; + */ + + dol_syslog(get_class($this)."::fetch rowid=".$rowid, LOG_DEBUG); + + $result = $this->db->query($sql); + if ($result) { + if ($this->db->num_rows($result)) { + $obj = $this->db->fetch_object($result); + + $this->id = $rowid; + $this->titre = $obj->titre; + $this->ref = $obj->titre; + $this->description = $obj->description; + $this->datec = $obj->datec; + $this->socid = $obj->fk_soc; + $this->statut = 0; + $this->fk_project = $obj->fk_projet; + $this->fk_contrat = $obj->fk_contrat; + $this->note_private = $obj->note_private; + $this->note_public = $obj->note_public; + $this->user_author = $obj->fk_user_author; + $this->modelpdf = $obj->model_pdf; + $this->rang = $obj->rang; + $this->special_code = $obj->special_code; + $this->frequency = $obj->frequency; + $this->unit_frequency = $obj->unit_frequency; + $this->date_when = $this->db->jdate($obj->date_when); + $this->date_last_gen = $this->db->jdate($obj->date_last_gen); + $this->nb_gen_done = $obj->nb_gen_done; + $this->nb_gen_max = $obj->nb_gen_max; + $this->auto_validate = $obj->auto_validate; + + $this->brouillon = 1; + + /* + * Lines + */ + $result=$this->fetch_lines(); + if ($result < 0) { + $this->error=$this->db->error(); + return -3; + } + return 1; + } else { + $this->error='Interventional with id '.$rowid.' not found sql='.$sql; + dol_syslog(get_class($this).'::Fetch Error '.$this->error, LOG_ERR); + return -2; + } + } else { + $this->error=$this->db->error(); + return -1; + } + } + + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Recupere les lignes de factures predefinies dans this->lines + * @param int $sall sall + * + * @return int 1 if OK, < 0 if KO + */ + public function fetch_lines($sall = 0) + { + // phpcs:enable + $sql = 'SELECT l.rowid, l.fk_product, l.product_type, l.label as custom_label, l.description, '; + $sql.= ' l.price, l.qty, l.tva_tx, l.remise, l.remise_percent, l.subprice, l.duree, '; + $sql.= ' l.total_ht, l.total_tva, l.total_ttc,'; + $sql.= ' l.rang, l.special_code,'; + $sql.= ' l.fk_unit, p.ref as product_ref, p.fk_product_type as fk_product_type,'; + $sql.= ' p.label as product_label, p.description as product_desc'; + $sql.= ' FROM '.MAIN_DB_PREFIX.'fichinterdet_rec as l'; + $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON l.fk_product = p.rowid'; + $sql.= ' WHERE l.fk_fichinter = '.$this->id; + + dol_syslog('FichInter-rec::fetch_lines', LOG_DEBUG); + $result = $this->db->query($sql); + if ($result) { + $num = $this->db->num_rows($result); + $i = 0; + while ($i < $num) { + $objp = $this->db->fetch_object($result); + $line = new FichinterLigne($this->db); + + $line->rowid = $objp->rowid; + $line->label = $objp->custom_label; // Label line + $line->desc = $objp->description; // Description line + $line->product_type = $objp->product_type; // Type of line + $line->product_ref = $objp->product_ref; // Ref product + $line->libelle = $objp->product_label; // deprecated + $line->product_label = $objp->product_label; // Label product + $line->product_desc = $objp->product_desc; // Description product + $line->fk_product_type = $objp->fk_product_type; // Type of product + $line->qty = $objp->qty; + $line->duree = $objp->duree; + $line->duration = $objp->duree; + $line->datei = $objp->date; + $line->subprice = $objp->subprice; + $line->tva_tx = $objp->tva_tx; + $line->remise_percent = $objp->remise_percent; + $line->fk_remise_except = $objp->fk_remise_except; + $line->fk_product = $objp->fk_product; + $line->date_start = $objp->date_start; + $line->date_end = $objp->date_end; + $line->date_start = $objp->date_start; + $line->date_end = $objp->date_end; + $line->info_bits = $objp->info_bits; + $line->total_ht = $objp->total_ht; + $line->total_tva = $objp->total_tva; + $line->total_ttc = $objp->total_ttc; + $line->code_ventilation = $objp->fk_code_ventilation; + $line->rang = $objp->rang; + $line->special_code = $objp->special_code; + $line->fk_unit = $objp->fk_unit; + + // Ne plus utiliser + $line->price = $objp->price; + $line->remise = $objp->remise; + + $this->lines[$i] = $line; + + $i++; + } + + $this->db->free($result); + return 1; + } else { + $this->error=$this->db->error(); + return -3; + } + } + + + /** + * Delete template fichinter rec + * + * @param int $rowid Id of fichinter rec to delete. If empty, we delete current instance of fichinter rec + * @param int $notrigger 1=Does not execute triggers, 0= execute triggers + * @param int $idwarehouse Id warehouse to use for stock change. + * @return int <0 if KO, >0 if OK + */ + public function delete($rowid = 0, $notrigger = 0, $idwarehouse = -1) + { + if (empty($rowid)) $rowid=$this->id; + + dol_syslog(get_class($this)."::delete rowid=".$rowid, LOG_DEBUG); + + $error=0; + $this->db->begin(); + + $sql = "DELETE FROM ".MAIN_DB_PREFIX."fichinterdet_rec WHERE fk_fichinter = ".$rowid; + dol_syslog($sql); + if ($this->db->query($sql)) { + $sql = "DELETE FROM ".MAIN_DB_PREFIX."fichinter_rec WHERE rowid = ".$rowid; + dol_syslog($sql); + if (! $this->db->query($sql)) { + $this->error=$this->db->lasterror(); + $error=-1; + } + } else { + $this->error=$this->db->lasterror(); + $error=-2; + } + + if (! $error) { + $this->db->commit(); + return 1; + } else { + $this->db->rollback(); + return $error; + } + } + + + /** + * Add a line to fichinter rec + * + * @param string $desc Description de la ligne + * @param integer $duration Durée + * @param string $datei Date + * @param int $rang Position of line + * @param double $pu_ht Prix unitaire HT (> 0 even for credit note) + * @param double $qty Quantite + * @param double $txtva Taux de tva force, sinon -1 + * @param int $fk_product Id du produit/service predefini + * @param double $remise_percent Pourcentage de remise de la ligne + * @param string $price_base_type HT or TTC + * @param int $info_bits Bits de type de lignes + * @param int $fk_remise_except Id remise + * @param double $pu_ttc Prix unitaire TTC (> 0 even for credit note) + * @param int $type Type of line (0=product, 1=service) + * @param int $special_code Special code + * @param string $label Label of the line + * @param string $fk_unit Unit + * @return int <0 if KO, Id of line if OK + */ + public function addline($desc, $duration, $datei, $rang = -1, $pu_ht = 0, $qty = 0, $txtva = 0, $fk_product = 0, $remise_percent = 0, $price_base_type = 'HT', $info_bits = 0, $fk_remise_except = '', $pu_ttc = 0, $type = 0, $special_code = 0, $label = '', $fk_unit = null) + { + global $mysoc; + + include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php'; + + // Check parameters + if ($type < 0) return -1; + + if ($this->brouillon) { + // Clean parameters + $remise_percent = price2num($remise_percent); + $qty = price2num($qty); + if (! $qty) $qty=1; + if (! $info_bits) $info_bits=0; + $pu_ht = price2num($pu_ht); + $pu_ttc = price2num($pu_ttc); + $txtva = price2num($txtva); + + if ($price_base_type=='HT') { + $pu=$pu_ht; + } else { + $pu=$pu_ttc; + } + + + // Calcul du total TTC et de la TVA pour la ligne a partir de + // qty, pu, remise_percent et txtva + // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker + // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva. + $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, 0, 0, 0, $price_base_type, $info_bits, $type, $mysoc); + + $total_ht = $tabprice[0]; + $total_tva = $tabprice[1]; + $total_ttc = $tabprice[2]; + + $product_type = $type; + if ($fk_product) { + $product = new Product($this->db); + $result = $product->fetch($fk_product); + $product_type = $product->type; + } + + $sql = "INSERT INTO ".MAIN_DB_PREFIX."fichinterdet_rec ("; + $sql.= "fk_fichinter"; + $sql.= ", label"; + $sql.= ", description"; + $sql.= ", date"; + $sql.= ", duree"; + //$sql.= ", price"; + //$sql.= ", qty"; + //$sql.= ", tva_tx"; + $sql.= ", fk_product"; + $sql.= ", product_type"; + $sql.= ", remise_percent"; + //$sql.= ", subprice"; + $sql.= ", remise"; + $sql.= ", total_ht"; + $sql.= ", total_tva"; + $sql.= ", total_ttc"; + $sql.= ", rang"; + //$sql.= ", special_code"; + $sql.= ", fk_unit"; + $sql.= ") VALUES ("; + $sql.= (int) $this->id; + $sql.= ", ".(! empty($label)?"'".$this->db->escape($label)."'":"null"); + $sql.= ", ".(! empty($desc)?"'".$this->db->escape($desc)."'":"null"); + $sql.= ", ".(! empty($datei)?"'".$this->db->idate($datei)."'":"null"); + $sql.= ", ".$duration; + //$sql.= ", ".price2num($pu_ht); + //$sql.= ", ".(!empty($qty)? $qty :(!empty($duration)? $duration :"null")); + //$sql.= ", ".price2num($txtva); + $sql.= ", ".(! empty($fk_product)? $fk_product :"null"); + $sql.= ", ".$product_type; + $sql.= ", ".(! empty($remise_percent)? $remise_percent:"null"); + //$sql.= ", '".price2num($pu_ht)."'"; + $sql.= ", null"; + $sql.= ", '".price2num($total_ht)."'"; + $sql.= ", '".price2num($total_tva)."'"; + $sql.= ", '".price2num($total_ttc)."'"; + $sql.= ", ".(int) $rang; + //$sql.= ", ".$special_code; + $sql.= ", ".(! empty($fk_unit) ? $fk_unit :"null"); + $sql.= ")"; + + dol_syslog(get_class($this)."::addline", LOG_DEBUG); + if ($this->db->query($sql)) { + return 1; + } else { + $this->error=$this->db->lasterror(); + return -1; + } + } + } + + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Rend la fichinter automatique + * + * @param User $user User object + * @param int $freq Freq + * @param string $courant Courant + * @return int 0 if OK, <0 if KO + */ + public function set_auto($user, $freq, $courant) + { + // phpcs:enable + if ($user->rights->fichinter->creer) { + $sql = "UPDATE ".MAIN_DB_PREFIX."fichinter_rec "; + $sql .= " SET frequency='".$this->db->escape($freq)."'"; + $sql .= ", last_gen='".$this->db->escape($courant)."'"; + $sql .= " WHERE rowid = ".$this->id; + + $resql = $this->db->query($sql); + + if ($resql) { + $this->frequency = $freq; + $this->last_gen = $courant; + return 0; + } else { + dol_print_error($this->db); + return -1; + } + } else { + return -2; + } + } + + /** + * Return clicable name (with picto eventually) + * + * @param int $withpicto Add picto into link + * @param string $option Where point the link + * @param int $max Maxlength of ref + * @param int $short 1=Return just URL + * @param string $moretitle Add more text to title tooltip + * @return string String with URL + */ + public function getNomUrl($withpicto = 0, $option = '', $max = 0, $short = 0, $moretitle = '') + { + global $langs; + + $result=''; + $label=$langs->trans("ShowInterventionModel").': '.$this->ref; + + $url = DOL_URL_ROOT.'/fichinter/card-rec.php?id='.$this->id; + + if ($short) return $url; + + $picto='intervention'; + + $link = ''; + $linkend=''; + + if ($withpicto) { + $result.= $link.img_object($label, $picto, 'class="classfortooltip"').$linkend; + } + if ($withpicto && $withpicto != 2) { + $result.=' '; + } + if ($withpicto != 2) { + $result.=$link.$this->ref.$linkend; + } + return $result; + } + + + /** + * Initialise an instance with random values. + * Used to build previews or test instances. + * id must be 0 if object instance is a specimen. + * + * @param string $option ''=Create a specimen fichinter with lines, 'nolines'=No lines + * @return void + */ + public function initAsSpecimen($option = '') + { + global $user, $langs, $conf; + + $now=dol_now(); + $arraynow=dol_getdate($now); + $nownotime=dol_mktime(0, 0, 0, $arraynow['mon'], $arraynow['mday'], $arraynow['year']); + + parent::initAsSpecimen($option); + + $this->usenewprice = 1; + } + + /** + * Function used to replace a thirdparty id with another one. + * + * @param DoliDB $db Database handler + * @param int $origin_id Old thirdparty id + * @param int $dest_id New thirdparty id + * @return bool + */ + public static function replaceThirdparty(DoliDB $db, $origin_id, $dest_id) + { + $tables = array( 'fichinter_rec' ); + + return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables); + } + + + /** + * Update frequency and unit + * + * @param int $frequency value of frequency + * @param string $unit unit of frequency (d, m, y) + * @return int <0 if KO, >0 if OK + */ + public function setFrequencyAndUnit($frequency, $unit) + { + if (! $this->table_element) { + dol_syslog(get_class($this)."::setFrequencyAndUnit called with table_element not defined", LOG_ERR); + return -1; + } + + if (!empty($frequency) && empty($unit)) { + dol_syslog(get_class($this)."::setFrequencyAndUnit called with frequency defined but unit not ", LOG_ERR); + return -2; + } + + $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; + $sql.= ' SET frequency = '.($frequency?$this->db->escape($frequency):'null'); + if (!empty($unit)) { + $sql.= ', unit_frequency = "'.$this->db->escape($unit).'"'; + } + $sql.= ' WHERE rowid = '.$this->id; + + dol_syslog(get_class($this)."::setFrequencyAndUnit", LOG_DEBUG); + if ($this->db->query($sql)) { + $this->frequency = $frequency; + if (!empty($unit)) $this->unit_frequency = $unit; + return 1; + } else { + dol_print_error($this->db); + return -1; + } + } + + /** + * Update the next date of execution + * + * @param datetime $date date of execution + * @param int $increment_nb_gen_done 0 do nothing more, >0 increment nb_gen_done + * @return int <0 if KO, >0 if OK + */ + public function setNextDate($date, $increment_nb_gen_done = 0) + { + if (! $this->table_element) { + dol_syslog(get_class($this)."::setNextDate was called on objet with property table_element not defined", LOG_ERR); + return -1; + } + $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; + $sql.= " SET date_when = ".($date ? "'".$this->db->idate($date)."'" : "null"); + if ($increment_nb_gen_done>0) $sql.= ', nb_gen_done = nb_gen_done + 1'; + $sql.= ' WHERE rowid = '.$this->id; + + dol_syslog(get_class($this)."::setNextDate", LOG_DEBUG); + if ($this->db->query($sql)) { + $this->date_when = $date; + if ($increment_nb_gen_done>0) $this->nb_gen_done++; + return 1; + } else { + dol_print_error($this->db); + return -1; + } + } + + /** + * Update the maximum period + * + * @param int $nb number of maximum period + * @return int <0 if KO, >0 if OK + */ + public function setMaxPeriod($nb) + { + if (! $this->table_element) { + dol_syslog(get_class($this)."::setMaxPeriod was called on objet with property table_element not defined", LOG_ERR); + return -1; + } + + if (empty($nb)) $nb=0; + + $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; + $sql.= ' SET nb_gen_max = '.$nb; + $sql.= ' WHERE rowid = '.$this->id; + + dol_syslog(get_class($this)."::setMaxPeriod", LOG_DEBUG); + if ($this->db->query($sql)) { + $this->nb_gen_max = $nb; + return 1; + } else { + dol_print_error($this->db); + return -1; + } + } + + /** + * Update the auto validate fichinter + * + * @param int $validate 0 to create in draft, 1 to create and validate fichinter + * @return int <0 if KO, >0 if OK + */ + public function setAutoValidate($validate) + { + if (! $this->table_element) { + dol_syslog(get_class($this)."::setAutoValidate called with property table_element not defined", LOG_ERR); + return -1; + } + + $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; + $sql.= ' SET auto_validate = '.$validate; + $sql.= ' WHERE rowid = '.$this->id; + + dol_syslog(get_class($this)."::setAutoValidate", LOG_DEBUG); + if ($this->db->query($sql)) { + $this->auto_validate = $validate; + return 1; + } else { + dol_print_error($this->db); + return -1; + } + } + + /** + * Update the Number of Generation Done + * + * @return int <0 if KO, >0 if OK + */ + public function updateNbGenDone() + { + if (! $this->table_element) { + dol_syslog(get_class($this)."::updateNbGenDone called with property table_element not defined", LOG_ERR); + return -1; + } + + $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; + $sql.= ' SET nb_gen_done = nb_gen_done + 1'; + $sql.= ' , date_last_gen = now()'; + // si on et arrivé à la fin des génération + if ($this->nb_gen_max == $this->nb_gen_done+1) + $sql.= ' , statut = 1'; + + $sql.= ' WHERE rowid = '.$this->id; + + dol_syslog(get_class($this)."::setAutoValidate", LOG_DEBUG); + if ($this->db->query($sql)) { + $this->nb_gen_done = $this->nb_gen_done+1; + $this->nb_gen_done = dol_now(); + return 1; + } else { + dol_print_error($this->db); + return -1; + } + } +} diff --git a/htdocs/hrm/index.php b/htdocs/hrm/index.php index 3ddba34571c..ef8df639d26 100644 --- a/htdocs/hrm/index.php +++ b/htdocs/hrm/index.php @@ -141,7 +141,7 @@ if (! empty($conf->holiday->enabled)) print '
'; print ''; print ''; - print ""; + print ''; print '
'.$langs->trans("Holidays").'
'; $out=''; @@ -197,8 +197,8 @@ if (! empty($conf->holiday->enabled) && $user->rights->holiday->read) $i = 0; - print '
'; - print ''; + print '
'; + print '
'; print ''; print ''; print ''; @@ -244,7 +244,8 @@ if (! empty($conf->holiday->enabled) && $user->rights->holiday->read) { print ''; } - print '
'.$langs->trans("BoxTitleLastLeaveRequests", min($max, $num)).''.$langs->trans("from").'
'.$langs->trans("None").'

'; + print '
'; + print '
'; } else dol_print_error($db); } @@ -272,8 +273,8 @@ if (! empty($conf->deplacement->enabled) && $user->rights->deplacement->lire) $i = 0; - print '
'; - print ''; + print '
'; + print '
'; print ''; print ''; print ''; @@ -344,8 +345,8 @@ if (! empty($conf->expensereport->enabled) && $user->rights->expensereport->lire $i = 0; - print '
'; - print '
'.$langs->trans("BoxTitleLastModifiedExpenses", min($max, $num)).''.$langs->trans("FeesKilometersOrAmout").'
'; + print '
'; + print '
'; print ''; print ''; print ''; diff --git a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql index 4f0cd4d39a9..960ebc5d12a 100644 --- a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql +++ b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql @@ -247,3 +247,75 @@ ALTER TABLE llx_societe ADD COLUMN socialnetworks text DEFAULT NULL AFTER email; ALTER TABLE llx_socpeople ADD COLUMN socialnetworks text DEFAULT NULL AFTER email; ALTER TABLE llx_user ADD COLUMN socialnetworks text DEFAULT NULL AFTER personal_email; +create table llx_fichinter_rec +( + rowid integer AUTO_INCREMENT PRIMARY KEY, + titre varchar(50) NOT NULL, + entity integer DEFAULT 1 NOT NULL, -- multi company id + fk_soc integer DEFAULT NULL, + datec datetime, -- date de creation + fk_contrat integer DEFAULT 0, -- contrat auquel est rattache la fiche + fk_user_author integer, -- createur + fk_projet integer, -- projet auquel est associe la facture + duree real, -- duree totale de l'intervention + description text, + modelpdf varchar(50), + note_private text, + note_public text, + frequency integer, -- frequency (for example: 3 for every 3 month) + unit_frequency varchar(2) DEFAULT 'm', -- 'm' for month (date_when must be a day <= 28), 'y' for year, ... + date_when datetime DEFAULT NULL, -- date for next gen (when an invoice is generated, this field must be updated with next date) + date_last_gen datetime DEFAULT NULL, -- date for last gen (date with last successfull generation of invoice) + nb_gen_done integer DEFAULT NULL, -- nb of generation done (when an invoice is generated, this field must incremented) + nb_gen_max integer DEFAULT NULL, -- maximum number of generation + auto_validate integer NULL DEFAULT NULL -- statut of the generated intervention + +)ENGINE=innodb; + +ALTER TABLE llx_fichinter_rec ADD UNIQUE INDEX idx_fichinter_rec_uk_titre (titre, entity); +ALTER TABLE llx_fichinter_rec ADD INDEX idx_fichinter_rec_fk_soc (fk_soc); +ALTER TABLE llx_fichinter_rec ADD INDEX idx_fichinter_rec_fk_user_author (fk_user_author); +ALTER TABLE llx_fichinter_rec ADD INDEX idx_fichinter_rec_fk_projet (fk_projet); +ALTER TABLE llx_fichinter_rec ADD CONSTRAINT fk_fichinter_rec_fk_user_author FOREIGN KEY (fk_user_author) REFERENCES llx_user (rowid); +ALTER TABLE llx_fichinter_rec ADD CONSTRAINT fk_fichinter_rec_fk_projet FOREIGN KEY (fk_projet) REFERENCES llx_projet (rowid); + +create table llx_fichinterdet_rec +( + rowid integer AUTO_INCREMENT PRIMARY KEY, + fk_fichinter integer NOT NULL, + date datetime, -- date de la ligne d'intervention + description text, -- description de la ligne d'intervention + duree integer, -- duree de la ligne d'intervention + rang integer DEFAULT 0, -- ordre affichage sur la fiche + total_ht DOUBLE(24, 8) NULL DEFAULT NULL, + subprice DOUBLE(24, 8) NULL DEFAULT NULL, + fk_parent_line integer NULL DEFAULT NULL, + fk_product integer NULL DEFAULT NULL, + label varchar(255) NULL DEFAULT NULL, + tva_tx DOUBLE(6, 3) NULL DEFAULT NULL, + localtax1_tx DOUBLE(6, 3) NULL DEFAULT 0, + localtax1_type VARCHAR(1) NULL DEFAULT NULL, + localtax2_tx DOUBLE(6, 3) NULL DEFAULT 0, + localtax2_type VARCHAR(1) NULL DEFAULT NULL, + qty double NULL DEFAULT NULL, + remise_percent double NULL DEFAULT 0, + remise double NULL DEFAULT 0, + fk_remise_except integer NULL DEFAULT NULL, + price DOUBLE(24, 8) NULL DEFAULT NULL, + total_tva DOUBLE(24, 8) NULL DEFAULT NULL, + total_localtax1 DOUBLE(24, 8) NULL DEFAULT 0, + total_localtax2 DOUBLE(24, 8) NULL DEFAULT 0, + total_ttc DOUBLE(24, 8) NULL DEFAULT NULL, + product_type INTEGER NULL DEFAULT 0, + date_start datetime NULL DEFAULT NULL, + date_end datetime NULL DEFAULT NULL, + info_bits INTEGER NULL DEFAULT 0, + buy_price_ht DOUBLE(24, 8) NULL DEFAULT 0, + fk_product_fournisseur_price integer NULL DEFAULT NULL, + fk_code_ventilation integer NOT NULL DEFAULT 0, + fk_export_commpta integer NOT NULL DEFAULT 0, + special_code integer UNSIGNED NULL DEFAULT 0, + fk_unit integer NULL DEFAULT NULL, + import_key varchar(14) NULL DEFAULT NULL +)ENGINE=innodb; + diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index f0a75facce6..225cada814f 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1587,6 +1587,7 @@ FCKeditorForProductDetails=WYSIWIG creation/edition of products details lines fo FCKeditorForMailing= WYSIWIG creation/edition for mass eMailings (Tools->eMailing) FCKeditorForUserSignature=WYSIWIG creation/edition of user signature FCKeditorForMail=WYSIWIG creation/edition for all mail (except Tools->eMailing) +FCKeditorForTicket=WYSIWIG creation/edition for tickets ##### Stock ##### StockSetup=Stock module setup IfYouUsePointOfSaleCheckModule=If you use the Point of Sale module (POS) provided by default or an external module, this setup may be ignored by your POS module. Most POS modules are designed by default to create an invoice immediately and decrease stock irrespective of the options here. So if you need or not to have a stock decrease when registering a sale from your POS, check also your POS module setup. diff --git a/htdocs/langs/en_US/bookmarks.lang b/htdocs/langs/en_US/bookmarks.lang index 5330ab6e87c..87466cadcfa 100644 --- a/htdocs/langs/en_US/bookmarks.lang +++ b/htdocs/langs/en_US/bookmarks.lang @@ -18,3 +18,4 @@ SetHereATitleForLink=Set a name for the bookmark UseAnExternalHttpLinkOrRelativeDolibarrLink=Use an external/absolute link (https://URL) or an internal/relative link (/DOLIBARR_ROOT/htdocs/...) ChooseIfANewWindowMustBeOpenedOnClickOnBookmark=Choose if the linked page should open in the current tab or a new tab BookmarksManagement=Bookmarks management +BookmarksMenuShortCut=Ctrl + shift + m diff --git a/htdocs/langs/fr_FR/admin.lang b/htdocs/langs/fr_FR/admin.lang index 3d15d7fe3d4..8fa04de8b11 100644 --- a/htdocs/langs/fr_FR/admin.lang +++ b/htdocs/langs/fr_FR/admin.lang @@ -1586,6 +1586,7 @@ FCKeditorForProductDetails=Création/édition WYSIWIG des lignes détails produi FCKeditorForMailing= Création/édition WYSIWIG des emailings (Outils->Emailings) FCKeditorForUserSignature=Création/édition WYSIWIG de la signature des utilisateurs FCKeditorForMail=Création/édition WYSIWIG tous les emails (sauf Outils->Emailings) +FCKeditorForTicket=Création/édition WYSIWIG pour les tickets ##### Stock ##### StockSetup=Configuration du module Stock / Entrepôt IfYouUsePointOfSaleCheckModule=Si vous utilisez un module Point de Vente (module POS fourni par défaut ou un autre module externe), cette configuration peut être ignoré par votre module point de vente. La plupart de modules Point de Vente sont conçus pour créer immédiatement une facture et de réduire les stocks par défaut quelles que soient les options ici. Donc, si vous avez besoin ou non d'avoir une diminution du stock lors de l'enregistrement d'une vente dans votre Point de Vente, vérifiez également la configuration de votre module POS. diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 845a3fd0873..75c0190ddcd 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -1602,6 +1602,10 @@ function top_menu($head, $title = '', $target = '', $disablejs = 0, $disablehead print '
'.$langs->trans("BoxTitleLastModifiedExpenses", min($max, $num)).''.$langs->trans("TotalTTC").'