diff --git a/build/makepack-timesheet.conf b/build/makepack-timesheet.conf index 63d6b69f..150e3576 100644 --- a/build/makepack-timesheet.conf +++ b/build/makepack-timesheet.conf @@ -21,6 +21,7 @@ htdocs/timesheet/class/TimesheetUserTasks.class.php htdocs/timesheet/class/index.php #homebox htdocs/timesheet/core/boxes/box_approval.php +htdocs/timesheet/core/boxes/box_time.php htdocs/timesheet/core/boxes/index.php #css htdocs/timesheet/core/css/timesheet.css diff --git a/htdocs/timesheet/AttendanceClock.php b/htdocs/timesheet/AttendanceClock.php index 7fe44dcb..e742a555 100644 --- a/htdocs/timesheet/AttendanceClock.php +++ b/htdocs/timesheet/AttendanceClock.php @@ -103,7 +103,8 @@ if (!empty($token)) { unset($_SESSION['timesheet'][$token]); } - +$token = getToken(); +$_SESSION['timesheet'][$token] = array(); /*************************************************** * VIEW * @@ -167,6 +168,7 @@ $html .= ''; } $html .= ''; +$html .= '\n"; $htmltmp .= $timesheet_attendance->printHTMLTaskList($headers, $userid); $pattern = "/(progressTask\[[^\]]+\]\[[^\]]+\])/i"; $replacement = '$1" onchange="updateProgress(event);'; diff --git a/htdocs/timesheet/Timesheet.php b/htdocs/timesheet/Timesheet.php index 564bcd1c..9cbbd5f8 100644 --- a/htdocs/timesheet/Timesheet.php +++ b/htdocs/timesheet/Timesheet.php @@ -49,6 +49,8 @@ $userid = is_object($user)?$user->id:$user; $postUserId = GETPOST('userid', 'int'); $submitted = GETPOST('submit', 'alpha'); +$submitted_next = GETPOST('submit_next', 'alpha'); +$save_next = GETPOST('save_next', 'alpha'); $tsUserId = GETPOST('tsUserId', 'int'); $admin = $user->admin || $user->rights->timesheet->timesheet->admin; @@ -66,7 +68,7 @@ } $SubordiateIds = getSubordinates($db, $userid, 2, array(), ALL, $entity = '1'); //$SubordiateIds[] = $userid; - if ($newuserid > 0 && in_array($newuserid, $SubordiateIds) || $admin) { + if ($newuserid > 0 && in_array($newuserid, $SubordiateIds) || $admin || $newuserid == $userid) { $SubordiateIds[] = $userid; $userid = $newuserid; } elseif ($action == 'getOtherTs') { @@ -124,7 +126,7 @@ $task_timesheet->update($user); } $ret = $task_timesheet->updateActuals($tasktab, $notesTask, $progressTask); - if ($submitted) { + if ($submitted || $submitted_next) { $task_timesheet->setStatus($user, SUBMITTED); $ret++; //$task_timesheet->status = "SUBMITTED"; @@ -160,6 +162,15 @@ if (!empty($token)) { unset($_SESSION['timesheet'][$token]); } + +if ($submitted_next ||$saved_next ){ + $dateStart = getStartDate($dateStart, 1); + $_SESSION["dateStart"] = $dateStart ; +} + + + + $task_timesheet->fetchAll($dateStart, $whitelistmode); if ($action == 'importCalandar'){ $task_timesheet->importCalandar(); diff --git a/htdocs/timesheet/TimesheetProjectInvoice.php b/htdocs/timesheet/TimesheetProjectInvoice.php index 5b864c1a..0f3e41f9 100644 --- a/htdocs/timesheet/TimesheetProjectInvoice.php +++ b/htdocs/timesheet/TimesheetProjectInvoice.php @@ -147,8 +147,23 @@ $Form .= ''.$langs->trans("Custom").':'.$langs->trans("Description").''.$langs->trans("Custom").':'.$langs->trans("UnitPriceHT").''; $Form .= ''.$langs->trans("Custom").':'.$langs->trans("VAT").''.$langs->trans("unitDuration").''.$langs->trans("savedDuration").''; $form = new Form($db); + $otherchoices = array('-999'=> $langs->transnoentities('not2invoice'), + '-998' => $langs->transnoentities('never2invoice')); + if ($propalId > 0){ + require_once DOL_DOCUMENT_ROOT."/comm/propal/class/propal.class.php"; + $propal = new Propal($db); + $propal->fetch($propalId); + $propal->fetch_lines(); + foreach($propal->lines as $lid => $line){ + if($line->product_type == 1){ + if ($line->fk_product) $line->label = getproductlabel($line->fk_product); + $otherchoices[-$lid] = $langs->transnoentities('Proposal').":".$line->label; + } + } + } + foreach ($resArray as $res) { - $Form .= htmlPrintServiceChoice($res["USER"], $res["TASK"], 'oddeven', $res["DURATION"], $res['LIST'], $mysoc, $socid); + $Form .= htmlPrintServiceChoice($res["USER"], $res["TASK"], 'oddeven', $res["DURATION"], $res['LIST'], $mysoc, $socid, $otherchoices); } $Form .= ''; $Form .= '\n"; @@ -177,8 +192,118 @@ $resArray = $_POST['userTask']; $hoursPerDay = $conf->global->TIMESHEET_DAY_DURATION; $task_time_array = array(); + $task_time_array_never = array(); + // copy the propal lines + $lineCount = 0; + // id -> db id + $propallines = []; + + if ( $propalId > 0) { // PROPAL + require_once DOL_DOCUMENT_ROOT."/comm/propal/class/propal.class.php"; + $propal = new Propal($db); + $propal->id= $propalId; + $propal->fetch_lines(); + foreach($propal->lines as $lid => $line){ + $label = (!empty($line->label) ? $line->label : ''); + $desc = (!empty($line->desc) ? $line->desc : $line->libelle); + $lineCount ++; + $product_type = ($line->product_type ? $line->product_type : 0); + // Date start + $date_start = false; + if ($line->date_debut_prevue) { + $date_start = $line->date_debut_prevue; + } + if ($line->date_debut_reel) { + $date_start = $line->date_debut_reel; + } + if ($line->date_start) { + $date_start = $line->date_start; + } + + // Date end + $date_end = false; + if ($line->date_fin_prevue) { + $date_end = $line->date_fin_prevue; + } + if ($line->date_fin_reel) { + $date_end = $line->date_fin_reel; + } + if ($line->date_end) { + $date_end = $line->date_end; + } + + // Reset fk_parent_line for no child products and special product + if (($line->product_type != 9 && empty($line->fk_parent_line)) || $line->product_type == 9) { + $fk_parent_line = 0; + } + + // Extrafields + if (method_exists($line, 'fetch_optionals')) { + $line->fetch_optionals(); + $array_options = $line->array_options; + } + + $tva_tx = $line->tva_tx; + if (!empty($line->vat_src_code) && !preg_match('/\(/', $tva_tx)) { + $tva_tx .= ' ('.$line->vat_src_code.')'; + } + + // View third's localtaxes for NOW and do not use value from origin. + // TODO Is this really what we want ? Yes if source is template invoice but what if proposal or order ? + $localtax1_tx = get_localtax($tva_tx, 1, $object->thirdparty); + $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty); + $result = 0; + $postdata['prod_entry_mode'] = 'predef'; + $postdata['dp_desc'] = $desc; + $postdata['tva_tx'] = $$tva_tx; + $postdata['price_ht'] =$line->total_ht; + $postdata['qty'] = (float) $line->qty; + if (!$conf->global->TIMESHEET_EVAL_ADDLINE){ + $result = $object->addline( + $desc, + $line->subprice, + $line->qty, + $tva_tx, + $localtax1_tx, + $localtax2_tx, + $line->fk_product, + $line->remise_percent, + $date_start, + $date_end, + 0, + $line->info_bits, + $line->fk_remise_except, + 'HT', + 0, + $product_type, + $line->rang, + $line->special_code, + $object->origin, + $line->rowid, + $fk_parent_line, + $line->fk_fournprice, + $line->pa_ht, + $label, + $array_options, + $line->situation_percent, + $line->fk_prev_id, + $line->fk_unit + ); + }else{ + $post_temp = $_POST; + $_POST = $postdata; + ob_start(); + eval($invoicecard); + ob_end_clean(); + $_POST = $post_temp; + $result = get_lastest_id('facture_fourn_det'); + } + if ($result>0)$propallines[$lineCount] = $result; + } + } + if ($id > 0 && is_array($resArray)) { $db->commit(); $invoicecard = str_replace( @@ -188,12 +313,40 @@ foreach ($resArray as $uId => $userTaskService) { //$userTaskService[$user][$task] = array('duration', 'VAT', 'Desc', 'PriceHT', 'Service', 'unit_duration', 'unit_duration_unit'); if (is_array($userTaskService))foreach ($userTaskService as $tId => $service) { + $durationTab = explode(':', $service['duration']); $duration = $durationTab[1]*60 + $durationTab[0]*3600; //$startday = dol_mktime(12, 0, 0, $month, 1, $year); //$endday = dol_mktime(12, 0, 0, $month, date('t', $startday), $year); $details = ''; - $result = ''; + $result = 0; + $factor = 1; + $unit_duration_unit = $service['unit_duration_unit']; + switch($unit_duration_unit){ + case 'h': + $unit_factor = 3600; + break; + case 'i': + $unit_factor = 60; + break; + case 's': + $unit_factor = 1; + break; + case 'w': + $unit_factor = 3600 * $hoursPerDay * 5; + break; + case 'm': + $unit_factor = 3600 * $hoursPerDay * 65 / 3; + break; + case 'y': + $unit_factor = 3600 * $hoursPerDay * 260; + break; + case 'l': + $unit_factor = $duration; + case 'd': + default: + $unit_factor = $hoursPerDay * 3600; + } if (($tId!='any') && $conf->global->TIMESHEET_INVOICE_SHOW_TASK)$details = "\n".$service['taskLabel']; if (($uId!='any')&& $conf->global->TIMESHEET_INVOICE_SHOW_USER)$details .= "\n".$service['userName']; //prepare the CURL params @@ -207,48 +360,12 @@ $postdata['date_endmonth'] = date('m', $dateEnd); $postdata['date_endyear'] = date('Y', $dateEnd); $postdata['addline']='Add'; - - - - if ($service['Service']>0) { + if ($service['Service'] > 0) { + $localtax1_tx = get_localtax($service['VAT'], 1, $object->thirdparty); $localtax2_tx = get_localtax($service['VAT'], 2, $object->thirdparty); $product = new Product($db); $product->fetch($service['Service']); - - $unit_duration_unit = substr($product->duration, -1); - switch($unit_duration_unit){ - case 'h': - $unit_factor = 3600; - break; - case 'i': - $unit_factor = 60; - break; - case 's': - $unit_factor = 1; - break; - case 'w': - $unit_factor = 3600*$hoursPerDay*5; - break; - case 'm': - $unit_factor = 3600*$hoursPerDay*65/3; - break; - case 'y': - $unit_factor = 3600*$hoursPerDay*260; - break; - case 'd': - default: - $unit_factor = $hoursPerDay*3600; - } - - $factor = intval(substr($product->duration, 0, -1)); - if ($factor == 0)$factor = 1;//to avoid divided by $factor0 - $quantity = round($duration/($factor*$unit_factor), $conf->global->TIMESHEET_ROUND); - $postdata['type'] = -1; - $postdata['prod_entry_mode'] = 'predef'; - $postdata['idprod'] = $service['Service']; - $postdata['qty'] = (float) $quantity; - if ($object->thirdparty->default_lang != '' && is_array($product->multilangs[$object->thirdparty->default_lang])) { $desc = $product->multilangs[$object->thirdparty->default_lang]['description']; @@ -257,6 +374,16 @@ $desc = $product->description; $label = $product->label; } + $factor = intval(substr($product->duration, 0, -1)); + if ($factor == 0) $factor = 1;//to avoid divided by $factor0 + $quantity = ($duration == $factor*$unit_factor) ? 1 : + round($duration/($factor*$unit_factor), $conf->global->TIMESHEET_ROUND); + $postdata['type'] = -1; + $postdata['prod_entry_mode'] = 'predef'; + $postdata['idprod'] = $service['Service']; + $postdata['qty'] = (float) $quantity; + + $prices = $product->getSellPrice( $mysoc,$object->thirdparty); $price_base_type = $prices['price_base_type']; @@ -270,13 +397,23 @@ $localtax1_tx, $localtax2_tx, $service['Service'], 0, $dateStart, $dateEnd, 0, 0, '', $price_base_type, $price_ttc, $product->type, -1, 0, '', 0, 0, null, 0, $label, 0, 100, '', $product->fk_unit); + }else{ + $result = $lineCount; + } + $lineCount ++; + } elseif ($service['Service'] > -997) { // propal + if(isset($task_time_array[$propallines[-$service['Service']]])){ + $task_time_array[$propallines[-$service['Service']]] .= ",".$service['taskTimeList']; + }else{ + $task_time_array[$propallines[-$service['Service']]] = $service['taskTimeList']; } - } elseif ($service['Service']<>-999) { + } elseif ($service['Service'] == -997) { // customized service + $localtax1_tx = get_localtax($service['VAT'], 1, $object->thirdparty); $localtax2_tx = get_localtax($service['VAT'], 2, $object->thirdparty); - $factor = ($service['unit_duration_unit'] == 'h')?3600:$hoursPerDay*3600;//FIXME support week and month - $factor = $factor*intval($service['unit_duration']); - $quantity = round($duration/$factor, $conf->global->TIMESHEET_ROUND); + $factor = intval($service['unit_duration']); + $quantity = ($duration == $factor*$unit_factor) ? 1 : + round($duration/($factor*$unit_factor), $conf->global->TIMESHEET_ROUND); $postdata['type'] = 1; $postdata['prod_entry_mode'] = 'free'; $postdata['dp_desc'] = $service['Desc']; @@ -288,7 +425,13 @@ $quantity, $service['VAT'], $localtax1_tx, $localtax2_tx, '', 0, $dateStart, $dateEnd, 0, 0, '', 'HT', '', 1, -1, 0, '', 0, 0, null, 0, '', 0, 100, '', ''); + }else { + $result = get_lastest_id('facture_fourn_det'); } + + $lineCount ++; + }elseif ($service['Service'] == -998){ // never invoice + $task_time_array_never[] = $service['taskTimeList']; } //add_invoice_line($postdata); @@ -302,11 +445,14 @@ ob_end_clean(); $_POST = $post_temp; } - - if ($service['taskTimeList'] <> '' && $result>0) + // set the taskTimeList to be updated in case of success of the invoice add line + if ($service['taskTimeList'] != '' && ($result>0 )){ $task_time_array[$result] = $service['taskTimeList']; + } } else $error++; } + + // End of object creation, we show it if (1) { if (version_compare(DOL_VERSION, "4.9.9") >= 0) { @@ -314,6 +460,10 @@ //dol_syslog("ProjectInvoice::setnvoice".$idLine.' '.$task_time_list, LOG_DEBUG); Update_task_time_invoice($id, $idLine, $task_time_list); } + foreach ($task_time_array_never AS $idLine => $task_time_list) { + //dol_syslog("ProjectInvoice::setnvoice".$idLine.' '.$task_time_list, LOG_DEBUG); + Update_task_time_invoice(-1, -1, $task_time_list); + } } ob_start(); header('Location: ' . $object->getNomUrl(0, '', 0, 1, '')); @@ -383,7 +533,7 @@ $sqlPropal = array('table' => 'propal' , 'keyfield' => 't.rowid', 'fields' => 't.ref, stp.libelle', 'join' => $joinPropal , 'where' => $socid?('t.fk_soc = '.$socid):'1 = 2', 'tail' => ''); - $htmlPropal = array('name' => 'propalid', 'class' => '', 'otherparam' => '', + $htmlPropal = array('name' => 'propalid', 'class' => 'not_mandatory', 'otherparam' => '', 'ajaxNbChar' => '', 'separator' => ' - '); $addChoices = null; $Form .= ''.$langs->trans('Propal').''; @@ -448,7 +598,7 @@ .(($invoicabletaskOnly == 1)?'checked':'').' >'; $Form .= ''; $Form .= '\n"; // if ($ajaxNbChar >= 0) $Form .= "\n\n"; break; @@ -527,9 +677,10 @@ function reload(form) * @param string $tasktimelist list of the tasktimespendid on which the time was spent * @param type $seller Seller id to calculate VAT * @param type $buyer buyer id to calculate VAT + * @param array(id=> desc) otherchoice * @return string HTML code */ -function htmlPrintServiceChoice($user, $task, $class, $duration, $tasktimelist, $seller, $buyer) +function htmlPrintServiceChoice($user, $task, $class, $duration, $tasktimelist, $seller, $buyer, $addchoices) { global $form, $langs, $conf, $db; $taskLabel = ''; @@ -553,8 +704,7 @@ function htmlPrintServiceChoice($user, $task, $class, $duration, $tasktimelist, $html .= ''; $html .= ''; $defaultService = getDefaultService($user, $task); - $addchoices = array(0 => $langs->transnoentities('Custom').': ' - .$taskLabel, '-999'=> $langs->transnoentities('not2invoice')); + $addchoices[-997] = $langs->transnoentities('Custom').': '.$taskLabel; $ajaxNbChar = $conf->global->PRODUIT_USE_SEARCH_TO_SELECT; $html .= ''; $html .= select_sellist(array('table' => 'product', @@ -582,12 +732,14 @@ function htmlPrintServiceChoice($user, $task, $class, $duration, $tasktimelist, .$user.']['.$task.'][unit_duration]" value = "1" >'; $html .= '
global->TIMESHEET_TIME_TYPE == "days")?'':'checked').'>'.$langs->trans('Hour'); + .(($conf->global->TIMESHEET_TIME_TYPE == "days")?'':'checked').' />'.$langs->trans('Hour'); $html .= '
global->TIMESHEET_TIME_TYPE == "days")?'checked':'').'>'.$langs->trans('Days').''; + .(($conf->global->TIMESHEET_TIME_TYPE == "days")?'checked':'').' />'.$langs->trans('Days'); + $html .= '
'.$langs->trans('Lumpsum').''; $html .= ''; + .' maxlength = "5" name = "userTask['.$user.']['.$task.'][duration]" value = "'.$duration.'" />'; $html .= ''; return $html; } @@ -662,3 +814,34 @@ function Update_task_time_invoice($idInvoice, $idLine, $task_time_list) if ($db->num_rows($resql))$res = true; return $res; } + +/** get the label of a product + * @param int $productId $product Id + * @return sting label + */ +function getproductlabel($productId){ + global $db; + require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; + $product = new Product($db); + $product->fetch($productId); + return $product->getNomUrl(0,'',0,-1,0); +} + +function get_lastest_id($table, $id){ + global $db; + $sql = 'SELECT TOP 1 rowid as lastid FROM'.MAIN_DB_PREFIX.$table + .' WHERE fk_facture_fourn ='.$id + .' ORDER BY rowid DESC'; + $resql = $db->query($sql); + $num = 0; + $resArray = array(); + if ($resql) { + $num = $db->num_rows($resql); + if($num == 1 ) + { + $obj = $db->fetch_object($resql); + return $obj->lastid; + } + } + return 0; +} \ No newline at end of file diff --git a/htdocs/timesheet/TimesheetReportUser.php b/htdocs/timesheet/TimesheetReportUser.php index 89c1cab3..79cd8d0a 100644 --- a/htdocs/timesheet/TimesheetReportUser.php +++ b/htdocs/timesheet/TimesheetReportUser.php @@ -66,7 +66,7 @@ $short = GETPOST('short', 'int'); $invoicedCol = GETPOST('invoicedcol', 'int'); $ungroup = GETPOST('ungroup', 'int'); - +$show_all = GETPOST('showAll', 'int'); //$userSelected = $userList[$userIdSelected]; $year = GETPOST('year', 'int'); @@ -93,8 +93,13 @@ // if the user can see ts for other the user id is diferent $userIdlist = array(); -$userIdlistfull = getSubordinates($db, $userid, 2, array(), ALL, $entity = '1'); -if (!empty($userIdSelected) && $userIdSelected <> -999 && $userIdSelected <> $userid) { +$userIdlistfull = getSubordinates($db, $userid, 2, array(), $admin ? ADMIN : ALL, $entity = '1', $admin); +if ($show_all) +{ + $userIdlistfull[] = $userid; + $userIdlist = $userIdlistfull; + +}else if (!empty($userIdSelected) && $userIdSelected <> $userid) { $userIdlistfull[] = $userid; if (in_array($userIdSelected, $userIdlist) || $admin ) { @@ -104,10 +109,7 @@ unset($action); $userIdlist[] = $userid; } -} elseif ($userIdSelected == -999) -{ - $userIdlist = $userIdlistfull; -}else{ +} else{ $userIdlist[] = $userid; } @@ -163,6 +165,9 @@ '; if($admin){ $form_output .= $form->select_dolusers($userIdSelected, 'userSelected'); + // select short + $form_output .= '
':'>').$langs->trans('All') ; } else { $form_output .= $form->select_dolusers($userIdSelected, 'userSelected', 0, null, 0, $userIdlist); } @@ -222,10 +227,26 @@ $model = $conf->global->TIMESHEET_EXPORT_FORMAT; //if(!empty($querryRes))$form_output .= ''.$langs->trans('TimesheetPDF').''; if ( ! empty( $querryRes ) && $conf->global->MAIN_MODULE_EXPORT ) { - $form_output .= '' . $langs->trans( 'Export' ) . ''; + $form_output .= '' . $langs->trans( 'Export' ) . ''; } if ( ! empty( $querryRes ) ) { - $form_output .= '' . $langs->trans( 'PDF' ) . ''; + $form_output .= '' . $langs->trans( 'PDF' ) . ''; } $form_output .= ''; diff --git a/htdocs/timesheet/TimesheetTeamApproval.php b/htdocs/timesheet/TimesheetTeamApproval.php index b8396b98..2bb01468 100644 --- a/htdocs/timesheet/TimesheetTeamApproval.php +++ b/htdocs/timesheet/TimesheetTeamApproval.php @@ -195,21 +195,23 @@ if ($conf->global->TIMESHEET_ADD_DOCS == 1) { require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; - $formfile = new FormFile($db); $object = $TTU; - $relativepathwithnofile = ''; $modulepart = 'timesheet'; $permission = 1;//$user->rights->timesheet->add; - $param = '&action=viewdoc&id='.$object->id; $ref = dol_sanitizeFileName($object->ref); - $upload_dir = $conf->timesheet->dir_output.'/tasks/' + $upload_dir = $conf->timesheet->dir_output.'/users/' .get_exdir($object->id, 2, 0, 0, $object, 'timesheet').$ref; - $filearray = dol_dir_list($upload_dir, 'files', - 0, '', '\.meta$', $sortfield, + $filearray = dol_dir_list($upload_dir, 'files', 0, '', '\.meta$', $sortfield, (strtolower($sortorder) == 'desc'?SORT_DESC:SORT_ASC), 1); + //$param = 'action = submitfile&id='.$object->id; + $param = ''; + $disablemove = 1; + $formfile = new FormFile($db); ob_start(); - $formfile->list_of_documents($filearray, $object, $modulepart, - $param, 0, $relativepathwithnofile, $permission); + $formfile->list_of_documents( + $filearray, $object, $modulepart, $param, + 0, '', 0, 0, '', 0, '', '', 0, 0, + $upload_dir, $sortfield, $sortorder, $disablemove); $Form .= ob_get_contents().'
'."\n"; ob_end_clean(); } @@ -313,9 +315,10 @@ function getTStobeApproved($level, $offset, $role, $subId) $obj = $db->fetch_object($resql); $tmpTs = NEW TimesheetUserTasks($db, $obj->fk_userid); $tmpTs->id = $obj->rowid; - //$tmpTs->userId = $obj->fk_userid; + $tmpTs->userId = $obj->fk_userid; $tmpTs->date_start = $tmpTs->db->jdate($obj->date_start); - $tmpTs->date_start_end = $tmpTs->db->jdate($obj->date_start); + $tmpTs->ref = $tmpTs->date_start.'_'.$tmpTs->userId; + //$tmpTs->date_end = $tmpTs->db->jdate($obj->date_start); $tmpTs->status = $obj->status; $tmpTs->planned_workload = $obj->planned_workload; $tmpTs->note = $obj->note; diff --git a/htdocs/timesheet/admin/timesheetsetup.php b/htdocs/timesheet/admin/timesheetsetup.php index dac842e4..21a2ab0b 100644 --- a/htdocs/timesheet/admin/timesheetsetup.php +++ b/htdocs/timesheet/admin/timesheetsetup.php @@ -65,7 +65,9 @@ $blockholiday = $conf->global->TIMESHEET_BLOCK_HOLIDAY; $addpublicholidaytime = $conf->global->TIMESHEET_ADD_PUBLICHOLIDAY_TIME; $blockpublicholiday = $conf->global->TIMESHEET_BLOCK_PUBLICHOLIDAY; +$overtimecheckweeks = $conf->global->TIMESHEET_OVERTIME_CHECK_WEEKS; $opendays = str_split($conf->global->TIMESHEET_OPEN_DAYS); + //approval $approvalbyweek = $conf->global->TIMESHEET_APPROVAL_BY_WEEK; $maxApproval = $conf->global->TIMESHEET_MAX_APPROVAL; @@ -73,6 +75,7 @@ if (count($apflows) != 6) { $apflows = array('_', '0', '0', '0', '0', '0'); } + //Invoice part $invoicemethod = $conf->global->TIMESHEET_INVOICE_METHOD; $invoicetasktime = $conf->global->TIMESHEET_INVOICE_TASKTIME; @@ -94,6 +97,7 @@ $exportFormat = $conf->global->TIMESHEET_EXPORT_FORMAT; $evalAddLine = $conf->global->TIMESHEET_EVAL_ADDLINE; $tsRound = intval($conf->global->TIMESHEET_ROUND); +$importagenda = intval($conf->global->TIMESHEET_IMPORT_AGENDA); $dropdownAjax = $conf->global->MAIN_DISABLE_AJAX_COMBOX; $searchbox = intval($conf->global->TIMESHEET_SEARCHBOX); $unblockInvoiced = $conf->global->TIMESHEET_UNBLOCK_INVOICED; @@ -101,6 +105,8 @@ $reportInvoicedCol= $conf->global->TIMESHEET_REPORT_INVOICED_COL; $reportUngroup = $conf->global->TIMESHEET_REPORT_UNGROUP; $allowPublic = $conf->global->TIMESHEET_ALLOW_PUBLIC; + + if (count($opendays)!=8) { $opendays = array('_', '0', '0', '0', '0', '0', '0', '0'); } @@ -216,6 +222,10 @@ function null2int($var, $int = 0) // block public holday $blockpublicholiday = getpost('blockpublicholiday', 'alpha'); dolibarr_set_const($db, "TIMESHEET_BLOCK_PUBLICHOLIDAY", $blockpublicholiday, 'chaine', 0, '', $conf->entity); + + // number of week to check for overtime box + $overtimecheckweeks = getpost('overtimecheckweeks', 'alpha'); + dolibarr_set_const($db, "TIMESHEET_OVERTIME_CHECK_WEEKS", $overtimecheckweeks, 'chaine', 0, '', $conf->entity); //docs $adddocs = getpost('adddocs', 'int'); dolibarr_set_const($db, "TIMESHEET_ADD_DOCS", $adddocs, 'chaine', 0, '', $conf->entity); @@ -238,7 +248,7 @@ function null2int($var, $int = 0) dolibarr_set_const($db, "TIMESHEET_INVOICE_TASKTIME", $invoicetasktime, 'chaine', 0, '', $conf->entity); $invoicetimetype = getpost('invoiceTimeType', 'alpha'); dolibarr_set_const($db, "TIMESHEET_INVOICE_TIMETYPE", $invoicetimetype, 'chaine', 0, '', $conf->entity); - $invoiceservice = getpost('invoiceService', 'int'); + $invoiceservice = getpost('invoiceservice', 'int'); dolibarr_set_const($db, "TIMESHEET_INVOICE_SERVICE", $invoiceservice, 'int', 0, '', $conf->entity); $invoiceshowtask = getpost('invoiceShowTask', 'int'); dolibarr_set_const($db, "TIMESHEET_INVOICE_SHOW_TASK", $invoiceshowtask, 'int', 0, '', $conf->entity); @@ -276,7 +286,8 @@ function null2int($var, $int = 0) dolibarr_set_const($db, "TIMESHEET_ALLOW_PUBLIC", $allowPublic, 'int', 0, '', $conf->entity); $tsRound = getpost('tsRound', 'int'); dolibarr_set_const($db, "TIMESHEET_ROUND", $tsRound, 'int', 0, '', $conf->entity); - + $importagenda = getpost('importagenda', 'int'); + dolibarr_set_const($db, "TIMESHEET_IMPORT_AGENDA", $importagenda, 'int', 0, '', $conf->entity); break; default: @@ -402,6 +413,12 @@ function null2int($var, $int = 0) echo ''.$langs->trans("blockpublicholidayDesc").''; echo '"; +// overtime week to check +echo ''.$langs->trans("overtimeCheckWeeks");//FIXTRAD +echo ''.$langs->trans("overtimeCheckWeeksDesc").'';// FIXTRAD +echo '"; + // add docs echo ''.$langs->trans("adddocs"); echo ''.$langs->trans("adddocsDesc").''; @@ -673,6 +690,11 @@ function null2int($var, $int = 0) echo ''.$langs->trans("tsRoundDesc").''; echo '"; +// IMPORT AGENDA +echo ''.$langs->trans("ImportAgenda"); +echo ''.$langs->trans("ImportAgendaDesc").''; +echo '"; // eval ADDLINE echo ''.$langs->trans("evalAddLine"); echo ''.$langs->trans("evalAddLineDesc").''; @@ -753,9 +775,9 @@ function null2int($var, $int = 0) echo ''.$langs->trans("invoiceService"); echo ''.$langs->trans("invoiceServiceDesc").''; echo ''; -$addchoices = array('-999'=> $langs->transnoentitiesnoconv('not2invoice'), -1=> $langs->transnoentitiesnoconv('Custom')); +$addchoices = array('-999'=> $langs->transnoentitiesnoconv('not2invoice'), -997=> $langs->transnoentitiesnoconv('Custom')); $ajaxNbChar = $conf->global->PRODUIT_USE_SEARCH_TO_SELECT; -$htmlProductArray = array('name' => 'invoiceService', 'ajaxNbChar'=>$ajaxNbChar); +$htmlProductArray = array('name' => 'invoiceservice', 'ajaxNbChar'=>$ajaxNbChar); $sqlProductArray = array('table' => 'product', 'keyfield' => 'rowid', 'fields' => 'ref, label', 'where' => 'tosell = 1 AND fk_product_type = 1', 'separator' => ' - '); print select_sellist($sqlProductArray, $htmlProductArray, $invoiceservice, $addchoices); echo ""; diff --git a/htdocs/timesheet/class/TimesheetReport.class.php b/htdocs/timesheet/class/TimesheetReport.class.php index 783e9b65..672e381c 100644 --- a/htdocs/timesheet/class/TimesheetReport.class.php +++ b/htdocs/timesheet/class/TimesheetReport.class.php @@ -85,26 +85,6 @@ public function initBasic($projectid, $userid, $name, $startDate, $stopDate, $mo $this->invoiceableOnly = $invoiceableOnly; $this->taskarray = $taskarray; $this->projectid = $projectid;// coul - if ($projectid && !is_array($projectid)) { - $this->project[$projectid] = new Project($this->db); - $this->project[$projectid]->fetch($projectid); - $this->ref[$projectid] = $this->project[$projectid]->ref.(($conf->global->TIMESHEET_HIDE_REF == 1) - ?'':' - '.$this->project[$projectid]->title); - $first = true; - $this->thirdparty[$projectid] = new Societe($this->db); - $this->thirdparty[$projectid]->fetch($this->project[$projectid]->socid); - } elseif (is_array($projectid)){ - foreach ($projectid as $id){ - $this->project[$id] = new Project($this->db); - $this->project[$id]->fetch($id); - $this->ref[$id] = $this->project[$id]->ref.(($conf->global->TIMESHEET_HIDE_REF == 1)? - '':' - '.$this->project[$id]->title); - $this->thirdparty[$id] = new Societe($this->db); - $this->thirdparty[$id]->fetch($this->project[$id]->socid); - } - - $first = true; - } $this->userid = $userid;// coul if ($userid && !is_array($userid)) { $this->user[$userid] = new User($this->db); @@ -306,6 +286,8 @@ public function getReportArray($forceGroup = false) $objtsk = new Task($this->db); $odlusrid=0; $objusr = new User($this->db); + $oldsocid = 0; + $objsoc = new Societe($this->db); // Loop on each record found, while($i < $numTaskTime) { @@ -325,7 +307,22 @@ public function getReportArray($forceGroup = false) if ($odlpjtid != $obj->projectid){ $objpjt->fetch($obj->projectid); $odlpjtid = $obj->projectid; - } + } + if ($oldsocid != $objpjt->socid && $objpjt->socid > 0){ + $objsoc->fetch($objpjt->socid); + } + # save the project info + if(!isset($this->project[$objpjt->id])){ + $this->project[$objpjt->id] = $objpjt; + $this->ref[$objpjt->id] = $objpjt->ref.(($conf->global->TIMESHEET_HIDE_REF == 1) + ?'':' - '.$objpjt->title); + $first = true; + $this->thirdparty[$objpjt->id] = new Societe($this->db); + $this->thirdparty[$objpjt->id]->fetch($objpjt->id); + } + + //update third party + $resArray[$obj->id] = array('projectId' => $obj->projectid, 'projectLabel' => $objpjt->ref.(($conf->global->TIMESHEET_HIDE_REF == 0)?'':' - '.$objpjt->title), 'projectRef' => $objpjt->ref, @@ -348,7 +345,9 @@ public function getReportArray($forceGroup = false) 'userLink' => $objusr->getNomUrl(0), 'note' =>($obj->note), 'invoiceable' => ($obj->invoiceable==1)?'1':'0', - 'invoiced' => ($obj->invoiced==1)?'1':'0'); + 'invoiced' => ($obj->invoiced==1)?'1':'0', + 'socname' => $objpjt->socid>0?($objsoc->code_client != ''? $objsoc->code_client.' - ':'').$objsoc->getNomUrl():'' + ); $i++; } $this->db->free($resql); @@ -607,17 +606,17 @@ public function buildFile($model = 'excel2017new', $save = false) 'taskRef' => 'taskRef', 'tasktitle' => 'taskTitle', 'dateDisplay' => 'Date', 'durationHours' => 'Hours', 'durationDays' => 'Days', 'userId' => 'userId', 'firstName' => 'Firstname', 'lastName' => 'Lastname', 'note' => 'Note', - 'invoiceable' => 'Invoiceable','invoiced' => 'Invoiced'); + 'invoiceable' => 'Invoiceable','invoiced' => 'Invoiced', 'socname' => 'ThirdParty' ); $arrayTypes = array('projectRef' => 'TextAuto', 'projectTitle' => 'TextAuto', 'taskRef' => 'TextAuto', 'tasktitle' => 'TextAuto', 'dateDisplay' => 'Date', 'durationHours' => 'TextAuto', 'durationDays' => 'Numeric', 'userId' => 'Numeric', 'firstName' => 'TextAuto', 'lastName' => 'TextAuto', 'note' => 'TextAuto', - 'invoiceable' => 'Numeric','invoiced' => 'TextAuto'); + 'invoiceable' => 'Numeric','invoiced' => 'TextAuto', 'socname' => 'TextAuto'); $arraySelected = array('projectRef' => 'projectRef', 'projectTitle' => 'projectTitle', 'taskRef' => 'taskRef', 'tasktitle' => 'tasktitle', 'userId' => 'userId', 'firstName' => 'firstName', 'lastName' => 'lastName', 'dateDisplay' => 'date', 'durationHours' => 'durationHours', 'durationDays' => 'durationDays', 'note' => 'note', - 'invoiceable' => 'invoiceable','invoiced' => 'invoiced'); + 'invoiceable' => 'invoiceable','invoiced' => 'invoiced', 'socname' => 'socname'); $resArray = $this->getReportArray(!($this->ungroup ==1)); diff --git a/htdocs/timesheet/class/TimesheetTask.class.php b/htdocs/timesheet/class/TimesheetTask.class.php index f9de22f4..4fd0f4c7 100644 --- a/htdocs/timesheet/class/TimesheetTask.class.php +++ b/htdocs/timesheet/class/TimesheetTask.class.php @@ -731,7 +731,7 @@ public function getHTMLLineDayCell($isOpenStatus, $holidayList=array()) if ($unblockInvoiced == 0) $isOpen = $isOpen && !$isInvoiced; if (count($holidayList)>=$dayCur){ $isOpen = $isOpen && - !($blockholiday == 1 && $holidayList[$dayCur]['am'] && $holidayList[$dayCur]['pm']) && + !($blockholiday == 1 && $holidayList[$dayCur]['pmStatus'] == 3 && $holidayList[$dayCur]['pm'] == 3) && !($blockPublicHoliday == 1 && $holidayList[$dayCur]['dayoff']); } diff --git a/htdocs/timesheet/class/TimesheetUserTasks.class.php b/htdocs/timesheet/class/TimesheetUserTasks.class.php index 9d5fbda8..73f4e1a2 100644 --- a/htdocs/timesheet/class/TimesheetUserTasks.class.php +++ b/htdocs/timesheet/class/TimesheetUserTasks.class.php @@ -557,9 +557,9 @@ public function fetchTaskTimesheet($userid = '') $sql .= ' AND (tsk.dateo <= \''.$this->db->idate($datestop).'\' OR tsk.dateo IS NULL)'; // show task only of people on the same project (not used for team leader) if ( !$user->admin && $userid != $user->id && !in_array($userid, $user->getAllChildIds())){ - $sql .= " AND ((tsk.rowid = (SELECT element_id FROM ".MAIN_DB_PREFIX."element_contact as ec LEFT JOIN ".MAIN_DB_PREFIX."c_type_contact as ctc ON(ctc.rowid = ec.fk_c_type_contact AND ctc.active = '1')"; + $sql .= " AND ((tsk.rowid in (SELECT element_id FROM ".MAIN_DB_PREFIX."element_contact as ec LEFT JOIN ".MAIN_DB_PREFIX."c_type_contact as ctc ON(ctc.rowid = ec.fk_c_type_contact AND ctc.active = '1')"; $sql .= " WHERE ec.fk_socpeople = '".$user->id."' AND ctc.element = 'project_task' AND element_id = tsk.rowid ))"; - $sql .= " OR (prj.rowid = (SELECT element_id FROM ".MAIN_DB_PREFIX."element_contact as ec LEFT JOIN ".MAIN_DB_PREFIX."c_type_contact as ctc ON(ctc.rowid = ec.fk_c_type_contact AND ctc.active = '1')"; + $sql .= " OR (prj.rowid in (SELECT element_id FROM ".MAIN_DB_PREFIX."element_contact as ec LEFT JOIN ".MAIN_DB_PREFIX."c_type_contact as ctc ON(ctc.rowid = ec.fk_c_type_contact AND ctc.active = '1')"; $sql .= " WHERE ec.fk_socpeople = '".$user->id."' AND ctc.element = 'project' AND element_id = prj.rowid )))"; } $sql .= ' ORDER BY prj.fk_soc, prjRef, tskRef '; @@ -784,18 +784,15 @@ public function updateStatus($user, $status = 0) public function getHTML( $ajax = false, $Approval = false) { global $langs; - $Form = $this->getHTMLHeader(); + $Form = $this->getHTMLHeader(true); // show the filter - $Form .= ''; - $Form .= ''.$langs->trans("Search").''; - $Form .= ''; $Form .= $this->getHTMLHolidayLines($ajax); $Form .= $this->getHTMLPublicHolidayLines($ajax); - if (!$Approval)$Form .= $this->getHTMLTotal(); + //if (!$Approval)$Form .= $this->getHTMLTotal(); //$Form .= ''; $Form .= $this->getHTMLtaskLines( $ajax); //$Form .= '';// overflow div - $Form .= $this->getHTMLTotal(); + //$Form .= $this->getHTMLTotal(); $Form .= ''; $Form .= $this->getHTMLNote($ajax); if (!$Approval) { @@ -805,19 +802,24 @@ public function getHTML( $ajax = false, $Approval = false) return $Form; } /* function to genegate the timesheet table header - * - * @return string html code + * @param bool $search dd search + * @return string html code */ -public function getHTMLHeader() +public function getHTMLHeader($search = false) { global $langs, $conf; $weeklength = getDayInterval($this->date_start, $this->date_end); $maxColSpan = $weeklength+count($this->headers); $format = ($langs->trans("FormatDateShort")!="FormatDateShort"?$langs->trans("FormatDateShort"):$conf->format_date_short); $html = ''; - $html .= ''; + $html .= ''; $html .= "\nid}\" class = \"noborder\" width = \"100%\">\n"; - ///Whitelist tab + if ($search) { + $html .= ''; + $html .= ''; + $html .= ''; + } + ///Whitelist tab if ($conf->global->TIMESHEET_TIME_SPAN == "month") { $format = "%d"; $html .= ''."\n"; @@ -848,12 +850,14 @@ public function getHTMLHeader() */ public function getHTMLFormHeader($ajax = false) { - global $langs; + global $langs, $conf; $html = 'date_start.'">'.$langs->trans('ImportCalandar').''; - return $html; + if($conf->agenda->enabled && $conf->global->TIMESHEET_IMPORT_AGENDA){ + $html .= ''.$langs->trans('ImportCalandar').''; + } + return $html; } /* function to genegate ttotal line * @@ -889,6 +893,9 @@ public function getHTMLFooter($ajax = false) //$html .= '\n"; if (in_array('1', array_slice($apflows, 1))) { $html .= '\n"; + $html .= '\n"; + }else{ + $html .= '\n"; } $html .= ''.$langs->trans('Cancel').''; } elseif ($this->status == SUBMITTED)$html .= '\n"; @@ -967,7 +974,7 @@ public function getHTMLtaskLines( $ajax = false) $blockOveride = 0; } $Lines .= $row->getTimesheetLine($this->headers, $this->id, $blockOveride, $holiday); - if ($i%10 == 0 && $nbline-$i >5) $Lines .= $this->getHTMLTotal(); + //if ($i%10 == 0 && $nbline-$i >5) $Lines .= $this->getHTMLTotal(); $i++; } } @@ -1118,27 +1125,27 @@ public function getNomUrl($htmlcontent, $id = 0, $ref = '', $withpicto = 0) } return $result; } -/** -* Return HTML to get other user -* -* @param string $idsList list of user id -* @param int $selected id that shoudl be selected -* @param int $admin is the user an admin -* @return string String with URL -*/ -public function getHTMLGetOtherUserTs($idsList, $selected, $admin) -{ - global $langs; - $form = new Form($this->db); - $HTML = ''; - if (!$admin) { - $HTML .= $form->select_dolusers($selected, 'userid', 0, null, 0, $idsList); - } else{ - $HTML .= $form->select_dolusers($selected, 'userid'); + /** + * Return HTML to get other user + * + * @param string $idsList list of user id + * @param int $selected id that shoudl be selected + * @param int $admin is the user an admin + * @return string String with URL + */ + public function getHTMLGetOtherUserTs($idsList, $selected, $admin) + { + global $langs; + $form = new Form($this->db); + $HTML = ''; + if (!$admin) { + $HTML .= $form->select_dolusers($selected, 'userid', 0, null, 0, $idsList); + } else{ + $HTML .= $form->select_dolusers($selected, 'userid'); + } + $HTML .= ' '; + return $HTML; } - $HTML .= ' '; - return $HTML; -} /** * Initialise object with example values * Id must be 0 if object instance is a specimen @@ -1173,6 +1180,7 @@ public function initAsSpecimen($test = false) $this->note = 'this is a test usertasktime'; } } + /****************************************************************************** * * AJAX methods @@ -1310,21 +1318,73 @@ public function sendApprovalReminders() */ public function sendTimesheetReminders() { - //check date: was yesterday a period end day ? - $yesteday = date("Y-m-d"); - 24 * 60 *60; - $date_end = getEndDate($yesteday); - if ($yesteday == $date_end) { + //check date: was yesterday a period end day ? + $date_start = getStartDate(time(), -1); + $date_end = getEndDate($date_start); + $ret = true; + $sql = "SELECT SUM(pt.task_duration)/3600 as duration, u.weeklyhours + u.email, u.weeklyhours + FROM ".MAIN_DB_PREFIX."element_contact as ec ON t.rowid = ec.element_id + LEFT JOIN '.MAIN_DB_PREFIX.'c_type_contact as ctc ON ctc.rowid = fk_c_type_contact + LEFT JOIN llx_projet_task_time pt ON pt.fk_user = fk_socpeople + LEFT JOIN llx_user u ON u.rowid = fk_socpeople + WHERE (ctc.element in (\'project\') + and pt.task_date BETWEEN $date_start AND $date_end + GROUP BY u.rowid "; + + dol_syslog(__METHOD__, LOG_DEBUG); + $emails = array(); + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + for ($i = 0;$i<$num;$i++) { + $obj = $this->db->fetch_object($resql); + // FIXME: addapt weekhour to openday / without holidays (union) + if ($obj->weeklyhours > $obj->duration) { + $emails[$obj->email][] = array( + "weeklyhour" => $obj->date_start, + "duration" => $obj->date_end + ); + } + } + } else { + dol_print_error($db); + $list = array(); + $ret = false; + } + if ($ret != false) { + foreach ($emails as $email => $data) { //get the list of user that have the ts right - $users = []; - //foreach user check if there is: no timesheet approaval or a tta in draft or rejected - // SELECT userid, "-1" as status FROM $user LEFT JOIN tta on userid=fk_user and $yesteray = date_end WHERE tta.id = NULL - // UNION - // SELECT userid, status FROM tta where status in (DRAFT, REJECTED) and $yesteray = date_end + $$url .= '/timesheet/Timesheet.php?dateStart='.$date_start; + $message = $langs->trans( + 'YouHaveMissingTimesheetMsg', + date(' d', $date_start), + $url + ); + $sendto = $email; + + $subject = $langs->transnoentities("YouHaveMissingTimesheet"); + if (!empty($sendto) && $sendto!="NULL") { + include_once DOL_DOCUMENT_ROOT .'/core/class/CMailFile.class.php'; + $mailfile = new CMailFile( + $subject, + $sendto, + null, + $message, + $filename_list = array(), + $mimetype_list = array(), + $mimefilename_list = array(), + $addr_cc, $addr_bcc = 0, + $deliveryreceipt = 0, + $msgishtml = 1 + ); + $mailfile->sendfile(); + } + } - //send email to user that need to submit a timesheet - } - return false; + + } diff --git a/htdocs/timesheet/core/boxes/box_approval.php b/htdocs/timesheet/core/boxes/box_approval.php index 829a38b4..636d3d4a 100644 --- a/htdocs/timesheet/core/boxes/box_approval.php +++ b/htdocs/timesheet/core/boxes/box_approval.php @@ -48,7 +48,7 @@ public function loadBox($max = 5) global $conf, $user, $langs, $db; $this->max = $max; $userid = is_object($user)?$user->id:$user; - $text = $langs->trans('Timesheet'); + $text = $langs->trans('Approval'); $this->info_box_head = array( 'text' => $text, 'limit' => dol_strlen($text) diff --git a/htdocs/timesheet/core/boxes/box_time.php b/htdocs/timesheet/core/boxes/box_time.php new file mode 100644 index 00000000..3395d754 --- /dev/null +++ b/htdocs/timesheet/core/boxes/box_time.php @@ -0,0 +1,187 @@ + + * This program is free software;you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation;either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY;without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** + * \file htdocs/core/boxes/box_time.php + * \ingroup factures + * \brief Module de generation de l'affichage de la box factures + */ +include_once DOL_DOCUMENT_ROOT.'/core/boxes/modules_boxes.php'; +$path = dirname(dirname(dirname(__FILE__))); +set_include_path($path); +require_once 'core/lib/timesheet.lib.php'; +global $dolibarr_main_url_root_alt; +$res = 0; +/** + * Class to manage the box to show last invoices + */ +class box_time extends ModeleBoxes +{ + public $boxcode = "timecount"; + public $boximg = "timesheet"; + public $boxlabel = "TimesheetDelta"; + public $depends = array("timesheet"); + public $db; + public $param; + public $info_box_head = array(); + public $info_box_contents = array(); + /** + * Load data into info_box_contents array to show array later. + * + * @param int $max Maximum number of records to load + * @return void + */ + public function loadBox($max = 5) + { + global $conf, $user, $langs, $db; + $this->max = $max; + $userid = is_object($user)?$user->id:$user; + $text = $langs->trans('TimesheetDelta'); + $this->info_box_head = array( + 'text' => $text, + 'limit' => dol_strlen($text) + ); + $admin = $user->admin || $user->rights->timesheet->timesheet->admin; + if ($user->rights->timesheet->timesheet->user ||$admin) { + $sqlweek = ''; + if ($this->db->type!='pgsql') { + $sqlweek = " + with digit as ( + select 0 as d union all + select 1 union all select 2 union all select 3 union all + select 4 union all select 5 union all select 6 union all + select 7 union all select 8 union all select 9 + ), + seq as ( + select a.d + (10 * b.d) + (100 * c.d) + (1000 * d.d) as num + from digit a + cross join + digit b + cross join + digit c + cross join + digit d + order by 1 + ) + SELECT SUM(pt.task_duration)/3600 as duration, + w.week, u.weeklyhours + FROM (SELECT YEARWEEK(DATE_ADD(NOW(), INTERVAL - num WEEK)) as week + FROM seq WHERE num <= ".$conf->global->TIMESHEET_OVERTIME_CHECK_WEEKS." + AND num > 1 ) as w + LEFT JOIN llx_projet_task_time pt ON YEARWEEK(pt.task_date) = w.week + LEFT JOIN llx_user u ON u.rowid = ".$userid." + + WHERE pt.fk_user = ".$userid." OR pt.fk_user is null + GROUP BY w.week;"; + }else { + // to be validated + $sqlweek = " SELECT SUM(pt.task_duration)/3600 as duration, + TO_CHAR(generate_series, 'YYYYWW') week, u.weeklyhours + FROM (generate_series(DATE_TRUNC('week', NOW() - INTERVAL '".$conf->global->TIMESHEET_OVERTIME_CHECK_WEEKS." WEEK'), DATE_TRUNC('week',NOW()) - INTERVAL 1 WEEK' )) + LEFT JOIN llx_projet_task_time pt ON generate_series = DATE_TRUNC('week',pt.task_date) + LEFT JOIN llx_user u on pt.fk_user = ".$userid." + WHERE pt.fk_user = ".$userid." OR pt.fk_user is null + GROUP BY generate_series;"; + } + $result = $db->query($sqlweek); + $delta = array(); + if ($result) { + $p_duration = array(); // FIXME take worktime as delfaut nb day in week * nb hour per day + $a_duration = array(); + $h_duration = array(); + $num = $db->num_rows($result); + while($num>0) + { + $obj = $db->fetch_object($result); + $p_duration[$obj->week] = isset($obj->weeklyhours) ? $obj->weeklyhours : $conf->global->TIMESHEET_DAY_DURATION * 5; // FIXME take worktime as delfaut nb day in week * nb hour per day + $a_duration[$obj->week] = isset($obj->duration) ? $obj->duration : 0; + $h_duration[$obj->week] = $this->getHolidayTime($obj->week, $userid, $obj->weeklyhours); + $delta[$obj->week] = ($p_duration[$obj->week] - $h_duration[$obj->week] - $a_duration[$obj->week]); + $num--; + } + $i=0; + // create the sums + $max_delta = max($delta); + $sum_delta = array_sum($delta); + if ($max_delta > 0){ + $this->info_box_contents[$i][] = array( + 'td' => 'align = "left"', + 'text' => $langs->trans('Max').': ', + 'text2'=> $conf->global->TIMESHEET_OVERTIME_CHECK_WEEKS.' '.$langs->trans('Weeks'), + 'asis' => 1, + ); + $this->info_box_contents[$i][] = array( + 'td' => 'align = "right"', + 'text' => $max_delta, + 'asis' => 1, + ); + $i++; + } + if ($sum_delta){ + $this->info_box_contents[$i][] = array( + 'td' => 'align = "left"', + 'text' => $langs->trans('Sum').': ', + 'text2'=> $conf->global->TIMESHEET_OVERTIME_CHECK_WEEKS.' '.$langs->trans('Weeks'), + 'asis' => 1, + ); + $this->info_box_contents[$i][] = array( + 'td' => 'align = "right"', + 'text' => $sum_delta, + 'asis' => 1, + ); + $i++; + } + $db->free($result); + } else { + $this->info_box_contents[0][0] = array( + 'td' => 'align = "left"', + 'maxlength' => 500, + 'text' =>($db->error().' sql='.$sqlweek), + ); + } + } else { + $this->info_box_contents[0][0] = array( + 'td' => 'align = "left"', + 'text' => $langs->trans("ReadPermissionNotAllowed"), + ); + } + } + // phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassAfterLastUsed + /** + * Method to show box + * + * @param array $head Array with properties of box title + * @param array $contents Array with properties of box lines + * @param INT $nooutput BLOCK OUTPUT + * @return void + */ + public function showBox($head = null, $contents = null, $nooutput = 0) + { + Parent::showBox($this->info_box_head, $this->info_box_contents); + } + + /** + * Method get the holiday duration + * + * @param int $yearweek yearweek to use + * @param INT $userid id of the user + * @param int $weeklyhours number of + * @return void + */ + public function getHolidayTime($yearweek, $userid, $weeklyhours){ // FIXME should use weeklyhours to get the amout of hours per day. new custom fields nb day worked per week ? + // FIXME should use weeklyhours to get the amout of hours per day. new custom fields nb day worked per week ? + return 0; + } +} diff --git a/htdocs/timesheet/core/js/timesheet.js b/htdocs/timesheet/core/js/timesheet.js index 852085df..d5637992 100644 --- a/htdocs/timesheet/core/js/timesheet.js +++ b/htdocs/timesheet/core/js/timesheet.js @@ -105,6 +105,7 @@ function updateAll(){ err=false; total=0; for(j=0;j TOTAL '; + html += ""; + for (var d = 0; d < daysLenth ; d++) + { + html += ""; + } + newRow.innerHTML= html + ''; + newRow.className = 'lineDynTotal'; + } + nld++;// count to row actually displayed + } + } + + +} + + /* * Function to update the line Total when there is any * @param @@ -269,7 +326,7 @@ function validateTime(object,col_id){ function updateAllLinesTotal(){ - var TotalList=document.getElementsByClassName('lineTotal'); + var TotalList=document.querySelectorAll('.lineTotal'); var nblineTotal = TotalList.length; for(i=0;i$conf->global->TIMESHEET_COL_DRAFT, @@ -115,31 +116,35 @@ function getSubordinates($db, $userid, $depth = 5, $ecludeduserid = array(), $ro $list = $user->getAllChildIds(); } - if ($role == PROJECT || $role == ALL){ + if ($role == PROJECT || $role == ALL || $role == ADMIN){ $sql[0] = 'SELECT DISTINCT fk_socpeople as userid FROM '.MAIN_DB_PREFIX.'element_contact'; - $sql[0] .= ' WHERE element_id in (SELECT element_id'; - $sql[0] .= ' FROM '.MAIN_DB_PREFIX.'element_contact AS ec'; - $sql[0] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_type_contact as ctc ON ctc.rowid = ec.fk_c_type_contact'; - $sql[0] .= ' WHERE ctc.active = \'1\' AND ctc.element in (\'project\', \'project_task\') AND (ctc.code LIKE \'%LEADER%\' OR ctc.code LIKE \'%BILLING%\' OR ctc.code LIKE \'%EXECUTIVE%\')'; - $sql[0] .= ' AND fk_socpeople in ('; - $sql[2] = ')) AND fk_socpeople not in ('; - $sql[4] = ')'; - $idlist = ''; - if (is_array($userid)) { - $ecludeduserid = array_merge($userid, $ecludeduserid); - $idlist = implode(", ", $userid); - } else{ - $ecludeduserid[] = $userid; - $idlist = $userid; - } - $sql[1] = $idlist; - $idlist = ''; - if (is_array($ecludeduserid)) { - $idlist = implode(", ", $ecludeduserid); - } elseif (!empty($ecludeduserid)) { - $idlist = $ecludeduserid; + if ($role != ADMIN){ + $sql[0] .= ' WHERE element_id in (SELECT element_id'; + $sql[0] .= ' FROM '.MAIN_DB_PREFIX.'element_contact AS ec'; + $sql[0] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_type_contact as ctc ON ctc.rowid = ec.fk_c_type_contact'; + if($role == PROJECT)$sql[0] .= ' WHERE ctc.active = \'1\' AND ctc.element in (\'project\', \'project_task\') AND (ctc.code LIKE \'%LEADER%\' OR ctc.code LIKE \'%BILLING%\' OR ctc.code LIKE \'%EXECUTIVE%\')'; + // only billing can see all + if($role == ALL)$sql[0] .= ' WHERE ctc.active = \'1\' AND ctc.element in (\'project\', \'project_task\') AND (ctc.code LIKE \'%BILLING%\')'; + $sql[0] .= ' AND fk_socpeople in ('; + $sql[2] = ')) AND fk_socpeople not in ('; + $sql[4] = ')'; + $idlist = ''; + if (is_array($userid)) { + $ecludeduserid = array_merge($userid, $ecludeduserid); + $idlist = implode(", ", $userid); + } else{ + $ecludeduserid[] = $userid; + $idlist = $userid; + } + $sql[1] = $idlist; + $idlist = ''; + if (is_array($ecludeduserid)) { + $idlist = implode(", ", $ecludeduserid); + } elseif (!empty($ecludeduserid)) { + $idlist = $ecludeduserid; + } + $sql[3] = $idlist; } - $sql[3] = $idlist; ksort($sql, SORT_NUMERIC); $sqlused = implode($sql); dol_syslog('form::get_subordinate role='.$role, LOG_DEBUG); diff --git a/htdocs/timesheet/core/modules/modtimesheet.class.php b/htdocs/timesheet/core/modules/modtimesheet.class.php index da6bc738..798cbbd0 100644 --- a/htdocs/timesheet/core/modules/modtimesheet.class.php +++ b/htdocs/timesheet/core/modules/modtimesheet.class.php @@ -54,7 +54,7 @@ public function __construct($db) $this->editor_name = 'Patrick Delcroix'; $this->editor_url = 'https://github.com/delcroip'; // Possible values for version are: 'development', 'experimental', 'dolibarr' or version - $this->version = '4.4.11'; + $this->version = '4.5.0'; // Key used in llx_cons table to save module status enabled/disabled(where timesheet is value of property name of module in uppercase) $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); // Where to store the module in setup page(0=common, 1=interface, 2=others, 3=very specific) @@ -208,8 +208,13 @@ public function __construct($db) $r++; $this->const[$r] = array("MAIN_DISABLE_AJAX_COMBOX", "int", "0", "disable combo box");// hours or days $r++; - $this->const[$r] = array("TIMESHEET_ALLOW_PUBLIC", "int", "0", "Allow all internal contact to book time on public projects");// hours or days + $this->const[$r] = array("MAIN_DISABLE_AJAX_COMBOX", "int", "0", "disable combo box");// hours or days + $r++; + $this->const[$r] = array("TIMESHEET_OVERTIME_CHECK_WEEKS", "int", "30", "Number of week used for the overwork box");// hours or days + $r++; + $this->const[$r] = array("TIMESHEET_TIMESHEET_IMPORT_AGENDA", "int", "0", "Enable the import agenda button");// hours or days $r++; + //$this->const[2] = array("CONST3", "chaine", "valeur3", "Libelle3"); // Array to add new pages in new tabs // Example: $this->tabs = array('objecttype:+tabname1:Title1:mylangfile@timesheet:$user->rights->timesheet->read:/timesheet/mynewtab1.php?id=__ID__', // To add a new tab identified by code tabname1 @@ -263,10 +268,15 @@ public function __construct($db) // Boxes // Add here list of php file(s) stored in core/boxes that contains class to show a box. $this->boxes = array( - 0 => array( - 'file' => 'box_approval.php@timesheet', - 'note' => 'timesheetApproval', - 'enabledbydefaulton' => 'Home')); // List of boxes + 0 => array( + 'file' => 'box_approval.php@timesheet', + 'note' => 'timesheetApproval', + 'enabledbydefaulton' => 'Home'), + 1 => array( + 'file' => 'box_time.php@timesheet', + 'note' => 'timesheet', + 'enabledbydefaulton' => 'Home') + ); // List of boxes // Example: //$this->boxes=array(array(0 => array('file' => 'myboxa.php', 'note' => '', 'enabledbydefaulton' => 'Home'), 1 => array('file' => 'myboxb.php', 'note' => ''), 2 => array('file' => 'myboxc.php', 'note' => ''));); // Permissions diff --git a/htdocs/timesheet/langs/de_DE/timesheet.lang b/htdocs/timesheet/langs/de_DE/timesheet.lang index eeb2edec..47c469bd 100644 --- a/htdocs/timesheet/langs/de_DE/timesheet.lang +++ b/htdocs/timesheet/langs/de_DE/timesheet.lang @@ -261,3 +261,10 @@ addpublicholidaytimeDesc = Schließen Sie die Feiertagszeit in die Gesamtzeile e blockholidayDesc = Zeiteinträge während der Ferien sperren blockpublicholidayDesc = Sperrzeiteingabe am Feiertag blockpublicholiday = Feiertag sperren +never2invoice = überprüft - nie in Rechnung gestellt +TimesheetDelta = Arbeitszeittabellen-Delta mit Vertragsstunden +Lumpsum = Pauschalbetrag +YouHaveMissingTimesheetMsg = Sie haben einen fehlenden Stundenzettel. \n\n es gibt nur %d h in den Systemen zu Ihren %d Wochenstunden für den Zeitraum %s - %s \n\n +YouHaveMissingTimesheet = Sie haben einen fehlenden Stundenzettel +SaveNext = Speichern & Weiter +SubmitNext = Einreichen & Weiter diff --git a/htdocs/timesheet/langs/en_US/timesheet.lang b/htdocs/timesheet/langs/en_US/timesheet.lang index 65e4ecbe..72dfafea 100644 --- a/htdocs/timesheet/langs/en_US/timesheet.lang +++ b/htdocs/timesheet/langs/en_US/timesheet.lang @@ -261,3 +261,10 @@ addpublicholidaytimeDesc = Include the public holiday time in the total line blockholidayDesc = Block time entries during holidays blockpublicholidayDesc = Block time entry on public holiday blockpublicholiday = Block public holiday +never2invoice = reviewed - Never to invoice +TimesheetDelta = Timesheet delta with contract hours +Lumpsum = Lumpsum +YouHaveMissingTimesheetMsg = You have missing timesheet.\n\nthere is only %d h in the systems on your %d weeklyhours for the period %s - %s\n\n +YouHaveMissingTimesheet = You have missing timesheet +SaveNext = Save & Next +SubmitNext = Submit & Next diff --git a/htdocs/timesheet/langs/es_ES/timesheet.lang b/htdocs/timesheet/langs/es_ES/timesheet.lang index ac9b2e9e..e0ea477f 100644 --- a/htdocs/timesheet/langs/es_ES/timesheet.lang +++ b/htdocs/timesheet/langs/es_ES/timesheet.lang @@ -261,3 +261,10 @@ addpublicholidaytimeDesc = Incluya el tiempo de los días festivos en la línea blockholidayDesc = Bloquear las entradas de tiempo durante las vacaciones blockpublicholidayDesc = Bloqueo de la entrada de tiempo en días festivos blockpublicholiday = Bloquear el día festivo +never2invoice = revisado - Nunca para facturar +TimesheetDelta = Delta de hoja de tiempo con horas de contrato +Lumpsum = Suma fija +YouHaveMissingTimesheetMsg = Le falta la hoja de tiempo. \n\n solo hay %d h en los sistemas en sus %d horas semanales para el período %s - %s \n\n +YouHaveMissingTimesheet = Le falta la hoja de tiempo +SaveNext = Guardar y Siguiente +SubmitNext = Enviar y Siguiente diff --git a/htdocs/timesheet/langs/fr_FR/timesheet.lang b/htdocs/timesheet/langs/fr_FR/timesheet.lang index 7b475e04..373c80b9 100644 --- a/htdocs/timesheet/langs/fr_FR/timesheet.lang +++ b/htdocs/timesheet/langs/fr_FR/timesheet.lang @@ -261,3 +261,10 @@ addpublicholidaytimeDesc = Inclure le temps du jour férié dans la ligne totale blockholidayDesc = Bloquer les entrées de temps pendant les vacances blockpublicholidayDesc = Blocage de la saisie des heures les jours fériés blockpublicholiday = Bloquer les jours fériés +never2invoice = Traité - Ne jamais facturer +TimesheetDelta = Delta de la feuille de temps avec les heures du contrat +Lumpsum = forfaitaire +YouHaveMissingTimesheetMsg = Vous avez une feuille de temps manquante. \n\n il n'y a que %d h dans les systèmes sur vos %d heures hebdomadaires pour la période %s - %s \n\n +YouHaveMissingTimesheet = Il vous manque une feuille de temps +SaveNext = Enregistrer et suivant +SubmitNext = Soumettre & Suivant diff --git a/htdocs/timesheet/langs/it_IT/timesheet.lang b/htdocs/timesheet/langs/it_IT/timesheet.lang index 063bc6a0..348ffbcc 100644 --- a/htdocs/timesheet/langs/it_IT/timesheet.lang +++ b/htdocs/timesheet/langs/it_IT/timesheet.lang @@ -261,3 +261,10 @@ addpublicholidaytimeDesc = Includere il tempo del giorno festivo nella linea tot blockholidayDesc = Bloccare le voci di tempo durante le vacanze blockpublicholidayDesc = Blocca l'inserimento del tempo nei giorni festivi blockpublicholiday = Blocca il giorno festivo +never2invoice = rivisto - Non fatturare mai +TimesheetDelta = Delta del foglio di lavoro con ore di contratto +Lumpsum = Forfettario +YouHaveMissingTimesheetMsg = Hai il foglio presenze mancante. \n\n ci sono solo %d h nei sistemi nelle tue %d ore settimanali per il periodo %s - %s \n\n +YouHaveMissingTimesheet = Hai il foglio presenze mancante +SaveNext = Salva & Avanti +SubmitNext = Invia & Avanti diff --git a/htdocs/timesheet/sql/llx_attendance_event.key.sql b/htdocs/timesheet/sql/llx_attendance_event.key.sql index a7a3bb8e..5446d7e2 100644 --- a/htdocs/timesheet/sql/llx_attendance_event.key.sql +++ b/htdocs/timesheet/sql/llx_attendance_event.key.sql @@ -20,8 +20,8 @@ -- this table is used to store the timesheet favorit -ALTER TABLE llx_attendance_event ADD CONSTRAINT fk_ts_ae_user_idm FOREIGN KEY (fk_user_modification) REFERENCES llx_user(rowid) ON DELETE NO ACTION ON UPDATE CASCADE; -ALTER TABLE llx_attendance_event ADD CONSTRAINT fk_ts_ae_user_id FOREIGN KEY (fk_userid) REFERENCES llx_user(rowid) ON DELETE NO ACTION ON UPDATE CASCADE; -ALTER TABLE llx_attendance_event ADD CONSTRAINT fk_ts_ae_project_id FOREIGN KEY (fk_project) REFERENCES llx_projet(rowid) ON DELETE NO ACTION ON UPDATE CASCADE; -ALTER TABLE llx_attendance_event ADD CONSTRAINT fk_ts_ae_third_party FOREIGN KEY (fk_third_party REFERENCES llx_soc(rowid) ON DELETE NO ACTION ON UPDATE CASCADE; -ALTER TABLE llx_attendance_event ADD CONSTRAINT fk_ts_ae_task FOREIGN KEY (fk_task) REFERENCES llx_projet_task(rowid) ON DELETE NO ACTION ON UPDATE CASCADE; +ALTER TABLE llx_attendance_event ADD CONSTRAINT fk_ts_ae_user_idm FOREIGN KEY (fk_user_modification) REFERENCES llx_user(rowid) ON DELETE SET NULL ON UPDATE CASCADE; +ALTER TABLE llx_attendance_event ADD CONSTRAINT fk_ts_ae_user_id FOREIGN KEY (fk_userid) REFERENCES llx_user(rowid) ON DELETE SET NULL ON UPDATE CASCADE; +ALTER TABLE llx_attendance_event ADD CONSTRAINT fk_ts_ae_project_id FOREIGN KEY (fk_project) REFERENCES llx_projet(rowid) ON DELETE CASCADE ON UPDATE CASCADE; +ALTER TABLE llx_attendance_event ADD CONSTRAINT fk_ts_ae_third_party FOREIGN KEY (fk_third_party REFERENCES llx_soc(rowid) ON DELETE SET NULL ON UPDATE CASCADE; +ALTER TABLE llx_attendance_event ADD CONSTRAINT fk_ts_ae_task FOREIGN KEY (fk_task) REFERENCES llx_projet_task(rowid) ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/htdocs/timesheet/sql/llx_project_task_time_approval.key.sql b/htdocs/timesheet/sql/llx_project_task_time_approval.key.sql index e8ee996a..94dc3982 100644 --- a/htdocs/timesheet/sql/llx_project_task_time_approval.key.sql +++ b/htdocs/timesheet/sql/llx_project_task_time_approval.key.sql @@ -20,16 +20,16 @@ -- this table is used to store the timesheet favorite -ALTER TABLE llx_project_task_time_approval ADD CONSTRAINT fk_ptta_user_idat FOREIGN KEY (fk_user_app_team) REFERENCES llx_user(rowid) ON DELETE NO ACTION ON UPDATE CASCADE; -ALTER TABLE llx_project_task_time_approval ADD CONSTRAINT fk_ptta_user_idap FOREIGN KEY (fk_user_app_project) REFERENCES llx_user(rowid) ON DELETE NO ACTION ON UPDATE CASCADE; -ALTER TABLE llx_project_task_time_approval ADD CONSTRAINT fk_ptta_user_idac FOREIGN KEY (fk_user_app_customer) REFERENCES llx_user(rowid) ON DELETE NO ACTION ON UPDATE CASCADE; -ALTER TABLE llx_project_task_time_approval ADD CONSTRAINT fk_ptta_user_idas FOREIGN KEY (fk_user_app_suplier) REFERENCES llx_user(rowid) ON DELETE NO ACTION ON UPDATE CASCADE; -ALTER TABLE llx_project_task_time_approval ADD CONSTRAINT fk_ptta_user_idac FOREIGN KEY (fk_user_app_other) REFERENCES llx_user(rowid) ON DELETE NO ACTION ON UPDATE CASCADE; +ALTER TABLE llx_project_task_time_approval ADD CONSTRAINT fk_ptta_user_idat FOREIGN KEY (fk_user_app_team) REFERENCES llx_user(rowid) ON DELETE SET NULL ON UPDATE CASCADE; +ALTER TABLE llx_project_task_time_approval ADD CONSTRAINT fk_ptta_user_idap FOREIGN KEY (fk_user_app_project) REFERENCES llx_user(rowid) ON DELETE SET NULL ON UPDATE CASCADE; +ALTER TABLE llx_project_task_time_approval ADD CONSTRAINT fk_ptta_user_idac FOREIGN KEY (fk_user_app_customer) REFERENCES llx_user(rowid) ON DELETE SET NULL ON UPDATE CASCADE; +ALTER TABLE llx_project_task_time_approval ADD CONSTRAINT fk_ptta_user_idas FOREIGN KEY (fk_user_app_suplier) REFERENCES llx_user(rowid) ON DELETE SET NULL ON UPDATE CASCADE; +ALTER TABLE llx_project_task_time_approval ADD CONSTRAINT fk_ptta_user_idac FOREIGN KEY (fk_user_app_other) REFERENCES llx_user(rowid) ON DELETE SET NULL ON UPDATE CASCADE; -ALTER TABLE llx_project_task_time_approval ADD CONSTRAINT fk_ptta_user_idc FOREIGN KEY (fk_user_creation) REFERENCES llx_user(rowid) ON DELETE NO ACTION ON UPDATE CASCADE; -ALTER TABLE llx_project_task_time_approval ADD CONSTRAINT fk_ptta_user_idm FOREIGN KEY (fk_user_modification) REFERENCES llx_user(rowid) ON DELETE NO ACTION ON UPDATE CASCADE; -ALTER TABLE llx_project_task_time_approval ADD CONSTRAINT fk_ptta_user_id FOREIGN KEY (fk_userid) REFERENCES llx_user(rowid) ON DELETE NO ACTION ON UPDATE CASCADE; -ALTER TABLE llx_project_task_time_approval ADD CONSTRAINT fk_ptta_task_id FOREIGN KEY (fk_projet_task) REFERENCES llx_projet_task(rowid) ON DELETE NO ACTION ON UPDATE CASCADE; +ALTER TABLE llx_project_task_time_approval ADD CONSTRAINT fk_ptta_user_idc FOREIGN KEY (fk_user_creation) REFERENCES llx_user(rowid) ON DELETE SET NULL ON UPDATE CASCADE; +ALTER TABLE llx_project_task_time_approval ADD CONSTRAINT fk_ptta_user_idm FOREIGN KEY (fk_user_modification) REFERENCES llx_user(rowid) ON DELETE SET NULL ON UPDATE CASCADE; +ALTER TABLE llx_project_task_time_approval ADD CONSTRAINT fk_ptta_user_id FOREIGN KEY (fk_userid) REFERENCES llx_user(rowid) ON DELETE CASCADE ON UPDATE CASCADE; +ALTER TABLE llx_project_task_time_approval ADD CONSTRAINT fk_ptta_task_id FOREIGN KEY (fk_projet_task) REFERENCES llx_projet_task(rowid) ON DELETE CASCADE ON UPDATE CASCADE; --/*llx_project_task_time_approval remove enum 2.3.3.5 --> 2.4 */ diff --git a/htdocs/timesheet/sql/llx_project_task_timesheet.key.sql b/htdocs/timesheet/sql/llx_project_task_timesheet.key.sql index af3d992e..a71b7c5d 100644 --- a/htdocs/timesheet/sql/llx_project_task_timesheet.key.sql +++ b/htdocs/timesheet/sql/llx_project_task_timesheet.key.sql @@ -17,8 +17,8 @@ -- =================================================================== -- TS Revision 2.0.2 -ALTER TABLE llx_project_task_timesheet ADD CONSTRAINT fk_ptts_user_idc FOREIGN KEY (fk_userid) REFERENCES llx_user(rowid) ON DELETE NO ACTION ON UPDATE CASCADE; -ALTER TABLE llx_project_task_timesheet ADD CONSTRAINT fk_ptts_user_idm FOREIGN KEY (fk_user_modification) REFERENCES llx_user(rowid) ON DELETE NO ACTION ON UPDATE CASCADE; +ALTER TABLE llx_project_task_timesheet ADD CONSTRAINT fk_ptts_user_idc FOREIGN KEY (fk_userid) REFERENCES llx_user(rowid) ON DELETE SET NULL ON UPDATE CASCADE; +ALTER TABLE llx_project_task_timesheet ADD CONSTRAINT fk_ptts_user_idm FOREIGN KEY (fk_user_modification) REFERENCES llx_user(rowid) ON DELETE SET NULL ON UPDATE CASCADE; --/*llx_project_task_timesheet remove enum 2.3.3.5 --> 2.4*/ ALTER TABLE llx_project_task_timesheet MODIFY COLUMN status integer default 1; diff --git a/htdocs/timesheet/sql/llx_projet_task_time.key.sql b/htdocs/timesheet/sql/llx_projet_task_time.key.sql index c59bc731..f6379502 100644 --- a/htdocs/timesheet/sql/llx_projet_task_time.key.sql +++ b/htdocs/timesheet/sql/llx_projet_task_time.key.sql @@ -21,7 +21,7 @@ ALTER TABLE llx_projet_task_time ADD COLUMN status integer default 1; -- enum( ALTER TABLE llx_projet_task_time ADD COLUMN fk_task_time_approval integer; -ALTER TABLE llx_projet_task_time ADD CONSTRAINT fk_ptt_ptta_id FOREIGN KEY (fk_task_time_approval) REFERENCES llx_project_task_time_approval(rowid) ON DELETE NO ACTION ON UPDATE CASCADE; +ALTER TABLE llx_projet_task_time ADD CONSTRAINT fk_ptt_ptta_id FOREIGN KEY (fk_task_time_approval) REFERENCES llx_project_task_time_approval(rowid) ON DELETE SET NULL ON UPDATE CASCADE; --/*llx_projet_task_tim remove enum 2.3.3.5 --> 2.4*/ ALTER TABLE llx_projet_task_time MODIFY COLUMN status integer default 1;
'.$langs->trans("Search").'