Show time to bill and billed in list of tasks

This commit is contained in:
Laurent Destailleur 2019-03-29 14:34:55 +01:00
parent 9a34e58474
commit 697a2e5576
4 changed files with 199 additions and 51 deletions

View File

@ -334,20 +334,21 @@ function project_admin_prepare_head()
/**
* Show task lines with a particular parent
*
* @param string $inc Line number (start to 0, then increased by recursive call)
* @param string $parent Id of parent project to show (0 to show all)
* @param Task[] $lines Array of lines
* @param int $level Level (start to 0, then increased/decrease by recursive call), or -1 to show all level in order of $lines without the recursive groupment feature.
* @param string $var Color
* @param int $showproject Show project columns
* @param int $taskrole Array of roles of user for each tasks
* @param int $projectsListId List of id of project allowed to user (string separated with comma)
* @param int $addordertick Add a tick to move task
* @param int $projectidfortotallink 0 or Id of project to use on total line (link to see all time consumed for project)
* @param string $inc Line number (start to 0, then increased by recursive call)
* @param string $parent Id of parent project to show (0 to show all)
* @param Task[] $lines Array of lines
* @param int $level Level (start to 0, then increased/decrease by recursive call), or -1 to show all level in order of $lines without the recursive groupment feature.
* @param string $var Color
* @param int $showproject Show project columns
* @param int $taskrole Array of roles of user for each tasks
* @param int $projectsListId List of id of project allowed to user (string separated with comma)
* @param int $addordertick Add a tick to move task
* @param int $projectidfortotallink 0 or Id of project to use on total line (link to see all time consumed for project)
* @param string $filterprogresscalc filter text
* @param string $showbilltime Add the column 'TimeToBill' and 'TimeBilled'
* @return void
*/
function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$taskrole, $projectsListId = '', $addordertick = 0, $projectidfortotallink = 0, $filterprogresscalc = '')
function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$taskrole, $projectsListId = '', $addordertick = 0, $projectidfortotallink = 0, $filterprogresscalc = '', $showbilltime=0)
{
global $user, $bc, $langs, $conf, $db;
global $projectstatic, $taskstatic;
@ -370,12 +371,14 @@ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$t
$numlines=count($lines);
// We declare counter as global because we want to edit them into recursive call
global $total_projectlinesa_spent,$total_projectlinesa_planned,$total_projectlinesa_spent_if_planned;
global $total_projectlinesa_spent,$total_projectlinesa_planned,$total_projectlinesa_spent_if_planned,$total_projectlinesa_tobill,$total_projectlinesa_billed;
if ($level == 0)
{
$total_projectlinesa_spent=0;
$total_projectlinesa_planned=0;
$total_projectlinesa_spent_if_planned=0;
$total_projectlinesa_tobill=0;
$total_projectlinesa_billed=0;
}
for ($i = 0 ; $i < $numlines ; $i++)
@ -439,15 +442,25 @@ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$t
print '<tr '.$bc[$var].' id="row-'.$lines[$i]->id.'">'."\n";
$projectstatic->id=$lines[$i]->fk_project;
$projectstatic->ref=$lines[$i]->projectref;
$projectstatic->public=$lines[$i]->public;
$projectstatic->title=$lines[$i]->projectlabel;
$projectstatic->bill_time=$lines[$i]->bill_time;
$taskstatic->id=$lines[$i]->id;
$taskstatic->ref=$lines[$i]->ref;
$taskstatic->label=($taskrole[$lines[$i]->id]?$langs->trans("YourRole").': '.$taskrole[$lines[$i]->id]:'');
$taskstatic->projectstatus = $lines[$i]->projectstatus;
$taskstatic->progress = $lines[$i]->progress;
$taskstatic->fk_statut = $lines[$i]->status;
$taskstatic->datee = $lines[$i]->date_end;
if ($showproject)
{
// Project ref
print "<td>";
//if ($showlineingray) print '<i>';
$projectstatic->id=$lines[$i]->fk_project;
$projectstatic->ref=$lines[$i]->projectref;
$projectstatic->public=$lines[$i]->public;
$projectstatic->title=$lines[$i]->projectlabel;
if ($lines[$i]->public || in_array($lines[$i]->fk_project, $projectsArrayId) || ! empty($user->rights->projet->all->lire)) print $projectstatic->getNomUrl(1);
else print $projectstatic->getNomUrl(1, 'nolink');
//if ($showlineingray) print '</i>';
@ -468,9 +481,6 @@ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$t
}
else
{
$taskstatic->id=$lines[$i]->id;
$taskstatic->ref=$lines[$i]->ref;
$taskstatic->label=($taskrole[$lines[$i]->id]?$langs->trans("YourRole").': '.$taskrole[$lines[$i]->id]:'');
print $taskstatic->getNomUrl(1, 'withproject');
}
print '</td>';
@ -495,10 +505,6 @@ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$t
// Date end
print '<td class="center">';
$taskstatic->projectstatus = $lines[$i]->projectstatus;
$taskstatic->progress = $lines[$i]->progress;
$taskstatic->fk_statut = $lines[$i]->status;
$taskstatic->datee = $lines[$i]->date_end;
print dol_print_date($lines[$i]->date_end, 'dayhour');
if ($taskstatic->hasDelay()) print img_warning($langs->trans("Late"));
print '</td>';
@ -548,6 +554,35 @@ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$t
}
print '</td>';
if ($showbilltime)
{
// Time not billed
print '<td class="right">';
if ($lines[$i]->bill_time)
{
print convertSecondToTime($lines[$i]->tobill, 'allhourmin');
$total_projectlinesa_tobill += $lines[$i]->tobill;
}
else
{
print '<span class="opacitymedium">'.$langs->trans("NA").'</span>';
}
print '</td>';
// Time billed
print '<td class="right">';
if ($lines[$i]->bill_time)
{
print convertSecondToTime($lines[$i]->billed, 'allhourmin');
$total_projectlinesa_billed += $lines[$i]->billed;
}
else
{
print '<span class="opacitymedium">'.$langs->trans("NA").'</span>';
}
print '</td>';
}
// Contacts of task
if (! empty($conf->global->PROJECT_SHOW_CONTACTS_IN_LIST))
{
@ -582,7 +617,7 @@ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$t
if ($level >= 0) // Call sublevels
{
$level++;
if ($lines[$i]->id) projectLinesa($inc, $lines[$i]->id, $lines, $level, $var, $showproject, $taskrole, $projectsListId, $addordertick);
if ($lines[$i]->id) projectLinesa($inc, $lines[$i]->id, $lines, $level, $var, $showproject, $taskrole, $projectsListId, $addordertick, $projectidfortotallink, $filterprogresscalc, $showbilltime);
$level--;
}
@ -597,7 +632,8 @@ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$t
}
}
if (($total_projectlinesa_planned > 0 || $total_projectlinesa_spent > 0) && $level <= 0)
if (($total_projectlinesa_planned > 0 || $total_projectlinesa_spent > 0 || $total_projectlinesa_tobill > 0 || $total_projectlinesa_billed > 0)
&& $level <= 0)
{
print '<tr class="liste_total nodrag nodrop">';
print '<td class="liste_total">'.$langs->trans("Total").'</td>';
@ -617,6 +653,15 @@ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$t
if ($total_projectlinesa_planned) print round(100 * $total_projectlinesa_spent / $total_projectlinesa_planned, 2).' %';
print '</td>';
print '<td></td>';
if ($showbilltime)
{
print '<td class="nowrap liste_total right">';
print convertSecondToTime($total_projectlinesa_tobill, 'allhourmin');
print '</td>';
print '<td class="nowrap liste_total right">';
print convertSecondToTime($total_projectlinesa_billed, 'allhourmin');
print '</td>';
}
// Contacts of task
if (! empty($conf->global->PROJECT_SHOW_CONTACTS_IN_LIST))
{

View File

@ -729,9 +729,10 @@ class Task extends CommonObject
* @param string $morewherefilter Add more filter into where SQL request (must start with ' AND ...')
* @param string $filteronprojuser Filter on user that is a contact of project
* @param string $filterontaskuser Filter on user assigned to task
* @param int $includebilltime Calculate also the time to bill and billed
* @return array Array of tasks
*/
public function getTasksArray($usert = null, $userp = null, $projectid = 0, $socid = 0, $mode = 0, $filteronproj = '', $filteronprojstatus = '-1', $morewherefilter = '', $filteronprojuser = 0, $filterontaskuser = 0)
public function getTasksArray($usert = null, $userp = null, $projectid = 0, $socid = 0, $mode = 0, $filteronproj = '', $filteronprojstatus = '-1', $morewherefilter = '', $filteronprojuser = 0, $filterontaskuser = 0, $includebilltime = 0)
{
global $conf;
@ -742,10 +743,14 @@ class Task extends CommonObject
// List of tasks (does not care about permissions. Filtering will be done later)
$sql = "SELECT ";
if ($filteronprojuser > 0 || $filterontaskuser > 0) $sql.= " DISTINCT"; // We may get several time the same record if user has several roles on same project/task
$sql.= " p.rowid as projectid, p.ref, p.title as plabel, p.public, p.fk_statut as projectstatus,";
$sql.= " p.rowid as projectid, p.ref, p.title as plabel, p.public, p.fk_statut as projectstatus, p.bill_time,";
$sql.= " t.rowid as taskid, t.ref as taskref, t.label, t.description, t.fk_task_parent, t.duration_effective, t.progress, t.fk_statut as status,";
$sql.= " t.dateo as date_start, t.datee as date_end, t.planned_workload, t.rang,";
$sql.= " s.rowid as thirdparty_id, s.nom as thirdparty_name, s.email as thirdparty_email";
if ($includebilltime)
{
$sql.=" , SUM(tt.task_duration * ".$this->db->ifsql("invoice_id IS NULL", "1", "0").") as tobill, SUM(tt.task_duration * ".$this->db->ifsql("invoice_id IS NULL", "0", "1").") as billed";
}
$sql.= " FROM ".MAIN_DB_PREFIX."projet as p";
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON p.fk_soc = s.rowid";
if ($mode == 0)
@ -756,6 +761,10 @@ class Task extends CommonObject
$sql.= ", ".MAIN_DB_PREFIX."c_type_contact as ctc";
}
$sql.= ", ".MAIN_DB_PREFIX."projet_task as t";
if ($includebilltime)
{
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."projet_task_time as tt ON tt.fk_task = t.rowid";
}
if ($filterontaskuser > 0)
{
$sql.= ", ".MAIN_DB_PREFIX."element_contact as ec2";
@ -774,12 +783,20 @@ class Task extends CommonObject
if ($filterontaskuser > 0)
{
$sql.= ", ".MAIN_DB_PREFIX."projet_task as t";
if ($includebilltime)
{
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."projet_task_time as tt ON tt.fk_task = t.rowid";
}
$sql.= ", ".MAIN_DB_PREFIX."element_contact as ec2";
$sql.= ", ".MAIN_DB_PREFIX."c_type_contact as ctc2";
}
else
{
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."projet_task as t on t.fk_projet = p.rowid";
if ($includebilltime)
{
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."projet_task_time as tt ON tt.fk_task = t.rowid";
}
}
$sql.= " WHERE p.entity IN (".getEntity('project').")";
}
@ -809,6 +826,15 @@ class Task extends CommonObject
if ($filteronproj) $sql.= natural_search(array("p.ref", "p.title"), $filteronproj);
if ($filteronprojstatus && $filteronprojstatus != '-1') $sql.= " AND p.fk_statut IN (".$filteronprojstatus.")";
if ($morewherefilter) $sql.=$morewherefilter;
if ($includebilltime)
{
$sql.=" GROUP BY p.rowid, p.ref, p.title, p.public, p.fk_statut, p.bill_time,";
$sql.=" t.datec, t.dateo, t.datee, t.tms,";
$sql.=" t.rowid, t.ref, t.label, t.description, t.fk_task_parent, t.duration_effective, t.progress, t.fk_statut,";
$sql.=" t.dateo, t.datee, t.planned_workload, t.rang,";
$sql.=" s.rowid, s.nom, s.email";
}
$sql.= " ORDER BY p.ref, t.rang, t.dateo";
//print $sql;exit;
@ -849,12 +875,17 @@ class Task extends CommonObject
$tasks[$i]->projectref = $obj->ref;
$tasks[$i]->projectlabel = $obj->plabel;
$tasks[$i]->projectstatus = $obj->projectstatus;
$tasks[$i]->bill_time = $obj->bill_time;
$tasks[$i]->label = $obj->label;
$tasks[$i]->description = $obj->description;
$tasks[$i]->fk_parent = $obj->fk_task_parent; // deprecated
$tasks[$i]->fk_task_parent = $obj->fk_task_parent;
$tasks[$i]->duration = $obj->duration_effective;
$tasks[$i]->planned_workload= $obj->planned_workload;
$tasks[$i]->tobill = $obj->tobill;
$tasks[$i]->billed = $obj->billed;
$tasks[$i]->progress = $obj->progress;
$tasks[$i]->fk_statut = $obj->status;
$tasks[$i]->public = $obj->public;

View File

@ -19,7 +19,7 @@
/**
* \file htdocs/projet/tasks.php
* \ingroup projet
* \ingroup project
* \brief List all tasks of a project
*/
@ -33,12 +33,18 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
// Load translation files required by the page
$langs->loadLangs(array("users", "projects"));
$langs->loadLangs(array('projects', 'users', 'companies'));
$action = GETPOST('action', 'alpha');
$massaction=GETPOST('massaction', 'alpha');
$show_files=GETPOST('show_files', 'int');
$confirm=GETPOST('confirm', 'alpha');
$toselect = GETPOST('toselect', 'array');
$id = GETPOST('id', 'int');
$ref = GETPOST('ref', 'alpha');
$taskref = GETPOST('taskref', 'alpha');
$action = GETPOST('action', 'alpha');
$backtopage=GETPOST('backtopage', 'alpha');
$cancel=GETPOST('cancel', 'alpha');
@ -78,6 +84,8 @@ $socid=0;
//if ($user->societe_id > 0) $socid = $user->societe_id; // For external user, no check is done on company because readability is managed by public status of project and assignement.
$result = restrictedArea($user, 'projet', $id, 'projet&project');
$diroutputmassaction=$conf->projet->dir_output . '/tasks/temp/massgeneration/'.$user->id;
// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
$hookmanager->initHooks(array('projecttaskscard','globalcard'));
@ -90,6 +98,34 @@ $planned_workload=$planned_workloadhour*3600+$planned_workloadmin*60;
$userAccess=0;
$arrayfields=array(
't.ref'=>array('label'=>$langs->trans("RefTask"), 'checked'=>1, 'position'=>80),
't.label'=>array('label'=>$langs->trans("LabelTask"), 'checked'=>1, 'position'=>80),
't.dateo'=>array('label'=>$langs->trans("DateStart"), 'checked'=>1, 'position'=>100),
't.datee'=>array('label'=>$langs->trans("DateEnd"), 'checked'=>1, 'position'=>101),
'p.ref'=>array('label'=>$langs->trans("ProjectRef"), 'checked'=>1),
'p.title'=>array('label'=>$langs->trans("ProjectLabel"), 'checked'=>0),
's.nom'=>array('label'=>$langs->trans("ThirdParty"), 'checked'=>0),
'p.fk_statut'=>array('label'=>$langs->trans("ProjectStatus"), 'checked'=>1),
't.planned_workload'=>array('label'=>$langs->trans("PlannedWorkload"), 'checked'=>1, 'position'=>102),
't.duration_effective'=>array('label'=>$langs->trans("TimeSpent"), 'checked'=>1, 'position'=>103),
't.progress_calculated'=>array('label'=>$langs->trans("ProgressCalculated"), 'checked'=>1, 'position'=>104),
't.progress'=>array('label'=>$langs->trans("ProgressDeclared"), 'checked'=>1, 'position'=>105),
't.tobill'=>array('label'=>$langs->trans("TimeToBill"), 'checked'=>0, 'position'=>110),
't.billed'=>array('label'=>$langs->trans("TimeBilled"), 'checked'=>0, 'position'=>111),
't.datec'=>array('label'=>$langs->trans("DateCreation"), 'checked'=>0, 'position'=>500),
't.tms'=>array('label'=>$langs->trans("DateModificationShort"), 'checked'=>0, 'position'=>500),
//'t.fk_statut'=>array('label'=>$langs->trans("Status"), 'checked'=>1, 'position'=>1000),
);
// Extra fields
if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label))
{
foreach($extrafields->attribute_label as $key => $val)
{
if (! empty($extrafields->attribute_list[$key])) $arrayfields["ef.".$key]=array('label'=>$extrafields->attribute_label[$key], 'checked'=>(($extrafields->attribute_list[$key]<0)?0:1), 'position'=>$extrafields->attribute_pos[$key], 'enabled'=>(abs($extrafields->attribute_list[$key])!=3 && $extrafields->attribute_perms[$key]));
}
}
/*
* Actions
@ -99,24 +135,38 @@ $parameters=array('id'=>$id);
$reshook=$hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
// Purge search criteria
if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) // All tests are required to be compatible with all browsers
if (empty($reshook))
{
$search_user_id="";
$search_taskref='';
$search_tasklabel='';
$search_dtstartday='';
$search_dtstartmonth='';
$search_dtstartyear='';
$search_dtendday='';
$search_dtendmonth='';
$search_dtendyear='';
$search_planedworkload='';
$search_timespend='';
$search_progresscalc='';
$search_progressdeclare='';
$toselect='';
$search_array_options=array();
// Selection of new fields
include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
// Purge search criteria
if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) // All tests are required to be compatible with all browsers
{
$search_user_id="";
$search_taskref='';
$search_tasklabel='';
$search_dtstartday='';
$search_dtstartmonth='';
$search_dtstartyear='';
$search_dtendday='';
$search_dtendmonth='';
$search_dtendyear='';
$search_planedworkload='';
$search_timespend='';
$search_progresscalc='';
$search_progressdeclare='';
$toselect='';
$search_array_options=array();
}
// Mass actions
$objectclass='Task';
$objectlabel='Tasks';
$permtoread = $user->rights->projet->lire;
$permtodelete = $user->rights->projet->supprimer;
$uploaddir = $conf->projet->dir_output.'/tasks';
include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
}
$morewherefilterarray=array();
@ -297,11 +347,17 @@ if ($action == 'createtask' && $user->rights->projet->creer)
* View
*/
$now = dol_now();
$form=new Form($db);
$formother=new FormOther($db);
$socstatic=new Societe($db);
$projectstatic = new Project($db);
$taskstatic = new Task($db);
$userstatic=new User($db);
$varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage;
$selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields
$title=$langs->trans("Project").' - '.$langs->trans("Tasks").' - '.$object->ref.' '.$object->name;
if (! empty($conf->global->MAIN_HTML_TITLE) && preg_match('/projectnameonly/', $conf->global->MAIN_HTML_TITLE) && $object->name) $title=$object->ref.' '.$object->name.' - '.$langs->trans("Tasks");
$help_url="EN:Module_Projects|FR:Module_Projets|ES:M&oacute;dulo_Proyectos";
@ -624,7 +680,7 @@ elseif ($id > 0 || ! empty($ref))
// Get list of tasks in tasksarray and taskarrayfiltered
// We need all tasks (even not limited to a user because a task to user can have a parent that is not affected to him).
$filteronthirdpartyid = $socid;
$tasksarray=$taskstatic->getTasksArray(0, 0, $object->id, $filteronthirdpartyid, 0, '', -1, $morewherefilter);
$tasksarray=$taskstatic->getTasksArray(0, 0, $object->id, $filteronthirdpartyid, 0, '', -1, $morewherefilter, 0, 0, 1);
// We load also tasks limited to a particular user
$tmpuser=new User($db);
if ($search_user_id > 0) $tmpuser->fetch($search_user_id);
@ -699,6 +755,15 @@ elseif ($id > 0 || ! empty($ref))
print '<input class="flat" type="text" size="4" name="search_progressdeclare" value="'.$search_progressdeclare.'">';
print '</td>';
if ($object->bill_time)
{
print '<td class="liste_titre right">';
print '</td>';
print '<td class="liste_titre right">';
print '</td>';
}
if (! empty($conf->global->PROJECT_SHOW_CONTACTS_IN_LIST)) print '<td></td>';
// Action column
@ -718,6 +783,11 @@ elseif ($id > 0 || ! empty($ref))
print_liste_field_titre("TimeSpent", $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'right ');
print_liste_field_titre("ProgressCalculated", $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'right ');
print_liste_field_titre("ProgressDeclared", $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'right ');
if ($object->bill_time)
{
print_liste_field_titre("TimeToBill", $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'right ');
print_liste_field_titre("TimeBilled", $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'right ');
}
if (! empty($conf->global->PROJECT_SHOW_CONTACTS_IN_LIST)) print_liste_field_titre("TaskRessourceLinks", $_SERVER["PHP_SELF"], '', '', '', $sortfield, $sortorder);
print_liste_field_titre('', $_SERVER["PHP_SELF"], "", '', '', 'width="80"', $sortfield, $sortorder, 'center maxwidthsearch ');
print "</tr>\n";
@ -726,11 +796,13 @@ elseif ($id > 0 || ! empty($ref))
{
// Show all lines in taskarray (recursive function to go down on tree)
$j=0; $level=0;
$nboftaskshown=projectLinesa($j, 0, $tasksarray, $level, true, 0, $tasksrole, $object->id, 1, $object->id, $filterprogresscalc);
$nboftaskshown=projectLinesa($j, 0, $tasksarray, $level, true, 0, $tasksrole, $object->id, 1, $object->id, $filterprogresscalc, ($object->bill_time?1:0));
}
else
{
print '<tr class="oddeven"><td colspan="10" class="opacitymedium">'.$langs->trans("NoTasks").'</td></tr>';
$colspan=10;
if ($object->bill_time) $colspan+=2;
print '<tr class="oddeven"><td colspan="'.$colspan.'" class="opacitymedium">'.$langs->trans("NoTasks").'</td></tr>';
}
print "</table>";

View File

@ -21,7 +21,7 @@
/**
* \file htdocs/projet/tasks/list.php
* \ingroup project
* \brief List all task of a project
* \brief List all tasks of a project
*/
require "../../main.inc.php";