From e0bae07f975aeb4275b88390377cc74d6120176a Mon Sep 17 00:00:00 2001 From: delcroip Date: Fri, 7 Apr 2017 20:28:04 +0200 Subject: [PATCH 1/7] NEW:Invoice creation from task Time --- htdocs/core/lib/generic.lib.php | 285 ++++++++++++++ .../install/mysql/migration/5.0.0-6.0.0.sql | 1 + .../mysql/tables/llx_projet_task_time.sql | 1 + htdocs/projet/projectInvoice.php | 355 ++++++++++++++++++ 4 files changed, 642 insertions(+) create mode 100644 htdocs/core/lib/generic.lib.php create mode 100644 htdocs/projet/projectInvoice.php diff --git a/htdocs/core/lib/generic.lib.php b/htdocs/core/lib/generic.lib.php new file mode 100644 index 00000000000..1fba25b349e --- /dev/null +++ b/htdocs/core/lib/generic.lib.php @@ -0,0 +1,285 @@ + + * + * 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 . + */ +//global $db; +global $langs; + + +/* + * function to genegate a select list from a table, the showed text will be a concatenation of some + * column defined in column bit, the Least sinificative bit will represent the first colum + * + * @param object $db db Object to do the querry + * @param string $table table which the enum refers to (without prefix) + * @param string $fieldValue field of the table which the enum refers to + * @param string $htmlName name to the form select + * @param string $selected which value must be selected + * @param string $selectparam to add parameters to the select + * @param array(string) $addtionnalChoices array of additionnal fields Array['VALUE']=string to show + * @return string html code + */ + +function select_enum($table, $fieldValue,$htmlName,$selected='',$selectparam='',$addtionnalChoices=null){ +global $langs; +global $db; + if($table=='' || $fieldValue=='' || $htmlName=='' ) + { + return 'error, one of the mandatory field of the function select_enum is missing'; + } + $sql='SHOW COLUMNS FROM ';//llx_hr_event_time LIKE 'audience'"; + $sql.=MAIN_DB_PREFIX.$table.' WHERE Field="'; + $sql.=$fieldValue.'"'; + //$sql.= " ORDER BY t.".$field; + + dol_syslog('form::select_enum sql='.$sql, LOG_DEBUG); + + $resql=$db->query($sql); + + if ($resql) + { + $i=0; + //return $table."this->db".$field; + $num = $db->num_rows($resql); + if($num) + { + + $obj = $db->fetch_object($resql); + if ($obj && strpos($obj->Type,'enum(')===0) + { + if(empty($selected) && !empty($obj->Default))$selected="'{$obj->Default}'"; + $select.='\n"; + }else{ + $select=""; + } + + }else{ + $select=""; + } + } + else + { + $error++; + dol_print_error($db); + $select=""; + } + + return $select; + + } +/* + * function to genegate a select list from a table, the showed text will be a concatenation of some + * column defined in column bit, the Least sinificative bit will represent the first colum + * + * @param object $db db Object to do the querry + * @param string $table table which the fk refers to (without prefix) + * @param string $fieldValue field of the table which the fk refers to, the one to put in the Valuepart + * @param string $htmlName name to the form select + * @param string $fieldToShow1 first part of the concatenation + * @param string $fieldToShow1 second part of the concatenation + * @param string $selected which value must be selected + * @param string $separator separator between the tow contactened fileds +* @param string $sqlTail to limit per entity, to filter ... +* @param string $selectparam to add parameters to the select + * @param array(string) $addtionnalChoices array of additionnal fields Array['VALUE']=string to show + + * @return string html code + */ +function select_generic($table, $fieldValue,$htmlName,$fieldToShow1,$fieldToShow2='',$selected='',$separator=' - ',$sqlTail='', $selectparam='', $addtionnalChoices=array('NULL'=>'NULL')){ + // + //return 'tada'; + global $conf,$langs,$db; + if($table=='' || $fieldValue=='' || $fieldToShow1=='' || $htmlName=='' ) + { + return 'error, one of the mandatory field of the function select_generic is missing'; + } + $select="\n"; + if ($conf->use_javascript_ajax) + { + include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php'; + $comboenhancement = ajax_combobox($htmlName); + $select.=$comboenhancement; + $nodatarole=($comboenhancement?' data-role="none"':''); + } + $select.='\n"; + return $select; + + } + + +/* + * function to genegate a select list from a table, the showed text will be a concatenation of some + * column defined in column bit, the Least sinificative bit will represent the first colum + * + * @param object $db db Object to do the querry + * @param string $table table which the fk refers to (without prefix) + * @param string $fieldValue field of the table which the fk refers to, the one to put in the Valuepart + * @param string $selected value selected of the field value column + * @param string $fieldToShow1 first part of the concatenation + * @param string $fieldToShow1 second part of the concatenation + * @param string $separator separator between the tow contactened fileds + * @param string $sqlTail to limit per entity, to filter ... + + * @return string html code + */ +function print_generic($table, $fieldValue,$selected,$fieldToShow1,$fieldToShow2="",$separator=' - ',$sqltail="",$sqljoin=""){ + //return $table.$db.$field; + global $db; + if($table=="" || $fieldValue=="" || $fieldToShow1=='') + { + return "error, one of the mandatory field of the function print_generic is missing"; + }else if (empty($selected)){ + return "NuLL"; + } + + $sql="SELECT"; + $sql.=" t.".$fieldValue; + $sql.=" ,".$fieldToShow1; + if(!empty($fieldToShow2)) + $sql.=" ,".$fieldToShow2; + $sql.= " FROM ".MAIN_DB_PREFIX.$table." as t"; + if(!empty($sqljoin)) + $sql.=' '.$sqljoin; + $sql.= " WHERE t.".$fieldValue."=".$selected; + if(!empty($sqlTail)) + $sql.=' '.$sqlTail; + + dol_syslog("form::print_generic sql=".$sql, LOG_DEBUG); + + $resql=$db->query($sql); + + if ($resql) + { + // support AS in the fields ex $field1='CONTACT(u.firstname,' ',u.lastname) AS fullname' + // with sqltail= 'JOIN llx_user as u ON t.fk_user=u.rowid' + $starfields1=strpos($fieldToShow1,' AS '); + if($starfields1>0){ + $fieldToShow1= substr($fieldToShow1, $starfields1+4); + } + $starfields2=strpos($fieldToShow2,' AS '); + if($starfields2>0){ + $fieldToShow2=substr($fieldToShow2, $starfields2+4); + } + + $num = $db->num_rows($resql); + if ( $num) + { + $obj = $db->fetch_object($resql); + + if ($obj) + { + $select=$obj->{$fieldToShow1}; + if(!empty($fieldToShow2)) + $select.=$separator.$obj->{$fieldToShow2}; + }else{ + $select= "NULL"; + } + }else{ + $select= "NULL"; + } + } + else + { + $error++; + dol_print_error($db); + $select.= "ERROR"; + } + //$select.="\n"; + return $select; + } + + /* + * function to genegate a select list from a table, the showed text will be a concatenation of some + * column defined in column bit, the Least sinificative bit will represent the first colum + * + * @param object $db db Object to do the querry + * @param int/array $userid ID of the user you want to get the subordinate liste * @param int $userid ID of the user you want to get the subordinate liste + * @param int $entity entity + * @return array List of the subordinate ids and level [[id][lvl]] + */ \ No newline at end of file diff --git a/htdocs/install/mysql/migration/5.0.0-6.0.0.sql b/htdocs/install/mysql/migration/5.0.0-6.0.0.sql index ceaf1f5be90..94e06271636 100644 --- a/htdocs/install/mysql/migration/5.0.0-6.0.0.sql +++ b/htdocs/install/mysql/migration/5.0.0-6.0.0.sql @@ -101,6 +101,7 @@ ALTER TABLE llx_facturedet_rec ADD COLUMN vat_src_code varchar(10) DEFAULT '' AF ALTER TABLE llx_extrafields ADD COLUMN langs varchar(24); ALTER TABLE llx_supplier_proposaldet ADD COLUMN fk_unit integer DEFAULT NULL; +ALTER TABLE llx_projet_task_time ADD COLUMN status enum('DRAFT','SUBMITTED','APPROVED','CANCELLED','REJECTED','CHALLENGED','INVOICED','UNDERAPPROVAL') DEFAULT 'DRAFT'; ALTER TABLE llx_ecm_files ADD COLUMN ref varchar(128) AFTER rowid; ALTER TABLE llx_ecm_files CHANGE COLUMN fullpath filepath varchar(255); diff --git a/htdocs/install/mysql/tables/llx_projet_task_time.sql b/htdocs/install/mysql/tables/llx_projet_task_time.sql index 897364a90e1..798006597d3 100644 --- a/htdocs/install/mysql/tables/llx_projet_task_time.sql +++ b/htdocs/install/mysql/tables/llx_projet_task_time.sql @@ -31,5 +31,6 @@ create table llx_projet_task_time import_key varchar(14), -- Import key datec date, -- Date creation time tms timestamp, -- Date update time + status enum('DRAFT','SUBMITTED','APPROVED','CANCELLED','REJECTED','CHALLENGED','INVOICED','UNDERAPPROVAL') DEFAULT 'DRAFT'; note text -- A comment )ENGINE=innodb; diff --git a/htdocs/projet/projectInvoice.php b/htdocs/projet/projectInvoice.php new file mode 100644 index 00000000000..ec3b8b69919 --- /dev/null +++ b/htdocs/projet/projectInvoice.php @@ -0,0 +1,355 @@ + + * + * 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 . + */ + + +//FIXME new param needed +define('INVOICE_METHOD','user'); +define('INVOICE_TASKTIME','all'); +define('INVOICE_SERVICE','-999'); +define('INVOICE_SHOW_TASK','1'); +define('INVOICE_SHOW_USER','1'); + +//load class +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/generic.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; + +//get param +$staticProject=new Project($db); +$projectId=GETPOST('projectid'); + +$socid=GETPOST('socid'); +$month=GETPOST('month'); +$year=GETPOST('year'); +$mode=GETPOST('invoicingMethod'); +$step=GETPOST('step'); +$ts2Invoice=GETPOST('ts2Invoice'); +$tsNotInvoiced=GETPOST('tsNotInvoiced'); +$userid= is_object($user)?$user->id:$user; +//init handling object +$form = new Form($db); + +//FIXME check autorisation for project and page/ + +if ($user->rights->facture->creer & hasProjectRight($userid,$projectid)) +{ + if($projectId>0)$staticProject->fetch($projectId); + if($socid==0 || !is_numeric($socid))$socid=$staticProject->socid; //FIXME check must be in place to ensure the user hqs the right to see the project details +$edit=1; +// avoid SQL issue +if(empty($month) || empty($year) || empty($projectId))$step=1; +//steps + switch ($step) + { + case '2':{ + $fields=($mode=='user')?'fk_user':(($mode=='taskUser')?'fk_user,fk_task':'fk_task'); + $sql= 'SELECT '.$fields.', SUM(tt.task_duration) as duration '; + $sql.=', GROUP_CONCAT(tt.rowid SEPARATOR ", ") as task_time_list'; + $sql.=' From '.MAIN_DB_PREFIX.'projet_task_time as tt'; + $sql.=' JOIN '.MAIN_DB_PREFIX.'projet_task as t ON tt.fk_task=t.rowid'; + $sql.=' WHERE t.fk_projet='.$projectId; + $sql.=' AND MONTH(tt.task_date)='.$month; + $sql.=' AND YEAR(tt.task_date)='.$year; + if($ts2Invoice!='all'){ + /*$sql.=' AND tt.rowid IN(SELECT GROUP_CONCAT(fk_project_tasktime_list SEPARATOR ", ")'; + $sql.=' FROM '.MAIN_DB_PREFIX.'project_tasktime_approval'; + $sql.=' WHERE status= "APPROVED" AND MONTH(start_date)='.$month; + $sql.=' AND YEAR(start_date)="'.$year.'")'; + $sql.=' AND YEAR(start_date)="'.$year.'")'; */ + $sql.=' AND tt.status = "APPROVED"'; + } + if($tsNotInvoiced==1){ + $sql.=' AND tt.invoice_id IS NULL'; + } + $sql.=' GROUP BY '.$fields; + dol_syslog('timesheet::timesheetProjectInvoice step2', LOG_DEBUG); + + + $Form ='
'."\n\t"; + $Form .=''; + $Form .=''; + $Form .=''; + $Form .=''; + $Form .=''; + $Form .=''; + + $resql=$db->query($sql); + $num=0; + $resArray=array(); + if ($resql) + { + $num = $db->num_rows($resql); + $i = 0; + + // Loop on each record found, + while ($i < $num) + { + $error=0; + $obj = $db->fetch_object($resql); + $duration=floor($obj->duration/3600).":".str_pad (floor($obj->duration%3600/60),2,"0",STR_PAD_LEFT); + switch($mode){ + case 'user': + //step 2.2 get the list of user (all or approved) + $resArray[]=array("USER" => $obj->fk_user,"TASK" =>'any',"DURATION"=>$duration,'LIST'=>$obj->task_time_list); + break; + case 'taskUser': + //step 2.3 get the list of taskUser (all or approved) + $resArray[]=array("USER" => $obj->fk_user,"TASK" =>$obj->fk_task,"DURATION"=>$duration,'LIST'=>$obj->task_time_list); + break; + default: + case 'task': + //step 2.1 get the list of task (all or approved) + $resArray[]=array("USER" => "any","TASK" =>$obj->fk_task,"DURATION"=>$duration,'LIST'=>$obj->task_time_list); + break; + } + + $i++; + } + $db->free($resql); + }else + { + dol_print_error($db); + return ''; + } +//var_dump($resArray); + //FIXME asign a service + price to each array elements (or price +auto generate name + $Form .=''."\n\t\t"; + $Form .=''; + $Form .=''; + $Form .=''; + $Form .=''; + $Form .=''; + $form = new Form($db); + foreach($resArray as $res){ + $Form .=htmlPrintServiceChoice($res["USER"],$res["TASK"],'pair',$res["DURATION"],$res['LIST'],$mysoc,$socid); + } + + $Form .='
'.$langs->trans("Step").' 2
'.$langs->trans("User").''.$langs->trans("Task").''.$langs->trans("Service").''.$langs->trans("Description").''.$langs->trans("PriceHT").''.$langs->trans("VAT").''.$langs->trans("unitDuration").''.$langs->trans("Duration").'
'; + $Form .='\n"; + + + + break;} + case 3: // review choice and list of item + quantity ( editable) + require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php'; + require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; + $object = new Facture($db); + + $db->begin(); + $error = 0; + + $dateinvoice = time(); + //$date_pointoftax = dol_mktime(12, 0, 0, $_POST['date_pointoftaxmonth'], $_POST['date_pointoftaxday'], $_POST['date_pointoftaxyear']); + // Si facture standard + $object->socid = $socid; + $object->type = Facture::TYPE_STANDARD; + $object->date = $dateinvoice; + $object->fk_project = $projectid; + $object->fetch_thirdparty(); + $id = $object->create($user); + $resArray=$_POST['userTask']; + $task_time_array=array(); + if(is_array($resArray)){ + 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); + var_dump($endday); + $details=''; + $result =''; + if(($tId!='any') && INVOICE_SHOW_TASK)$details="\n".$service['taskLabel']; + if(($uId!='any')&& INVOICE_SHOW_USER)$details.="\n".$service['userName']; + + if($service['Service']>0){ + $product = new Product($db); + $product->fetch($service['Service']); + + $unit_duration_unit=substr($product->duration, -1); + $factor=($unit_duration_unit=='h')?3600:8*3600;//FIXME support week and month + $factor=$factor*intval(substr($product->duration,0, -1)); + $quantity= $duration/$factor; + $result = $object->addline($product->description.$details, $product->price, $quantity, $product->tva_tx, $product->localtax1_tx, $product->localtax2_tx, $service['Service'], 0, $startday, $endday, 0, 0, '', $product->price_base_type, $product->price_ttc, $product->type, -1, 0, '', 0, 0, null, 0, '', 0, 100, '', $product->fk_unit); + + + }elseif ($service['Service']<>-999){ + $factor=($service['unit_duration_unit']=='h')?3600:8*3600;//FIXME support week and month + $factor=$factor*intval($service['unit_duration']); + + $quantity= $duration/$factor; + $result = $object->addline($service['Desc'].$details, $service['PriceHT'], $quantity, $service['VAT'], '', '', '', 0, $startday, $endday, 0, 0, '', 'HT', '', 1, -1, 0, '', 0, 0, null, 0, '', 0, 100, '', ''); + + } + if($service['taskTimeList']<>'' && $result>0)$task_time_array[$result]=$service['taskTimeList']; + }else $error++; + } + }else $error++; + + // End of object creation, we show it + if ($id > 0 && ! $error) + { + $db->commit(); + foreach($task_time_array AS $idLine=> $task_time_list){ + //dol_syslog("ProjectInvoice::setnvoice".$idLine.' '.$task_time_list, LOG_DEBUG); + Update_task_time_invoice($id,$idLine,$task_time_list); + } + + header('Location: ' . $object->getNomUrl(0,'',0,1,'')); + exit(); + } + else + { + $db->rollback(); + //header('Location: ' . $_SERVER["PHP_SELF"] . '?step=0'); + setEventMessages($object->error, $object->errors, 'errors'); + + } + + break; + + case 1: + +$edit=0; + case 0: + default: + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; + $htmlother = new FormOther($db); + $sqlTail=''; + + if(!$user->admin){ + $sqlTail=' JOIN llx_element_contact ON t.rowid= element_id '; + $sqlTail.=' WHERE fk_c_type_contact = "160" '; + $sqlTail.=' AND fk_socpeople="'.$userid.'"'; + } + $Form =''."\n\t"; + $Form .=''."\n\t\t"; + $Form .=''; + // $Form .=''; + // $Form .=''; + $Form .='\n\t\t"; + +//cust list + $Form .=''; +//all ts or only approved + $ts2Invoice=INVOICE_TASKTIME; + $Form .='"; +// not alreqdy invoice + $Form .=''; + + $Form .='
'.$langs->trans("Step").' '.$step.''; + $invoicingMethod=INVOICE_METHOD; + $Form .='
'.$langs->trans('Project').''; + $Form .=select_generic('projet', 'rowid','projectid','ref','title',$projectId,' - ','', 'fk_status=1',null); + $Form .='
'.$langs->trans('Month').' - '.$langs->trans('Year').''.$htmlother->select_month($month, 'month').' - '.$htmlother->selectyear($year,'year',1,10,3).'
'.$langs->trans('Month').'
'.$langs->trans('Customer').'
'.$langs->trans('Mode').' '.$langs->trans("Task").' '; + $Form .=' '.$langs->trans("User")." "; + $Form .=' '.$langs->trans("Task").'&'.$langs->trans("User")."
'.$langs->trans('Customer').''.$form->select_company($socid, 'socid', '(s.client=1 OR s.client=2 OR s.client=3)', 1).'
'.$langs->trans('TimesheetToInvoice').' '.$langs->trans("approvedOnly").' '; + $Form .=' '.$langs->trans("All")."
'.$langs->trans('TimesheetNotInvoiced'); + $Form .='
'; + + $Form .='\n"; + + break; + } +}else{ + $accessforbidden = accessforbidden("you don't have enough rights to see this page"); +} +/*************************************************** +* VIEW +* +* Put here all code to build page +****************************************************/ +$morejs=array("/timesheet/core/js/jsparameters.php","/timesheet/core/js/timesheet.js"); +llxHeader('',$langs->trans('TimesheetInvoice'),'','','','',$morejs); + + +print $Form; + + + +llxFooter(); +$db->close(); + + + +/*************************************************** +* FUNCTIONS +* +* Put here all code of the functions +****************************************************/ + + + +/*** + * Function to print the line to chose between a predefined service or an ad-hoc one + */ +function htmlPrintServiceChoice($user,$task,$class,$duration,$tasktimelist,$seller,$byer){ + global $form,$langs; + $userName=($user=='any')?(' - '):print_generic('user','rowid',$user,'lastname','firstname',' '); + $taskLabel=($task=='any')?(' - '):print_generic('projet_task','rowid',$task,'ref','label',' '); + $html=''.$userName; + $html.=''.$taskLabel; + $html.=''; + $html.=''; + $html.=''; + $defaultService=INVOICE_SERVICE; + $addchoices=array('-999'=> $langs->trans('not2invoice')); + $html.=''.select_generic('product', 'rowid','userTask['.$user.']['.$task.'][Service]','ref','description',$defaultService,$separator=' - ',$sqlTail='', $selectparam='tosell=1 AND fk_product_type=1',$addchoices).''; + $html.=''; + $html.=''; + //$html.=''; + $html.=''.$form->load_tva('userTask['.$user.']['.$task.'][VAT]', -1, $seller, $buyer, 0, 0, '', false, 1).''; + $html.=''; + $html.='
'.$langs->trans('Hour'); + $html.='
'.$langs->trans('Days').''; + $html.=''; + + $html.=''; + return $html; +} + +function hasProjectRight($userid,$projectid){ + global $db,$user; + $res=true; + if($projectid && !$user->admin){ + $sql=' SELECT rowid FROM '.MAIN_DB_PREFIX.'element_contact '; + $sql.=' WHERE fk_c_type_contact = "160" AND element_id="'.$projectid; + $sql.='" AND fk_socpeople="'.$userid.'"'; + $resql=$db->query($sql); + if (!$resql)$res=false; + } + return $res; +} + +function Update_task_time_invoice($idInvoice, $idLine,$task_time_list){ + global $db; + $res=true; + $sql='UPDATE '.MAIN_DB_PREFIX.'projet_task_time'; + $sql.=" SET invoice_id={$idInvoice}, invoice_line_id={$idLine}"; + $sql.=" WHERE rowid in ({$task_time_list})"; + dol_syslog("ProjectInvoice::setnvoice", LOG_DEBUG); + $resql=$db->query($sql); + if (!$resql)$res=false; + return $res; +} \ No newline at end of file From 34787dc1d74d762535db0df001b7b7d2b15b12f5 Mon Sep 17 00:00:00 2001 From: delcroix Patrick Date: Tue, 2 May 2017 16:07:03 +0200 Subject: [PATCH 2/7] Update 5.0.0-6.0.0.sql --- htdocs/install/mysql/migration/5.0.0-6.0.0.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/install/mysql/migration/5.0.0-6.0.0.sql b/htdocs/install/mysql/migration/5.0.0-6.0.0.sql index 94e06271636..3a995b0dc96 100644 --- a/htdocs/install/mysql/migration/5.0.0-6.0.0.sql +++ b/htdocs/install/mysql/migration/5.0.0-6.0.0.sql @@ -101,7 +101,7 @@ ALTER TABLE llx_facturedet_rec ADD COLUMN vat_src_code varchar(10) DEFAULT '' AF ALTER TABLE llx_extrafields ADD COLUMN langs varchar(24); ALTER TABLE llx_supplier_proposaldet ADD COLUMN fk_unit integer DEFAULT NULL; -ALTER TABLE llx_projet_task_time ADD COLUMN status enum('DRAFT','SUBMITTED','APPROVED','CANCELLED','REJECTED','CHALLENGED','INVOICED','UNDERAPPROVAL') DEFAULT 'DRAFT'; +ALTER TABLE llx_projet_task_time ADD COLUMN status enum('PLANNED','DRAFT','SUBMITTED','APPROVED','CANCELLED','REJECTED','CHALLENGED','INVOICED','UNDERAPPROVAL') DEFAULT 'DRAFT'; ALTER TABLE llx_ecm_files ADD COLUMN ref varchar(128) AFTER rowid; ALTER TABLE llx_ecm_files CHANGE COLUMN fullpath filepath varchar(255); From 4b0d3ad6c6eddf27cde26c0889e900f677460a8c Mon Sep 17 00:00:00 2001 From: delcroix Patrick Date: Tue, 2 May 2017 16:07:19 +0200 Subject: [PATCH 3/7] Update llx_projet_task_time.sql --- htdocs/install/mysql/tables/llx_projet_task_time.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/install/mysql/tables/llx_projet_task_time.sql b/htdocs/install/mysql/tables/llx_projet_task_time.sql index 798006597d3..e3453a256f0 100644 --- a/htdocs/install/mysql/tables/llx_projet_task_time.sql +++ b/htdocs/install/mysql/tables/llx_projet_task_time.sql @@ -31,6 +31,6 @@ create table llx_projet_task_time import_key varchar(14), -- Import key datec date, -- Date creation time tms timestamp, -- Date update time - status enum('DRAFT','SUBMITTED','APPROVED','CANCELLED','REJECTED','CHALLENGED','INVOICED','UNDERAPPROVAL') DEFAULT 'DRAFT'; + status enum('PLANNED','DRAFT','SUBMITTED','APPROVED','CANCELLED','REJECTED','CHALLENGED','INVOICED','UNDERAPPROVAL') DEFAULT 'DRAFT'; note text -- A comment )ENGINE=innodb; From e9d3db084a5b9a35796c45cd4ed2117762a401c8 Mon Sep 17 00:00:00 2001 From: patrick Delcroix Date: Sat, 10 Nov 2018 15:35:56 +0100 Subject: [PATCH 4/7] new: link to the compta-files.php in the accountancy left menu --- htdocs/compta/compta-files.php | 173 ++++++++++++------------ htdocs/core/menus/standard/eldy.lib.php | 3 +- htdocs/langs/fr_FR/accountancy.lang | 1 + 3 files changed, 92 insertions(+), 85 deletions(-) diff --git a/htdocs/compta/compta-files.php b/htdocs/compta/compta-files.php index d8f4885a3b2..570f921a0fe 100644 --- a/htdocs/compta/compta-files.php +++ b/htdocs/compta/compta-files.php @@ -32,7 +32,7 @@ require_once DOL_DOCUMENT_ROOT.'/compta/sociales/class/chargesociales.class.php' restrictedArea($user,'banque'); -$langs->load("companies"); +$langs->load("accountancy"); if (! empty($conf->facture->enabled)) $langs->load("bills"); $date_start =GETPOST('date_start','alpha'); $date_startDay= GETPOST('date_startday','int'); @@ -218,98 +218,103 @@ if($result & $action=="dl"){ /* * View */ + + +llxHeader('',$title,$help_url); + +$h=0; +$head[$h][0] = $_SERVER["PHP_SELF"].$varlink; +$head[$h][1] = $langs->trans("AccountantFiles"); +$head[$h][2] = 'AccountantFiles'; +dol_fiche_head($head, 'AccountantFiles'); $form = new Form($db); $userstatic=new User($db); $title=$langs->trans("ComptaFiles").' - '.$langs->trans("List"); -//if (! empty($conf->global->MAIN_HTML_TITLE) && preg_match('/thirdpartynameonly/',$conf->global->MAIN_HTML_TITLE) && $object->name) $title=$object->name.' - '.$langs->trans("Symmary"); -$help_url='EN:Module_Accounting|FR:Module_Compatibilite'; //FIXME -llxHeader('',$title,$help_url); print ''."\n\t\t"; -if (!empty($date_start) && !empty($date_stop))echo dol_print_date($date_start)." - ".dol_print_date($date_stop); -print ''; -print ''; -//if (! empty($arrayfields['f.datef']['checked'])) -print_liste_field_titre($arrayfields['date']['label'],$_SERVER["PHP_SELF"],"date","",$param,'align="center" class="nowrap"',$sortfield,$sortorder); -print ''; -print ''; -print ''; -print ''; -print ''; -print ''; -print ''; -print ''; -if ($result) -{ - $TData = dol_sort_array($filesarray, 'date', 'ASC'); - if(empty($TData)) { - print ''; - } else { - // Sort array by date ASC to calucalte balance +print ''.$langs->trans("ReportPeriod").': '.$form->select_date($date_start,'date_start',0,0,0,"",1,1,1); +print ' - '.$form->select_date($date_stop,'date_stop',0,0,0,"",1,1,1)."\n"; +print ''."\n\t\t"; +if (!empty($date_start) && !empty($date_stop)){ + echo dol_print_date($date_start)." - ".dol_print_date($date_stop); + print '
'.$langs->trans("Type").''.$langs->trans("Ref").''.$langs->trans("File").''.$langs->trans("Paid").''.$langs->trans("Debit").''.$langs->trans("Credit").''.$langs->trans("Balance").'
'.$langs->trans("NoItem").'
'; + print ''; + print_liste_field_titre($arrayfields['date']['label'],$_SERVER["PHP_SELF"],"date","",$param,'align="center" class="nowrap"',$sortfield,$sortorder); + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + if ($result) + { + $TData = dol_sort_array($filesarray, 'date', 'ASC'); + if(empty($TData)) { + print ''; + } else { + // Sort array by date ASC to calucalte balance - $totalDebit = 0; - $totalCredit = 0; - // Balance calculation - $balance = 0; - foreach($TData as &$data1) { - if($data1['item']!='Invoice'&& $data1['item']!='Donation' ){ - $data1['amount']=-$data1['amount']; - } - if ($data1['amount']>0){ - }else{ - } - $balance += $data1['amount']; - $data1['balance'] = $balance; - } - // Display array - foreach($TData as $data) { - $html_class = ''; - //if (!empty($data['fk_facture'])) $html_class = 'facid-'.$data['fk_facture']; - //elseif (!empty($data['fk_paiement'])) $html_class = 'payid-'.$data['fk_paiement']; - print ''; - print "\n"; - print ''; - print ''; - print '\n"; - print ''; - print '\n"; - $totalDebit += ($data['amount'] > 0) ? abs($data['amount']) : 0; - print '\n"; - $totalCredit += ($data['amount'] > 0) ? 0 : abs($data['amount']); - // Balance - print '\n"; - print "\n"; - } - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print "\n"; - } - } -print "
'.$langs->trans("Type").''.$langs->trans("Ref").''.$langs->trans("File").''.$langs->trans("Paid").''.$langs->trans("Debit").''.$langs->trans("Credit").''.$langs->trans("Balance").'
'.$langs->trans("NoItem").'
"; - print dol_print_date($data['date'],'day'); - print "'.$data['item'].''.$data['ref'].' ".$data['name']."'.$data['paid'].''.(($data['amount'] > 0) ? price(abs($data['amount'])) : '')."'.(($data['amount'] > 0) ? '' : price(abs($data['amount'])))."'.price($data['balance'])."
 '.price($totalDebit).''.price($totalCredit).''.price(price2num($totalDebit - $totalCredit, 'MT')).'
"; -print '
'."\n\t\t\t"; + $totalDebit = 0; + $totalCredit = 0; + // Balance calculation + $balance = 0; + foreach($TData as &$data1) { + if($data1['item']!='Invoice'&& $data1['item']!='Donation' ){ + $data1['amount']=-$data1['amount']; + } + if ($data1['amount']>0){ + }else{ + } + $balance += $data1['amount']; + $data1['balance'] = $balance; + } + // Display array + foreach($TData as $data) { + $html_class = ''; + //if (!empty($data['fk_facture'])) $html_class = 'facid-'.$data['fk_facture']; + //elseif (!empty($data['fk_paiement'])) $html_class = 'payid-'.$data['fk_paiement']; + print ''; + print ""; + print dol_print_date($data['date'],'day'); + print "\n"; + print ''.$data['item'].''; + print ''.$data['ref'].''; + print ' ".$data['name']."\n"; + print ''.$data['paid'].''; + print ''.(($data['amount'] > 0) ? price(abs($data['amount'])) : '')."\n"; + $totalDebit += ($data['amount'] > 0) ? abs($data['amount']) : 0; + print ''.(($data['amount'] > 0) ? '' : price(abs($data['amount'])))."\n"; + $totalCredit += ($data['amount'] > 0) ? 0 : abs($data['amount']); + // Balance + print ''.price($data['balance'])."\n"; + print "\n"; + } + print ''; + print ' '; + print ''.price($totalDebit).''; + print ''.price($totalCredit).''; + print ''.price(price2num($totalDebit - $totalCredit, 'MT')).''; + print ''; + print "\n"; + } + } + print ""; + print ''."\n\t\t\t"; -print ''; -print ''; + print ''; + print ''; -//print ''; -//print ''; -//print ''; + //print ''; + //print ''; + //print ''; -//print ''; -//print ''; -//print ''; - - -print '
'."\n\t\t\n\t\t\n\t\t\t"; + //print ''; + //print ''; + //print ''; + print ''."\n\t\t\n\t\t\n\t\t\t"; +} llxFooter(); diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index 2c2c2d999f7..e172a83697c 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -1107,7 +1107,8 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu // Balance $newmenu->add("/accountancy/bookkeeping/balance.php?mainmenu=accountancy&leftmenu=accountancy_balance",$langs->trans("AccountBalance"),1,$user->rights->accounting->mouvements->lire); - + // Files + $newmenu->add("/compta/compta-files.php?mainmenu=accountancy&leftmenu=accountancy_files",$langs->trans("AccountantFiles"),1,$user->rights->accounting->mouvements->lire); // Reports $langs->load("compta"); diff --git a/htdocs/langs/fr_FR/accountancy.lang b/htdocs/langs/fr_FR/accountancy.lang index 4f546828652..b9d2bc6dabb 100644 --- a/htdocs/langs/fr_FR/accountancy.lang +++ b/htdocs/langs/fr_FR/accountancy.lang @@ -229,6 +229,7 @@ ListOfProductsWithoutAccountingAccount=Liste des produits non liés à un compte ChangeBinding=Changer les liens Accounted=Comptabilisé NotYetAccounted=Pas encore comptabilisé +AccountantFiles = Justificatifs comptablilité ## Admin ApplyMassCategories=Application en masse des catégories From fa9ecd9f9767e48444486b14d2428a25efc4ee13 Mon Sep 17 00:00:00 2001 From: patrick Delcroix Date: Sat, 10 Nov 2018 15:46:51 +0100 Subject: [PATCH 5/7] clean: align with upstream --- htdocs/core/lib/generic.lib.php | 285 -------------- .../install/mysql/migration/5.0.0-6.0.0.sql | 1 - .../mysql/tables/llx_projet_task_time.sql | 1 - htdocs/projet/projectInvoice.php | 355 ------------------ 4 files changed, 642 deletions(-) delete mode 100644 htdocs/core/lib/generic.lib.php delete mode 100644 htdocs/projet/projectInvoice.php diff --git a/htdocs/core/lib/generic.lib.php b/htdocs/core/lib/generic.lib.php deleted file mode 100644 index 1fba25b349e..00000000000 --- a/htdocs/core/lib/generic.lib.php +++ /dev/null @@ -1,285 +0,0 @@ - - * - * 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 . - */ -//global $db; -global $langs; - - -/* - * function to genegate a select list from a table, the showed text will be a concatenation of some - * column defined in column bit, the Least sinificative bit will represent the first colum - * - * @param object $db db Object to do the querry - * @param string $table table which the enum refers to (without prefix) - * @param string $fieldValue field of the table which the enum refers to - * @param string $htmlName name to the form select - * @param string $selected which value must be selected - * @param string $selectparam to add parameters to the select - * @param array(string) $addtionnalChoices array of additionnal fields Array['VALUE']=string to show - * @return string html code - */ - -function select_enum($table, $fieldValue,$htmlName,$selected='',$selectparam='',$addtionnalChoices=null){ -global $langs; -global $db; - if($table=='' || $fieldValue=='' || $htmlName=='' ) - { - return 'error, one of the mandatory field of the function select_enum is missing'; - } - $sql='SHOW COLUMNS FROM ';//llx_hr_event_time LIKE 'audience'"; - $sql.=MAIN_DB_PREFIX.$table.' WHERE Field="'; - $sql.=$fieldValue.'"'; - //$sql.= " ORDER BY t.".$field; - - dol_syslog('form::select_enum sql='.$sql, LOG_DEBUG); - - $resql=$db->query($sql); - - if ($resql) - { - $i=0; - //return $table."this->db".$field; - $num = $db->num_rows($resql); - if($num) - { - - $obj = $db->fetch_object($resql); - if ($obj && strpos($obj->Type,'enum(')===0) - { - if(empty($selected) && !empty($obj->Default))$selected="'{$obj->Default}'"; - $select.='\n"; - }else{ - $select=""; - } - - }else{ - $select=""; - } - } - else - { - $error++; - dol_print_error($db); - $select=""; - } - - return $select; - - } -/* - * function to genegate a select list from a table, the showed text will be a concatenation of some - * column defined in column bit, the Least sinificative bit will represent the first colum - * - * @param object $db db Object to do the querry - * @param string $table table which the fk refers to (without prefix) - * @param string $fieldValue field of the table which the fk refers to, the one to put in the Valuepart - * @param string $htmlName name to the form select - * @param string $fieldToShow1 first part of the concatenation - * @param string $fieldToShow1 second part of the concatenation - * @param string $selected which value must be selected - * @param string $separator separator between the tow contactened fileds -* @param string $sqlTail to limit per entity, to filter ... -* @param string $selectparam to add parameters to the select - * @param array(string) $addtionnalChoices array of additionnal fields Array['VALUE']=string to show - - * @return string html code - */ -function select_generic($table, $fieldValue,$htmlName,$fieldToShow1,$fieldToShow2='',$selected='',$separator=' - ',$sqlTail='', $selectparam='', $addtionnalChoices=array('NULL'=>'NULL')){ - // - //return 'tada'; - global $conf,$langs,$db; - if($table=='' || $fieldValue=='' || $fieldToShow1=='' || $htmlName=='' ) - { - return 'error, one of the mandatory field of the function select_generic is missing'; - } - $select="\n"; - if ($conf->use_javascript_ajax) - { - include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php'; - $comboenhancement = ajax_combobox($htmlName); - $select.=$comboenhancement; - $nodatarole=($comboenhancement?' data-role="none"':''); - } - $select.='\n"; - return $select; - - } - - -/* - * function to genegate a select list from a table, the showed text will be a concatenation of some - * column defined in column bit, the Least sinificative bit will represent the first colum - * - * @param object $db db Object to do the querry - * @param string $table table which the fk refers to (without prefix) - * @param string $fieldValue field of the table which the fk refers to, the one to put in the Valuepart - * @param string $selected value selected of the field value column - * @param string $fieldToShow1 first part of the concatenation - * @param string $fieldToShow1 second part of the concatenation - * @param string $separator separator between the tow contactened fileds - * @param string $sqlTail to limit per entity, to filter ... - - * @return string html code - */ -function print_generic($table, $fieldValue,$selected,$fieldToShow1,$fieldToShow2="",$separator=' - ',$sqltail="",$sqljoin=""){ - //return $table.$db.$field; - global $db; - if($table=="" || $fieldValue=="" || $fieldToShow1=='') - { - return "error, one of the mandatory field of the function print_generic is missing"; - }else if (empty($selected)){ - return "NuLL"; - } - - $sql="SELECT"; - $sql.=" t.".$fieldValue; - $sql.=" ,".$fieldToShow1; - if(!empty($fieldToShow2)) - $sql.=" ,".$fieldToShow2; - $sql.= " FROM ".MAIN_DB_PREFIX.$table." as t"; - if(!empty($sqljoin)) - $sql.=' '.$sqljoin; - $sql.= " WHERE t.".$fieldValue."=".$selected; - if(!empty($sqlTail)) - $sql.=' '.$sqlTail; - - dol_syslog("form::print_generic sql=".$sql, LOG_DEBUG); - - $resql=$db->query($sql); - - if ($resql) - { - // support AS in the fields ex $field1='CONTACT(u.firstname,' ',u.lastname) AS fullname' - // with sqltail= 'JOIN llx_user as u ON t.fk_user=u.rowid' - $starfields1=strpos($fieldToShow1,' AS '); - if($starfields1>0){ - $fieldToShow1= substr($fieldToShow1, $starfields1+4); - } - $starfields2=strpos($fieldToShow2,' AS '); - if($starfields2>0){ - $fieldToShow2=substr($fieldToShow2, $starfields2+4); - } - - $num = $db->num_rows($resql); - if ( $num) - { - $obj = $db->fetch_object($resql); - - if ($obj) - { - $select=$obj->{$fieldToShow1}; - if(!empty($fieldToShow2)) - $select.=$separator.$obj->{$fieldToShow2}; - }else{ - $select= "NULL"; - } - }else{ - $select= "NULL"; - } - } - else - { - $error++; - dol_print_error($db); - $select.= "ERROR"; - } - //$select.="\n"; - return $select; - } - - /* - * function to genegate a select list from a table, the showed text will be a concatenation of some - * column defined in column bit, the Least sinificative bit will represent the first colum - * - * @param object $db db Object to do the querry - * @param int/array $userid ID of the user you want to get the subordinate liste * @param int $userid ID of the user you want to get the subordinate liste - * @param int $entity entity - * @return array List of the subordinate ids and level [[id][lvl]] - */ \ No newline at end of file diff --git a/htdocs/install/mysql/migration/5.0.0-6.0.0.sql b/htdocs/install/mysql/migration/5.0.0-6.0.0.sql index 3a995b0dc96..ceaf1f5be90 100644 --- a/htdocs/install/mysql/migration/5.0.0-6.0.0.sql +++ b/htdocs/install/mysql/migration/5.0.0-6.0.0.sql @@ -101,7 +101,6 @@ ALTER TABLE llx_facturedet_rec ADD COLUMN vat_src_code varchar(10) DEFAULT '' AF ALTER TABLE llx_extrafields ADD COLUMN langs varchar(24); ALTER TABLE llx_supplier_proposaldet ADD COLUMN fk_unit integer DEFAULT NULL; -ALTER TABLE llx_projet_task_time ADD COLUMN status enum('PLANNED','DRAFT','SUBMITTED','APPROVED','CANCELLED','REJECTED','CHALLENGED','INVOICED','UNDERAPPROVAL') DEFAULT 'DRAFT'; ALTER TABLE llx_ecm_files ADD COLUMN ref varchar(128) AFTER rowid; ALTER TABLE llx_ecm_files CHANGE COLUMN fullpath filepath varchar(255); diff --git a/htdocs/install/mysql/tables/llx_projet_task_time.sql b/htdocs/install/mysql/tables/llx_projet_task_time.sql index e3453a256f0..897364a90e1 100644 --- a/htdocs/install/mysql/tables/llx_projet_task_time.sql +++ b/htdocs/install/mysql/tables/llx_projet_task_time.sql @@ -31,6 +31,5 @@ create table llx_projet_task_time import_key varchar(14), -- Import key datec date, -- Date creation time tms timestamp, -- Date update time - status enum('PLANNED','DRAFT','SUBMITTED','APPROVED','CANCELLED','REJECTED','CHALLENGED','INVOICED','UNDERAPPROVAL') DEFAULT 'DRAFT'; note text -- A comment )ENGINE=innodb; diff --git a/htdocs/projet/projectInvoice.php b/htdocs/projet/projectInvoice.php deleted file mode 100644 index ec3b8b69919..00000000000 --- a/htdocs/projet/projectInvoice.php +++ /dev/null @@ -1,355 +0,0 @@ - - * - * 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 . - */ - - -//FIXME new param needed -define('INVOICE_METHOD','user'); -define('INVOICE_TASKTIME','all'); -define('INVOICE_SERVICE','-999'); -define('INVOICE_SHOW_TASK','1'); -define('INVOICE_SHOW_USER','1'); - -//load class -require '../main.inc.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/generic.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; -require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; - -//get param -$staticProject=new Project($db); -$projectId=GETPOST('projectid'); - -$socid=GETPOST('socid'); -$month=GETPOST('month'); -$year=GETPOST('year'); -$mode=GETPOST('invoicingMethod'); -$step=GETPOST('step'); -$ts2Invoice=GETPOST('ts2Invoice'); -$tsNotInvoiced=GETPOST('tsNotInvoiced'); -$userid= is_object($user)?$user->id:$user; -//init handling object -$form = new Form($db); - -//FIXME check autorisation for project and page/ - -if ($user->rights->facture->creer & hasProjectRight($userid,$projectid)) -{ - if($projectId>0)$staticProject->fetch($projectId); - if($socid==0 || !is_numeric($socid))$socid=$staticProject->socid; //FIXME check must be in place to ensure the user hqs the right to see the project details -$edit=1; -// avoid SQL issue -if(empty($month) || empty($year) || empty($projectId))$step=1; -//steps - switch ($step) - { - case '2':{ - $fields=($mode=='user')?'fk_user':(($mode=='taskUser')?'fk_user,fk_task':'fk_task'); - $sql= 'SELECT '.$fields.', SUM(tt.task_duration) as duration '; - $sql.=', GROUP_CONCAT(tt.rowid SEPARATOR ", ") as task_time_list'; - $sql.=' From '.MAIN_DB_PREFIX.'projet_task_time as tt'; - $sql.=' JOIN '.MAIN_DB_PREFIX.'projet_task as t ON tt.fk_task=t.rowid'; - $sql.=' WHERE t.fk_projet='.$projectId; - $sql.=' AND MONTH(tt.task_date)='.$month; - $sql.=' AND YEAR(tt.task_date)='.$year; - if($ts2Invoice!='all'){ - /*$sql.=' AND tt.rowid IN(SELECT GROUP_CONCAT(fk_project_tasktime_list SEPARATOR ", ")'; - $sql.=' FROM '.MAIN_DB_PREFIX.'project_tasktime_approval'; - $sql.=' WHERE status= "APPROVED" AND MONTH(start_date)='.$month; - $sql.=' AND YEAR(start_date)="'.$year.'")'; - $sql.=' AND YEAR(start_date)="'.$year.'")'; */ - $sql.=' AND tt.status = "APPROVED"'; - } - if($tsNotInvoiced==1){ - $sql.=' AND tt.invoice_id IS NULL'; - } - $sql.=' GROUP BY '.$fields; - dol_syslog('timesheet::timesheetProjectInvoice step2', LOG_DEBUG); - - - $Form ='
'."\n\t"; - $Form .=''; - $Form .=''; - $Form .=''; - $Form .=''; - $Form .=''; - $Form .=''; - - $resql=$db->query($sql); - $num=0; - $resArray=array(); - if ($resql) - { - $num = $db->num_rows($resql); - $i = 0; - - // Loop on each record found, - while ($i < $num) - { - $error=0; - $obj = $db->fetch_object($resql); - $duration=floor($obj->duration/3600).":".str_pad (floor($obj->duration%3600/60),2,"0",STR_PAD_LEFT); - switch($mode){ - case 'user': - //step 2.2 get the list of user (all or approved) - $resArray[]=array("USER" => $obj->fk_user,"TASK" =>'any',"DURATION"=>$duration,'LIST'=>$obj->task_time_list); - break; - case 'taskUser': - //step 2.3 get the list of taskUser (all or approved) - $resArray[]=array("USER" => $obj->fk_user,"TASK" =>$obj->fk_task,"DURATION"=>$duration,'LIST'=>$obj->task_time_list); - break; - default: - case 'task': - //step 2.1 get the list of task (all or approved) - $resArray[]=array("USER" => "any","TASK" =>$obj->fk_task,"DURATION"=>$duration,'LIST'=>$obj->task_time_list); - break; - } - - $i++; - } - $db->free($resql); - }else - { - dol_print_error($db); - return ''; - } -//var_dump($resArray); - //FIXME asign a service + price to each array elements (or price +auto generate name - $Form .=''."\n\t\t"; - $Form .=''; - $Form .=''; - $Form .=''; - $Form .=''; - $Form .=''; - $form = new Form($db); - foreach($resArray as $res){ - $Form .=htmlPrintServiceChoice($res["USER"],$res["TASK"],'pair',$res["DURATION"],$res['LIST'],$mysoc,$socid); - } - - $Form .='
'.$langs->trans("Step").' 2
'.$langs->trans("User").''.$langs->trans("Task").''.$langs->trans("Service").''.$langs->trans("Description").''.$langs->trans("PriceHT").''.$langs->trans("VAT").''.$langs->trans("unitDuration").''.$langs->trans("Duration").'
'; - $Form .='\n"; - - - - break;} - case 3: // review choice and list of item + quantity ( editable) - require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php'; - require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; - $object = new Facture($db); - - $db->begin(); - $error = 0; - - $dateinvoice = time(); - //$date_pointoftax = dol_mktime(12, 0, 0, $_POST['date_pointoftaxmonth'], $_POST['date_pointoftaxday'], $_POST['date_pointoftaxyear']); - // Si facture standard - $object->socid = $socid; - $object->type = Facture::TYPE_STANDARD; - $object->date = $dateinvoice; - $object->fk_project = $projectid; - $object->fetch_thirdparty(); - $id = $object->create($user); - $resArray=$_POST['userTask']; - $task_time_array=array(); - if(is_array($resArray)){ - 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); - var_dump($endday); - $details=''; - $result =''; - if(($tId!='any') && INVOICE_SHOW_TASK)$details="\n".$service['taskLabel']; - if(($uId!='any')&& INVOICE_SHOW_USER)$details.="\n".$service['userName']; - - if($service['Service']>0){ - $product = new Product($db); - $product->fetch($service['Service']); - - $unit_duration_unit=substr($product->duration, -1); - $factor=($unit_duration_unit=='h')?3600:8*3600;//FIXME support week and month - $factor=$factor*intval(substr($product->duration,0, -1)); - $quantity= $duration/$factor; - $result = $object->addline($product->description.$details, $product->price, $quantity, $product->tva_tx, $product->localtax1_tx, $product->localtax2_tx, $service['Service'], 0, $startday, $endday, 0, 0, '', $product->price_base_type, $product->price_ttc, $product->type, -1, 0, '', 0, 0, null, 0, '', 0, 100, '', $product->fk_unit); - - - }elseif ($service['Service']<>-999){ - $factor=($service['unit_duration_unit']=='h')?3600:8*3600;//FIXME support week and month - $factor=$factor*intval($service['unit_duration']); - - $quantity= $duration/$factor; - $result = $object->addline($service['Desc'].$details, $service['PriceHT'], $quantity, $service['VAT'], '', '', '', 0, $startday, $endday, 0, 0, '', 'HT', '', 1, -1, 0, '', 0, 0, null, 0, '', 0, 100, '', ''); - - } - if($service['taskTimeList']<>'' && $result>0)$task_time_array[$result]=$service['taskTimeList']; - }else $error++; - } - }else $error++; - - // End of object creation, we show it - if ($id > 0 && ! $error) - { - $db->commit(); - foreach($task_time_array AS $idLine=> $task_time_list){ - //dol_syslog("ProjectInvoice::setnvoice".$idLine.' '.$task_time_list, LOG_DEBUG); - Update_task_time_invoice($id,$idLine,$task_time_list); - } - - header('Location: ' . $object->getNomUrl(0,'',0,1,'')); - exit(); - } - else - { - $db->rollback(); - //header('Location: ' . $_SERVER["PHP_SELF"] . '?step=0'); - setEventMessages($object->error, $object->errors, 'errors'); - - } - - break; - - case 1: - -$edit=0; - case 0: - default: - require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; - $htmlother = new FormOther($db); - $sqlTail=''; - - if(!$user->admin){ - $sqlTail=' JOIN llx_element_contact ON t.rowid= element_id '; - $sqlTail.=' WHERE fk_c_type_contact = "160" '; - $sqlTail.=' AND fk_socpeople="'.$userid.'"'; - } - $Form =''."\n\t"; - $Form .=''."\n\t\t"; - $Form .=''; - // $Form .=''; - // $Form .=''; - $Form .='\n\t\t"; - -//cust list - $Form .=''; -//all ts or only approved - $ts2Invoice=INVOICE_TASKTIME; - $Form .='"; -// not alreqdy invoice - $Form .=''; - - $Form .='
'.$langs->trans("Step").' '.$step.''; - $invoicingMethod=INVOICE_METHOD; - $Form .='
'.$langs->trans('Project').''; - $Form .=select_generic('projet', 'rowid','projectid','ref','title',$projectId,' - ','', 'fk_status=1',null); - $Form .='
'.$langs->trans('Month').' - '.$langs->trans('Year').''.$htmlother->select_month($month, 'month').' - '.$htmlother->selectyear($year,'year',1,10,3).'
'.$langs->trans('Month').'
'.$langs->trans('Customer').'
'.$langs->trans('Mode').' '.$langs->trans("Task").' '; - $Form .=' '.$langs->trans("User")." "; - $Form .=' '.$langs->trans("Task").'&'.$langs->trans("User")."
'.$langs->trans('Customer').''.$form->select_company($socid, 'socid', '(s.client=1 OR s.client=2 OR s.client=3)', 1).'
'.$langs->trans('TimesheetToInvoice').' '.$langs->trans("approvedOnly").' '; - $Form .=' '.$langs->trans("All")."
'.$langs->trans('TimesheetNotInvoiced'); - $Form .='
'; - - $Form .='\n"; - - break; - } -}else{ - $accessforbidden = accessforbidden("you don't have enough rights to see this page"); -} -/*************************************************** -* VIEW -* -* Put here all code to build page -****************************************************/ -$morejs=array("/timesheet/core/js/jsparameters.php","/timesheet/core/js/timesheet.js"); -llxHeader('',$langs->trans('TimesheetInvoice'),'','','','',$morejs); - - -print $Form; - - - -llxFooter(); -$db->close(); - - - -/*************************************************** -* FUNCTIONS -* -* Put here all code of the functions -****************************************************/ - - - -/*** - * Function to print the line to chose between a predefined service or an ad-hoc one - */ -function htmlPrintServiceChoice($user,$task,$class,$duration,$tasktimelist,$seller,$byer){ - global $form,$langs; - $userName=($user=='any')?(' - '):print_generic('user','rowid',$user,'lastname','firstname',' '); - $taskLabel=($task=='any')?(' - '):print_generic('projet_task','rowid',$task,'ref','label',' '); - $html=''.$userName; - $html.=''.$taskLabel; - $html.=''; - $html.=''; - $html.=''; - $defaultService=INVOICE_SERVICE; - $addchoices=array('-999'=> $langs->trans('not2invoice')); - $html.=''.select_generic('product', 'rowid','userTask['.$user.']['.$task.'][Service]','ref','description',$defaultService,$separator=' - ',$sqlTail='', $selectparam='tosell=1 AND fk_product_type=1',$addchoices).''; - $html.=''; - $html.=''; - //$html.=''; - $html.=''.$form->load_tva('userTask['.$user.']['.$task.'][VAT]', -1, $seller, $buyer, 0, 0, '', false, 1).''; - $html.=''; - $html.='
'.$langs->trans('Hour'); - $html.='
'.$langs->trans('Days').''; - $html.=''; - - $html.=''; - return $html; -} - -function hasProjectRight($userid,$projectid){ - global $db,$user; - $res=true; - if($projectid && !$user->admin){ - $sql=' SELECT rowid FROM '.MAIN_DB_PREFIX.'element_contact '; - $sql.=' WHERE fk_c_type_contact = "160" AND element_id="'.$projectid; - $sql.='" AND fk_socpeople="'.$userid.'"'; - $resql=$db->query($sql); - if (!$resql)$res=false; - } - return $res; -} - -function Update_task_time_invoice($idInvoice, $idLine,$task_time_list){ - global $db; - $res=true; - $sql='UPDATE '.MAIN_DB_PREFIX.'projet_task_time'; - $sql.=" SET invoice_id={$idInvoice}, invoice_line_id={$idLine}"; - $sql.=" WHERE rowid in ({$task_time_list})"; - dol_syslog("ProjectInvoice::setnvoice", LOG_DEBUG); - $resql=$db->query($sql); - if (!$resql)$res=false; - return $res; -} \ No newline at end of file From 72f8730ce8cf1648ab70adac9c7623ff3a5c23e3 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 15 Dec 2018 12:08:32 +0100 Subject: [PATCH 6/7] Update eldy.lib.php --- htdocs/core/menus/standard/eldy.lib.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index e172a83697c..36434c0c18c 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -1107,8 +1107,13 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu // Balance $newmenu->add("/accountancy/bookkeeping/balance.php?mainmenu=accountancy&leftmenu=accountancy_balance",$langs->trans("AccountBalance"),1,$user->rights->accounting->mouvements->lire); - // Files - $newmenu->add("/compta/compta-files.php?mainmenu=accountancy&leftmenu=accountancy_files",$langs->trans("AccountantFiles"),1,$user->rights->accounting->mouvements->lire); + + // Files + if (! empty($conf->global->MAIN_FEATURES_LEVEL > 2)) + { + $newmenu->add("/compta/compta-files.php?mainmenu=accountancy&leftmenu=accountancy_files",$langs->trans("AccountantFiles"),1,$user->rights->accounting->mouvements->lire); + } + // Reports $langs->load("compta"); From 48aa6e9ccffd472097f0eba0d9db31137068c014 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 15 Dec 2018 12:09:13 +0100 Subject: [PATCH 7/7] Update eldy.lib.php --- htdocs/core/menus/standard/eldy.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index 36434c0c18c..7c3ba15af01 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -1109,7 +1109,7 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu $newmenu->add("/accountancy/bookkeeping/balance.php?mainmenu=accountancy&leftmenu=accountancy_balance",$langs->trans("AccountBalance"),1,$user->rights->accounting->mouvements->lire); // Files - if (! empty($conf->global->MAIN_FEATURES_LEVEL > 2)) + if (! empty($conf->global->MAIN_FEATURES_LEVEL) && $conf->global->MAIN_FEATURES_LEVEL > 2) { $newmenu->add("/compta/compta-files.php?mainmenu=accountancy&leftmenu=accountancy_files",$langs->trans("AccountantFiles"),1,$user->rights->accounting->mouvements->lire); }