load->database(); } public function mod_getformtache($id,$section,$section_id) { global $mem_data, $validation; $this->load->model('Config_model'); $this->load->model('FxForm_model'); // vas chercher les info de la fiche $mem_data['section']=$section; $mem_data['section_id']=$section_id; $mem_data['id']=$id; $mem_data['terminer'] =1; $mem_data['projet']=''; if ($id != 0){ $info = $this->mod_getRecord($id); $mem_data['terminer'] = $info->tach_active; $mem_data['projet']=$info->com_compagnie.' ('.$info->proj_nom.')'; } // ----------------------------------- $mem_champ = 'tach_aqui_id'; $mem_value = ($id == 0 ? '' : $info->$mem_champ); $mem_data['select'][$mem_champ]['choix'] = $this->Config_model->conf_getRepresentantsClient(); // value multipli select $mem_value = explode(',', $mem_value); $mem_data['select'][$mem_champ]['value'] = $mem_value; $mem_data['label'][$mem_champ] = 'Responsable '; $mem_data['icon'][$mem_champ] = ''; // ----------------------------------------- // ------------------------------------------------------------------------- $mem_champ = 'tach_note_demande'; $mem_value = ($id == 0 ? '' : $info->$mem_champ); $this->FxForm_model->fxinputtxt($mem_champ, $mem_value, 'Demande', '', 'Demande'); // ------------------------------------------------------------------------- // ------------------------------------------------------------------------- $mem_champ = 'tach_note_suivie'; $mem_value = ($id == 0 ? '' : $info->$mem_champ); $this->FxForm_model->fxinputtxt($mem_champ, $mem_value, 'Suivie', '', 'Demande'); // ------------------------------------------------------------------------- $mem_champ = 'tach_echeance_date'; $mem_data['icon'][$mem_champ] = 'icon-append fa fa-calendar'; $mem_value = ($id == 0 ? '' : $info->$mem_champ); $mem_data['value'][$mem_champ] = $mem_value; $this->FxForm_model->fxinputtxt($mem_champ, $mem_value, 'Echeance', '', '', 'form_datetime', '', ''); // ------------------------------------------------------------------------- $mem_champ = 'tach_type'; if (strtoupper($section)=='PROJETS') $mem_liste='a'; else $mem_liste='b'; if (strtoupper($section) == 'PROJETS') { $mem_liste = 'a'; } elseif (strtoupper($section) == 'CLIENTS') { $mem_liste = 'a'; } elseif (strtoupper($section) == 'FOURNISSEURS') { $mem_liste = 'a'; }else { $mem_liste = 'b'; } $mem_value = ($id == 0 ? '' : $info->$mem_champ); $mem_data['select'][$mem_champ]['choix'] = $this->Config_model->conf_getGenresTache('fr', true, $mem_liste,'t'); // value multipli select // $mem_value = explode(',', $mem_value); $mem_data['select'][$mem_champ]['value'] = $mem_value; if (strtoupper($section)=='PROJETS' || strtoupper($section)=='CLIENTS' || strtoupper($section)=='FOURNISSEURS') $mem_data['label'][$mem_champ] = 'Statut'; else $mem_data['label'][$mem_champ] = 'Type'; // ------------------------------------------------------------------------- $mem_champ = 'tach_statut'; $mem_value = ($id == 0 ? '' : $info->$mem_champ); $mem_data['select'][$mem_champ]['choix'] = $this->Config_model->conf_getGenresTache('fr', true, $mem_liste,'s'); // value multipli select // $mem_value = explode(',', $mem_value); $mem_data['select'][$mem_champ]['value'] = $mem_value; $mem_data['label'][$mem_champ] = 'Statut'; // $mem_data['validation'] = $this->FxForm_model->fxValidation($validation['rule'], $validation['message']); return $mem_data; } public function mod_getforminfo($id,$section,$section_id) { $mem_data = array(); $mem_data = $this->mod_getformtache($id,$section,$section_id); return $mem_data; } public function mod_createRecordbd($data,$section,$section_id,$details_id) { $pref='tach'; $mem_data=[]; // print_r($data); foreach($data as $k=>$v){ if (substr($k,0,strlen($pref))==$pref) $mem_data[$k]=$v; } // print_r($mem_data); $mem_data['tach_create_date']=date("Y-m-d H:i:s"); $mem_data['tach_active']=1; $mem_data['tach_create_user_id']=$_SESSION['id']; $mem_data['tach_section']=$section; $mem_data['tach_section_id']=$section_id; $mem_data['tach_details_id']=$details_id; $this->db->insert('tach_details', $mem_data); $id = $this->db->insert_id(); if($this->config->item('pw_client')=="ms1") { // ------------------------------------------------------- // ----- Google Calendar (try/catch pour ne pas casser l’UX) // --------- BLOC DE TEST (à retirer plus tard) ---------- $info=$this->Config_model->fx_info_google_calendar($id); log_message('debug', 'Contenu de $info : ' . print_r($info, true)); $aqui = $info['email'] ?? ""; log_message('debug', 'Contenu de : ' . $aqui); $mem_data['nomclientfour']=$info["com_client_affiche"]; if ($mem_aqui=!"") { $mem_data['tach_type_nom']=$this->Config_model->conf_getGenresTache_id( $mem_data['tach_type']); $mem_data['tach_statut_nom']=$this->Config_model->conf_getGenresTache_id( $mem_data['tach_statut']); $mem_data['tach_assignee_email']= $aqui; $mem_data['tach_title'] = "⏱️𝗠·𝗦⁻¹🔸".$mem_data['nomclientfour']."❘".$mem_data['tach_type_nom']." ". $mem_data['tach_statut_nom']; $mem_data['tach_description'] = "Ceci est une tâche insérée automatiquement via l'API Google Calendar."; $mem_data['tach_start'] = $mem_data["tach_echeance_date"]; // heure de début $mem_data['tach_end'] = $mem_data["tach_echeance_date"]; // heure de fin $mem_data['tach_timezone'] = "America/Toronto"; // fuseau horaire // $mem_data['tach_assignee_email'] = $mem_data["tach_assignee_email"]; // email cible $this->create_google_reunion($mem_data, $id); } } return $id; } public function mod_createRecordbdold($data,$section,$section_id,$details_id) { // if (!isset($data['com_actif'])) // $data['com_actif']=0; // creation de la chaine de save $pref='tach'; $mem_data=array(); foreach($data as $key => $value ) { if (substr($key,0,strlen($pref))==$pref){ $mem_data[$key]=$value; } } $mem_data['tach_create_date']=date("Y-m-d H:i:s"); $mem_data['tach_active']=1; $mem_data['tach_create_user_id']=$_SESSION['id']; $mem_data['tach_section']=$section; $mem_data['tach_section_id']=$section_id; $mem_data['tach_details_id']=$details_id; $str = $this->db->insert('tach_details', $mem_data); $ok=true; return $this->db->insert_id(); } public function mod_saveRecordbd($data, $id) { $pref = 'tach'; $mem_data = array(); // 1) Collecte des champs tach_* foreach ($data as $key => $value) { if (substr($key, 0, strlen($pref)) == $pref) { $mem_data[$key] = $value; } } // 2) Boutons d’action (Activer/Terminer) if (isset($data['button'])) { if ($data['button'] == 'Activer') { $mem_data['tach_active'] = 1; } if ($data['button'] == 'Terminer') { $mem_data['tach_active'] = 0; $mem_data['tach_fin_user_date'] = date("Y-m-d H:i:s"); $mem_data['tach_fin_user_id'] = $_SESSION['id']; } } // 3) Update BD $mem_where = "tach_id = " . (int)$id; $this->db->update('tach_details', $mem_data, $mem_where); // 4) Sync Google Calendar (client ms1 seulement) if ($this->config->item('pw_client') == "ms1") { // On relit l’enregistrement complet (incluant eventId/email potentiels) $row = $this->db->get_where('tach_details', ['tach_id' => (int)$id])->row_array(); log_message('debug', 'mod saveContenu de $row: ' . $row); // Si l’email assignée n’est pas là, on refait le lookup comme au CREATE if (empty($row['tach_assignee_email']) && !empty($row['tach_aqui_id'])) { $info=$this->Config_model->fx_info_google_calendar($id); $mem_data['nomclientfour']=$info["com_client_affiche"]; $aqui = $info['email'] ?? ""; log_message('debug', 'mod saveContenu de : ' . $aqui); $row['tach_assignee_email'] = $aqui; } $mem_data['tach_type_nom']=$this->Config_model->conf_getGenresTache_id( $mem_data['tach_type']); $mem_data['tach_statut_nom']=$this->Config_model->conf_getGenresTache_id( $mem_data['tach_statut']); $row['tach_title'] = "⏱️𝗠·𝗦⁻¹🔸". $mem_data['nomclientfour']."▷".$mem_data['tach_type_nom']." ". $mem_data['tach_statut_nom']; // Valeurs par défaut cohérentes avec le CREATE $row['tach_timezone'] = "America/Toronto"; // Source de vérité: tach_echeance_date utilisé pour start/end $row['tach_start'] = $row['tach_echeance_date']; $row['tach_end'] = $row['tach_echeance_date']; // ROUTAGE selon le bouton ou édition simple if (isset($data['button'])) { if ($data['button'] == 'Terminer') { // Ferme la tâche -> SUPPRIME l’événement $this->delete_google_reunion($row, $id); } elseif ($data['button'] == 'Activer') { // Active : // - pas d’event -> CREATE // - event présent -> UPDATE if (empty($row['tach_gcal_event_id'])) { $this->create_google_reunion($row, $id); } else { $this->update_google_reunion($row, $id); } } else { // Autres boutons -> traite comme une ÉDITION if (!empty($row['tach_gcal_event_id']) && (int)$row['tach_active'] === 1) { $this->update_google_reunion($row, $id); } } } else { // ÉDITION sans bouton -> UPDATE si actif et event existant if (!empty($row['tach_gcal_event_id']) && (int)$row['tach_active'] === 1) { $this->update_google_reunion($row, $id); } } } return true; } public function mod_saveRecordbdold( $data,$id) { $pref='tach'; // creation de la chaine de save $mem_data = array(); foreach ($data as $key => $value) { if (substr($key, 0, strlen($pref)) == $pref) { $mem_data[$key] = $value; } } if (isset($data['button'])){ if ($data['button']=='Activer'){ $mem_data['tach_active']=1; } if ($data['button']=='Terminer'){ $mem_data['tach_active']=0; $mem_data['tach_fin_user_date']=date("Y-m-d H:i:s"); $mem_data['tach_fin_user_id']=$_SESSION['id']; } } $mem_where = "tach_id =" . $id; $str = $this->db->update('tach_details', $mem_data, $mem_where); $ok = true; return $ok; } public function mod_getRecordCount() { $this->db->select('count(*) as allcount'); $this->db->from('tach_details'); $query = $this->db->get(); $result = $query->result_array(); return $result[0]['allcount']; } public function mod_getRecord($id) { $this->db->select('*'); $this->db->from('tach_details'); $this->db->join('proj_entete', 'tach_details.tach_section_id = proj_id and tach_details.tach_section="Projets"', 'left'); $this->db->join('cli_compte', 'proj_entete.proj_client_id = com_id', 'left'); $this->db->where('tach_id',$id); $this->db->limit(1); $query = $this->db->get(); return $query->row(); } public function mod_getRecordCountfilter($filtre1 = "", $filtre2 = "", $filtre3 = "",$filtre4 = "",$listactive) { // list la bb client $this->db->select('count(*) as allcount'); $this->db->from('tach_details'); $this->db->join('usa_usagers aqui', 'tach_details.tach_aqui_id = aqui.usa_id ', 'left'); $this->db->join('usa_usagers create', 'tach_details.tach_create_user_id = create.usa_id ', 'left'); $this->db->join('usa_usagers fin', 'tach_details.tach_create_user_id = fin.usa_id ', 'left'); $this->db->join('tach_genres', 'tach_details.tach_type = gen_id', 'left'); if ($filtre1 != "") $this->db->where("tach_section='" . $filtre1."'"); if ($filtre2 != "") $this->db->where("tach_details.tach_aqui_id",$filtre2); if ($filtre3 != "") $this->db->where("tach_type=" . $filtre3); if ($listactive==1) $this->db->where("tach_details.tach_active!=0"); $query = $this->db->get(); $result = $query->result_array(); return $result[0]['allcount']; } public function mod_getRecords($record, $recordPerPage,$filtre1 = "", $filtre2 = "", $filtre3 = "",$filtre4 = "",$trie="",$listactive) { // list la bb client $this->db->select('*,statut.gen_id as statutid, type.gen_nom_fr as type_fr, statut.gen_nom_fr as statut_fr,projdetails.det_desc,DATEDIFF( now(),tach_create_date) AS days,fournisseur.com_compagnie as fournisseur,client.com_compagnie as compagnie, CONCAT(aqui.usa_prenom," ",aqui.usa_nom) as usa_aqui,CONCAT(create.usa_prenom," ",create.usa_nom) as usa_create,CONCAT(fin.usa_prenom," ",fin.usa_nom) as usa_fin'); $this->db->from('tach_details'); $this->db->join('usa_usagers aqui', 'tach_details.tach_aqui_id = aqui.usa_id ', 'left'); $this->db->join('usa_usagers create', 'tach_details.tach_create_user_id = create.usa_id ', 'left'); $this->db->join('usa_usagers fin', 'tach_details.tach_create_user_id = fin.usa_id ', 'left'); $this->db->join('tach_genres type', 'tach_details.tach_type = type.gen_id', 'left'); $this->db->join('tach_genres statut', 'tach_details.tach_statut = statut.gen_id', 'left'); $this->db->join('proj_entete', 'tach_details.tach_section_id = proj_id and (tach_details.tach_section="Projets" or tach_details.tach_section="projetsclient" or tach_details.tach_section="projetsfournisseur" )', 'left'); $this->db->join('cli_compte client', 'tach_details.tach_section_id = client.com_id and tach_details.tach_section="Clients"', 'left'); $this->db->join('fou_compte fournisseur', 'tach_details.tach_section_id = fournisseur.com_id and tach_details.tach_section="Fournisseurs"', 'left'); $this->db->join('proj_details_details projdetails', 'tach_details.tach_details_id = projdetails.detail_id', 'left'); $this->db->join('proj_details projdetails1', 'tach_details.tach_details_id = projdetails1.proj_det_id', 'left'); $this->db->join('pro_descriptions prodescriptions', 'projdetails1.proj_prod_id = prodescriptions.des_id', 'left'); $this->db->join('cli_compte', 'proj_entete.proj_client_id = cli_compte.com_id', 'left'); if ($trie != "null"){ $this->db->order_by($trie); }else{ } //$this->db->order_by('tach_echeance_date'); if ($filtre1 != "") $this->db->where("tach_section='" . $filtre1."'"); if ($filtre2 != "") $this->db->where("tach_details.tach_aqui_id",$filtre2); if ($filtre4 != "") $this->db->where("tach_details.tach_create_user_id",$filtre4); if ($filtre3 != "") $this->db->where("tach_type=" . $filtre3); if ($listactive==1) $this->db->where("tach_details.tach_active!=0"); $query = $this->db->get(); $result = $query->result_array(); // a faire sl affiche tableau de tache // print_r($result); return $result; } public function mod_getRecordstache($record, $recordPerPage,$filtre1 = "", $filtre2 = "", $filtre3 = "",$filtre4 = "",$trie="",$listactive) { // list la bb client $this->db->select('*,statut.gen_id as statutid, type.gen_nom_fr as type_fr, statut.gen_nom_fr as statut_fr,projdetails.det_desc,DATEDIFF( now(),tach_create_date) AS days,fournisseur.com_compagnie as fournisseur,client.com_compagnie as compagnie, CONCAT(aqui.usa_prenom," ",aqui.usa_nom) as usa_aqui,CONCAT(create.usa_prenom," ",create.usa_nom) as usa_create,CONCAT(fin.usa_prenom," ",fin.usa_nom) as usa_fin'); $this->db->from('tach_details'); $this->db->join('usa_usagers aqui', 'tach_details.tach_aqui_id = aqui.usa_id ', 'left'); $this->db->join('usa_usagers create', 'tach_details.tach_create_user_id = create.usa_id ', 'left'); $this->db->join('usa_usagers fin', 'tach_details.tach_create_user_id = fin.usa_id ', 'left'); $this->db->join('tach_genres type', 'tach_details.tach_type = type.gen_id', 'left'); $this->db->join('tach_genres statut', 'tach_details.tach_statut = statut.gen_id', 'left'); $this->db->join('proj_entete', 'tach_details.tach_section_id = proj_id and (tach_details.tach_section="Projets" or tach_details.tach_section="projetsclient" or tach_details.tach_section="projetsfournisseur" )', 'left'); $this->db->join('cli_compte client', 'tach_details.tach_section_id = client.com_id and tach_details.tach_section="Clients"', 'left'); $this->db->join('fou_compte fournisseur', 'tach_details.tach_section_id = fournisseur.com_id and tach_details.tach_section="Fournisseurs"', 'left'); $this->db->join('proj_details_details projdetails', 'tach_details.tach_details_id = projdetails.detail_id', 'left'); $this->db->join('proj_details projdetails1', 'tach_details.tach_details_id = projdetails1.proj_det_id', 'left'); $this->db->join('pro_descriptions prodescriptions', 'projdetails1.proj_prod_id = prodescriptions.des_id', 'left'); $this->db->join('cli_compte', 'proj_entete.proj_client_id = cli_compte.com_id', 'left'); if ($trie != "null"){ if ($trie === 'tach_echeance_date') { $this->db->order_by( "CASE WHEN tach_details.tach_echeance_date = '0000-00-00' OR tach_details.tach_echeance_date IS NULL THEN '9999-12-31' ELSE tach_details.tach_echeance_date END", null, false ); } else { $this->db->order_by($trie); } } //$this->db->order_by('tach_echeance_date'); if ($filtre1 != "") $this->db->where("statut.gen_id='" . $filtre1."'"); if ($filtre2 != "") $this->db->where("tach_details.tach_aqui_id",$filtre2); if ($filtre4 != "") $this->db->where("tach_details.tach_create_user_id",$filtre4); if ($filtre3 != "") $this->db->where("tach_type=" . $filtre3); if ($listactive==1) $this->db->where("tach_details.tach_active!=0"); $query = $this->db->get(); $result = $query->result_array(); // a faire sl affiche tableau de tache // print_r($result); return $result; } public function mod_listtache($section,$section_id,$details_id=0) { $this->db->select('*,statut.gen_id as statutid,genres.gen_id as typeid,statut.gen_nom_fr as statut_fr,genres.gen_nom_fr as gen_nom_fr, CONCAT(aqui.usa_prenom," ",aqui.usa_nom) as usa_aqui,CONCAT(create.usa_prenom," ",create.usa_nom) as usa_create,CONCAT(fin.usa_prenom," ",fin.usa_nom) as usa_fin'); $this->db->from('tach_details'); $this->db->join('usa_usagers aqui', 'tach_details.tach_aqui_id = aqui.usa_id ', 'left'); $this->db->join('usa_usagers create', 'tach_details.tach_create_user_id = create.usa_id ', 'left'); $this->db->join('usa_usagers fin', 'tach_details.tach_create_user_id = fin.usa_id ', 'left'); $this->db->join('tach_genres genres', 'tach_details.tach_type = genres.gen_id', 'left'); $this->db->join('tach_genres statut', 'tach_details.tach_statut = statut.gen_id', 'left'); $this->db->where('tach_section',$section); $this->db->where('tach_section_id',$section_id); $this->db->join('proj_details_details projdetails', 'tach_details.tach_details_id = projdetails.detail_id', 'left'); $this->db->join('proj_details projdetails1', 'tach_details.tach_details_id = projdetails1.proj_det_id', 'left'); $this->db->join('pro_descriptions prodescriptions', 'projdetails1.proj_prod_id = prodescriptions.des_id', 'left'); $this->db->join('fou_compte fournisseur', 'projdetails1.proj_fou_id = fournisseur.com_id', 'left'); if ($details_id!=0){ $this->db->where('tach_details_id',$details_id); } $this->db->order_by('tach_echeance_date'); $query = $this->db->get(); $result = $query->result_array(); return $result ; } public function mod_listtache_count_jour($filtre1) { $this->db->select('*,projet.com_compagnie as com_projet, CONCAT(aqui.usa_prenom," ",aqui.usa_nom) as usa_aqui,CONCAT(create.usa_prenom," ",create.usa_nom) as usa_create,CONCAT(fin.usa_prenom," ",fin.usa_nom) as usa_fin,,fournisseur.com_compagnie as fournisseur'); $this->db->from('tach_details'); $this->db->join('usa_usagers aqui', 'tach_details.tach_aqui_id = aqui.usa_id ', 'left'); $this->db->join('usa_usagers create', 'tach_details.tach_create_user_id = create.usa_id ', 'left'); $this->db->join('usa_usagers fin', 'tach_details.tach_create_user_id = fin.usa_id ', 'left'); $this->db->join('tach_genres', 'tach_details.tach_type = gen_id', 'left'); $this->db->join('proj_entete', 'tach_details.tach_section_id = proj_id AND LOWER(tach_details.tach_section) LIKE "%projet%"', 'left'); $this->db->join('cli_compte client', 'tach_details.tach_section_id = client.com_id and tach_details.tach_section="Clients"', 'left'); $this->db->join('cli_compte projet', 'projet.com_id=proj_entete.proj_client_id AND LOWER(tach_details.tach_section) LIKE "%projet%"', 'left'); $this->db->join('fou_compte fournisseur', 'tach_details.tach_section_id = fournisseur.com_id and tach_details.tach_section="Fournisseurs"', 'left'); if ($filtre1!=0) $this->db->where('tach_details.tach_aqui_id',$filtre1); // $this->db->where('tach_section',$section); // $this->db->where('tach_section_id',$section_id); $this->db->where('tach_active',1); $this->db->order_by('tach_echeance_date'); $query = $this->db->get(); $result = $query->result_array(); $sortie['details']=$result; $sortie['jour']=array(); $index_date=0; $mem_date=''; foreach ($sortie['details'] as $key => $row){ $goto=$row['tach_section']; if($row['tach_section']=='projetsclient' || $row['tach_section']=='projetsfournisseur'){ $goto='projets';} if($mem_date!=$row['tach_echeance_date']){ $index_date++; $mem_date=$row['tach_echeance_date']; $sortie['jour'][$index_date]['start']=$row['tach_echeance_date']; $sortie['jour'][$index_date]['qte']=0; $sortie['jour'][$index_date]['details']=''; } //$mem_link_go = anchor( $row['tach_section'].'/formsl/' .$row['tach_section_id'], ' ', 'target="tache" class="btn btn-primary btn-circle glyphicon glyphicon-circle-arrow-right " '); $mem_link_go = anchor( $goto.'/form/' .$row['tach_section_id'], ' ', 'class="btn btn-primary btn-circle glyphicon glyphicon-circle-arrow-right " '); $sortie['jour'][$index_date]['qte']=$sortie['jour'][$index_date]['qte']+1; $sortie['jour'][$index_date]['details']=$sortie['jour'][$index_date]['details'].' '.$mem_link_go.' '.$row['gen_nom_fr'].' •'.$row['com_projet'].'•'.$row['com_compagnie'].$row['proj_nom'].' Res :'.$row['usa_aqui'].' '. '
'; } if ($sortie['details']!=null){ if($mem_date!=$row['tach_echeance_date']){ $index_date++; $sortie['jour'][$index_date]['start']=$row['tach_echeance_date']; $sortie['jour'][$index_date]['qte']=0; } $goto=$row['tach_section']; if($row['tach_section']=='projetsclient' || $row['tach_section']=='projetsfournisseur'){ $goto='projets';} // $mem_link_go = anchor( $row['tach_section'].'/formsl2/' .$row['tach_section_id'], ' ', 'target="tache" class="btn btn-primary btn-circle glyphicon glyphicon-circle-arrow-right " '); $mem_link_go = anchor( $goto.'/form/' .$row['tach_section_id'], ' ', 'class="btn btn-primary btn-circle glyphicon glyphicon-circle-arrow-right " '); $sortie['jour'][$index_date]['qte']=$sortie['jour'][$index_date]['qte']+1; $sortie['jour'][$index_date]['details']=$sortie['jour'][$index_date]['details'].' '.$mem_link_go.' '.$row['gen_nom_fr'].' '.$row['com_projet'].' '.$row['com_compagnie'].$row['proj_nom'].' Res :'.$row['usa_aqui'].' '. '
'; } return $sortie ; } public function mod_listtache_btn($section,$section_id,$details_id=0) { $data=$this->Tache_model->mod_listtache($section,$section_id,$details_id); $mem_bt=''; foreach($data as $key => $value ) { $mem_color='btn-warning'; if ($value['tach_active']==0){ $mem_color='btn-success'; }else{ if ($value['tach_echeance_date']< date("Y-m-d")){ $mem_color='btn-danger'; } } // $mem_titre=$value['gen_nom_fr'].' Responsable :'.$value['usa_aqui'].' Echeance :'.$value['tach_echeance_date']; $mem_titre=$value['gen_nom_fr'].' Demande : '.$value['tach_note_demande'].' Suivie : '.$value['tach_note_suivie']; $mem_bt =$mem_bt.''; // $mem_bt =$mem_bt.'Tache_model->mod_listtache($section,$section_id,$details_id); if (strtoupper($section)=='PROJETS') $mem_bt = ''; else $mem_bt = '
Echeance StatutProduitResponsable
'; foreach($data as $key => $value ) { $mem_color='btn-warning'; if ($value['tach_active']==0){ $mem_color='btn-success'; }else{ if ($value['tach_echeance_date']< date("Y-m-d")){ $mem_color='btn-danger'; } } // $mem_titre=$value['gen_nom_fr'].' Responsable :'.$value['usa_aqui'].' Echeance :'.$value['tach_echeance_date']; $mem_titre=$value['gen_nom_fr'].' Demande : '.$value['tach_note_demande'].' Suivie : '.$value['tach_note_suivie']; // $mem_row = '
'; // $mem_row =$mem_row.'
'.$value['usa_aqui'].'
'; // $mem_row =$mem_row.'
'.$value['tach_echeance_date'].'
'; // $mem_row =$mem_row.'
'.$value['des_nom_fr'].'
'; // $mem_row = ''; $mem_row = ''; $mem_row =$mem_row. ''; if (strtoupper($section)!='PROJETS'){ $mem_row =$mem_row. ''; $mem_row =$mem_row. ''; }else{ $mem_row =$mem_row. ''; } $mem_row =$mem_row. ''; $mem_row =$mem_row. ''; $mem_bt=$mem_bt.$mem_row; // $mem_bt =$mem_bt.'a'; } $mem_bt =$mem_bt. '
EcheanceTypeStatutProduitResponsable
'.$value['usa_aqui'].' '.$value['tach_echeance_date'].''.$value['com_compagnie'].'-'.$value['det_desc'].'-'.$value['des_nom_fr'].'
'.$value['tach_echeance_date'].' '.$value['gen_nom_fr'].''.$value['statut_fr'].''.$value['gen_nom_fr'].''.$value['com_compagnie'].'-'.$value['det_desc'].'-'.$value['des_nom_fr'].''.$value['usa_aqui'].'
'; echo $mem_bt; } function create_google_reunion($data, $id){ $tach_section_id = (int) trim($data['tach_section_id']); $goto=$data['tach_section']; if($data['tach_section']=='projetsclient' || $data['tach_section']=='projetsfournisseur'){ $goto='projets';} $base = rtrim($this->config->item('base_url'), '/'); // CI3 $href = $base . '/index.php/' . $goto. '/form/' . $tach_section_id ; $data['tach_description'] = $data['tach_note_demande'] .'
CRM'; log_message('debug', 'create Contenu de $data : ' . print_r($data, true)); try { try { $rid = uniqid('GCAL:', false); // id corrélé pour suivre une exécution log_message('error', "$rid ENTER createEvent()"); // marqueur d'entrée $this->load->library('GCalService'); log_message('error', "$rid lib GCalService loaded=" . (isset($this->gcalservice) ? 'yes' : 'no')); // Tâche / contexte (si $id existe dans ce scope) if (isset($id)) { log_message('error', "$rid tach_id=$id"); } else { log_message('error', "$rid WARN tach_id not set in this scope"); } // Données entrantes $assignee = $data['tach_assignee_email'] ?? ''; $tz = $data['tach_timezone'] ?? 'America/Toronto'; $startRaw = $data['tach_start'] ?? ''; $endRaw = $data['tach_end'] ?? ''; $dueRaw = $data['tach_echeance_date'] ?? ''; log_message('error', "$rid INPUT assignee=$assignee tz=$tz startRaw=$startRaw endRaw=$endRaw dueRaw=$dueRaw"); // Convertis vers ISO8601 $startIso = $startRaw ? date('c', strtotime($startRaw)) : ''; $endIso = $endRaw ? date('c', strtotime($endRaw)) : ''; // **** AUTO-PLACEMENT si heures manquantes/minuit **** $baseTime = $this->config->item('gcal_autoplace_time') ?? '08:00'; $durationMin = (int)($this->config->item('gcal_autoplace_duration') ?? 1); $dateYmd = !empty($dueRaw) ? date('Y-m-d', strtotime($dueRaw)) : date('Y-m-d', strtotime($startRaw ?: 'now')); $isMidnightStart = !empty($startRaw) && (substr(date('H:i', strtotime($startRaw)), 0, 5) === '00:00'); $isMidnightEnd = !empty($endRaw) && (substr(date('H:i', strtotime($endRaw)), 0, 5) === '00:00'); log_message('error', "$rid TIME pre slot startIso=$startIso endIso=$endIso dateYmd=$dateYmd midStart=" . ($isMidnightStart?'1':'0') . " midEnd=" . ($isMidnightEnd?'1':'0')); if (empty($startRaw) || empty($endRaw) || $isMidnightStart || $isMidnightEnd) { log_message('error', "$rid CALL gcal_find_slot_minute assignee=$assignee baseTime=$baseTime durationMin=$durationMin"); $slot = $this->gcal_find_slot_minute($assignee, $dateYmd, $tz, $baseTime, $durationMin); $startIso = $slot['startIso'] ?? $startIso; $endIso = $slot['endIso'] ?? $endIso; log_message('error', "$rid SLOT result startIso=$startIso endIso=$endIso"); } $payload = [ 'summary' => $data['tach_title'] ?? 'Tâche', 'description' => $data['tach_description'] ?? '', 'start' => $startIso, 'end' => $endIso, 'timezone' => $tz, ]; // Log du payload (compact, sans caractères échappés moches) $payloadLog = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); log_message('error', "$rid PAYLOAD $payloadLog"); // Avant l'appel Google $calendarId = 'primary'; log_message('error', "$rid CALL GCalService.createEvent(subject=$assignee, calendarId=$calendarId)"); $res = $this->gcalservice->createEvent($assignee, $calendarId, $payload); // Résultat Google $eventId = is_array($res) ? ($res['eventId'] ?? '') : ''; $gcalIdOut = is_array($res) ? ($res['calendarId'] ?? '') : ''; log_message('error', "$rid RETURN eventId=$eventId calendarIdOut=$gcalIdOut"); // Update DB if (isset($id)) { $okDb = $this->db->update('tach_details', [ 'tach_gcal_event_id' => $eventId, 'tach_gcal_calendar_id' => $gcalIdOut ], "tach_id=".$id); log_message('error', "$rid DB update ok=" . ($okDb?'1':'0') . " affected_rows=" . $this->db->affected_rows()); } else { log_message('error', "$rid SKIP DB update (tach_id missing)"); } log_message('error', "$rid EXIT createEvent() OK"); } catch (Throwable $e) { // Throwable pour avoir les Error/TypeError aussi log_message('error', "$rid EXCEPTION ". $e->getMessage()); log_message('error', "$rid TRACE \n". $e->getTraceAsString()); // (on garde ton comportement : pas de rethrow) } } catch (Exception $e) { log_message('error', 'GCal create error: '.$e->getMessage()); // à toi de voir si tu veux notifier l’utilisateur } } function update_google_reunion($data, $id) { try { $this->load->library('GCalService'); // Sécurité minimale if (empty($data['tach_assignee_email']) || empty($data['tach_gcal_event_id'])) { log_message('error', 'GCal UPDATE: pas d’email ou pas d’eventId pour tach_id=' . $id); return; } $tach_section_id = (int) trim($data['tach_section_id']); $goto=$data['tach_section']; if($data['tach_section']=='projetsclient' || $data['tach_section']=='projetsfournisseur'){ $goto='projets';} $base = rtrim($this->config->item('base_url'), '/'); // CI3 $href = $base . '/index.php/' . $goto. '/form/' . $tach_section_id ; $description = ($data['tach_note_demande'] ?? '') . '
CRM'; $tz = $data['tach_timezone'] ?? 'America/Toronto'; // Source de vérité pour les dates: tach_echeance_date (comme au create) $startIso = date('c', strtotime($data['tach_echeance_date'] ?? $data['tach_start'] ?? 'now')); $endIso = date('c', strtotime($data['tach_echeance_date'] ?? $data['tach_end'] ?? 'now')); // ******** AJOUT : auto-placement minute par minute si heure absente ou à minuit ******** $baseTime = $this->config->item('gcal_autoplace_time') ?? '08:00'; $durationMin = (int)($this->config->item('gcal_autoplace_duration') ?? 1); $dateYmd = !empty($data['tach_echeance_date']) ? date('Y-m-d', strtotime($data['tach_echeance_date'])) : date('Y-m-d', strtotime($data['tach_start'] ?? 'now')); $hasStart = !empty($data['tach_start']); $hasEnd = !empty($data['tach_end']); $isMidnightStart = $hasStart && (substr(date('H:i', strtotime($data['tach_start'])),0,5) === '00:00'); $isMidnightEnd = $hasEnd && (substr(date('H:i', strtotime($data['tach_end'])),0,5) === '00:00'); if (!$hasStart || !$hasEnd || $isMidnightStart || $isMidnightEnd) { $slot = $this->gcal_find_slot_minute($data['tach_assignee_email'], $dateYmd, $tz, $baseTime, $durationMin); $startIso = $slot['startIso']; $endIso = $slot['endIso']; } // ******** FIN AJOUT ******** $payload = [ 'summary' => $data['tach_title'] ?? 'Tâche', 'description' => $description, 'start' => $startIso, 'end' => $endIso, 'timezone' => $tz, ]; // Update (PATCH) l’événement existant $this->gcalservice->updateEvent($data['tach_assignee_email'], 'primary', $data['tach_gcal_event_id'], $payload); log_message('debug', 'GCal UPDATE OK pour tach_id=' . $id); } catch (Exception $e) { // Si l’événement n’existe plus (404) → on le recrée proprement $msg = $e->getMessage(); if (stripos($msg, '404') !== false || stripos($msg, 'not found') !== false) { log_message('error', 'GCal update: event introuvable, recréation. tach_id=' . $id . ' | ' . $msg); $this->create_google_reunion($data, $id); } else { log_message('error', 'GCal update error tach_id=' . $id . ' : ' . $msg); } } } function delete_google_reunion($data, $id) { try { $this->load->library('GCalService'); if (!empty($data['tach_assignee_email']) && !empty($data['tach_gcal_event_id'])) { $this->gcalservice->deleteEvent($data['tach_assignee_email'], 'primary', $data['tach_gcal_event_id']); log_message('debug', 'GCal DELETE OK pour tach_id=' . $id); } else { log_message('debug', 'GCal DELETE: rien à supprimer (pas d’eventId ou pas d’email) pour tach_id=' . $id); } // On nettoie les champs GCal dans la BD $this->db->update('tach_details', [ 'tach_gcal_event_id' => null, 'tach_gcal_calendar_id' => null, ], "tach_id=" . (int)$id); } catch (Exception $e) { log_message('error', 'GCal delete error tach_id=' . $id . ' : ' . $e->getMessage()); } } /** * Trouve le prochain créneau libre (minute par minute) à partir d'une heure de base, * en interrogeant UNIQUEMENT Google Calendar (FreeBusy) pour l'utilisateur ciblé. * * Prérequis config (application/config/config.php) : * $config['google_sa_keyfile'] = APPPATH.'third_party/google/sa.json'; // chemin absolu vers la clé JSON du compte de service * $config['google_sa_impersonate'] = true; // true si Domain-Wide Delegation activée et autorisée * * Notes : * - Le compte de service doit avoir DWD activé et autorisé sur le scope https://www.googleapis.com/auth/calendar * - L'admin Google Workspace doit autoriser le SA à "se faire passer" (impersonate) pour les utilisateurs du domaine * - Cette fonction NE modifie rien dans Google ; elle ne fait que LIRE via FreeBusy. */ /** * Google-only (Service Account + FreeBusy) — ne dépend pas de GCalService. * Trouve le prochain créneau libre (minute par minute) à partir d'une heure de base. * Prérequis config: * $config['google_sa_keyfile'] = '/chemin/absolu/vers/sa.json'; * $config['google_sa_impersonate'] = true; // si DWD activée */ private function gcal_find_slot_minute($assigneeEmail, $dateYmd, $tz = 'America/Toronto', $baseTime = '08:00', $durationMin = 1) { if (empty($assigneeEmail)) { log_message('error', '[GCal] gcal_find_slot_minute: assigneeEmail manquant'); $tzObj = new DateTimeZone('America/Toronto'); $start = new DateTime("$dateYmd $baseTime:00", $tzObj); $end = (clone $start)->modify("+$durationMin minutes"); return ['startIso' => $start->format(DateTime::RFC3339), 'endIso' => $end->format(DateTime::RFC3339)]; } try { $tzObj = new DateTimeZone($tz); } catch (Exception $e) { $tzObj = new DateTimeZone('America/Toronto'); } $dayStart = new DateTime("$dateYmd 00:00:00", $tzObj); $dayEnd = new DateTime("$dateYmd 23:59:59", $tzObj); // Charger les classes Google (Composer/autoload) if (!class_exists('Google_Client')) { $paths = [ APPPATH.'third_party/google-api-php-client/vendor/autoload.php', APPPATH.'third_party/google/vendor/autoload.php', FCPATH.'vendor/autoload.php', ]; $loaded = false; foreach ($paths as $p) { if (is_file($p)) { require_once $p; $loaded = true; break; } } if (!$loaded) { log_message('error', '[GCal] google-api-php-client introuvable (autoload.php).'); $start = new DateTime("$dateYmd $baseTime:00", $tzObj); $end = (clone $start)->modify("+$durationMin minutes"); return ['startIso' => $start->format(DateTime::RFC3339), 'endIso' => $end->format(DateTime::RFC3339)]; } } $keyFile = $this->config->item('google_sa_keyfile'); $doImpersonate= (bool)($this->config->item('google_sa_impersonate') ?? true); if (empty($keyFile) || !is_file($keyFile)) { log_message('error', '[GCal] Clé de compte de service introuvable: '.$keyFile); $start = new DateTime("$dateYmd $baseTime:00", $tzObj); $end = (clone $start)->modify("+$durationMin minutes"); return ['startIso' => $start->format(DateTime::RFC3339), 'endIso' => $end->format(DateTime::RFC3339)]; } try { $client = new Google_Client(); $client->setAuthConfig($keyFile); $client->setScopes([Google_Service_Calendar::CALENDAR_READONLY]); if ($doImpersonate) { $client->setSubject($assigneeEmail); } $service = new Google_Service_Calendar($client); // FreeBusy sur la journée $fbReq = new Google_Service_Calendar_FreeBusyRequest(); $fbReq->setTimeMin($dayStart->format(DateTime::RFC3339)); $fbReq->setTimeMax($dayEnd->format(DateTime::RFC3339)); $fbReq->setTimeZone($tz); $item = new Google_Service_Calendar_FreeBusyRequestItem(); $item->setId('primary'); $fbReq->setItems([$item]); $fbResp = $service->freebusy->query($fbReq); $cals = $fbResp->getCalendars(); $busy = []; if (isset($cals['primary'])) { $blocks = $cals['primary']['busy'] ?? []; foreach ($blocks as $b) { $s = new DateTime($b['start']); $e = new DateTime($b['end']); $s->setTimezone($tzObj); $e->setTimezone($tzObj); $busy[] = [$s, $e]; } } else { foreach ($cals as $cal) { $blocks = $cal['busy'] ?? []; foreach ($blocks as $b) { $s = new DateTime($b['start']); $e = new DateTime($b['end']); $s->setTimezone($tzObj); $e->setTimezone($tzObj); $busy[] = [$s, $e]; } break; } } // Tri par start usort($busy, function($a,$b){ return $a[0] <=> $b[0]; }); // Balayage minute par minute $candidate = new DateTime("$dateYmd $baseTime:00", $tzObj); $endOfDay = new DateTime("$dateYmd 23:59:59", $tzObj); for ($i=0; $i<1440; $i++) { if ($candidate > $endOfDay) break; $candEnd = (clone $candidate)->modify("+$durationMin minutes"); $conflict = false; foreach ($busy as $pair) { $bs = $pair[0]; $be = $pair[1]; if ($candidate < $be && $candEnd > $bs) { $conflict = true; break; } } if (!$conflict) { return [ 'startIso' => $candidate->format(DateTime::RFC3339), 'endIso' => $candEnd->format(DateTime::RFC3339), ]; } $candidate->modify('+1 minute'); } // Fallback (journée saturée) $fallbackStart = new DateTime("$dateYmd $baseTime:00", $tzObj); $fallbackEnd = (clone $fallbackStart)->modify("+$durationMin minutes"); return ['startIso' => $fallbackStart->format(DateTime::RFC3339), 'endIso' => $fallbackEnd->format(DateTime::RFC3339)]; } catch (Exception $e) { log_message('error', '[GCal] gcal_find_slot_minute FreeBusy error: '.$e->getMessage()); $start = new DateTime("$dateYmd $baseTime:00", $tzObj); $end = (clone $start)->modify("+$durationMin minutes"); return ['startIso' => $start->format(DateTime::RFC3339), 'endIso' => $end->format(DateTime::RFC3339)]; } } }