diff --git a/class/msAgenda.php b/class/msAgenda.php
new file mode 100644
index 00000000..1af8d972
--- /dev/null
+++ b/class/msAgenda.php
@@ -0,0 +1,412 @@
+
+ * http://www.medshake.net
+ *
+ * MedShakeEHR is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * MedShakeEHR 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 MedShakeEHR. If not, see .
+ */
+
+/**
+ * Gestion de l'agenda et des rendez-vous
+ *
+ * @author Bertrand Boutillier
+ */
+
+class msAgenda
+{
+ /**
+ * Event ID
+ * @var int
+ */
+ private $_eventID;
+
+ /**
+ * User ID ( agenda de l'utilisateur n° )
+ * @var int
+ */
+ private $_userID;
+
+ /**
+ * Date de début au format ISO8601
+ * @var string
+ */
+ private $_startDate;
+
+ /**
+ * Date de fin au format ISO8601
+ * @var string
+ */
+ private $_endDate;
+
+ /**
+ * Motif du rdv
+ * @var string
+ */
+ private $_motif;
+ /**
+ * Type du rdv
+ * @var string
+ */
+ private $_type;
+ /**
+ * ID du patient
+ * @var int
+ */
+ private $_patientID;
+ /**
+ * Tableau des types de rdv
+ * @var array
+ */
+ private $_tabTypesRdv;
+
+ /**
+ * set patientID
+ * @param int $_patientID ID du patient
+ */
+ public function set_patientID($_patientID)
+ {
+ $this->_patientID = $_patientID;
+ return $this;
+ }
+
+
+ /**
+ * set motif
+ * @param string $_motif motid de rendez-vous
+ */
+ public function set_motif($_motif)
+ {
+ $this->_motif = $_motif;
+ return $this;
+ }
+
+ /**
+ * set type
+ * @param string $_type type de rendez-vous
+ */
+ public function set_type($_type)
+ {
+ $this->_type = $_type;
+ return $this;
+ }
+
+
+ /**
+ * Set startDate
+ * @param string $startDate format ISO8601
+ */
+ public function setStartDate($startDate)
+ {
+ $this->_startDate = $startDate;
+ return $this;
+ }
+
+ /**
+ * Set eventID
+ * @param int $_eventID eventID
+ */
+ public function set_eventID($_eventID)
+ {
+ $this->_eventID = $_eventID;
+ return $this;
+ }
+
+ /**
+ * Set userID (= n° du calendrier)
+ * @param int $_userID N° commun user/calendrier
+ */
+ public function set_userID($_userID)
+ {
+ $this->_userID = $_userID;
+ return $this;
+ }
+
+ /**
+ * Set endDate
+ * @param string $endDate format ISO8601
+ */
+ public function setEndDate($endDate)
+ {
+ $this->_endDate = $endDate;
+ return $this;
+ }
+
+ /**
+ * Ajouter ou update un rendez-vous en fonction de la présente ou non
+ * de l'envetID
+ */
+ public function addOrUpdateRdv()
+ {
+ if (!isset($this->_startDate)) {
+ throw new Exception('StartDate n\'est pas définie');
+ }
+ if (!isset($this->_endDate)) {
+ throw new Exception('EndDate n\'est pas définie');
+ }
+ if (!isset($this->_userID)) {
+ throw new Exception('UserID n\'est pas défini');
+ }
+ if (!isset($this->_patientID)) {
+ throw new Exception('PatientID n\'est pas défini');
+ }
+ if (!isset($this->_type)) {
+ throw new Exception('Type n\'est pas défini');
+ }
+
+ $data=array(
+ 'userid'=>$this->_userID,
+ 'start'=>$this->_startDate,
+ 'end'=>$this->_endDate,
+ 'type'=>$this->_type,
+ 'patientid'=>$this->_patientID,
+ 'motif'=>$this->_motif
+ );
+
+ if (isset($this->_eventID)) {
+ $data['id']=$this->_eventID;
+ } else {
+ $this->_eventID=$data['id']=time();
+ $data['dateAdd']=date('Y-m-d H:i:s');
+ }
+
+ msSQL::sqlInsert('agenda', $data);
+ return $this->getEventByID();
+ }
+
+ /**
+ * Obtenir les rendez-vous sur une plage calendaire déterminée
+ * @return array tableau des rendez-vous
+ */
+ public function getEvents()
+ {
+ if (!isset($this->_startDate)) {
+ throw new Exception('StartDate n\'est pas définie');
+ }
+ if (!isset($this->_endDate)) {
+ throw new Exception('EndDate n\'est pas définie');
+ }
+ if (!isset($this->_userID)) {
+ throw new Exception('UserID n\'est pas défini');
+ }
+ $formatedEvents=[];
+
+ if ($events=msSQL::sql2tab("select a.id, a.start, a.end, a.type, a.patientid, a.statut, a.absente, a.motif, concat(n.value, ' ', p.value) as name
+ from agenda as a
+ left join objets_data as n on n.toID=a.patientid and n.outdated='' and n.deleted='' and n.typeID='2'
+ left join objets_data as p on p.toID=a.patientid and p.outdated='' and p.deleted='' and p.typeID='3'
+ where a.userid='".$this->_userID."' and a.statut='actif' and a.start >= '".$this->_startDate."' and a.end <= '".$this->_endDate."'
+ group by a.id")) {
+ foreach ($events as $e) {
+ $formatedEvents[]=$this->_formatEvent($e);
+ }
+ }
+ return $formatedEvents;
+ }
+
+ /**
+ * Obtenir les data d'un rendez-vous par son ID
+ * @return array tableau des rendez-vous
+ */
+ public function getEventByID()
+ {
+ if (!isset($this->_eventID)) {
+ throw new Exception('EventID n\'est pas définie');
+ }
+
+ if ($event=msSQL::sqlUnique("select a.id, a.start, a.end, a.type, a.patientid, a.statut, a.absente, a.motif, concat(n.value, ' ', p.value) as name
+ from agenda as a
+ left join objets_data as n on n.toID=a.patientid and n.outdated='' and n.deleted='' and n.typeID='2'
+ left join objets_data as p on p.toID=a.patientid and p.outdated='' and p.deleted='' and p.typeID='3'
+ where a.id= '".$this->_eventID."'
+ group by a.id")) {
+ $formatedEvent=$this->_formatEvent($event);
+ }
+ return $formatedEvent;
+ }
+
+ /**
+ * Formater un rendez-vous
+ * @param array $e tableau datas rdv
+ * @return array rendez-vous formaté
+ */
+ private function _formatEvent($e)
+ {
+ global $p;
+ if (!isset($this->_tabTypeRdv)) {
+ if (is_file($p['config']['webDirectory'].'agendasConfigurations/configTypesRdv'.$this->_userID.'.yml')) {
+ $this->_tabTypeRdv=Spyc::YAMLLoad($p['config']['webDirectory'].'agendasConfigurations/configTypesRdv'.$this->_userID.'.yml');
+ } else {
+ $this->_tabTypeRdv=array(
+ '[C]'=> array(
+ 'descriptif'=>'Consultation',
+ 'backgroundColor'=>'#2196f3',
+ 'borderColor'=>'#1e88e5',
+ 'duree'=>15
+ )
+ );
+ }
+ }
+
+ if (isset($this->_tabTypeRdv[$e['type']]['textColor'])) {
+ $textColor=$this->_tabTypeRdv[$e['type']]['textColor'];
+ } else {
+ $textColor='#fff';
+ }
+
+ if ($e['absente']=='oui') {
+ $class=array('hasmenu','eventAbsent');
+ } else {
+ $class=array('hasmenu');
+ }
+
+ $re=@array(
+ 'id'=>$e['id'],
+ 'title'=>$e['name'],
+ 'allDay'=>false,
+ 'start'=>$e['start'],
+ 'end'=>$e['end'],
+ 'editable'=>true,
+ 'backgroundColor'=> $this->_tabTypeRdv[$e['type']]['backgroundColor'],
+ 'borderColor' => $this->_tabTypeRdv[$e['type']]['borderColor'],
+ 'textColor'=>$textColor,
+ 'className'=>$class,
+ 'motif'=>$e['motif'],
+ 'type'=>$e['type'],
+ 'patientid'=>$e['patientid'],
+ 'absent'=>$e['absente']
+ );
+
+ if ($e['type']=='[off]') {
+ $re['title']="Fermeture";
+ }
+
+ return $re;
+ }
+
+ /**
+ * Supprimer un rendez-vous
+ * @return void
+ */
+ public function delEvent()
+ {
+ if (!isset($this->_eventID)) {
+ throw new Exception('EventID n\'est pas défini');
+ }
+ if (!isset($this->_userID)) {
+ throw new Exception('UserID n\'est pas défini');
+ }
+
+ $data=array(
+ 'id'=>$this->_eventID,
+ 'userid'=>$this->_userID,
+ 'statut'=>'deleted'
+ );
+ msSQL::sqlInsert('agenda', $data);
+ }
+
+ /**
+ * Déplacer un rendez-vous
+ * @return void
+ */
+ public function moveEvent()
+ {
+ if (!isset($this->_eventID)) {
+ throw new Exception('EventID n\'est pas défini');
+ }
+ if (!isset($this->_userID)) {
+ throw new Exception('UserID n\'est pas défini');
+ }
+ if (!isset($this->_startDate)) {
+ throw new Exception('StartDate n\'est pas définie');
+ }
+ if (!isset($this->_endDate)) {
+ throw new Exception('EndDate n\'est pas définie');
+ }
+ $data=array(
+ 'id'=>$this->_eventID,
+ 'userid'=>$this->_userID,
+ 'start'=>$this->_startDate,
+ 'end'=>$this->_endDate
+ );
+ msSQL::sqlInsert('agenda', $data);
+ }
+ /**
+ * Obtenir l'historique de rdv du patient
+ * @param int $limit nombe max de résultats
+ * @return array tableau des data d'historique
+ */
+ public function getHistoriquePatient($limit=10)
+ {
+ $data['stats']['total']=msSQL::sqlUniqueChamp("select count(id) from agenda where patientid='".$this->_patientID."'");
+ $data['stats']['ok']=msSQL::sqlUniqueChamp("select count(id) from agenda where patientid='".$this->_patientID."' and statut!='deleted' and absente!='oui'");
+ $data['stats']['annule']=msSQL::sqlUniqueChamp("select count(id) from agenda where patientid='".$this->_patientID."' and statut='deleted'");
+ $data['stats']['absent']=msSQL::sqlUniqueChamp("select count(id) from agenda where patientid='".$this->_patientID."' and absente='oui'");
+ $data['historique']=msSQL::sql2tab("select DATE_FORMAT(start, '%Y %m %d - %H:%i') as start, DATE_FORMAT(start, '%Y-%m-%dT%TZ') as dateiso, type, statut, absente, motif from agenda where patientid='".$this->_patientID."' order by start desc limit $limit");
+
+ return $data;
+ }
+
+ /**
+ * Marquer un rendez-vous comme non honoré
+ */
+ public function setPasVenu()
+ {
+ if (!isset($this->_eventID)) {
+ throw new Exception('EventID n\'est pas défini');
+ }
+ if (!isset($this->_userID)) {
+ throw new Exception('UserID n\'est pas défini');
+ }
+
+
+ $actuel=$this->getEventByID();
+
+ if ($actuel['absent']=='oui') {
+ $absent='non';
+ } else {
+ $absent='oui';
+ }
+
+ $data=array(
+ 'id'=>$this->_eventID,
+ 'userid'=>$this->_userID,
+ 'absente'=>$absent
+ );
+ msSQL::sqlInsert('agenda', $data);
+ }
+
+ public function getPatientsOfTheDay() {
+ if (!isset($this->_userID)) {
+ throw new Exception('UserID n\'est pas défini');
+ }
+ $this->setStartDate(date("Y-m-d 00:00:00"));
+ $this->setEndDate(date("Y-m-d 23:59:59"));
+ if($data=$this->getEvents()) {
+ foreach ($data as $v) {
+ if ($v['type'] != '[off]') {
+ $tab[]=array(
+ "id"=> $v['patientid'],
+ "identite"=> $v['title'],
+ "type"=> $v['type'],
+ "heure"=> date("H:i", strtotime($v['start']))
+ );
+ }
+ }
+ return $tab;
+ }
+ }
+}
diff --git a/controlers/agenda/actions/agendaAjax.php b/controlers/agenda/actions/agendaAjax.php
new file mode 100644
index 00000000..bf46fa88
--- /dev/null
+++ b/controlers/agenda/actions/agendaAjax.php
@@ -0,0 +1,80 @@
+
+ * http://www.medshake.net
+ *
+ * MedShakeEHR is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * MedShakeEHR 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 MedShakeEHR. If not, see .
+ */
+
+/**
+ * Agenda : les requêtes ajax
+ *
+ * @author Bertrand Boutillier
+ */
+
+$debug='';
+$m=$match['params']['m'];
+
+
+$acceptedModes=array(
+ 'getEvents', // Obtenir le json des events
+ 'delEvent', // effacer un rdv
+ 'moveEvent', // déplacer un rdv
+ 'searchPatient', //chercher patient
+ 'getPatientAdminData', //obetnir les data patient
+ 'setNewRdv', // ajouter ou updater un rdv
+ 'setEventPasVenu', // marquer rendez-vous non honoré / honoré
+ 'getHistoriquePatient', // obtenir l'historique de rendez-vous d'un patient
+);
+
+if (!in_array($m, $acceptedModes)) {
+ die;
+}
+
+
+// Extraire un form et lancer nouvelle Cs
+if ($m=='getEvents') {
+ include('inc-ajax-getEvents.php');
+}
+// Effacer un RDV
+elseif ($m=='delEvent') {
+ include('inc-ajax-delEvent.php');
+}
+// Déplacer un RDV
+elseif ($m=='moveEvent') {
+ include('inc-ajax-moveEvent.php');
+}
+// Déplacer un RDV
+elseif ($m=='searchPatient') {
+ include('inc-ajax-searchPatient.php');
+}
+// Obtenir les data patient
+elseif ($m=='getPatientAdminData') {
+ include('inc-ajax-getPatientAdminData.php');
+}
+// Ajouter ou updater un rdv
+elseif ($m=='setNewRdv') {
+ include('inc-ajax-setNewRdv.php');
+}
+// Marquer rendez-vous non honoré / honoré
+elseif ($m=='setEventPasVenu') {
+ include('inc-ajax-setEventPasVenu.php');
+}
+// Obtenir l'historique de rendez-vous d'un patient
+elseif ($m=='getHistoriquePatient') {
+ include('inc-ajax-getHistoriquePatient.php');
+}
diff --git a/controlers/agenda/actions/inc-ajax-delEvent.php b/controlers/agenda/actions/inc-ajax-delEvent.php
new file mode 100644
index 00000000..e6ef764f
--- /dev/null
+++ b/controlers/agenda/actions/inc-ajax-delEvent.php
@@ -0,0 +1,35 @@
+
+ * http://www.medshake.net
+ *
+ * MedShakeEHR is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * MedShakeEHR 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 MedShakeEHR. If not, see .
+ */
+
+/**
+ * Agenda : supprimer un rdv de l'agenda
+ *
+ * @author Bertrand Boutillier
+ */
+
+ $event = new msAgenda();
+ $event->set_userID($match['params']['userID']);
+ $event->set_eventID($_POST['eventid']);
+ $event->delEvent();
+
+header('Content-Type: application/json');
+echo json_encode(array("status"=>"ok"));
diff --git a/controlers/agenda/actions/inc-ajax-getEvents.php b/controlers/agenda/actions/inc-ajax-getEvents.php
new file mode 100644
index 00000000..ec594b8f
--- /dev/null
+++ b/controlers/agenda/actions/inc-ajax-getEvents.php
@@ -0,0 +1,35 @@
+
+ * http://www.medshake.net
+ *
+ * MedShakeEHR is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * MedShakeEHR 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 MedShakeEHR. If not, see .
+ */
+
+/**
+ * Agenda : obtenir les events pour peupler l'agenda
+ *
+ * @author Bertrand Boutillier
+ */
+
+$events = new msAgenda();
+$events->setStartDate($_GET['start']);
+$events->setEndDate($_GET['end']);
+$events->set_userID($match['params']['userID']);
+
+header('Content-Type: application/json');
+echo json_encode($events->getEvents());
diff --git a/controlers/agenda/actions/inc-ajax-getHistoriquePatient.php b/controlers/agenda/actions/inc-ajax-getHistoriquePatient.php
new file mode 100644
index 00000000..525c7927
--- /dev/null
+++ b/controlers/agenda/actions/inc-ajax-getHistoriquePatient.php
@@ -0,0 +1,32 @@
+
+ * http://www.medshake.net
+ *
+ * MedShakeEHR is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * MedShakeEHR 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 MedShakeEHR. If not, see .
+ */
+
+/**
+ * Agenda : obtenir l'historique de rdv d'un patient
+ *
+ * @author Bertrand Boutillier
+ */
+
+$histo = new msAgenda();
+$histo->set_patientID($_POST['patientID']);
+header('Content-Type: application/json');
+echo json_encode($histo->getHistoriquePatient());
diff --git a/controlers/agenda/actions/inc-ajax-getPatientAdminData.php b/controlers/agenda/actions/inc-ajax-getPatientAdminData.php
new file mode 100644
index 00000000..43e1df26
--- /dev/null
+++ b/controlers/agenda/actions/inc-ajax-getPatientAdminData.php
@@ -0,0 +1,32 @@
+
+ * http://www.medshake.net
+ *
+ * MedShakeEHR is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * MedShakeEHR 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 MedShakeEHR. If not, see .
+ */
+
+/**
+ * Agenda : obtenir les infos administratives patient
+ *
+ * @author Bertrand Boutillier
+ */
+
+$patient = new msPeople();
+$patient->setToID($_POST['patientID']);
+header('Content-Type: application/json');
+echo json_encode($patient->getSimpleAdminDatas());
diff --git a/controlers/agenda/actions/inc-ajax-moveEvent.php b/controlers/agenda/actions/inc-ajax-moveEvent.php
new file mode 100644
index 00000000..89e33b07
--- /dev/null
+++ b/controlers/agenda/actions/inc-ajax-moveEvent.php
@@ -0,0 +1,38 @@
+
+ * http://www.medshake.net
+ *
+ * MedShakeEHR is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * MedShakeEHR 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 MedShakeEHR. If not, see .
+ */
+
+/**
+ * Agenda : déplacer un rdv de l'agenda
+ *
+ * @author Bertrand Boutillier
+ */
+
+$event = new msAgenda();
+$event->set_userID($match['params']['userID']);
+$event->set_eventID($_POST['eventid']);
+$event->setStartDate($_POST['start']);
+$event->setEndDate($_POST['end']);
+$event->moveEvent();
+
+
+header('Content-Type: application/json');
+echo json_encode(array("status"=>"ok"));
diff --git a/controlers/agenda/actions/inc-ajax-searchPatient.php b/controlers/agenda/actions/inc-ajax-searchPatient.php
new file mode 100644
index 00000000..03796766
--- /dev/null
+++ b/controlers/agenda/actions/inc-ajax-searchPatient.php
@@ -0,0 +1,52 @@
+
+ * http://www.medshake.net
+ *
+ * MedShakeEHR is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * MedShakeEHR 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 MedShakeEHR. If not, see .
+ */
+
+/**
+ * Agenda : chercher patient
+ *
+ * @author Bertrand Boutillier
+ */
+
+ $term = msSQL::cleanVar($_GET['term']);
+ $a_json = array();
+
+ if ($data=msSQL::sql2tab("select p.id, concat(d2.value, ' ', d3.value) as identite, d8.value as ddn
+ from people as p
+ left join objets_data as d2 on d2.toID=p.id and d2.typeID=2 and d2.outdated='' and d2.deleted=''
+ left join objets_data as d8 on d8.toID=p.id and d8.typeID=8 and d8.outdated='' and d8.deleted=''
+ left join objets_data as d3 on d3.toID=p.id and d3.typeID=3 and d3.outdated='' and d3.deleted=''
+ where concat(d2.value, ' ', d3.value) like '%".$term."%'
+ group by p.id
+ order by d2.value, d3.value limit 20")) {
+
+ foreach ($data as $k=>$v) {
+ $a_json[]=array(
+ 'label'=>trim($v['identite']).' '.$v['ddn'],
+ 'value'=>trim($v['identite']),
+ 'patientID'=>$v['id'],
+ );
+ }
+ }
+
+
+header('Content-Type: application/json');
+echo json_encode($a_json);
diff --git a/controlers/agenda/actions/inc-ajax-setEventPasVenu.php b/controlers/agenda/actions/inc-ajax-setEventPasVenu.php
new file mode 100644
index 00000000..47872044
--- /dev/null
+++ b/controlers/agenda/actions/inc-ajax-setEventPasVenu.php
@@ -0,0 +1,35 @@
+
+ * http://www.medshake.net
+ *
+ * MedShakeEHR is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * MedShakeEHR 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 MedShakeEHR. If not, see .
+ */
+
+/**
+ * Agenda : marquer un rendez-vous comme non honoré
+ *
+ * @author Bertrand Boutillier
+ */
+
+ $event = new msAgenda();
+ $event->set_userID($match['params']['userID']);
+ $event->set_eventID($_POST['eventID']);
+ $event->setPasVenu();
+
+header('Content-Type: application/json');
+echo json_encode(array("status"=>"ok"));
diff --git a/controlers/agenda/actions/inc-ajax-setNewRdv.php b/controlers/agenda/actions/inc-ajax-setNewRdv.php
new file mode 100644
index 00000000..244ef527
--- /dev/null
+++ b/controlers/agenda/actions/inc-ajax-setNewRdv.php
@@ -0,0 +1,42 @@
+
+ * http://www.medshake.net
+ *
+ * MedShakeEHR is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * MedShakeEHR 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 MedShakeEHR. If not, see .
+ */
+
+/**
+ * Agenda : ajouter un rdv dans l'agenda
+ *
+ * @author Bertrand Boutillier
+ */
+
+$event = new msAgenda();
+if($_POST['eventID']>0) $event->set_eventID($_POST['eventID']);
+$event->set_userID($match['params']['userID']);
+$event->set_patientID($_POST['patientID']);
+$event->setStartDate($_POST['start']);
+$event->setEndDate($_POST['end']);
+$event->set_motif($_POST['motif']);
+$event->set_type($_POST['type']);
+$dataEvent=$event->addOrUpdateRdv();
+
+//print_r($_POST);
+
+header('Content-Type: application/json');
+echo json_encode($dataEvent);
diff --git a/controlers/agenda/agenda.php b/controlers/agenda/agenda.php
new file mode 100644
index 00000000..e753e9cc
--- /dev/null
+++ b/controlers/agenda/agenda.php
@@ -0,0 +1,58 @@
+
+ * http://www.medshake.net
+ *
+ * MedShakeEHR is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * MedShakeEHR 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 MedShakeEHR. If not, see .
+ */
+
+/**
+ * Agenda
+ *
+ * @author Bertrand Boutillier
+ */
+
+$debug='';
+$template="agenda";
+
+// userID
+if(isset($match['params']['userID'])) $p['page']['userID']=$match['params']['userID'];
+
+//paramètres de l'agenda
+if(is_file($p['config']['webDirectory'].'agendasConfigurations/configAgenda'.$match['params']['userID'].'.js')) {
+ $p['page']['configAgenda']=file_get_contents($p['config']['webDirectory'].'agendasConfigurations/configAgenda'.$match['params']['userID'].'.js');
+}
+
+// types de rendez-vous
+if(is_file($p['config']['webDirectory'].'agendasConfigurations/configTypesRdv'.$match['params']['userID'].'.yml')) {
+ $p['page']['typeRdv']=Spyc::YAMLLoad($p['config']['webDirectory'].'agendasConfigurations/configTypesRdv'.$match['params']['userID'].'.yml');
+} else {
+ $p['page']['typeRdv']=array(
+ '[C]'=> array(
+ 'descriptif'=>'Consultation',
+ 'backgroundColor'=>'#2196f3',
+ 'borderColor'=>'#1e88e5',
+ 'duree'=>15
+ )
+ );
+}
+
+//formulaire prise rdv
+$formPriseRdv = new msForm();
+$formPriseRdv->setFormID(30);
+$formPriseRdv->setTypeForNameInForm('byName');
+$p['page']['formPriseRdv']=$formPriseRdv->getForm();
diff --git a/controlers/agenda/agendaPatientsOfTheDay.php b/controlers/agenda/agendaPatientsOfTheDay.php
new file mode 100644
index 00000000..3eb7232e
--- /dev/null
+++ b/controlers/agenda/agendaPatientsOfTheDay.php
@@ -0,0 +1,34 @@
+
+ * http://www.medshake.net
+ *
+ * MedShakeEHR is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * MedShakeEHR 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 MedShakeEHR. If not, see .
+ */
+
+/**
+ * Agenda : générer un json des patients du jour
+ *
+ *
+ * @author Bertrand Boutillier
+ */
+
+$events = new msAgenda();
+$events->set_userID($match['params']['userID']);
+
+header('Content-Type: application/json');
+echo json_encode($events->getPatientsOfTheDay());
diff --git a/controlers/configuration/actions/inc-action-configAgendaSave.php b/controlers/configuration/actions/inc-action-configAgendaSave.php
new file mode 100644
index 00000000..2663a8e5
--- /dev/null
+++ b/controlers/configuration/actions/inc-action-configAgendaSave.php
@@ -0,0 +1,44 @@
+
+ * http://www.medshake.net
+ *
+ * MedShakeEHR is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * MedShakeEHR 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 MedShakeEHR. If not, see .
+ */
+
+/**
+ * Config > action : sauver la configuration d'un agenda
+ *
+ * @author Bertrand Boutillier
+ */
+
+//utilisateurs pouvant avoir un agenda
+$agendaUsers= new msPeople();
+$autorisedUsers=$agendaUsers->getUsersListForService('administratifPeutAvoirAgenda');
+
+//construction du répertoire
+msTools::checkAndBuildTargetDir($p['config']['webDirectory'].'agendasConfigurations/');
+
+if($_POST['userID']>0 and in_array($_POST['userID'], array_keys($autorisedUsers))) {
+ file_put_contents($p['config']['webDirectory'].'agendasConfigurations/configAgenda'.$_POST['userID'].'.js', $_POST['configAgenda']);
+ file_put_contents($p['config']['webDirectory'].'agendasConfigurations/configTypesRdv'.$_POST['userID'].'.yml', $_POST['configTypesRdv']);
+
+ if(empty($_POST['configAgenda'])) unlink($p['config']['webDirectory'].'agendasConfigurations/configAgenda'.$_POST['userID'].'.js');
+ if(empty($_POST['configTypesRdv'])) unlink($p['config']['webDirectory'].'agendasConfigurations/configTypesRdv'.$_POST['userID'].'.yml');
+}
+
+msTools::redirection('/configuration/agenda/'.$_POST['userID'].'/');
diff --git a/controlers/configuration/configAgenda.php b/controlers/configuration/configAgenda.php
new file mode 100644
index 00000000..c0a9e356
--- /dev/null
+++ b/controlers/configuration/configAgenda.php
@@ -0,0 +1,61 @@
+
+ * http://www.medshake.net
+ *
+ * MedShakeEHR is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * MedShakeEHR 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 MedShakeEHR. If not, see .
+ */
+
+/**
+ * Config : gérer les paramètres des agendas
+ *
+ * @author Bertrand Boutillier
+ */
+
+ //admin uniquement
+ if (!msUser::checkUserIsAdmin()) {
+ $template="forbidden";
+ } else {
+ $template="configAgenda";
+ $debug='';
+
+ //config défaut
+ if (!isset($match['params']['userID'])) {
+ $p['page']['configDefaut']=Spyc::YAMLLoad('../config/config.yml');
+ }
+
+ //utilisateurs pouvant avoir un agenda
+ $agendaUsers= new msPeople();
+ $p['page']['agendaUsers']=$agendaUsers->getUsersListForService('administratifPeutAvoirAgenda');
+
+ // si user
+ if (isset($match['params']['userID'])) {
+
+ $p['page']['selectUser']=$match['params']['userID'];
+
+ //paramètres de l'agenda
+ if(is_file($p['config']['webDirectory'].'agendasConfigurations/configAgenda'.$match['params']['userID'].'.js')) {
+ $p['page']['configAgenda']=file_get_contents($p['config']['webDirectory'].'agendasConfigurations/configAgenda'.$match['params']['userID'].'.js');
+ }
+
+ // types de rendez-vous
+ if(is_file($p['config']['webDirectory'].'agendasConfigurations/configTypesRdv'.$match['params']['userID'].'.yml')) {
+ $p['page']['typeRdv']=file_get_contents($p['config']['webDirectory'].'agendasConfigurations/configTypesRdv'.$match['params']['userID'].'.yml');
+ }
+
+ }
+ }
diff --git a/public_html/agendasConfigurations/readme.txt b/public_html/agendasConfigurations/readme.txt
new file mode 100644
index 00000000..291ef498
--- /dev/null
+++ b/public_html/agendasConfigurations/readme.txt
@@ -0,0 +1 @@
+répertoire pour fichiers de configuration des agendas
diff --git a/public_html/js/agenda.js b/public_html/js/agenda.js
new file mode 100644
index 00000000..12155b7f
--- /dev/null
+++ b/public_html/js/agenda.js
@@ -0,0 +1,522 @@
+/*
+ * This file is part of MedShakeEHR.
+ *
+ * Copyright (c) 2017
+ * Bertrand Boutillier
+ * http://www.medshake.net
+ *
+ * MedShakeEHR is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * MedShakeEHR 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 MedShakeEHR. If not, see .
+ */
+
+/**
+ * Fonctions JS pour la gestion d'agendas
+ *
+ * @author Bertrand Boutillier
+ */
+
+$(document).ready(function() {
+ popstop = 0;
+ $(function() {
+ $('[data-toggle="popover"]').popover();
+
+ })
+
+ userID = $('#calendar').attr('data-userID');
+ if (typeof hiddenDays == 'undefined') {
+ hiddenDays = [0];
+ }
+ if (typeof minTime == 'undefined') {
+ minTime = '08:00:00';
+ }
+ if (typeof maxTime == 'undefined') {
+ maxTime = '20:45:00';
+ }
+ if (typeof slotDuration == 'undefined') {
+ slotDuration = '00:15:00';
+ }
+ if (typeof businessHours == 'undefined') {
+ businessHours = [{
+ dow: [1, 2, 3, 4, 5, 6],
+ start: '08:00',
+ end: '21:20',
+ }];
+ }
+ if (typeof eventSources == 'undefined') {
+ eventSources = [{
+ url: '/agenda/' + userID + '/ajax/getEvents/'
+ },
+ {
+ events: [{
+ start: '13:00',
+ end: '14:00',
+ dow: [1, 2, 3, 4, 5],
+ rendering: 'background',
+ className: 'fc-nonbusiness'
+ }, {
+ start: '13:00',
+ end: maxTime,
+ dow: [6],
+ rendering: 'background',
+ className: 'fc-nonbusiness'
+ }]
+ }
+ ]
+ }
+
+
+ $('#calendar').fullCalendar({
+
+ defaultView: 'agendaWeek',
+ locale: 'fr',
+ hiddenDays: hiddenDays,
+ customButtons: {
+ nextMonth: {
+ icon: 'right-double-arrow',
+ click: function() {
+ $('#calendar').fullCalendar('incrementDate', moment.duration(1, 'months'));
+ }
+ },
+ lastMonth: {
+ icon: 'left-double-arrow',
+ click: function() {
+ $('#calendar').fullCalendar('incrementDate', moment.duration(-1, 'months'));
+ }
+ },
+ },
+ header: {
+ left: 'lastMonth,prev,next,nextMonth today',
+ center: '',
+ right: 'title'
+ },
+ minTime: minTime,
+ maxTime: maxTime,
+ slotDuration: slotDuration,
+ weekNumbers: true,
+ allDaySlot: false,
+ allDayText: '-',
+ selectable: true,
+ slotLabelFormat: 'H:mm',
+ nowIndicator: true,
+ businessHours: businessHours,
+ slotEventOverlap: false,
+ contentHeight: 'auto',
+ eventSources: eventSources,
+ eventRender: function(event, element) {
+ element.attr('data-eventid', event.id);
+ if (event.rendering != 'background' && popstop == 0 ) {
+ element.popover({
+ title: event.name,
+ placement: 'bottom',
+ content: event.type + ' ' + event.motif,
+ container: 'body',
+ trigger: 'hover'
+ });
+ }
+ },
+ eventClick: function(eventClicked, jsEvent, view) {},
+ eventDragStart: function( event, jsEvent, ui, view ) {
+ popstop = 1;
+ },
+ eventDragStop: function( event, jsEvent, ui, view ) {
+ popstop = 0;
+ },
+ eventDrop: function(event, delta, revertFunc) {
+ $('div.popover').popover('hide');
+ if (confirm("Confirmez-vous le déplacement de ce rendez-vous ?")) {
+ moveEvent(event);
+ } else {
+ revertFunc();
+ }
+ },
+ eventResizeStart: function( event, jsEvent, ui, view ) {
+ popstop = 1;
+ },
+ eventResizeStop: function( event, jsEvent, ui, view ) {
+ popstop = 0;
+ },
+ eventResize: function(event, delta, revertFunc) {
+ $('div.popover').popover('hide');
+ if (confirm("Confirmez-vous le changement de durée de ce rendez-vous ?")) {
+ resizeEvent(event);
+ } else {
+ revertFunc();
+ }
+ },
+ select: function(start, end, jsEvent, view) {
+ $('div.popover').popover('hide');
+ formatRdvData4Display(start, end);
+ },
+ navLinks: true,
+ navLinkDayClick: function(date, jsEvent) {
+ if (confirm("Souhaitez-vous fermer cette journée ?")) {
+ closeDay(date);
+ }
+ }
+ })
+
+
+ $.contextMenu({
+ selector: ".hasmenu",
+ items: {
+ editer: {
+ name: "Editer ce rendez-vous",
+ callback: function(key, opt) {
+ eventid = this.attr('data-eventid');
+ eventData = $('#calendar').fullCalendar('clientEvents', eventid);
+ getEventData4Edit(eventData[0]);
+ }
+ },
+ ouvrirDossier: {
+ name: "Ouvrir le dossier patient",
+ callback: function(key, opt) {
+ eventid = this.attr('data-eventid');
+ eventData = $('#calendar').fullCalendar('clientEvents', eventid);
+ window.open('/patient/' + eventData[0]['patientid'] + '/', '_blank');
+ }
+ },
+ separator1: "-----",
+ pasvenupasprev: {
+ name: "Marquer RDV honoré / non honoré",
+ callback: function(key, opt) {
+ eventid = this.attr('data-eventid');
+ setEventPasVenu(eventid);
+ }
+ },
+ separator2: "-----",
+ supprimer: {
+ name: "Supprimer",
+ callback: function(key, opt) {
+ eventid = this.attr('data-eventid');
+ deleteEvent(eventid);
+ }
+ },
+ }
+ });
+
+
+ $("#buttonCanceled").on("click", function(e) {
+ e.preventDefault();
+ clean();
+ });
+
+ $("#buttonSubmit").on("click", function(e) {
+ e.preventDefault();
+ setNewRdv();
+ });
+
+ $("#formRdv").on("click", ".donothing", function(e) {
+ e.preventDefault();
+ });
+
+ $('#search').on("focus", function(e) {
+ clean();
+ });
+
+ $("#historiquePatient").on("click", "button.moveToDate", function(e) {
+ e.preventDefault();
+ $('#calendar').fullCalendar('gotoDate', $(this).attr('data-date'));
+ });
+
+ //chercher patiente
+ $('#search').autocomplete({
+ source: '/agenda/' + userID + '/ajax/searchPatient/',
+ select: function(event, ui) {
+ getPatientAdminData(ui.item.patientID);
+ }
+ });
+
+
+
+ $("#formRdv input[data-typeid]").typeWatch({
+ wait: 1000,
+ highlight: false,
+ allowSubmit: false,
+ captureLength: 1,
+ callback: function(value) {
+ patientID = $('#patientID').val();
+ if (patientID > 0) {
+ patientID = $('#patientID').val();
+ typeID = $(this).attr("data-typeID");
+ source = $(this);
+ instance = '';
+ setPeopleData(value, patientID, typeID, source, instance);
+ }
+ }
+ });
+
+
+});
+
+function setNewRdv() {
+ $.ajax({
+ url: '/agenda/' + userID + '/ajax/setNewRdv/',
+ type: "post",
+ data: {
+ eventID: $('#eventID').val(),
+ patientID: $('#patientID').val(),
+ userID: $('#calendar').attr('data-userID'),
+ start: $('#eventStartID').val(),
+ end: $('#eventEndID').val(),
+ type: $('#type').val(),
+ motif: $('#motif').val(),
+ },
+ dataType: "json",
+ success: function(data) {
+ $('#calendar').fullCalendar('refetchEvents');
+ clean();
+ },
+ error: function() {
+ alert('Il y a un problème. Il faut recharger la page.');
+ },
+ });
+}
+
+function closeDay(date) {
+ datedujour = date.format('YYYY-MM-DD');
+ $.ajax({
+ url: '/agenda/' + userID + '/ajax/setNewRdv/',
+ type: "post",
+ data: {
+ eventID: '',
+ patientID: '0',
+ userID: $('#calendar').attr('data-userID'),
+ start: datedujour + ' ' + minTime,
+ end: datedujour + ' ' + maxTime,
+ type: '[off]',
+ motif: 'Fermé',
+ },
+ dataType: "json",
+ success: function(data) {
+ $('#calendar').fullCalendar('refetchEvents');
+ clean();
+ },
+ error: function() {
+ alert('Il y a un problème. Il faut recharger la page.');
+ },
+ });
+}
+
+function getPatientAdminData(patientID) {
+ userID = $('#calendar').attr('data-userID');
+ $.ajax({
+ url: '/agenda/' + userID + '/ajax/getPatientAdminData/',
+ type: "post",
+ data: {
+ patientID: patientID,
+ },
+ dataType: "json",
+ success: function(data) {
+ $('#patientID').val(patientID);
+ $.each(data, function(index, value) {
+ if ($("#p_2ID").length) $("#p_" + index + "ID").val(value);
+ });
+ getHistoriquePatient(patientID);
+ },
+ error: function() {
+ alert('Il y a un problème. Il faut recharger la page.');
+ },
+ });
+}
+
+function getHistoriquePatient(patientID) {
+ $.ajax({
+ url: '/agenda/' + userID + '/ajax/getHistoriquePatient/',
+ type: "post",
+ data: {
+ patientID: patientID,
+ },
+ dataType: "json",
+ success: function(data) {
+ $.each(data['historique'], function(index, dat) {
+ chaine = '