diff --git a/htdocs/admin/tools/purge.php b/htdocs/admin/tools/purge.php index 9249186f574..1bc3fea3909 100644 --- a/htdocs/admin/tools/purge.php +++ b/htdocs/admin/tools/purge.php @@ -48,60 +48,10 @@ if (! empty($conf->syslog->enabled)) */ if ($action=='purge' && ! preg_match('/^confirm/i',$choice) && ($choice != 'allfiles' || $confirm == 'yes') ) { - $filesarray=array(); + require_once DOL_DOCUMENT_ROOT.'/core/class/utils.class.php'; + $utils = new Utils($db); + $count = $utils->purgeFiles($choice); - if ($choice=='tempfiles') - { - // Delete temporary files - if ($dolibarr_main_data_root) - { - $filesarray=dol_dir_list($dolibarr_main_data_root,"directories",1,'^temp$'); - } - } - - if ($choice=='allfiles') - { - // Delete all files - if ($dolibarr_main_data_root) - { - $filesarray=dol_dir_list($dolibarr_main_data_root,"all",0,'','install\.lock$'); - } - } - - if ($choice=='logfile') - { - $filesarray[]=array('fullname'=>$filelog,'type'=>'file'); - } - - $count=0; - if (count($filesarray)) - { - foreach($filesarray as $key => $value) - { - //print "x ".$filesarray[$key]['fullname']."
\n"; - if ($filesarray[$key]['type'] == 'dir') - { - $count+=dol_delete_dir_recursive($filesarray[$key]['fullname']); - } - elseif ($filesarray[$key]['type'] == 'file') - { - // If (file that is not logfile) or (if logfile with option logfile) - if ($filesarray[$key]['fullname'] != $filelog || $choice=='logfile') - { - $count+=(dol_delete_file($filesarray[$key]['fullname'])?1:0); - } - } - } - - // Update cachenbofdoc - if (! empty($conf->ecm->enabled) && $choice=='allfiles') - { - require_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmdirectory.class.php'; - $ecmdirstatic = new EcmDirectory($db); - $result = $ecmdirstatic->refreshcachenboffile(1); - } - } - if ($count) $mesg=$langs->trans("PurgeNDirectoriesDeleted", $count); else $mesg=$langs->trans("PurgeNothingToDelete"); setEventMessages($mesg, null, 'mesgs'); @@ -159,7 +109,7 @@ if (preg_match('/^confirm/i',$choice)) { print '
'; $formquestion=array(); - print $form->formconfirm($_SERVER["PHP_SELF"].'?choice=allfiles', $langs->trans('Purge'), $langs->trans('ConfirmPurge').' '.img_warning(), 'purge', $formquestion, 'no', 2); + print $form->formconfirm($_SERVER["PHP_SELF"].'?choice=allfiles', $langs->trans('Purge'), $langs->trans('ConfirmPurge').img_warning().' ', 'purge', $formquestion, 'no', 2); } diff --git a/htdocs/cashdesk/css/style.css b/htdocs/cashdesk/css/style.css index d639230564b..bbb03bafde5 100644 --- a/htdocs/cashdesk/css/style.css +++ b/htdocs/cashdesk/css/style.css @@ -337,7 +337,7 @@ p.titre { /* -------------- Boutons --------------------- */ .bouton_ajout_article { margin-top: 10px; - width: 100%; + width: 60%; height: 40px; } diff --git a/htdocs/compta/bank/ligne.php b/htdocs/compta/bank/ligne.php index 0f73e5cb6cf..13b65f0baf1 100644 --- a/htdocs/compta/bank/ligne.php +++ b/htdocs/compta/bank/ligne.php @@ -535,7 +535,7 @@ if ($result) if ($user->rights->banque->modifier) { print ''; - print 'rappro?' disabled':'').' value="'.price($objp->amount).'"> '.$langs->trans("Currency".$conf->currency); + print 'rappro?' disabled':'').' value="'.price($objp->amount).'"> '.$langs->trans("Currency".$acct->currency_code); print ''; } else diff --git a/htdocs/compta/bank/rappro.php b/htdocs/compta/bank/rappro.php index a2d7cb832b5..6e91a180e50 100644 --- a/htdocs/compta/bank/rappro.php +++ b/htdocs/compta/bank/rappro.php @@ -154,6 +154,7 @@ $acct->fetch($id); $now=dol_now(); $sql = "SELECT b.rowid, b.dateo as do, b.datev as dv, b.amount, b.label, b.rappro, b.num_releve, b.num_chq, b.fk_type as type"; +$sql.= ", b.fk_bordereau"; $sql.= " FROM ".MAIN_DB_PREFIX."bank as b"; $sql.= " WHERE rappro=0 AND fk_account=".$acct->id; $sql.= " ORDER BY dateo ASC"; @@ -291,7 +292,7 @@ if ($resql) // Type + Number $label=($langs->trans("PaymentType".$objp->type)!="PaymentType".$objp->type)?$langs->trans("PaymentType".$objp->type):$objp->type; // $objp->type is a code if ($label=='SOLD') $label=''; - print ''.$label.($objp->num_chq?' '.$objp->num_chq:'').''; + print ''.$label.($objp->num_chq?' '.$objp->num_chq:'').($objp->fk_bordereau>0?' ('.$objp->fk_bordereau.')':'').''; // Description print ''; diff --git a/htdocs/compta/bank/releve.php b/htdocs/compta/bank/releve.php index 84c2edde0dd..0025fb62fd8 100644 --- a/htdocs/compta/bank/releve.php +++ b/htdocs/compta/bank/releve.php @@ -327,6 +327,7 @@ else // Recherche les ecritures pour le releve $sql = "SELECT b.rowid, b.dateo as do, b.datev as dv,"; $sql.= " b.amount, b.label, b.rappro, b.num_releve, b.num_chq, b.fk_type,"; + $sql.= " b.fk_bordereau,"; $sql.= " ba.rowid as bankid, ba.ref as bankref, ba.label as banklabel"; $sql.= " FROM ".MAIN_DB_PREFIX."bank_account as ba"; $sql.= ", ".MAIN_DB_PREFIX."bank as b"; @@ -373,7 +374,7 @@ else } else { $type_label=($langs->trans("PaymentTypeShort".$objp->fk_type)!="PaymentTypeShort".$objp->fk_type)?$langs->trans("PaymentTypeShort".$objp->fk_type):$objp->fk_type; } - print ''.$type_label.' '.($objp->num_chq?$objp->num_chq:'').''; + print ''.$type_label.' '.($objp->num_chq?$objp->num_chq:'').($objp->fk_bordereau>0?' ('.$objp->fk_bordereau.')':'').''; // Description print ''; diff --git a/htdocs/compta/facture.php b/htdocs/compta/facture.php index 558ba09ef8f..b3f3bd25c17 100644 --- a/htdocs/compta/facture.php +++ b/htdocs/compta/facture.php @@ -2992,7 +2992,7 @@ else if ($id > 0 || ! empty($ref)) print ''; - if ($object->type != Facture::TYPE_CREDIT_NOTE && $action != 'editinvoicedate' && ! empty($object->brouillon) && $user->rights->facture->creer) + if ($object->type != Facture::TYPE_CREDIT_NOTE && $action != 'editinvoicedate' && ! empty($object->brouillon) && $user->rights->facture->creer && empty($conf->global->FAC_FORCE_DATE_VALIDATION)) print ''; print '
'; print $langs->trans('Date'); print 'id . '">' . img_edit($langs->trans('SetDate'), 1) . '
'; print ''; diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index 78f12335f36..a1a1d1cc69a 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -706,6 +706,11 @@ if (empty($reshook)) $result = $object->validate($user); } + else if ($action == 'reopen' && $user->rights->contrat->creer) + { + $result = $object->reopen($user); + } + // Close all lines else if ($action == 'confirm_close' && $confirm == 'yes' && $user->rights->contrat->creer) { @@ -1916,7 +1921,12 @@ else if ($user->rights->contrat->creer) print '
'.$langs->trans("Validate").'
'; else print '
'.$langs->trans("Validate").'
'; } - + if ($object->statut == 1 && $nbofservices) + { + if ($user->rights->contrat->creer) print '
'.$langs->trans("Modify").'
'; + else print '
'.$langs->trans("Modify").'
'; + } + if (! empty($conf->facture->enabled) && $object->statut > 0 && $object->nbofservicesclosed < $nbofservices) { $langs->load("bills"); @@ -1976,6 +1986,12 @@ else print '
'; + // List of actions on element + include_once DOL_DOCUMENT_ROOT . '/core/class/html.formactions.class.php'; + $formactions = new FormActions($db); + $somethingshown = $formactions->showactions($object, 'contract', $socid); + + print '
'; } } diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 905c9fa08a2..9e8b1de5d07 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -472,7 +472,71 @@ class Contrat extends CommonObject } + /** + * Unvalidate a contract + * + * @param User $user Objet User + * @param int $notrigger 1=Does not execute triggers, 0=execute triggers + * @return int <0 if KO, >0 if OK + */ + function reopen($user, $notrigger=0) + { + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + global $langs, $conf; + $now=dol_now(); + + $error=0; + dol_syslog(get_class($this).'::reopen user='.$user->id); + + $this->db->begin(); + + $this->fetch_thirdparty(); + + $sql = "UPDATE ".MAIN_DB_PREFIX."contrat SET statut = 0"; + //$sql.= ", fk_user_valid = null, date_valid = null"; + $sql .= " WHERE rowid = ".$this->id . " AND statut = 1"; + + dol_syslog(get_class($this)."::validate", LOG_DEBUG); + $resql = $this->db->query($sql); + if (! $resql) + { + dol_print_error($this->db); + $error++; + $this->error=$this->db->lasterror(); + } + + // Trigger calls + if (! $error && ! $notrigger) + { + // Call trigger + $result=$this->call_trigger('CONTRACT_REOPEN',$user); + if ($result < 0) { + $error++; + } + // End call triggers + } + + // Set new ref and define current statut + if (! $error) + { + $this->statut=0; + $this->brouillon=1; + $this->date_validation=$now; + } + + if (! $error) + { + $this->db->commit(); + return 1; + } + else + { + $this->db->rollback(); + return -1; + } + } + /** * Load a contract from database * diff --git a/htdocs/core/class/html.formprojet.class.php b/htdocs/core/class/html.formprojet.class.php index 498604d9307..4f65d5327d1 100644 --- a/htdocs/core/class/html.formprojet.class.php +++ b/htdocs/core/class/html.formprojet.class.php @@ -539,9 +539,10 @@ class FormProjets * @param int $showempty Add an empty line * @param int $useshortlabel Use short label * @param int $showallnone Add choice "All" and "None" + * @param int $showpercent Show default probability for status * @return int|string The HTML select list of element or '' if nothing or -1 if KO */ - function selectOpportunityStatus($htmlname, $preselected=0, $showempty=1, $useshortlabel=0, $showallnone=0) + function selectOpportunityStatus($htmlname, $preselected=0, $showempty=1, $useshortlabel=0, $showallnone=0, $showpercent=0) { global $conf, $langs; @@ -557,7 +558,7 @@ class FormProjets $i = 0; if ($num > 0) { - $sellist = ''; if ($showempty) $sellist.= ''; if ($showallnone) $sellist.= ''; if ($showallnone) $sellist.= ''; @@ -565,7 +566,7 @@ class FormProjets { $obj = $this->db->fetch_object($resql); - $sellist .=''; diff --git a/htdocs/core/class/utils.class.php b/htdocs/core/class/utils.class.php new file mode 100644 index 00000000000..3132423d614 --- /dev/null +++ b/htdocs/core/class/utils.class.php @@ -0,0 +1,129 @@ + + * + * 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 + * 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/core/class/utils.class.php + * \ingroup core + * \brief File for Utils class + */ + + +/** + * Class to manage utility methods + */ +class Utils +{ + var $db; + + /** + * Constructor + * + * @param DoliDB $db Database handler + */ + function __construct($db) + { + $this->db = $db; + } + + + /** + * Purge files into directory of data files. + * + * @param string $choice Choice of purge mode ('tempfiles', 'tempfilesold' to purge temp older than 24h, 'allfiles', 'logfiles') + * @return int Nb of files deleted + */ + function purgeFiles($choice='tempfilesold') + { + global $conf, $dolibarr_main_data_root; + + dol_syslog("Utils::purgeFiles choice=".$choice, LOG_DEBUG); + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + + $filesarray=array(); + if (empty($choice)) $choice='tempfilesold'; + + if ($choice=='tempfiles' || $choice=='tempfilesold') + { + // Delete temporary files + if ($dolibarr_main_data_root) + { + $filesarray=dol_dir_list($dolibarr_main_data_root,"directories",1,'^temp$','','','',2); + if ($choice == 'tempfilesold') + { + $now = dol_now(); + foreach($filesarray as $key => $val) + { + if ($val['date'] > ($now - (24 * 3600))) unset($filesarray[$key]); // Discard files not older than 24h + } + } + } + } + + if ($choice=='allfiles') + { + // Delete all files + if ($dolibarr_main_data_root) + { + $filesarray=dol_dir_list($dolibarr_main_data_root,"all",0,'','install\.lock$'); + } + } + + if ($choice=='logfile') + { + // Define filelog to discard it from purge + $filelog=''; + if (! empty($conf->syslog->enabled)) + { + $filelog=SYSLOG_FILE; + $filelog=preg_replace('/DOL_DATA_ROOT/i',DOL_DATA_ROOT,$filelog); + } + + $filesarray[]=array('fullname'=>$filelog,'type'=>'file'); + } + + $count=0; + if (count($filesarray)) + { + foreach($filesarray as $key => $value) + { + //print "x ".$filesarray[$key]['fullname']."
\n"; + if ($filesarray[$key]['type'] == 'dir') + { + $count+=dol_delete_dir_recursive($filesarray[$key]['fullname']); + } + elseif ($filesarray[$key]['type'] == 'file') + { + // If (file that is not logfile) or (if logfile with option logfile) + if ($filesarray[$key]['fullname'] != $filelog || $choice=='logfile') + { + $count+=(dol_delete_file($filesarray[$key]['fullname'])?1:0); + } + } + } + + // Update cachenbofdoc + if (! empty($conf->ecm->enabled) && $choice=='allfiles') + { + require_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmdirectory.class.php'; + $ecmdirstatic = new EcmDirectory($this->db); + $result = $ecmdirstatic->refreshcachenboffile(1); + } + } + + return $count; + } +} diff --git a/htdocs/core/lib/tax.lib.php b/htdocs/core/lib/tax.lib.php index cd128cec817..758301c9171 100644 --- a/htdocs/core/lib/tax.lib.php +++ b/htdocs/core/lib/tax.lib.php @@ -110,7 +110,7 @@ function vat_by_thirdparty($db, $y, $date_start, $date_end, $modetax, $direction if ($modetax == 1) { // If vat paid on due invoices (non draft) - $sql = "SELECT s.rowid as socid, s.nom as name, s.siren as tva_intra, s.tva_assuj as assuj,"; + $sql = "SELECT s.rowid as socid, s.nom as name, s.tva_intra as tva_intra, s.tva_assuj as assuj,"; $sql.= " sum(f.$total_ht) as amount, sum(f.".$total_tva.") as tva,"; $sql.= " sum(f.localtax1) as localtax1,"; $sql.= " sum(f.localtax2) as localtax2"; diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php index 11d904f58d4..06b3bc89860 100644 --- a/htdocs/core/modules/DolibarrModules.class.php +++ b/htdocs/core/modules/DolibarrModules.class.php @@ -936,10 +936,11 @@ class DolibarrModules // Can not be abstract, because we need to insta if (! $err) { - $sql = "INSERT INTO ".MAIN_DB_PREFIX."cronjob (module_name, datec, label, jobtype, classesname, objectname, methodename, command, params, note, frequency, unitfrequency, entity)"; + $sql = "INSERT INTO ".MAIN_DB_PREFIX."cronjob (module_name, datec, datestart, label, jobtype, classesname, objectname, methodename, command, params, note, frequency, unitfrequency, entity)"; $sql.= " VALUES ("; $sql.= "'".$this->db->escape($this->rights_class)."', "; $sql.= "'".$this->db->idate($now)."', "; + $sql.= "'".$this->db->idate($now)."', "; $sql.= "'".$this->db->escape($label)."', "; $sql.= "'".$this->db->escape($jobtype)."', "; $sql.= ($class?"'".$this->db->escape($class)."'":"null").","; diff --git a/htdocs/core/modules/modCron.class.php b/htdocs/core/modules/modCron.class.php index aefb599a9b7..4981eeb0089 100644 --- a/htdocs/core/modules/modCron.class.php +++ b/htdocs/core/modules/modCron.class.php @@ -99,6 +99,12 @@ class modCron extends DolibarrModules $this->rights_class = 'cron'; $r=0; + // Cronjobs + $this->cronjobs = array( + 0=>array('label'=>'PurgeDeleteTemporaryFilesShort', 'jobtype'=>'method', 'class'=>'core/class/utils.class.php', 'objectname'=>'Utils', 'method'=>'purgeFiles', 'parameters'=>'', 'comment'=>'PurgeDeleteTemporaryFiles', 'frequency'=>1, 'unitfrequency'=>3600 * 24 * 7), + // 1=>array('label'=>'My label', 'jobtype'=>'command', 'command'=>'', 'parameters'=>'', 'comment'=>'Comment', 'frequency'=>1, 'unitfrequency'=>3600*24) + ); + $this->rights[$r][0] = 23001; $this->rights[$r][1] = 'Read cron jobs'; $this->rights[$r][3] = 1; diff --git a/htdocs/cron/card.php b/htdocs/cron/card.php index e91b359ed98..76781d6645e 100644 --- a/htdocs/cron/card.php +++ b/htdocs/cron/card.php @@ -1,7 +1,7 @@ - * Copyright (C) 2013-2015 Laurent Destailleur + * Copyright (C) 2013-2016 Laurent Destailleur * * 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 @@ -539,7 +539,7 @@ else print ''; print $langs->trans('CronLabel').""; - print "".$object->label; + print "".$langs->trans($object->label); print ""; print ""; @@ -579,7 +579,7 @@ else print ''; print $langs->trans('CronNote').""; - print $object->note; + print $langs->trans($object->note); print ""; print ''; diff --git a/htdocs/cron/class/cronjob.class.php b/htdocs/cron/class/cronjob.class.php index a66fcd9597c..a22b4aa21c0 100644 --- a/htdocs/cron/class/cronjob.class.php +++ b/htdocs/cron/class/cronjob.class.php @@ -500,7 +500,6 @@ class Cronjob extends CommonObject $error=0; // Clean parameters - if (isset($this->label)) $this->label=trim($this->label); if (isset($this->jobtype)) $this->jobtype=trim($this->jobtype); if (isset($this->command)) $this->command=trim($this->command); @@ -524,7 +523,7 @@ class Cronjob extends CommonObject // Check parameters // Put here code to add a control on parameters values if (dol_strlen($this->datestart)==0) { - $this->errors[]=$langs->trans('CronFieldMandatory',$langs->trans('CronDtStart')); + $this->errors[]=$langs->trans('CronFieldMandatory',$langs->transnoentitiesnoconv('CronDtStart')); $error++; } if ((dol_strlen($this->datestart)!=0) && (dol_strlen($this->dateend)!=0) && ($this->dateend<$this->datestart)) { @@ -532,32 +531,32 @@ class Cronjob extends CommonObject $error++; } if (empty($this->label)) { - $this->errors[]=$langs->trans('CronFieldMandatory',$langs->trans('CronLabel')); + $this->errors[]=$langs->trans('CronFieldMandatory',$langs->transnoentitiesnoconv('CronLabel')); $error++; } if (empty($this->unitfrequency)) { - $this->errors[]=$langs->trans('CronFieldMandatory',$langs->trans('CronFrequency')); + $this->errors[]=$langs->trans('CronFieldMandatory',$langs->transnoentitiesnoconv('CronFrequency')); $error++; } if (($this->jobtype=='command') && (empty($this->command))) { - $this->errors[]=$langs->trans('CronFieldMandatory',$langs->trans('CronCommand')); + $this->errors[]=$langs->trans('CronFieldMandatory',$langs->transnoentitiesnoconv('CronCommand')); $error++; } if (($this->jobtype=='method') && (empty($this->classesname))) { - $this->errors[]=$langs->trans('CronFieldMandatory',$langs->trans('CronClass')); + $this->errors[]=$langs->trans('CronFieldMandatory',$langs->transnoentitiesnoconv('CronClass')); $error++; } if (($this->jobtype=='method' || $this->jobtype == 'function') && (empty($this->methodename))) { - $this->errors[]=$langs->trans('CronFieldMandatory',$langs->trans('CronMethod')); + $this->errors[]=$langs->trans('CronFieldMandatory',$langs->transnoentitiesnoconv('CronMethod')); $error++; } if (($this->jobtype=='method') && (empty($this->objectname))) { - $this->errors[]=$langs->trans('CronFieldMandatory',$langs->trans('CronObject')); + $this->errors[]=$langs->trans('CronFieldMandatory',$langs->transnoentitiesnoconv('CronObject')); $error++; } if (($this->jobtype=='function') && (empty($this->libname))) { - $this->errors[]=$langs->trans('CronFieldMandatory',$langs->trans('CronLib')); + $this->errors[]=$langs->trans('CronFieldMandatory',$langs->transnoentitiesnoconv('CronLib')); $error++; } @@ -592,7 +591,7 @@ class Cronjob extends CommonObject $sql.= " libname=".(isset($this->libname)?"'".$this->db->escape($this->libname)."'":"null"); $sql.= " WHERE rowid=".$this->id; - $this->db->begin(); + $this->db->begin(); dol_syslog(get_class($this)."::update", LOG_DEBUG); $resql = $this->db->query($sql); @@ -841,6 +840,8 @@ class Cronjob extends CommonObject global $langs, $conf; $now=dol_now(); + $error = 0; + $retval = ''; $langs->load('cron'); @@ -889,7 +890,7 @@ class Cronjob extends CommonObject } - // Update last run date (to track launch) + // Update last run date (to track running jobs) $this->datelastrun=$now; $this->lastoutput=''; $this->lastresult=''; @@ -904,49 +905,63 @@ class Cronjob extends CommonObject if ($this->jobtype=='method') { // load classes - $file = "/".$this->module_name."/class/".$this->classesname; - $ret=dol_include_once($file,$this->objectname); - if ($ret===false) + $ret=dol_include_once($this->classesname,$this->objectname); + if (! $error && $ret===false) { - $this->error=$langs->trans('CronCannotLoadClass',$file,$this->objectname); + $this->error=$langs->trans('CronCannotLoadClass',$this->classesname,$this->objectname); dol_syslog(get_class($this)."::run_jobs ".$this->error, LOG_ERR); - return -1; + $this->lastoutput = $this->error; + $this->lastresult = -1; + $retval = $this->lastresult; + $error++; } // Load langs - $result=$langs->load($this->module_name.'@'.$this->module_name); - if ($result<0) + if (! $error) { - dol_syslog(get_class($this)."::run_jobs Cannot load module langs".$langs->error, LOG_ERR); - return -1; + $result=$langs->load($this->module_name.'@'.$this->module_name); + if ($result<0) + { + dol_syslog(get_class($this)."::run_jobs Cannot load module lang file - ".$langs->error, LOG_ERR); + $this->lastoutput = $langs->error; + $this->lastresult = -1; + $retval = $this->lastresult; + $error++; + } } - - dol_syslog(get_class($this)."::run_jobs ".$this->objectname."->".$this->methodename."(".$this->params.");", LOG_DEBUG); - - // Create Object for the call module - $object = new $this->objectname($this->db); - - $params_arr = explode(", ",$this->params); - if (!is_array($params_arr)) + + if (! $error) { - $result = call_user_func(array($object, $this->methodename), $this->params); - } - else - { - $result = call_user_func_array(array($object, $this->methodename), $params_arr); - } - - if ($result===false) - { - dol_syslog(get_class($this)."::run_jobs ".$object->error, LOG_ERR); - return -1; - } - else - { - $this->lastoutput=var_export($result,true); - $this->lastresult=var_export($result,true); - } - + dol_syslog(get_class($this)."::run_jobs ".$this->objectname."->".$this->methodename."(".$this->params.");", LOG_DEBUG); + + // Create Object for the call module + $object = new $this->objectname($this->db); + + $params_arr = explode(", ",$this->params); + if (!is_array($params_arr)) + { + $result = call_user_func(array($object, $this->methodename), $this->params); + } + else + { + $result = call_user_func_array(array($object, $this->methodename), $params_arr); + } + + if ($result===false) + { + dol_syslog(get_class($this)."::run_jobs ".$object->error, LOG_ERR); + $this->lastoutput = $object->error; + $this->lastresult = -1; + $retval = $this->lastresult; + $error++; + } + else + { + $this->lastoutput='NA'; + $this->lastresult=var_export($result,true); + $retval = $this->lastresult; + } + } } if($this->jobtype == 'function') @@ -981,12 +996,16 @@ class Cronjob extends CommonObject if ($result === false) { dol_syslog(get_class($this) . "::run_jobs " . $object->error, LOG_ERR); - return -1; + + $this->lastoutput = $object->error; + $this->lastresult = -1; + $retval = $this->lastresult; } else { $this->lastoutput=var_export($result,true); - $this->lastresult=var_export($result,true); + $this->lastresult=var_export($result,true); // Return code + $retval = $this->lastresult; } } @@ -1029,9 +1048,7 @@ class Cronjob extends CommonObject dol_syslog(get_class($this)."::run_jobs output_arr:".var_export($output_arr,true), LOG_DEBUG); - // Update with result - $this->lastoutput=''; if (is_array($output_arr) && count($output_arr)>0) { foreach($output_arr as $val) @@ -1049,7 +1066,7 @@ class Cronjob extends CommonObject } else { - return 1; + return $error?-1:1; } } @@ -1089,26 +1106,26 @@ class Cronjob extends CommonObject if (empty($this->datenextrun)) { - $this->datenextrun = $now + ($this->frequency * $this->unitfrequency); + if (empty($this->datestart)) $this->datenextrun = $now + ($this->frequency * $this->unitfrequency); + else $this->datenextrun = $this->datestart + ($this->frequency * $this->unitfrequency); + } + + if ($this->datenextrun < $now && $this->frequency > 0 && $this->unitfrequency > 0) + { + // Loop until date is after future + while ($this->datenextrun < $now) + { + $this->datenextrun += ($this->frequency * $this->unitfrequency); + + // TODO For exact frequency (every month, every year, ...), use instead a dol_time_plus_duree($time, $duration_value, $duration_unit) + } } else { - if ($this->datenextrun < $now && $this->frequency > 0) - { - // Loop until date is after future - while ($this->datenextrun < $now) - { - $this->datenextrun += ($this->frequency * $this->unitfrequency); - - // TODO For exact frequency (every month, every year, ...), use instead a dol_time_plus_duree($time, $duration_value, $duration_unit) - } - } - else - { - //$this->datenextrun=$this->datenextrun + ($this->frequency * $this->unitfrequency); - } + //$this->datenextrun=$this->datenextrun + ($this->frequency * $this->unitfrequency); } + // Archive job if ($this->autodelete == 2) { @@ -1116,7 +1133,7 @@ class Cronjob extends CommonObject || ($this->dateend && ($this->datenextrun > $this->dateend))) { $this->status = 2; - dol_syslog(get_class($this)."::reprogram_jobs Job must be set to archived", LOG_ERR); + dol_syslog(get_class($this)."::reprogram_jobs Job will be set to archived", LOG_ERR); } } diff --git a/htdocs/cron/list.php b/htdocs/cron/list.php index 867695cade6..3ff7e974408 100644 --- a/htdocs/cron/list.php +++ b/htdocs/cron/list.php @@ -54,7 +54,7 @@ if ($status == '') $status=-2; $search_label=GETPOST("search_label",'alpha'); if (empty($sortorder)) $sortorder="DESC"; -if (empty($sortfield)) $sortfield="t.datenextrun"; +if (empty($sortfield)) $sortfield="t.status"; if (empty($arch)) $arch = 0; if ($page == -1) { $page = 0 ; @@ -99,24 +99,26 @@ if ($action == 'confirm_execute' && $confirm == "yes" && $user->rights->cron->ex $now = dol_now(); // Date we start - $result = $object->run_jobs($user->login); - if ($result < 0) { + $resrunjob = $object->run_jobs($user->login); + if ($resrunjob < 0) { setEventMessages($object->error, $object->errors, 'errors'); } - else + + // Programm next run + $res = $object->reprogram_jobs($user->login, $now); + if ($res > 0) { - $res = $object->reprogram_jobs($user->login, $now); - if ($res > 0) + if ($resrunjob >= 0) // We add result of reprogram ony if no error message already reported { if ($object->lastresult > 0) setEventMessages($langs->trans("JobFinished"), null, 'warnings'); else setEventMessages($langs->trans("JobFinished"), null, 'mesgs'); - $action=''; - } - else - { - setEventMessages($object->error, $object->errors, 'errors'); - $action=''; } + $action=''; + } + else + { + setEventMessages($object->error, $object->errors, 'errors'); + $action=''; } header("Location: ".DOL_URL_ROOT.'/cron/list.php?status=-2'); // Make a call to avoid to run twice job when using back @@ -246,21 +248,19 @@ if ($num > 0) if ($line->jobtype=='method') { $text=$langs->trans("CronClass"); - $texttoshow=$langs->trans('CronModule').':'.$line->module_name.'
'; - $texttoshow.=$langs->trans('CronClass').':'. $line->classesname.'
'; - $texttoshow.=$langs->trans('CronObject').':'. $line->objectname.'
'; - $texttoshow.=$langs->trans('CronMethod').':'. $line->methodename; - if(!empty($line->params)) { - $texttoshow.='
'.$langs->trans('CronArgs').':'. $line->params; - } + $texttoshow=$langs->trans('CronModule').': '.$line->module_name.'
'; + $texttoshow.=$langs->trans('CronClass').': '. $line->classesname.'
'; + $texttoshow.=$langs->trans('CronObject').': '. $line->objectname.'
'; + $texttoshow.=$langs->trans('CronMethod').': '. $line->methodename; + $texttoshow.='
'.$langs->trans('CronArgs').':'. $line->params; + $texttoshow.='
'.$langs->trans('Comment').':'. $line->note; } elseif ($line->jobtype=='command') { $text=$langs->trans('CronCommand'); $texttoshow=$langs->trans('CronCommand').': '.dol_trunc($line->command); - if(!empty($line->params)) { - $texttoshow='
'.$langs->trans('CronArgs').':'. $line->params; - } + $texttoshow.='
'.$langs->trans('CronArgs').':'. $line->params; + $texttoshow.='
'.$langs->trans('Comment').':'. $line->note; } print $form->textwithpicto($text, $texttoshow, 1); print ''; @@ -297,7 +297,7 @@ if ($num > 0) print ''; print ''; - if(!empty($line->lastresult)) {print dol_trunc($line->lastresult);} + if ($line->lastresult != '') {print dol_trunc($line->lastresult);} print ''; print ''; diff --git a/htdocs/fichinter/class/fichinter.class.php b/htdocs/fichinter/class/fichinter.class.php index c177eb7965c..147850223cf 100644 --- a/htdocs/fichinter/class/fichinter.class.php +++ b/htdocs/fichinter/class/fichinter.class.php @@ -153,6 +153,7 @@ class Fichinter extends CommonObject $sql.= ", ".$conf->entity; $sql.= ", ".$user->id; $sql.= ", ".$user->id; + $sql.= ", ".$user->id; $sql.= ", ".($this->description?"'".$this->db->escape($this->description)."'":"null"); $sql.= ", '".$this->db->escape($this->modelpdf)."'"; $sql.= ", ".($this->fk_project ? $this->fk_project : 0); diff --git a/htdocs/install/mysql/migration/3.9.0-4.0.0.sql b/htdocs/install/mysql/migration/3.9.0-4.0.0.sql index 911e8c957d3..f2b3ff181cc 100644 --- a/htdocs/install/mysql/migration/3.9.0-4.0.0.sql +++ b/htdocs/install/mysql/migration/3.9.0-4.0.0.sql @@ -38,3 +38,5 @@ ALTER TABLE llx_cronjob MODIFY COLUMN unitfrequency varchar(255) NOT NULL DEFAUL ALTER TABLE llx_facture ADD INDEX idx_facture_fk_statut (fk_statut); +UPDATE llx_projet as p set p.opp_percent = (SELECT percent FROM llx_c_lead_status as cls WHERE cls.rowid = p.fk_opp_status) WHERE p.opp_percent IS NULL AND p.fk_opp_status IS NOT NULL; + \ No newline at end of file diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 13368cbfc06..55eb22f0aee 100755 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -154,6 +154,7 @@ Purge=Purge PurgeAreaDesc=This page allows you to delete all files built or stored by Dolibarr (temporary files or all files in %s directory). Using this feature is not necessary. It is provided for users whose Dolibarr is hosted by a provider that does not offer permissions to delete files built by the web server. PurgeDeleteLogFile=Delete log file %s defined for Syslog module (no risk to loose data) PurgeDeleteTemporaryFiles=Delete all temporary files (no risk to loose data) +PurgeDeleteTemporaryFilesShort=Delete temporary files PurgeDeleteAllFilesInDocumentsDir=Delete all files in directory %s. Temporary files but also database backup dumps, files attached to elements (third parties, invoices, ...) and uploaded into the ECM module will be deleted. PurgeRunNow=Purge now PurgeNothingToDelete=No directory or file to delete. diff --git a/htdocs/langs/en_US/projects.lang b/htdocs/langs/en_US/projects.lang index 95d6b7fe55f..1300963c2a8 100644 --- a/htdocs/langs/en_US/projects.lang +++ b/htdocs/langs/en_US/projects.lang @@ -132,6 +132,8 @@ TaskModifiedInDolibarr=Task %s modified TaskDeletedInDolibarr=Task %s deleted OpportunityStatus=Opportunity status OpportunityStatusShort=Opp. status +OpportunityProbability=Opportunity probability +OpportunityProbabilityShort=Opp. probab. OpportunityAmount=Opportunity amount OpportunityAmountShort=Opp. amount ##### Types de contacts ##### @@ -166,6 +168,7 @@ ProjectsWithThisUserAsContact=Projects with this user as contact TasksWithThisUserAsContact=Tasks assigned to this user ResourceNotAssignedToProject=Not assigned to project ResourceNotAssignedToTask=Not assigned to task +ResourceNotAssignedToTheTask=Not assigned to the task AssignTaskToMe=Assign task to me AssignTask=Assign ProjectOverview=Overview @@ -182,7 +185,7 @@ YouCanCompleteRef=If you want to complete the ref with some information (to use OpenedProjectsByThirdparties=Opened projects by thirdparties OpportunityTotalAmount=Opportunities total amount OpportunityPonderatedAmount=Opportunities weighted amount -OpportunityPonderatedAmountDesc=Opportunities amount weighted with probability (depending on status of opportunity) +OpportunityPonderatedAmountDesc=Opportunities amount weighted with probability OppStatusPROSP=Prospection OppStatusQUAL=Qualification OppStatusPROPO=Proposal diff --git a/htdocs/projet/activity/perday.php b/htdocs/projet/activity/perday.php index ddcae068381..7e23fe123d0 100644 --- a/htdocs/projet/activity/perday.php +++ b/htdocs/projet/activity/perday.php @@ -110,6 +110,35 @@ if ($action == 'addtime' && GETPOST('assigntask')) { $idfortaskuser=$user->id; $result = $object->add_contact($idfortaskuser, GETPOST("type"), 'internal'); + + if ($result >= 0 || $result == -2) // Contact add ok or already contact of task + { + // Test if we are already contact of the project (should be rare but sometimes we can add as task contact without being contact of project, like when admin user has been removed from contact of project) + $sql='SELECT ec.rowid FROM '.MAIN_DB_PREFIX.'element_contact as ec, '.MAIN_DB_PREFIX.'c_type_contact as tc WHERE tc.rowid = ec.fk_c_type_contact'; + $sql.=' AND ec.fk_socpeople = '.$idfortaskuser." AND ec.element_id = '.$object->fk_project.' AND tc.element = 'project' AND source = 'internal'"; + $resql=$db->query($sql); + if ($resql) + { + $obj=$db->fetch_object($resql); + if (! $obj) // User is not already linked to project, so we will create link to first type + { + $project = new Project($db); + $project->fetch($object->fk_project); + // Get type + $listofprojcontact=$project->liste_type_contact('internal'); + + if (count($listofprojcontact)) + { + $typeforprojectcontact=reset(array_keys($listofprojcontact)); + $result = $project->add_contact($idfortaskuser, $typeforprojectcontact, 'internal'); + } + } + } + else + { + dol_print_error($db); + } + } } if ($result < 0) diff --git a/htdocs/projet/activity/perweek.php b/htdocs/projet/activity/perweek.php index 13bfa001630..57da487aee0 100644 --- a/htdocs/projet/activity/perweek.php +++ b/htdocs/projet/activity/perweek.php @@ -122,7 +122,36 @@ if ($action == 'addtime' && GETPOST('assigntask')) if (! $error) { $idfortaskuser=$user->id; - $result = $object->add_contact($idfortaskuser, GETPOST("type"), 'internal'); + $result = $object->add_contact($idfortaskuser, GETPOST("type"), 'internal'); + + if (! $result || $result == -2) // Contact add ok or already contact of task + { + // Test if we are already contact of the project (should be rare but sometimes we can add as task contact without being contact of project, like when admin user has been removed from contact of project) + $sql='SELECT ec.rowid FROM '.MAIN_DB_PREFIX.'element_contact as ec, '.MAIN_DB_PREFIX.'c_type_contact as tc WHERE tc.rowid = ec.fk_c_type_contact'; + $sql.=' AND ec.fk_socpeople = '.$idfortaskuser." AND ec.element_id = '.$object->fk_project.' AND tc.element = 'project' AND source = 'internal'"; + $resql=$db->query($sql); + if ($resql) + { + $obj=$db->fetch_object($resql); + if (! $obj) // User is not already linked to project, so we will create link to first type + { + $project = new Project($db); + $project->fetch($object->fk_project); + // Get type + $listofprojcontact=$project->liste_type_contact('internal'); + + if (count($listofprojcontact)) + { + $typeforprojectcontact=reset(array_keys($listofprojcontact)); + $result = $project->add_contact($idfortaskuser, $typeforprojectcontact, 'internal'); + } + } + } + else + { + dol_print_error($db); + } + } } if ($result < 0) diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index 2266f012964..66baf0c650d 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -42,6 +42,7 @@ $backtopage=GETPOST('backtopage','alpha'); $cancel=GETPOST('cancel','alpha'); $status=GETPOST('status','int'); $opp_status=GETPOST('opp_status','int'); +$opp_percent=price2num(GETPOST('opp_percent','alpha')); if ($id == '' && $ref == '' && ($action != "create" && $action != "add" && $action != "update" && ! $_POST["cancel"])) accessforbidden(); @@ -145,6 +146,7 @@ if (empty($reshook)) $object->date_end=$date_end; $object->statuts = $status; $object->opp_status = $opp_status; + $object->opp_percent = $opp_percent; // Fill array 'array_options' with data from add form $ret = $extrafields->setOptionalsFromPost($extralabels,$object); @@ -232,7 +234,8 @@ if (empty($reshook)) if (isset($_POST['opp_amount'])) $object->opp_amount = price2num(GETPOST('opp_amount')); if (isset($_POST['budget_amount'])) $object->budget_amount= price2num(GETPOST('budget_amount')); if (isset($_POST['opp_status'])) $object->opp_status = $opp_status; - + if (isset($_POST['opp_percent'])) $object->opp_percent = $opp_percent; + // Fill array 'array_options' with data from add form $ret = $extrafields->setOptionalsFromPost($extralabels,$object); if ($ret < 0) $error++; @@ -505,6 +508,13 @@ if ($action == 'create' && $user->rights->projet->creer) print $formproject->selectOpportunityStatus('opp_status',$object->opp_status); print ''; + // Opportunity probability + print ''.$langs->trans("OpportunityProbability").''; + print ' %'; + print ''; + print ''; + print ''; + // Opportunity amount print ''.$langs->trans("OpportunityAmount").''; print ''; @@ -544,7 +554,23 @@ if ($action == 'create' && $user->rights->projet->creer) print ''; print ''; - + + // Change probability from status + print ''; } else { @@ -670,15 +696,20 @@ else print ''; print ''; + // Opportunity probability + print ''.$langs->trans("OpportunityProbability").''; + print ' %'; + print ''; + // Opportunity amount print ''.$langs->trans("OpportunityAmount").''; - print ''; + print ''; print ''; } // Budget print ''.$langs->trans("Budget").''; - print ''; + print ''; print ''; // Description @@ -750,15 +781,20 @@ else if ($code) print $langs->trans("OppStatus".$code); print ''; + // Opportunity percent + print ''.$langs->trans("OpportunityProbability").''; + if (strcmp($object->opp_percent,'')) print price($object->opp_percent,'',$langs,1,0).' %'; + print ''; + // Opportunity Amount print ''.$langs->trans("OpportunityAmount").''; - if (strcmp($object->opp_amount,'')) print price($object->opp_amount,'',$langs,0,0,0,$conf->currency); + if (strcmp($object->opp_amount,'')) print price($object->opp_amount,'',$langs,1,0,0,$conf->currency); print ''; } // Budget print ''.$langs->trans("Budget").''; - if (strcmp($object->budget_amount, '')) print price($object->budget_amount,'',$langs,0,0,0,$conf->currency); + if (strcmp($object->budget_amount, '')) print price($object->budget_amount,'',$langs,1,0,0,$conf->currency); print ''; // Description @@ -788,7 +824,24 @@ else print ''; - + // Change probability from status + print ''; + + /* * Boutons actions */ diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index a0a6bd7ae94..bf08da2231e 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -231,11 +231,12 @@ class Project extends CommonObject global $langs, $conf; $error=0; - + // Clean parameters $this->title = trim($this->title); $this->description = trim($this->description); if ($this->opp_amount < 0) $this->opp_amount=''; + if ($this->opp_percent < 0) $this->opp_percent=''; if (dol_strlen(trim($this->ref)) > 0) { @@ -247,7 +248,7 @@ class Project extends CommonObject $sql.= ", description = '" . $this->db->escape($this->description) . "'"; $sql.= ", fk_soc = " . ($this->socid > 0 ? $this->socid : "null"); $sql.= ", fk_statut = " . $this->statut; - $sql.= ", fk_opp_status = " . ($this->opp_status > 0 ? $this->opp_status : 'null'); + $sql.= ", fk_opp_status = " . ((is_numeric($this->opp_status) && $this->opp_status != '') ? $this->opp_status : 'null'); $sql.= ", opp_percent = " . ((is_numeric($this->opp_percent) && $this->opp_percent != '') ? $this->opp_percent : 'null'); $sql.= ", public = " . ($this->public ? 1 : 0); $sql.= ", datec=" . ($this->date_c != '' ? "'".$this->db->idate($this->date_c)."'" : 'null'); diff --git a/htdocs/projet/graph_opportunities.inc.php b/htdocs/projet/graph_opportunities.inc.php index 6cae34bddfa..558bd7307ee 100644 --- a/htdocs/projet/graph_opportunities.inc.php +++ b/htdocs/projet/graph_opportunities.inc.php @@ -1,7 +1,7 @@ global->PROJECT_USE_OPPORTUNITIES)) { - $sql = "SELECT COUNT(p.rowid) as nb, SUM(p.opp_amount) as opp_amount, p.fk_opp_status as opp_status"; + $sql = "SELECT COUNT(p.rowid) as nb, SUM(p.opp_amount) as opp_amount, SUM(p.opp_amount * p.opp_percent) as ponderated_opp_amount, p.fk_opp_status as opp_status"; $sql.= " FROM ".MAIN_DB_PREFIX."projet as p"; $sql.= " WHERE p.entity = ".$conf->entity; $sql.= " AND p.fk_statut = 1"; @@ -9,6 +9,7 @@ if (! empty($conf->global->PROJECT_USE_OPPORTUNITIES)) if ($socid) $sql.= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".$socid.")"; $sql.= " GROUP BY p.fk_opp_status"; $resql = $db->query($sql); + if ($resql) { $num = $db->num_rows($resql); @@ -32,7 +33,7 @@ if (! empty($conf->global->PROJECT_USE_OPPORTUNITIES)) $valsamount[$obj->opp_status]=$obj->opp_amount; $totalnb+=$obj->nb; $totalamount+=$obj->opp_amount; - $ponderated_opp_amount = $ponderated_opp_amount + price2num($listofoppstatus[$obj->opp_status] * $obj->opp_amount / 100); + $ponderated_opp_amount+=$obj->ponderated_opp_amount; } $total+=$row[0]; } @@ -40,6 +41,8 @@ if (! empty($conf->global->PROJECT_USE_OPPORTUNITIES)) } $db->free($resql); + $ponderated_opp_amount = $ponderated_opp_amount / 100; + print ''; print ''."\n"; $var=true; @@ -53,7 +56,7 @@ if (! empty($conf->global->PROJECT_USE_OPPORTUNITIES)) if (empty($labelstatus)) $labelstatus=$listofopplabel[$status]; //$labelstatus .= ' ('.$langs->trans("Coeff").': '.price2num($listofoppstatus[$status]).')'; - $labelstatus .= ' - '.price2num($listofoppstatus[$status]).'%'; + //$labelstatus .= ' - '.price2num($listofoppstatus[$status]).'%'; $dataseries[]=array('label'=>$labelstatus,'data'=>(isset($valsamount[$status])?(float) $valsamount[$status]:0)); if (! $conf->use_javascript_ajax) @@ -75,7 +78,7 @@ if (! empty($conf->global->PROJECT_USE_OPPORTUNITIES)) //if ($totalinprocess != $total) //print ''; print ''; - print ''; + print ''; print "
'.$langs->trans("Statistics").' - '.$langs->trans("OpportunitiesStatusForOpenedProjects").'
'.$langs->trans("Total").' ('.$langs->trans("CustomersOrdersRunning").')'.$totalinprocess.'
'.$langs->trans("OpportunityTotalAmount").''.price($totalamount, 0, '', 1, -1, -1, $conf->currency).'
'.$langs->trans("OpportunityPonderatedAmount").''.price($ponderated_opp_amount, 0, '', 1, -1, -1, $conf->currency).'
'.$langs->trans("OpportunityPonderatedAmount").''.price(price2num($ponderated_opp_amount,'MT'), 0, '', 1, -1, -1, $conf->currency).'

"; } else diff --git a/htdocs/projet/list.php b/htdocs/projet/list.php index b5fb7e31666..7eea03111ee 100644 --- a/htdocs/projet/list.php +++ b/htdocs/projet/list.php @@ -1,6 +1,6 @@ - * Copyright (C) 2004-2015 Laurent Destailleur + * Copyright (C) 2004-2016 Laurent Destailleur * Copyright (C) 2005 Marc Bariley / Ocebo * Copyright (C) 2005-2010 Regis Houssin * Copyright (C) 2013 Cédric Salvador @@ -70,6 +70,7 @@ $search_year=GETPOST("search_year"); $search_all=GETPOST("search_all"); $search_status=GETPOST("search_status",'int'); $search_opp_status=GETPOST("search_opp_status",'alpha'); +$search_opp_percent=GETPOST("search_opp_percent",'alpha'); $search_public=GETPOST("search_public",'int'); $search_user=GETPOST('search_user','int'); $search_sale=GETPOST('search_sale','int'); @@ -127,8 +128,9 @@ $arrayfields=array( 'p.datee'=>array('label'=>$langs->trans("DateEnd"), 'checked'=>1, 'position'=>101), 'p.public'=>array('label'=>$langs->trans("Visibility"), 'checked'=>1, 'position'=>102), 'p.opp_amount'=>array('label'=>$langs->trans("OpportunityAmountShort"), 'checked'=>1, 'enabled'=>$conf->global->PROJECT_USE_OPPORTUNITIES, 'position'=>103), - 'p.fk_opp_status'=>array('label'=>$langs->trans("OpportunityStatusShort"), 'checked'=>1, 'enabled'=>$conf->global->PROJECT_USE_OPPORTUNITIES, 'position'=>104), - 'p.datec'=>array('label'=>$langs->trans("DateCreationShort"), 'checked'=>0, 'position'=>500), + 'p.fk_opp_status'=>array('label'=>$langs->trans("OpportunityStatusShort"), 'checked'=>1, 'enabled'=>$conf->global->PROJECT_USE_OPPORTUNITIES, 'position'=>104), + 'p.opp_percent'=>array('label'=>$langs->trans("OpportunityProbabilityShort"), 'checked'=>1, 'enabled'=>$conf->global->PROJECT_USE_OPPORTUNITIES, 'position'=>105), + 'p.datec'=>array('label'=>$langs->trans("DateCreationShort"), 'checked'=>0, 'position'=>500), 'p.tms'=>array('label'=>$langs->trans("DateModificationShort"), 'checked'=>0, 'position'=>500), 'p.fk_statut'=>array('label'=>$langs->trans("Status"), 'checked'=>1, 'position'=>1000), ); @@ -208,7 +210,7 @@ if (count($listofprojectcontacttype) == 0) $listofprojectcontacttype[0]='0'; $distinct='DISTINCT'; // We add distinct until we are added a protection to be sure a contact of a project and task is only once. $sql = "SELECT ".$distinct." p.rowid as projectid, p.ref, p.title, p.fk_statut, p.fk_opp_status, p.public, p.fk_user_creat"; -$sql.= ", p.datec as date_creation, p.dateo as date_start, p.datee as date_end, p.opp_amount, p.tms as date_update"; +$sql.= ", p.datec as date_creation, p.dateo as date_start, p.datee as date_end, p.opp_amount, p.opp_percent, p.tms as date_update"; $sql.= ", s.nom as name, s.rowid as socid"; $sql.= ", cls.code as opp_status_code"; // Add fields for extrafields @@ -311,6 +313,7 @@ if ($resql) if ($search_societe != '') $param.='&search_societe='.$search_societe; if ($search_status >= 0) $param.='&search_status='.$search_status; if ((is_numeric($search_opp_status) && $search_opp_status >= 0) || in_array($search_opp_status, array('all','none'))) $param.='&search_opp_status='.urlencode($search_opp_status); + if ((is_numeric($search_opp_percent) && $search_opp_percent >= 0) || in_array($search_opp_percent, array('all','none'))) $param.='&search_opp_percent='.urlencode($search_opp_percent); if ($search_public != '') $param.='&search_public='.$search_public; if ($search_user > 0) $param.='&search_user='.$search_user; if ($search_sale > 0) $param.='&search_sale='.$search_sale; @@ -392,7 +395,8 @@ if ($resql) if (! empty($arrayfields['p.datee']['checked'])) print_liste_field_titre($arrayfields['p.datee']['label'],$_SERVER["PHP_SELF"],"p.datee","",$param,'align="center"',$sortfield,$sortorder); if (! empty($arrayfields['p.public']['checked'])) print_liste_field_titre($arrayfields['p.public']['label'],$_SERVER["PHP_SELF"],"p.public","",$param,"",$sortfield,$sortorder); if (! empty($arrayfields['p.opp_amount']['checked'])) print_liste_field_titre($arrayfields['p.opp_amount']['label'],$_SERVER["PHP_SELF"],'p.opp_amount',"",$param,'align="right"',$sortfield,$sortorder); - if (! empty($arrayfields['p.fk_opp_status']['checked'])) print_liste_field_titre($arrayfields['p.fk_opp_status']['label'],$_SERVER["PHP_SELF"],'p.fk_opp_status',"",$param,'align="center"',$sortfield,$sortorder); + if (! empty($arrayfields['p.fk_opp_status']['checked'])) print_liste_field_titre($arrayfields['p.fk_opp_status']['label'],$_SERVER["PHP_SELF"],'p.fk_opp_status',"",$param,'align="center"',$sortfield,$sortorder); + if (! empty($arrayfields['p.opp_percent']['checked'])) print_liste_field_titre($arrayfields['p.opp_percent']['label'],$_SERVER["PHP_SELF"],'p.opp_percent',"",$param,'align="right"',$sortfield,$sortorder); // Extra fields if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) { @@ -475,6 +479,11 @@ if ($resql) print $formproject->selectOpportunityStatus('search_opp_status',$search_opp_status,1,1,1); print ''; } + if (! empty($arrayfields['p.opp_percent']['checked'])) + { + print ''; + print ''; + } // Extra fields if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) { @@ -559,7 +568,7 @@ if ($resql) } print ''; } - // Sales Rapresentatives + // Sales Representatives if (! empty($arrayfields['commercial']['checked'])) { print ''; @@ -623,7 +632,7 @@ if ($resql) if (! empty($arrayfields['p.opp_amount']['checked'])) { print ''; - if ($obj->opp_status_code) print price($obj->opp_amount, 1, '', 1, - 1, - 1, $conf->currency); + if ($obj->opp_status_code) print price($obj->opp_amount, 1, '', 1, -1, -1, $conf->currency); print ''; } if (! empty($arrayfields['p.fk_opp_status']['checked'])) @@ -632,6 +641,12 @@ if ($resql) if ($obj->opp_status_code) print $langs->trans("OppStatusShort".$obj->opp_status_code); print ''; } + if (! empty($arrayfields['p.opp_percent']['checked'])) + { + print ''; + if ($obj->opp_percent) print price($obj->opp_percent, 1, '', 1, 0).'%'; + print ''; + } // Extra fields if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) { diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index ac0adf33c77..5ed3655615e 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -395,7 +395,7 @@ if ($id > 0 || ! empty($ref)) if (count($contactsoftask)>0) { $userid=$contactsoftask[0]; - print $form->select_dolusers((GETPOST('userid')?GETPOST('userid'):$userid), 'userid', 0, '', 0, '', $contactsoftask, 0, 0, 0, '', 0, $langs->trans("ResourceNotAssignedToTask")); + print $form->select_dolusers((GETPOST('userid')?GETPOST('userid'):$userid), 'userid', 0, '', 0, '', $contactsoftask, 0, 0, 0, '', 0, $langs->trans("ResourceNotAssignedToTheTask")); } else { @@ -405,7 +405,7 @@ if ($id > 0 || ! empty($ref)) // Note print ''; - print ''; + print ''; print ''; // Progress declared @@ -528,7 +528,7 @@ if ($id > 0 || ! empty($ref)) print ''; if ($_GET['action'] == 'editline' && $_GET['lineid'] == $task_time->rowid) { - print ''; + print ''; } else { diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index ccb3f01d293..30f97b557d4 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -1195,7 +1195,7 @@ div.vmenu, td.vmenu { .searchform { padding-top: 4px; } a.vmenu:link, a.vmenu:visited, a.vmenu:hover, a.vmenu:active { font-size:px; font-family: ; text-align: ; font-weight: bold; } -font.vmenudisabled { font-size:px; font-family: ; text-align: ; font-weight: bold; color: #aaa; } +font.vmenudisabled { font-size:px; font-family: ; text-align: ; font-weight: bold; color: #aaa; margin-left: 4px; } a.vmenu:link, a.vmenu:visited { color: #; } a.vsmenu:link, a.vsmenu:visited, a.vsmenu:hover, a.vsmenu:active, span.vsmenu { font-size:px; font-family: ; text-align: ; font-weight: normal; color: #202020; margin: 1px 1px 1px 8px; } @@ -2233,6 +2233,10 @@ div.pagination li.litext a:hover { background-color: transparent; background-image: none; } +div.pagination li.litext a:hover { + background-color: transparent; + background-image: none; +} dol_use_jmobile)) { ?> div.pagination li.litext { padding-top: 13px; diff --git a/htdocs/theme/md/img/object_billa.png b/htdocs/theme/md/img/object_billa.png index 19d4be8371d..1485aea5aef 100644 Binary files a/htdocs/theme/md/img/object_billa.png and b/htdocs/theme/md/img/object_billa.png differ diff --git a/htdocs/theme/md/img/object_billd.png b/htdocs/theme/md/img/object_billd.png index 19d4be8371d..93b0e55d046 100644 Binary files a/htdocs/theme/md/img/object_billd.png and b/htdocs/theme/md/img/object_billd.png differ diff --git a/htdocs/theme/md/img/object_billr.png b/htdocs/theme/md/img/object_billr.png index 19d4be8371d..e921b9d9f1f 100644 Binary files a/htdocs/theme/md/img/object_billr.png and b/htdocs/theme/md/img/object_billr.png differ diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 782eb0d66a2..02896756c64 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -1231,11 +1231,11 @@ div.vmenu, td.vmenu { .searchform { padding-top: 8px; } a.vmenu:link, a.vmenu:visited, a.vmenu:hover, a.vmenu:active { font-size:px; font-family: ; text-align: ; font-weight: bold; } -font.vmenudisabled { font-size:px; font-family: ; text-align: ; font-weight: bold; color: #93a5aa; } +font.vmenudisabled { font-size:px; font-family: ; text-align: ; font-weight: bold; color: #aaa; margin-left: 4px; } a.vmenu:link, a.vmenu:visited { color: #; } a.vsmenu:link, a.vsmenu:visited, a.vsmenu:hover, a.vsmenu:active, span.vsmenu { font-size:px; font-family: ; text-align: ; font-weight: normal; color: #202020; margin: 1px 1px 1px 8px; } -font.vsmenudisabled { font-size:px; font-family: ; text-align: ; font-weight: normal; color: #93a5aa; } +font.vsmenudisabled { font-size:px; font-family: ; text-align: ; font-weight: normal; color: #aaa; } a.vsmenu:link, a.vsmenu:visited { color: #; } font.vsmenudisabledmargin { margin: 1px 1px 1px 8px; } diff --git a/htdocs/webservices/server_thirdparty.php b/htdocs/webservices/server_thirdparty.php index 542e2980c45..50b8e80e363 100644 --- a/htdocs/webservices/server_thirdparty.php +++ b/htdocs/webservices/server_thirdparty.php @@ -685,9 +685,9 @@ function getListOfThirdParties($authentication,$filterthirdparty) foreach($filterthirdparty as $key => $val) { if ($key == 'name' && $val != '') $sql.=" AND s.name LIKE '%".$db->escape($val)."%'"; - if ($key == 'client' && $val != '') $sql.=" AND s.client = ".$db->escape($val); - if ($key == 'supplier' && $val != '') $sql.=" AND s.fournisseur = ".$db->escape($val); - if ($key == 'category' && $val != '') $sql.=" AND s.rowid IN (SELECT fk_soc FROM ".MAIN_DB_PREFIX."categorie_societe WHERE fk_categorie=".$db->escape($val).") "; + if ($key == 'client' && (int) $val > 0) $sql.=" AND s.client = ".$db->escape($val); + if ($key == 'supplier' && (int) $val > 0) $sql.=" AND s.fournisseur = ".$db->escape($val); + if ($key == 'category' && (int) $val > 0) $sql.=" AND s.rowid IN (SELECT fk_soc FROM ".MAIN_DB_PREFIX."categorie_societe WHERE fk_categorie=".$db->escape($val).") "; } dol_syslog("Function: getListOfThirdParties", LOG_DEBUG);