noalyss Version-9
follow_up.class.php
Go to the documentation of this file.
1<?php
2
3/*
4 * This file is part of NOALYSS.
5 *
6 * NOALYSS is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * NOALYSS is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with NOALYSS; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20// Copyright Author Dany De Bontridder danydb@aevalys.eu
21require_once NOALYSS_INCLUDE.'/lib/user_common.php';
22
23/**
24 * \file
25 * \brief class_action for manipulating actions
26 * action can be :
27 * <ul>
28 * <li>an invoice
29 * <li>a meeting
30 * <li>an order
31 * <li>a letter
32 * </ul>
33 * The table document_type are the possible actions
34 */
35
36/**
37 * \class
38 * \brief class_action for manipulating actions
39 * action can be :
40 * <ul>
41 * <li> a meeting
42 * <li>an order
43 * <li>a letter
44 * </ul>
45 * The table document_type are the possible actions
46 */
48{
49
50 var $db; /*!< $db database connexion */
51 var $ag_timestamp; /*!< $ag_timestamp document date (ag_gestion.ag_timestamp) */
52 var $dt_id; /*!< $dt_id type of the document (document_type.dt_id) */
53 var $ag_state; /*!< $ag_state stage of the document (printed, send to client...) */
54 var $d_number; /*!< $d_number number of the document */
55 var $d_filename; /*!< $d_filename filename's document */
56 var $d_mimetype; /*!< $d_mimetype document's filename */
57 var $ag_title; /*!< $ag_title title document */
58 var $f_id; /*!< $f_id fiche id (From field ) */
59 var $ag_ref; /*!< $ag_ref is the ref */
60 var $ag_hour; /*!< $ag_hour is the hour of the meeting, action */
61 var $ag_priority; /*!< $ag_priority is the priority 1 High, 2 medium, 3 low */
62 var $ag_dest; /*!< $ag_dest person who is in charged */
63 var $ag_contact; /*!< $ag_contact contact */
64 var $ag_remind_date; /*!< $ag_contact contact */
65 var $ag_description; /*!< description of the action with HTML tag*/
66 var $ag_id; //!< Follow_Up.ag_id
67 var $f_id_dest; /*!< followup action recipient */
68 var $aAction_detail; //!< Array of action details
69
70 /**
71 * @var integer $ag_description_id if greater than 0 , it is the id in action_comment
72 * of the description (1st comment)
73 */
75 /**
76 * $operation string related operation
77 */
79
80 /**
81 * @brief $action string related action
82 */
84
85 /**
86 * @brief constructor
87 * \brief constructor
88 * \param p_cn database connection
89 */
90 function __construct($p_cn, $p_id=0)
91 {
92 $this->db=$p_cn;
93 $this->ag_id=$p_id;
94 $this->f_id=0;
95 $this->aAction_detail=array();
96 $this->operation="";
97 $this->action="";
98 $this->f_id_dest=0;
99 $this->ag_priority=2;
100 }
101
102 public function __toString(): string
103 {
104 $r = " Follow_Up object =>";
105 $r .= 'ag_timestamp = ['. $this->ag_timestamp.']';
106 $r .= 'dt_id = ['. $this->dt_id.']';
107 $r .= 'ag_state = ['. $this->ag_state.']';
108 $r .= 'd_number = ['. $this->d_number.']';
109 $r .= 'd_filename = ['. $this->d_filename.']';
110 $r .= 'd_mimetype = ['. $this->d_mimetype.']';
111 $r .= 'ag_title = ['. $this->ag_title.']';
112 $r .= 'f_id = ['. $this->f_id.']';
113 $r .= 'ag_ref = ['. $this->ag_ref.']';
114 $r .= 'ag_hour = ['. $this->ag_hour.']';
115 $r .= 'ag_priority = ['. $this->ag_priority.']';
116 $r .= 'ag_dest = ['. $this->ag_dest.']';
117 $r .= 'ag_contact = ['. $this->ag_contact.']';
118 $r .= 'ag_remind_date = ['. $this->ag_remind_date.']';
119 $r .= 'f_id_dest = ['. $this->f_id_dest.']';
120 $r .= 'ag_description = ['. $this->ag_description.']';
121
122 return $r;
123
124 }
125
126
127 /**
128 * @brief Create a filter based on the current user,
129 * @remark type $g_user Connected user
130 * @param type $cn Database connection
131 * @param type $p_mode Mode is R (for Read) or W (for write)
132 * @return string SQL where clause to include in the SQL
133 * example: (ag_dest in (select p_granted from user_sec_action_profile where p_id=x)
134 */
135 static function sql_security_filter($cn, $p_mode)
136 {
137 global $g_user;
138 $profile=$cn->get_value("select p_id from profile_user where user_name=$1", array($g_user->login));
139 if ($profile=='')
140 die("Security");
141 if ( $g_user->isAdmin() == 1) {
142 return "(true)";
143 }
144 if ($p_mode=='R')
145 {
146 $sql=" (ag_dest in (select p_granted from user_sec_action_profile where p_id=$profile and ua_right !='X' ) ) ";
147 } else if ($p_mode=='W')
148 {
149 $sql=" ( ag_dest in (select p_granted from user_sec_action_profile where p_id=$profile and ua_right in ('W','O') ) )";
150 } else {
151 record_log(_('Securité'));
152 throw new Exception(_('Securité'));
153 }
154 return $sql;
155 }
156
157 //----------------------------------------------------------------------
158 /**
159 * \brief Display the object, the tags for the FORM
160 * are in the caller. It will be used for adding and updating
161 * action
162 * \note If ag_id is not equal to zero then it is an update otherwise
163 * it is a new document
164 *
165 * \param $p_view form will be in readonly mode (value: READ, UPD or NEW )
166 * \param $p_gen true we show the tag for generating a doc (value : true or false) and adding files
167 * \param $p_base is the ac parameter
168 * \param $retour is the html code for the return button
169 * \note update the reference number or the document type is not allowed
170 *
171 *
172 * \return string containing the html code
173 */
174 function display($p_view, $p_gen, $p_base, $retour="")
175 {
176 global $g_user;
177 if ($p_view=='UPD')
178 {
179 $upd=true;
180 $readonly=false;
181 }
182 elseif ($p_view=="NEW")
183 {
184 $upd=false;
185 $readonly=false;
186 }
187 elseif ($p_view=='READ')
188 {
189 $upd=true;
190 $readonly=true;
191 }
192 else
193 {
194 throw new Exception('class_action'.__LINE__.'Follow_Up::Display error unknown parameter'.$p_view);
195 }
196
197
198 // Compute the widget
199 // Date
200 $date=new IDate();
201 $date->readOnly=$readonly;
202 $date->name="ag_timestamp";
203 $date->id="ag_timestamp";
205
206 $remind_date=new IDate();
207 $remind_date->readOnly=$readonly;
208 $remind_date->name="ag_remind_date";
209 $remind_date->id="ag_remind_date";
210 $remind_date->value=$this->ag_remind_date;
211
212
213 // Doc Type
214 $doc_type=new ISelect();
215 $doc_type->name="dt_id";
216 $doc_type->value=$this->db->make_array("select dt_id,dt_value from document_type order by dt_value", 1);
217 $doc_type->selected=$this->dt_id;
218 $doc_type->readOnly=$readonly;
219 $str_doc_type=$doc_type->input();
220
221 // Description
222 $desc=new ITextArea();
223 $desc->set_enrichText("enrich");
224 $desc->style=' class="itextarea" style="width:80%;margin-left:5%;"';
225 $desc->name="ag_comment";
226 $desc->readOnly=$readonly;
227 $acomment=$this->db->get_array("SELECT agc_id, ag_id, to_char(agc_date,'DD.MM.YYYY HH24:MI') as str_agc_date, agc_comment, agc_comment_raw,tech_user
228 FROM action_gestion_comment where ag_id=$1 order by agc_id", array($this->ag_id)
229 );
230
231 // List opération liées
232 $operation=$this->db->get_array("select ago_id,j.jr_id,j.jr_internal,j.jr_comment,to_char(j.jr_date,'DD.MM.YY') as str_date
233 from jrn as j join action_gestion_operation as ago on (j.jr_id=ago.jr_id)
234 where ag_id=$1 order by jr_date", array($this->ag_id));
235 $iconcerned=new IConcerned('operation');
236
237 // List related action
238 $iaction=new IRelated_Action('action');
239 $iaction->value=(isset($this->action))?$this->action:"";
240
241 // state
242 // Retrieve the value
243 $a=$this->db->make_array("select s_id,s_value from document_state ");
244 $state=new ISelect();
245 $state->readOnly=$readonly;
246 $state->name="ag_state";
247 $state->value=$a;
248 $state->selected=$this->ag_state;
249 $str_state=$state->input();
250
251 // Retrieve the value if there is an attached doc
252 $doc_ref="";
253 // Document id
254
255 $h2=new IHidden();
256 $h2->name="d_id";
257 $h2->value=$this->d_id;
258
259 if ($this->d_id!=0&&$this->d_id!="")
260 {
261 $h2->readonly=($p_view=='NEW')?false:true;
262 $doc=new Document($this->db, $this->d_id);
263 $doc->get();
264 if (noalyss_strlentrim($doc->d_lob)!=0)
265 {
266 $d_id=new IHidden();
267 $doc_ref="<p> Document ".$doc->anchor().'</p>';
268 $doc_ref.=$h2->input().$d_id->input('d_id', $this->d_id);
269 }
270 }
271
272
273 // title
274 $title=new IText();
275 $title->readOnly=$readonly;
276 $title->name="ag_title";
277 $title->value=$this->ag_title;
278 $title->size=60;
279 $title->style='style="font-size:2rem;font-weight:bold"';
280
281
282 // Priority of the ag_priority
283 $ag_priority=new ISelect();
284 $ag_priority->readOnly=$readonly;
285 $ag_priority->name="ag_priority";
287 $ag_priority->value=array(array('value'=>1, 'label'=>_('Haute')),
288 array('value'=>2, 'label'=>_('Normale')),
289 array('value'=>3, 'label'=>_('Basse'))
290 );
291 $str_ag_priority=$ag_priority->input();
292
293 // hour of the action (meeting) ag_hour
294 $ag_hour=new IText();
295 $ag_hour->readOnly=$readonly;
296 $ag_hour->name="ag_hour";
298 $ag_hour->size=6;
299 $ag_hour->javascript=" onblur=check_hour('ag_hour');";
300 $str_ag_hour=$ag_hour->input();
301
302 // Profile in charged of the action
303 $ag_dest=new ISelect();
304 $ag_dest->readOnly=$readonly;
305 $ag_dest->name="ag_dest";
306 // select profile
307 $aAg_dest=$this->db->make_array("select p_id as value, ".
308 "p_name as label ".
309 " from profile where p_id in ".$g_user->sql_writable_profile()." order by 2");
310
311 $ag_dest->value=$aAg_dest;
312 $ag_dest->selected=$this->ag_dest;
313 $str_ag_dest=$ag_dest->input();
314
315 // ag_ref
316 // Always false for update
317
318 $client_label=new ISpan();
319
320 /* Add button */
321 $f_add_button=new IButton('add_card');
322 $f_add_button->label=_('Créer une nouvelle fiche');
323 $f_add_button->set_attribute('ipopup', 'ipop_newcard');
324 $filter=$this->db->make_list('select fd_id from fiche_def ');
325 $f_add_button->set_attribute('filter', $filter);
326
327 $f_add_button->javascript=" select_card_type(this);";
328 $str_add_button=$f_add_button->input();
329
330 // f_id_dest sender
331 if ($this->qcode_dest!=NOTFOUND&&noalyss_strlentrim($this->qcode_dest)!=0)
332 {
333 $tiers=new Fiche($this->db);
334 $tiers->get_by_qcode($this->qcode_dest);
335 $qcode_dest_label=strtoupper($tiers->strAttribut(1));
336 $qcode_dest_label.=" ".$tiers->strAttribut(ATTR_DEF_FIRST_NAME,0);
337 $this->f_id_dest=$tiers->id;
338 }
339 else
340 {
341 $qcode_dest_label=($this->f_id_dest==0||trim($this->qcode_dest??"")=="")?'Interne ':'Error';
342 }
343
344 $h_ag_id=new IHidden();
345 // if concerns another action : show the link otherwise nothing
346 //
347 // sender
348 $w=new ICard();
349 $w->readOnly=$readonly;
350 $w->jrn=0;
351 $w->name='qcode_dest';
352 $w->value=($this->f_id_dest!=0)?$this->qcode_dest:"";
353 $w->label="";
354 $list_recipient=$this->db->make_list('select fd_id from fiche_def');
355 $w->extra=$list_recipient;
356 $w->set_attribute('typecard', $list_recipient);
357 $w->set_dblclick("fill_ipopcard(this);");
358 $w->set_attribute('ipopup', 'ipopcard');
359
360 // name of the field to update with the name of the card
361 $w->set_attribute('label', 'qcode_dest_label');
362 // name of the field to update with the name of the card
363 $w->set_attribute('typecard', $w->extra);
364 $w->set_function('fill_data');
365 $w->javascript=sprintf(' onchange="fill_data_onchange(\'%s\');" ', $w->name);
366
367
368 $sp=new ISpan();
369 $sp->extra='class="text-"';
370 $sp->name='qcode_dest_label';
371 $sp->value=$qcode_dest_label;
372
373 // autre - a refaire pour avoir plusieurs fiches
374 // Sur le modèle des tags
375 $ag_contact=new ICard();
376 $ag_contact->readOnly=$readonly;
377 $ag_contact->jrn=0;
378 $ag_contact->name='ag_contact';
379 $ag_contact->value='';
380 $ag_contact->set_attribute('ipopup', 'ipopcard');
381 if ($this->ag_contact!=0)
382 {
383 $contact=new Fiche($this->db, $this->ag_contact);
384 $ag_contact->value=$contact->get_quick_code();
385 }
386
387 $ag_contact->label="";
388
389 $list_contact=$this->db->make_list('select fd_id from fiche_def where frd_id=16');
390 $ag_contact->extra=$list_contact;
391
392 $ag_contact->set_dblclick("fill_ipopcard(this);");
393 // name of the field to update with the name of the card
394 $ag_contact->set_attribute('label', 'ag_contact_label');
395 // name of the field to update with the name of the card
396 $ag_contact->set_attribute('typecard', $list_contact);
397 $ag_contact->set_function('fill_data');
398 $ag_contact->javascript=sprintf(' onchange="fill_data_onchange(\'%s\');" ', $ag_contact->name);
399
400 $spcontact=new ISpan();
401 $spcontact->name='ag_contact_label';
402 $spcontact->value='';
403 $fiche_contact=new Fiche($this->db,$this->ag_contact);
404
405 if ($fiche_contact->id!=0)
406 {
407 $spcontact->value=strtoupper($fiche_contact->strAttribut(ATTR_DEF_NAME)??"");
408 $spcontact->value.=" ".$fiche_contact->strAttribut(ATTR_DEF_FIRST_NAME,0);
409 }
410
411
412 $h_agrefid=new IHidden();
413 $iag_ref=new IText("ag_ref");
414 $iag_ref->value=$this->ag_ref;
415 $iag_ref->readOnly=false;
416 $str_ag_ref=$iag_ref->input();
417 // Preparing the return string
418 $r="";
419
420 /* for new files */
421 $upload=new IFile();
422 $upload->name="file_upload[]";
423 $upload->set_multiple(true);
424 $upload->setAlertOnSize(true);
425 $upload->readOnly=$readonly;
426 $upload->value="";
427 $aAttachedFile=$this->db->get_array('select d_id,d_filename,d_description,d_mimetype,'.
428 '\'export.php?act=RAW:document&'.
429 Dossier::get().'&d_id=\'||d_id as link'.
430 ' from document where ag_id=$1', array($this->ag_id));
431 /* create the select for document */
432 $aDocMod=new ISelect();
433 $aDocMod->name='doc_mod';
434 $aDocMod->value=$this->db->make_array('select md_id,dt_value||\' : \'||md_name as md_name'.
435 ' from document_modele join document_type on (md_type=dt_id)'.
436 " where md_affect ='GES' and md_type = $1 ".
437 ' order by md_name',0,[$this->dt_id]);
438 $str_select_doc=$aDocMod->input();
439 /* if no document then do not show the generate button */
440 if (empty($aDocMod->value))
441 $str_submit_generate="";
442 else
443 $str_submit_generate=HtmlInput::submit("generate", _("Génére le document"));
444
446
447 /* fid = Icard */
448 $icard=new ICard();
449 $icard->jrn=0;
450 $icard->table=0;
451 $icard->extra2='QuickCode';
452 $icard->noadd="no";
453 $icard->extra='all';
454
455 /* Text desc */
456 $text=new IText();
457 $num=new INum();
458
459 /* Add the needed hidden values */
460 $r.=dossier::hidden();
461
462 $r.=HtmlInput::request_to_hidden(array("closed_action", "remind_date_end", "remind_date", "sag_ref", "only_internal", "state", "qcode", "ag_dest_query", "action_query", "tdoc", "date_start", "date_end", "hsstate", "searchtag"));
463 $a_tag=$this->tag_get();
464 $menu=new Default_Menu();
465 /* get template */
466 ob_start();
467 require NOALYSS_TEMPLATE.'/follow_up-display.php';
468 $content=ob_get_contents();
469 ob_end_clean();
470 $r.=$content;
471
472 //hidden
473 $r.="<p>";
474 $r.=$h2->input();
475 $r.=$h_ag_id->input('ag_id', $this->ag_id);
476 $hidden2=new IHidden();
477 $r.=$hidden2->input('f_id_dest', $this->f_id_dest);
478 $r.="</p>";
479
480 return $r;
481 }
482
483 //----------------------------------------------------------------------
484 /**
485 * \brief This function shows the detail of an action thanks the ag_id
486 */
487 function get()
488 {
489 $sql="select ag_id,to_char (ag_timestamp,'DD.MM.YYYY') as ag_timestamp,".
490 " f_id_dest,ag_title,ag_ref,d_id,ag_type,ag_state, ag_owner, ".
491 " ag_dest, ag_hour, ag_priority, ag_contact,to_char (ag_remind_date,'DD.MM.YYYY') as ag_remind_date ".
492 " from action_gestion left join document using (ag_id) where ag_id=".$this->ag_id;
493 $r=$this->db->exec_sql($sql);
495 if ($row==false)
496 {
497 $this->ag_id=0;
498 return;
499 }
500 $this->ag_timestamp=$row[0]['ag_timestamp'];
501 $this->ag_contact=$row[0]['ag_contact'];
502 $this->f_id_dest=$row[0]['f_id_dest'];
503 $this->ag_title=$row[0]['ag_title'];
504 $this->ag_type=$row[0]['ag_type'];
505 $this->ag_ref=$row[0]['ag_ref'];
506 $this->ag_state=$row[0]['ag_state'];
507 $this->d_id=$row[0]['d_id'];
508 $this->ag_dest=$row[0]['ag_dest'];
509 $this->ag_hour=$row[0]['ag_hour'];
510 $this->ag_priority=$row[0]['ag_priority'];
511 $this->ag_remind_date=$row[0]['ag_remind_date'];
512 $this->ag_owner=$row[0]['ag_owner'];
513
514 $action_detail=new Follow_Up_Detail($this->db);
515 $action_detail->set_parameter('ag_id', $this->ag_id);
516 $this->aAction_detail=$action_detail->load_all();
517
518
519 // if there is no document set 0 to d_id
520 if ($this->d_id=="")
521 $this->d_id=0;
522 // if there is a document fill the object
523 if ($this->d_id!=0)
524 {
525 $this->state=$row['0']['ag_state'];
526 $this->ag_state=$row[0]['ag_state'];
527 }
528 $this->dt_id=$this->ag_type;
529 $aexp=new Fiche($this->db, $this->f_id_dest);
530 $this->qcode_dest=$aexp->strAttribut(ATTR_DEF_QUICKCODE);
531 }
532
533 /**
534 * \brief Save the document and propose to save the generated document or
535 * to upload one, the data are included except the file. Temporary the generated
536 * document is save.
537 * The files into $_FILES['file_upload'] will be saved
538 * @note the array $_POST['input_desc'] must be set, contains the description
539 * of the uploaded files
540 *
541 * \return
542 */
543 function save()
544 {
545
546
547 $str_file="";
548 $add_file='';
549
550 // f_id exp
551 $exp=new Fiche($this->db);
552 $exp->get_by_qcode($this->qcode_dest);
553 $exp->id=($exp->id==0)?null:$exp->id;
554
555 $contact=new Fiche($this->db);
556 $contact->get_by_qcode($this->ag_contact);
557
558 if (trim($this->ag_title??"")=="")
559 {
560 $doc_mod=new document_type($this->db);
561 $doc_mod->dt_id=$this->dt_id;
562 $doc_mod->get();
563 $this->ag_title=$doc_mod->dt_value;
564 }
565 $this->ag_id=$this->db->get_next_seq('action_gestion_ag_id_seq');
566 $seq_name="seq_doc_type_".$this->dt_id;
567 // to avoid duplicate
568 do {
569 // Create the reference
570 $ag_ref=$this->db->get_value('select dt_prefix from document_type where dt_id=$1', array($this->dt_id)).'-'.$this->db->get_next_seq($seq_name);
571 // if reference does not exist , finish the loop
572 if ( $this->db->get_value("select count(*) from action_gestion where ag_ref = $1",array($ag_ref)) == 0)
573 break;
574 } while (1);
575 // check if the reference already exist and try to compute new one
576 $this->ag_ref=$ag_ref;
577 // save into the database
578 if ($this->ag_remind_date!=null||$this->ag_remind_date!='')
579 {
580 $sql="insert into action_gestion".
581 "(ag_id,ag_timestamp,ag_type,ag_title,f_id_dest,ag_ref, ag_dest, ".
582 " ag_hour, ag_priority,ag_owner,ag_contact,ag_state,ag_remind_date) ".
583 " values ($1,to_date($2,'DD.MM.YYYY'),$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,to_date($13,'DD.MM.YYYY'))";
584 }
585 else
586 {
587 $this->ag_remind_date=null;
588 $sql="insert into action_gestion".
589 "(ag_id,ag_timestamp,ag_type,ag_title,f_id_dest,ag_ref, ag_dest, ".
590 " ag_hour, ag_priority,ag_owner,ag_contact,ag_state,ag_remind_date) ".
591 " values ($1,to_date($2,'DD.MM.YYYY'),$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13)";
592 }
593 $this->db->exec_sql($sql, array($this->ag_id, /* 1 */
594 $this->ag_timestamp, /* 2 */
595 $this->dt_id, /* 3 */
596 $this->ag_title, /* 4 */
597 $exp->id, /* 5 */
598 $this->ag_ref, /* 6 */
599 $this->ag_dest, /* 7 */
600 $this->ag_hour, /* 8 */
601 $this->ag_priority, /* 9 */
602 $_SESSION[SESSION_KEY.'g_user'], /* 10 */
603 $contact->id, /* 11 */
604 $this->ag_state, /* 12 */
605 $this->ag_remind_date /* 13 */
606 )
607 );
608 $http=new HttpInput();
609 $nb_item=$http->post("nb_item","number",0);
610 /* insert also the details */
611 for ($i=0; $i<$nb_item; $i++)
612 {
613 $act=new Follow_Up_Detail($this->db);
614 $act->from_array($_POST, $i);
615 if ($act->f_id==0)
616 continue;
617 $act->ag_id=$this->ag_id;
618 $act->save();
619 }
620
621 /* upload the documents */
622 $doc=new Document($this->db);
623 $doc->upload($this->ag_id);
624 if (noalyss_trim($this->ag_comment??"")!='' && Document_Option::can_add_comment($this->ag_id))
625 {
626 $this->db->exec_sql("insert into action_gestion_comment (ag_id,tech_user,agc_comment,agc_comment_raw) values ($1,$2,$3,$4)"
627 , array($this->ag_id, $_SESSION[SESSION_KEY.'g_user'], strip_tags($this->ag_description),$this->ag_comment));
628 }
629 if (noalyss_trim($this->ag_description)!='' && Document_Option::can_add_comment($this->ag_id))
630 {
631 $this->db->exec_sql("insert into action_gestion_comment (ag_id,tech_user,agc_comment,agc_comment_raw) values ($1,$2,$3,$4)"
632 , array($this->ag_id, $_SESSION[SESSION_KEY.'g_user'],strip_tags($this->ag_description), $this->ag_description));
633 }
634 $this->insert_operation();
635 $this->insert_action();
636 }
637 /**
638 * @brief return the SQL to make a list of actions
639 * Colum :
640 * - my_date string date action format DD.MM.YYYY
641 * - my_remind string date reminder format DD.MM.YYYY
642 * - str_last_comment string last colemnt format DD.MM.YYYY
643 * - last_comment date last comment
644 * - f_id_dest int fiche.f_id concerned card
645 * - s_value string state of the action (cloturé, à suivre ,...)
646 * - s_id int id of document_state
647 * - ag_title string Title of the follow-up
648 * - dt_value string Type of document
649 * - ag_ref, string ref of the action
650 * - ag_priority int priority of the action
651 * - ag_state, int state of the followup (see table : document_state )
652 * - dest string profil group
653 * - name string name of the recipient
654 * - qcode string qcode of the recipient
655 * - tag string list of tags separated by comma
656 * - tags_color string list of tag colors separated by comma
657 * @returns a SQL string to retrieve list of actions
658 */
659 public static function SQL_list_action():string
660 {
661 $sql = " select ag_id,to_char(ag_timestamp,'DD.MM.YYYY') as my_date,
662 to_char(ag_remind_date,'DD.MM.YYYY') as my_remind,
663 to_char(coalesce((select max(agc_date) from action_gestion_comment as agc where agc.ag_id=ag.ag_id),ag_timestamp),'DD.MM.YY') as str_last_comment,
664 coalesce((select max(agc_date) from action_gestion_comment as agc where agc.ag_id=ag.ag_id),ag_timestamp) as last_comment,
665 f_id_dest,
666 s_id,
667 s_value,
668 ag_title,dt_value,ag_ref, ag_priority,ag_state,
669 coalesce((select p_name from profile where p_id=ag_dest),'Aucun groupe') as dest,
670 (select ad_value from fiche_Detail where f_id=ag.f_id_dest and ad_id=1) as name,
671 (select ad_value from fiche_Detail where f_id=ag.f_id_dest and ad_id=23) as qcode,
672 array_to_string((select array_agg(t1.t_tag) from action_tags as a1 join tags as t1 on (a1.t_id=t1.t_id) where a1.ag_id=ag.ag_id ),',') as tags,
673 array_to_string((select array_agg(t1.t_color) from action_tags as a1 join tags as t1 on (a1.t_id=t1.t_id) where a1.ag_id=ag.ag_id ),',') as tags_color
674 from action_gestion as ag
675 join document_type on (ag_type=dt_id)
676 join document_state on (ag_state=s_id)
677 ";
678 return $sql;
679 }
680 /**
681 * @brief myList($p_base, $p_filter = "", $p_search = "")
682 * Show list of action by default if sorted on date
683 * @param $p_base base url with ac...
684 * @param $p_filter filters on the document_type
685 * @param $p_search must a valid sql command ( ex 'and ag_title like upper('%hjkh%'))
686 * @see Follow_Up::create_query()
687 * @return string containing html code
688 */
689 function myList($p_base, $p_filter="", $p_search="")
690 {
691 // for the sort
692 $arg=HtmlInput::get_to_string(array("closed_action", "remind_date_end", "remind_date", "sag_ref", "only_internal", "state", "qcode", "ag_dest_query", "action_query", "tdoc", "date_start", "date_end", "hsstate", "searchtag"),"");
693 $url=$p_base.$arg;
694
695 $table=new Sort_Table();
696 // 0
697 $table->add(_('Date Doc.'), $url, 'order by ag_timestamp asc', 'order by ag_timestamp desc', 'da', 'dd');
698 //$table->add(_('Date Comm.'), $url, 'order by last_comment', 'order by last_comment desc', 'dca', 'dcd');
699 //1
700 $table->add(_('Date Limite'), $url, 'order by ag_remind_date asc nulls last', 'order by ag_remind_date desc nulls last', 'ra', 'rd');
701 //2
702 $table->add(_('Réf.'), $url, 'order by ag_ref asc', 'order by ag_ref desc', 'ra', 'rd');
703 //3
704 $table->add(_('Etiquette'), $url, 'order by tags asc nulls last', 'order by tags desc nulls last', 'taa', 'tad');
705 //4
706 $table->add(_('Groupe'), $url, "order by coalesce((select p_name from profile where p_id=ag_dest),'Aucun groupe')", "order by coalesce((select p_name from profile where p_id=ag_dest),'Aucun groupe') desc", 'dea', 'ded');
707 //5
708 $table->add(_('Dest/Exp'), $url, 'order by qcode asc nulls last', 'order by qcode desc nulls last', 'ea', 'ed');
709 //6
710 $table->add(_('Titre'), $url, 'order by ag_title asc', 'order by ag_title desc', 'ta', 'td');
711 //7
712 $table->add(_('Etat'), $url, 'order by s_value asc', 'order by s_value desc', 'ea', 'ed');
713
714 $ord=(!isset($_GET['ord']))?"dd":$_GET['ord'];
715 $sort=$table->get_sql_order($ord);
716
718 $p_filter_doc=" dt_id in ( $p_filter )";
719 else
720 $p_filter_doc=" 1=1 ";
721
722 // make SQL to find the action
723 $sql=Follow_Up::SQL_list_action()." where $p_filter_doc $p_search $sort";
724
725 $max_line=$this->db->count_sql($sql);
726 $step=$_SESSION[SESSION_KEY.'g_pagesize'];
727 $page=(isset($_GET['offset']))?$_GET['page']:1;
728 $offset=(isset($_GET['offset']))?Database::escape_string($_GET['offset']):0;
729 if ($step!=-1)
730 $limit=" LIMIT $step OFFSET $offset ";
731 else
732 $limit='';
734
735 $Res=$this->db->exec_sql($sql.$limit);
737
738 $r="";
739 $r.=HtmlInput::filter_table('mylist_tb', '1,2,3,4,5,6,7,8,9',1);
740 $r.='<p>'.$bar.'</p>';
741
742 $r.='<table id="mylist_tb" class="document">';
743 $r.="<tr>";
744 $r.='<th name="ag_id_td" style="display:none" >'.ICheckBox::toggle_checkbox('ag', 'list_ag_frm').'</th>';
745 $r.='<th style="width:5.57%">'.$table->get_header(0).'</th>';
746 $r.='<th style="width:5.57%">'.$table->get_header(1).'</th>';
747 $r.='<th style="width:5.57%">'.$table->get_header(2).'</th>';
748 $r.='<th style="width:5.57%">'.$table->get_header(5).'</th>';
749// $r.='<th>'.$table->get_header(1).'</th>';
750 $r.=th('Priorité','style="width:5.57%"');
751 $r.='<th style="min-width:45%">'.$table->get_header(6).'</th>';
752 $r.='<th style="width:5.57%">'.$table->get_header(7).'</th>';
753 $r.='<th style="max-width:10%">'.$table->get_header(3).'</th>';
754 $r.='<th style="width:5.57%">'.$table->get_header(4).'</th>';
755 $r.="</tr>";
756
757
758 // if there are no records return a message
759 if ($a_row==false || sizeof($a_row)==0 )
760 {
761 $r='<div style="clear:both">';
762 $r.='<hr>'._("Aucun enregistrement trouvé");
763 $r.="</div>";
764 return $r;
765 }
766 $today=date('d.m.Y');
767 $i=0;
768 $checkbox=new ICheckBox("mag_id[]");
769 $checkbox->set_range("action_followup_ck");
770 //show the sub_action
771 foreach ($a_row as $row)
772 {
773 $href='<A class="document" HREF="'.$p_base.HtmlInput::get_to_string(array("closed_action", "remind_date_end", "remind_date", "sag_ref", "only_internal", "state", "gDossier", "qcode", "ag_dest_query", "action_query", "tdoc", "date_start", "date_end", "hsstate", "searchtag", "ac"), "").'&sa=detail&ag_id='.$row['ag_id'].'" title="'.$row['name'].'">';
774 $i++;
775 $tr=($i%2==0)?'even':'odd';
776 if ($row['ag_priority']<2)
777 $tr='priority1';
778 $st='';
779 if ($row['my_date']==$today)
780 $st=' style="font-weight:bold; border:2px solid orange;"';
781 $date_remind=format_date($row['my_remind'], 'DD.MM.YYYY', 'YYYYMMDD');
782 $date_today=date('Ymd');
783 if ($date_remind!=""&&$date_remind==$date_today&&$row['ag_state']!=1&&$row['ag_state']!=3)
784 $st=' style="font-weight:bold;background:orange"';
785 if ($date_remind!=""&&$date_remind<$date_today&&$row['ag_state']!=1&&$row['ag_state']!=3)
786 $st=' style="font-weight:bold;background:#FF0000;color:white;"';
787 $r.="<tr class=\"$tr\" $st>";
788 $checkbox->value=$row['ag_id'];
789 $r.='<td name="ag_id_td" style="display:none">'.$checkbox->input().'</td>';
790 $r.="<td>".$href.smaller_date($row['my_date']).'</a>'."</td>";
791 //$r.="<td>".$href.$row['str_last_comment'].'</a>'."</td>";
792 $r.="<td>".$href.smaller_date($row['my_remind']).'</a>'."</td>";
793 $r.="<td>".$href.$row['ag_ref'].'</a>'."</td>";
794 // Expediteur
795 if ($row['qcode']!='')
796 {
797 $jsexp=sprintf("javascript:showfiche('%s')", $row['qcode']);
798 $r.="<td>$href".$row['qcode'].'</a></td>';
799 }
800 else
801 $r.="<td></td>";
802
803 /*
804 * State
805 */
806 switch ($row['ag_priority'])
807 {
808 case 1:
809 $priority=_('Haute');
810 break;
811 case 2:
812 $priority=_("Normale");
813 break;
814 case 3:
815 $priority=_("Basse");
816 break;
817 }
818 $r.=td($priority);
819
820 $r.='<td>'.$href.
821 h($row['ag_title'])."</A></td>";
822 $r.="<td>".$row['s_value']."</td>";
823 $r.="<td>";
824 if ($row['tags']!=""){
825 $r.=$href;
826 $aColor=explode(",", $row["tags_color"]);
827 $aTags=explode(",", $row["tags"]);
828 $nb_tag=count($aTags);
829 for ( $x=0;$x<$nb_tag;$x++) {
830 $r.=sprintf('<span style="font-size:75%%;padding:1px;border-color:transparent" class="tagcell tagcell-color%s">%s</span>',$aColor[$x],$aTags[$x]);
831 $r.="&nbsp;";
832 } // end loop $x
833 $r.='</a>';
834 }
835 $r.="</td>";
836 $r.="<td>".$href.h($row['dest']).'</a>'."</td>";
837
838
839
840
841
842
843
844
845 $r.="</tr>";
846 }
847
848 $r.="</table>";
849
850 $r.='<p>'.$bar.'</p>';
851 $r.=ICheckBox::javascript_set_range("action_followup_ck");
852 return $r;
853 }
854
855 /**
856 * @brief display list of followup , used with card
857 * @param $query string SQL query
858 * @param $extra_sql string extra to add to the query , example "limit 20"
859 * @return void
860 */
861 function view_list($query,$extra_sql="")
862 {
864 $sql = " $sql $query order by ag_timestamp desc $extra_sql";
865 require_once NOALYSS_TEMPLATE."/follow_up-view_list.php";
866 }
867 //----------------------------------------------------------------------
868 /**
869 * \brief Update the data into the database, the field ag_description could contain some HTML tags and must be
870 * saved in 2 column : one without formatting , one with.
871 * @code
872 [p_jrn] =>
873 [sa] =>
874 [gDossier] => 25
875 [p_jrn_deb_max_line] => 10
876 [p_ech_lib] => echeance
877 [p_jrn_type] => FIN
878 [p_jrn_name] => Financier
879 [bank] => COMPTE
880 [min_row] => 5
881 [p_description] => Concerne tous les mouvements financiers (comptes en banque, caisses, visa...)
882 [jrn_def_pj_pref] => FIN
883 [jrn_def_pj_seq] => 0
884 [jrn_enable] => 1
885 [FIN_FICHEDEB] => (fd_id )
886 [defaultCurrency]
887 *
888 [action_frm] => update
889 @endcode
890 *
891 * @note [defaultCurrency] => 0 exists in the array if the bank account has no operation and the currency can
892 * be set
893 *
894 * \return true on success otherwise false
895 */
896 function update()
897 {
898
899 // if ag_id == 0 nothing to do
900 if ($this->ag_id==0)
901 return;
902 // retrieve customer
903 // f_id
904
905 if (trim($this->qcode_dest??"")=="")
906 {
907 // internal document
908 $this->f_id_dest=null; // internal document
909 }
910 else
911 {
912 $tiers=new Fiche($this->db);
913 if ($tiers->get_by_qcode($this->qcode_dest)== 1) // Error we cannot retrieve this qcode
914 $this->f_id_dest=null; // internal document
915 else
916 $this->f_id_dest=$tiers->id;
917 }
918 $contact=new Fiche($this->db);
919 if ($contact->get_by_qcode($this->ag_contact)== 1)
920 $contact->id=null;
921
922 // reload the old one
923 $old=new Follow_Up($this->db);
924 $old->ag_id=$this->ag_id;
925 $old->get();
926 // If ag_ref changed then check if unique
927 if ($old->ag_ref!=$this->ag_ref)
928 {
929 $nAg_ref=$this->db->get_value("select count(*) from action_gestion where ag_ref=$1", array($this->ag_ref));
930 if ($nAg_ref!=0)
931 {
932 echo h2("Référence en double, référence non sauvée", 'class="error"');
933 $this->ag_ref=$old->ag_ref;
934 }
935 }
936
937
938 if ($this->ag_remind_date!=null)
939 {
940 $this->db->exec_sql("update action_gestion set ".
941 " ag_timestamp=to_date($1,'DD.MM.YYYY'),".
942 " ag_title=$2,".
943 " ag_type=$3, ".
944 " f_id_dest=$4, ".
945 "ag_state=$5,".
946 " ag_hour = $7 ,".
947 " ag_priority = $8 ,".
948 " ag_dest = $9 , ".
949 " ag_contact = $10, ".
950 " ag_ref = $11, ".
951 " ag_remind_date=to_date($12,'DD.MM.YYYY') ".
952 " where ag_id = $6", array(
953 $this->ag_timestamp, /* 1 */
954 $this->ag_title, /* 2 */
955 $this->dt_id, /* 3 */
956 $this->f_id_dest, /* 4 */
957 $this->ag_state, /* 5 */
958 $this->ag_id, /* 6 */
959 $this->ag_hour, /* 7 */
960 $this->ag_priority, /* 8 */
961 $this->ag_dest, /* 9 */
962 $contact->id, /* 10 */
963 $this->ag_ref, /* 11 */
964 $this->ag_remind_date /* 12 */
965 ));
966 }
967 else
968 {
969 $this->db->exec_sql("update action_gestion set ".
970 " ag_timestamp=to_date($1,'DD.MM.YYYY'),".
971 " ag_title=$2,".
972 " ag_type=$3, ".
973 " f_id_dest=$4, ".
974 "ag_state=$5,".
975 " ag_hour = $7 ,".
976 " ag_priority = $8 ,".
977 " ag_dest = $9 , ".
978 " ag_contact = $10, ".
979 " ag_ref = $11, ".
980 " ag_remind_date=null ".
981 " where ag_id = $6", array(
982 $this->ag_timestamp, /* 1 */
983 $this->ag_title, /* 2 */
984 $this->dt_id, /* 3 */
985 $this->f_id_dest, /* 4 */
986 $this->ag_state, /* 5 */
987 $this->ag_id, /* 6 */
988 $this->ag_hour, /* 7 */
989 $this->ag_priority, /* 8 */
990 $this->ag_dest, /* 9 */
991 $contact->id, /* 10 */
992 $this->ag_ref /* 11 */
993 ));
994 }
995 // upload documents
996 $doc=new Document($this->db);
997 $document_saved=$doc->upload($this->ag_id);
998
999 /* save action details */
1000 $http=new HttpInput();
1001 $nb_item=$http->post("nb_item","number",0);
1002 for ($i=0; $i< $nb_item ; $i++)
1003 {
1004 $act=new Follow_Up_Detail($this->db);
1005 $act->from_array($_POST, $i);
1006 if ($act->f_id==0&&$act->ad_id!=0)
1007 $act->delete();
1008 if ($act->f_id==0)
1009 continue;
1010 $act->save();
1011 }
1012 if (trim(strip_tags($this->ag_comment??"")) !='')
1013 {
1014 $notag_comment=strip_tags($this->ag_comment);
1015 $action_comment_id=$this->db->get_value("insert into action_gestion_comment (ag_id,tech_user,agc_comment,agc_comment_raw) values ($1,$2,$3,$4) returning agc_id"
1016 , array($this->ag_id, $_SESSION[SESSION_KEY.'g_user'], $notag_comment,$this->ag_comment));
1017 // saved also documents for this comment
1018 if ( ! empty ($document_saved) && Document_Option::is_enable_comment($this->dt_id)) {
1019 foreach ($document_saved as $document_id) {
1020 $this->db->exec_sql("insert into action_comment_document(document_id,action_gestion_comment_id) values ($1,$2)",
1021 [$document_id,$action_comment_id]);
1022 }
1023 }
1024 }
1025 if (trim(strip_tags($this->ag_description??""))!='' )
1026 {
1027 if ( $this->ag_description_id <0)
1028 $this->ag_description_id = $this->db->get_value("
1029 insert into action_gestion_comment (ag_id,tech_user,agc_comment,agc_comment_raw)
1030 values ($1,$2,$3,$4)
1031 returning agc_id"
1032 , array($this->ag_id, $_SESSION[SESSION_KEY.'g_user'],strip_tags($this->ag_description), $this->ag_description));
1033 else
1034 $this->db->exec_sql("
1035 update action_gestion_comment
1036 set agc_comment = $1 ,
1037 agc_comment_raw = $2,
1038 tech_user= $3
1039 where agc_id = $4 "
1040 , array(strip_tags($this->ag_description), $this->ag_description, $_SESSION[SESSION_KEY.'g_user'],
1041 $this->ag_description_id));
1042
1043 if ( ! empty ($document_saved)) {
1044 foreach ($document_saved as $document_id) {
1045 $this->db->exec_sql("insert into action_comment_document(document_id,action_gestion_comment_id) values ($1,$2)",
1046 [$document_id,$this->ag_description_id]);
1047 }
1048 }
1049 }
1050 $this->insert_operation();
1051 $this->insert_action();
1052 return true;
1053 }
1054
1055 /**
1056 * \brief generate the document and add it to the action
1057 * \param md_id is the id of the document_modele
1058 * \param $p_array contains normally the $_POST
1059 */
1060 function generate_document($md_id, $p_array)
1061 {
1062 $doc=new Document($this->db);
1063 $mod=new Document_Modele($this->db, $md_id);
1064 $mod->load();
1065 $doc->f_id=$this->f_id_dest;
1066 $doc->md_id=$md_id;
1067 $doc->ag_id=$this->ag_id;
1068 $doc->Generate($p_array,$this->ag_id);
1069 }
1070
1071 /**
1072 * \brief put an array in the variable member, the indice
1073 * is the member name
1074 * \param $p_array to parse
1075 * - ag_id id of the Follow_up
1076 * - ag_ref reference of the action
1077 * - qcode_dest quick_code of the card of dest
1078 * - f_id_dest f_id of the card of dest
1079 * - dt_id Document_Modele::dt_id
1080 * - ag_state document_state::s_id (default:2)
1081 * - ag_title title of the action
1082 * - ag_hour
1083 * - ag_dest Profile, profile of the user
1084 * - ag_comment comment
1085 * - ag_remind_date Remind Date
1086 * - operation related operation
1087 * - action related action
1088 * - op deprecated
1089 * \return nothing
1090 */
1092 {
1093 global $g_user;
1094 $http=new HttpInput();
1095 $http->set_array($p_array);
1096 $this->ag_id=$http->extract("ag_id","number",0);
1097 $this->ag_ref=$http->extract("ag_ref","string","");
1098 $this->qcode_dest=$http->extract("qcode_dest","string","");
1099 $this->f_id_dest=$http->extract("f_id_dest","string",null);
1100 $this->ag_timestamp=$http->extract("ag_timestamp","string",date('d.m.Y'));
1101 $this->ag_timestamp=(isDate($this->ag_timestamp)==0)?date('d.m.Y'):$this->ag_timestamp;
1102 $this->dt_id=$http->extract("dt_id","string","");
1103 $this->ag_state=$http->extract("ag_state","number",2);
1104 $this->ag_title=$http->extract("ag_title","string","");
1105 $this->ag_hour=$http->extract("ag_hour","string","");
1106 $this->ag_dest=$http->extract("ag_dest","string",$g_user->get_profile());
1107 $this->ag_priority=$http->extract("ag_priority","string","2");
1108 $this->ag_contact=$http->extract("ag_contact","string","");
1109 $ag_comment=trim($http->extract("ag_comment","raw",""));
1110 if ( strip_tags($ag_comment) == '')
1111 $this->ag_comment='';
1112 else
1113 $this->ag_comment=$ag_comment;
1114 $ag_description=trim($http->extract("ag_description","raw",""));
1115 if ( strip_tags($ag_description) == '')
1116 $this->ag_description='';
1117 else
1118 $this->ag_description=$ag_description;
1119 $this->ag_description_id=$http->extract("ag_description_id","string",-1);
1120 $this->ag_remind_date=$http->extract("ag_remind_date","string",null);
1121 $this->operation=$http->extract("operation","string",null);
1122 $this->action=$http->extract("action","string",null);
1123 }
1124
1125 /**
1126 * \brief remove the action
1127 *
1128 */
1129 function remove()
1130 {
1131 $this->get();
1132 // remove the key
1133 $sql="delete from action_gestion where ag_id=$1";
1134 $this->db->exec_sql($sql, array($this->ag_id));
1135
1136 /* check the number of attached document */
1137 $doc=new Document($this->db);
1138 $aDoc=$doc->get_all($this->ag_id);
1139 if (!empty($aDoc))
1140 {
1141 // if there are documents
1142 for ($i=0; $i<sizeof($aDoc); $i++)
1143 {
1144 $aDoc[$i]->remove();
1145 }
1146 }
1147 }
1148
1149 /**
1150 * \brief return the last p_limit operation into an array, there is a security
1151 * on user
1152 * \param $p_limit is the max of operation to return
1153 * \return $p_array of Follow_Up object
1154 */
1155 function get_last($p_limit)
1156 {
1157
1158 $sql="select coalesce(vw_name,'Interne') as vw_name,ag_hour,quick_code,ag_id,ag_title,ag_ref, dt_value,to_char(ag_timestamp,'DD.MM.YYYY') as ag_timestamp_fmt,ag_timestamp ".
1159 " from action_gestion join document_type ".
1160 " on (ag_type=dt_id) "
1161 . "left join vw_fiche_attr on (f_id=f_id_dest) "
1162 . "where ag_state in (2,3) "
1163 . "and ".self::sql_security_filter($this->db,'R').
1164 "order by ag_timestamp desc limit $p_limit";
1165 $array=$this->db->get_array($sql);
1166 return $array;
1167 }
1168
1169 /**
1170 * @brief get the action where the remind day is today
1171 * @return array
1172 */
1173 function get_today()
1174 {
1175 $sql="select ag_ref,ag_hour,coalesce(vw_name,'Interne') as vw_name,ag_id,ag_title,ag_ref, dt_value,to_char(ag_remind_date,'DD.MM.YYYY') as ag_timestamp_fmt,ag_timestamp ".
1176 " from action_gestion join document_type ".
1177 " on (ag_type=dt_id)
1178 left join vw_fiche_attr on (f_id=f_id_dest)
1179 where
1180 ag_state not in (1,4)
1181 and to_char(ag_remind_date,'DDMMYYYY')=to_char(now(),'DDMMYYYY')
1182 and ". self::sql_security_filter($this->db,'R');
1183 $array=$this->db->get_array($sql);
1184 return $array;
1185 }
1186
1187 /**
1188 * @brief get the action where the remind day is today
1189 * @return array
1190 */
1191 function get_late()
1192 {
1193 $sql="select ag_ref,ag_hour,coalesce(vw_name,'Interne') as vw_name,ag_id,ag_title,ag_ref, dt_value,to_char(ag_remind_date,'DD.MM.YYYY') as ag_timestamp_fmt,ag_timestamp ".
1194 " from action_gestion join document_type ".
1195 " on (ag_type=dt_id) left join vw_fiche_attr on (f_id=f_id_dest) where ag_state not in (1,4)
1196 and to_char(ag_remind_date,'YYMMDD') < to_char(now(),'YYMMDD') and ".self::sql_security_filter($this->db,'R');
1197 $array=$this->db->get_array($sql);
1198 return $array;
1199 }
1200
1201 /**
1202 * @brief insert a related operation
1203 */
1205 {
1206 if (trim($this->operation??"")=='')
1207 return;
1208 $array=explode(",", $this->operation);
1209 for ($i=0; $i<count($array); $i++)
1210 {
1211 if ($this->db->get_value("select count(*) from action_gestion_operation
1212 where ag_id=$1 and jr_id=$2", array($this->ag_id, $array[$i]))==0)
1213 {
1214 $this->db->exec_sql("insert into action_gestion_operation (ag_id,jr_id) values ($1,$2)", array($this->ag_id, $array[$i]));
1215 }
1216 }
1217 }
1218
1219 /**
1220 * @brief remove a related operation
1221 * @deprecated not used : dead_code
1222 * @todo to remove
1223 */
1225 {
1226 if ($this->op==null)
1227 return;
1228 $op=$this->op;
1229 for ($i=0; $i<count($op); $i++)
1230 {
1231 $this->db->exec_sql("delete from action_gestion_operation where ago_id=$1", array($op[$i]));
1232 }
1233 }
1234
1235 /**
1236 * @brief Display only a search box for searching an action
1237 * @param $cn database connx
1238 * @param $inner true if coming from an ajax (ajax_search_action)
1239 */
1240 static function display_search($cn, $inner=false)
1241 {
1242 global $g_user;
1243 $http=new HttpInput();
1244 $a=$http->get("action_query","string","");
1245 $qcode=$http->get("qcode","string","");
1246
1248
1249 if (isset($_REQUEST['f_id']))
1250 {
1251 $f_id=$http->request('f_id','number');
1253 $f=new Fiche($cn, $f_id);
1254 $supl_hidden.=HtmlInput::hidden('qcode_dest', $f->get_quick_code());
1255 }
1256
1257 /**
1258 * Show the default button (add action, show search...)
1259 */
1260 if (!$inner)
1261 require_once NOALYSS_TEMPLATE.'/action_button.php';
1262
1263 $w=new ICard();
1264 if ( $inner ) $w->autocomplete=0;
1265 $w->name='qcode';
1266 $w->id=$w->generate_id($w->name);
1267 $w->value=$qcode;
1268 $w->extra="all";
1269 $w->typecard='all';
1270 $w->jrn=0;
1271 $w->table=0;
1272 $list=$cn->make_list("select fd_id from fiche_def where frd_id in (4,8,9,14,15,16,25)");
1273 $w->extra=$list;
1274
1275
1276 /* type of documents */
1277 $type_doc=new ISelect('tdoc');
1278 $aTDoc=$cn->make_array('select dt_id,dt_value from document_type order by dt_value');
1279 $aTDoc[]=array('value'=>'-1', 'label'=>_('Tous les types'));
1280 $type_doc->value=$aTDoc;
1281 $type_doc->selected=(isset($_GET['tdoc']))?$_GET['tdoc']:-1;
1282
1283 /* State of documents */
1284 $type_state=new ISelect('state');
1285 $aState=$cn->make_array('select s_id,s_value from document_state order by s_value');
1286 $aState[]=array('value'=>'-1', 'label'=>_('Tous les actions ouvertes'));
1287 $type_state->value=$aState;
1288 $type_state->selected=(isset($_GET['state']))?$_GET['state']:-1;
1289
1290
1291
1292 /* Except State of documents */
1293 $hsExcptype_state=new ISelect('hsstate');
1294 $aExcpState=$cn->make_array('select s_id,s_value from document_state order by s_value');
1295 $aExcpState[]=array('value'=>'-1', 'label'=>_('Aucun'));
1296 $hsExcptype_state->value=$aExcpState;
1297 $hsExcptype_state->selected=(isset($_GET['hsstate']))?$_GET['hsstate']:-1;
1298
1299
1300 // date
1301 $start=new IDate('date_start');
1302 $start->value=(isset($_GET['date_start']))?$_GET['date_start']:"";
1303 $end=new IDate('date_end');
1304 $end->value=(isset($_GET['date_end']))?$_GET['date_end']:"";
1305
1306 // Closed action
1307 $closed_action=new ICheckBox('closed_action');
1308 $closed_action->selected=(isset($_GET['closed_action']))?true:false;
1309
1310 // Internal
1311 $only_internal=new ICheckBox('only_internal');
1312 $only_internal->selected=(isset($_GET['only_internal']))?true:false;
1313 // select profile
1314 $aAg_dest=$cn->make_array("select p_id as value, ".
1315 "p_name as label ".
1316 " from profile where p_id in ".
1317 $g_user->sql_readable_profile().
1318 "order by 2");
1319 $aAg_dest[]=array('value'=>'-2', 'label'=>_('Tous les profils'));
1320 $ag_dest=new ISelect();
1321 $ag_dest->name="ag_dest_query";
1322 $ag_dest->value=$aAg_dest;
1323 $ag_dest->selected=$http->get("ag_dest_query","number",-2);
1324 $str_ag_dest=$ag_dest->input();
1325 $osag_ref=new IText("sag_ref");
1326 $osag_ref->value=$http->get('sag_ref',"string","");
1327 $remind_date=new IDate('remind_date');
1328 $remind_date->value=$http->get('remind_date',"string","");
1329 $remind_date_end=new IDate('remind_date_end');
1330 $remind_date_end->value=$http->get('remind_date_end',"string","");
1331 $otag=new Tag($cn);
1332
1333 // show the action in
1334 require_once NOALYSS_TEMPLATE.'/action_search.php';
1335 }
1336
1337 /**
1338 * @brief display a form with the saved search
1339 * @return voidµ
1340 */
1341 public static function display_saved_search()
1342 {
1343 $http=new HttpInput();
1344 echo \HtmlInput::button_action("Recherches sauvées",sprintf("list_filter_followup('%s','%s')",Dossier::id(),$http->request("ac")));
1345
1346 }
1347 /**
1348 * @brief show a list of documents
1349 * @param $cn database connextion
1350 * @param $p_base base URL
1351 */
1352 static function show_action_list($cn, $p_base)
1353 {
1354
1357
1358 $act=new Follow_Up($cn);
1359 /** \brief
1360 * \note The field 'recherche' is about a part of the title or a ref. number
1361 */
1363
1364 echo '<form method="POST" id="list_ag_frm" style="display:inline">';
1365 echo HtmlInput::request_to_hidden(array("gDossier", "ac", "sb", "sc", "f_id"));
1366 require_once NOALYSS_TEMPLATE.'/action_other_action.php';
1367 echo $act->myList($p_base, "", $query);
1368 echo '</form>';
1369
1370 }
1371 /**
1372 * @brief Show a button for adding follow-up action, display the FORM
1373 * @param array $pa_param , will be converted in a HIDDEN input type in the form
1374 */
1375 static function show_action_add($pa_param)
1376 {
1377 require_once NOALYSS_TEMPLATE.'/followup-show-action-add.php';
1378
1379 }
1380
1381 /**
1382 *@brief Create a subquery to filter thanks the selected tag
1383 * @param $cn db connx
1384 * @param $p_array
1385 * @return SQL
1386 */
1387 static function filter_by_tag($cn, $p_array=null)
1388 {
1389 if ($p_array==null)
1391
1392 if (count($p_array['searchtag'])==0)
1393 return "";
1394 $query="";
1395 $operand = "1 = 0 ";
1396 if ($p_array['tag_option'] == 0 )
1397 {
1398 $operand=" and ";
1399 } elseif ($p_array['tag_option']==1)
1400 {
1401 $operand=" or ";
1402 }
1403 $and=" ";
1404 for ($i=0; $i<count($p_array['searchtag']); $i++)
1405 {
1406 if (isNumber($p_array['searchtag'][$i])==1) {
1407 $query .= $and .' ag_id in (select ag_id from action_tags where t_id= '.sql_string($p_array['searchtag'][$i]).')';
1408 $and = $operand;
1409 }
1410 }
1411 return "and (".$query.")";
1412 }
1413
1414 /**
1415 * @brief Get date from $_GET and create the sql stmt for the query
1416 * @note the query is taken from $_GET
1417 * @see {Follow_Up::ShowActionList}
1418 * @return string SQL condition
1419 */
1420 static function create_query($cn, $p_array=null)
1421 {
1422 if ($p_array==null) $p_array=$_GET;
1423 $http=new HttpInput();
1424 $http->set_array($p_array);
1425 $search_docid=0; // search for a document
1426 $action_query="";
1427 $ag_state=""; //<! selected status of the event , if not set or equal to -1 , it is all of them
1428 //
1429 // search for a specific document id (ag_id) , if given then status and date doesn't count
1430 if (isset ($p_array['ag_id']) && isNumber($p_array['ag_id'])==1&&$p_array['ag_id']!=0)
1431 {
1432 $action_query=" and ag_id= ".sql_string($p_array['ag_id']);
1433 $search_docid=$p_array['ag_id'];
1434 return $action_query;
1435 }
1436 if (isset($_REQUEST['action_query']) && trim($_REQUEST['action_query']??"") != "")
1437 {
1438 $action_query = $http->extract('action_query');
1439 // if a query is request build the sql stmt
1440 $action_query="and (ag_title ilike '%".sql_string($action_query)."%' ".
1441 "or ag_ref ='".trim(sql_string($action_query??"")).
1442 "' or ag_id in (select ag_id from action_gestion_comment ".
1443 " where agc_comment ilike '%".trim(sql_string($action_query??""))."%')".
1444 ")";
1445 }
1446
1447 $str="";
1448 if (isset($p_array['qcode']))
1449 {
1450 // verify that qcode is not empty
1451 if (noalyss_strlentrim($p_array['qcode'])!=0)
1452 {
1453
1454 $fiche=new Fiche($cn);
1455 $fiche->get_by_qcode($http->extract('qcode'));
1456 // if quick code not found then nothing
1457 if ($fiche->id==0)
1458 $str=' and false ';
1459 else
1460 $str=" and (f_id_dest= ".$fiche->id." or ag_id in (select ag_id from action_person as ap where ap.f_id=".$fiche->id.") or ag_contact=".$fiche->id." )";
1461 }
1462 }
1463 if (isset($p_array['tdoc'])&&$p_array['tdoc'] !=-1)
1464 {
1465 $action_query .= ' and dt_id = '.sql_string($p_array['tdoc']);
1466 }
1467 if (isset($p_array['state'])&&$p_array['state'] !=-1)
1468 {
1469 $action_query .= ' and ag_state= '.sql_string($p_array['state']);
1470 // a status is selected
1471 $ag_state=$p_array['state'];
1472 }
1473 if (isset($p_array['hsstate'])&&$p_array['hsstate']!=-1)
1474 {
1475 $action_query .= ' and ag_state <> '.sql_string($p_array['hsstate']);
1476 }
1477 if (isset($p_array['sag_ref'])&&trim($p_array['sag_ref']??"")!="")
1478 {
1479 $action_query .= " and ag_ref= '".sql_string($p_array['sag_ref'])."'";
1480 }
1481
1482 if (isset($_GET['only_internal']))
1483 $action_query .= ' and f_id_dest=0 ';
1484
1485 if (isset($p_array['date_start'])&&isDate($p_array['date_start'])!=null)
1486 {
1487 $action_query.=" and ag_timestamp >= to_date('".$p_array['date_start']."','DD.MM.YYYY')";
1488 }
1489 if (isset($p_array['date_end'])&&isDate($p_array['date_end'])!=null)
1490 {
1491 $action_query.=" and ag_timestamp <= to_date('".$p_array['date_end']."','DD.MM.YYYY')";
1492 }
1493 if (isset($p_array['ag_dest_query'])&&$p_array['ag_dest_query']!=-2)
1494 {
1495 $action_query.= " and ((ag_dest = ".sql_string($p_array['ag_dest_query'])." and ".self::sql_security_filter($cn, "R").") or ".
1496 "(ag_dest = ".sql_string($p_array['ag_dest_query'])." and ".self::sql_security_filter($cn, "R")." and ".
1497 " ag_owner='".$_SESSION[SESSION_KEY.'g_user']."'))";
1498 }
1499 else
1500 {
1501 $action_query .=" and (ag_owner='".$_SESSION[SESSION_KEY.'g_user']."' or ".self::sql_security_filter($cn, "R")." or ag_dest=-1 )";
1502 }
1503
1504
1505 if (isset ($p_array['ag_id']) && isNumber($p_array['ag_id'])==1&&$p_array['ag_id']!=0)
1506 {
1507 $action_query .= " and to_date('".sql_string($p_array['$remind_date'])."','DD.MM.YYYY')<= ag_remind_date";
1508 }
1509 if (isset($p_array['remind_date_end'])&&$p_array['remind_date_end']!=""&&isDate($p_array['$remind_date_end'])==$p_array['remind_date_end'])
1510 {
1511 $action_query .= " and to_date('".sql_string($p_array['remind_date_end'])."','DD.MM.YYYY')>= ag_remind_date";
1512 }
1513 // only for open action or a closing status is selected
1514 if (!isset($p_array['closed_action']) && $ag_state == "")
1515 {
1516 $action_query.=" and s_status is null ";
1517 }
1518 if (isset($p_array['searchtag']))
1519 {
1520 $action_query .= Follow_Up::filter_by_tag($cn, $p_array);
1521 }
1522 if ( DEBUGNOALYSS > 1) {
1523 print __FILE__.__LINE__."QUERY = [ $action_query.$str]";
1524 }
1525 return $action_query.$str;
1526 }
1527
1528 /**
1529 * @brief Show the result of a search in an inner windows, the result is limited to 25
1530 * @param Database $cn database connx
1531 * @param string $p_sql where clause of the query
1532 */
1533 static function short_list($cn, $p_sql)
1534 {
1535 $sql="
1536 select ag_id,to_char(ag_timestamp,'DD.MM.YY') as my_date,
1537 f_id_dest,
1538 substr(ag_title,1,40) as sub_ag_title,dt_value,ag_ref, ag_priority,ag_state,
1539 coalesce((select p_name from profile where p_id=ag_dest),'Aucun groupe') as dest,
1540 (select ad_value from fiche_Detail where f_id=action_gestion.f_id_dest and ad_id=1) as name
1541 from action_gestion
1542 join document_type on (ag_type=dt_id)
1543 join document_state on (s_id=ag_state)
1544 where $p_sql";
1545 $max_line=$cn->count_sql($sql);
1546
1547 $limit=($max_line>25)?25:$max_line;
1548 $Res=$cn->exec_sql($sql."limit ".$limit);
1550 require_once NOALYSS_TEMPLATE.'/action_search_result.php';
1551 }
1552
1553 /**
1554 * @brief Insert a related action into the table action_gestion_related
1555 */
1556 function insert_action()
1557 {
1558 if (trim($this->action??"")=='')
1559 return;
1560 $array=explode(",", $this->action);
1561 for ($i=0; $i<count($array); $i++)
1562 {
1563 // Do not insert an option child of himself
1564 if ( $this->ag_id == $array[$i]) {
1565 continue;
1566 }
1567
1568 if ($this->db->get_value("select count(*) from action_gestion_related
1569 where (aga_least=$1 and aga_greatest=$2) or (aga_greatest=$1 and aga_least=$2)", array($array[$i], $this->ag_id))==0)
1570 {
1571 $this->db->exec_sql("insert into action_gestion_related(aga_least,aga_greatest) values ($1,$2)", array($this->ag_id, $array[$i]));
1572 }
1573 }
1574 }
1575 /**
1576 * @brief export to CSV the query the p_array has
1577 * @param array $p_array
1578 @see create_query
1579 */
1581 {
1582
1583
1584 $p_search=self::create_query($this->db, $p_array);
1585 $sql="
1586 select ag_id,
1587 to_char(ag_timestamp,'DD.MM.YYYY') as my_date,
1588 to_char(ag_remind_date,'DD.MM.YYYY') as my_remind,
1589 to_char(coalesce((select max(agc_date) from action_gestion_comment as agc where agc.ag_id=ag_id),ag_timestamp),'DD.MM.YY') as last_comment,
1590 array_to_string((select array_agg(t1.t_tag) from action_tags as a1 join tags as t1 on (a1.t_id=t1.t_id) where a1.ag_id=ag.ag_id ),',') as tags,
1591 (select ad_value from fiche_Detail where f_id=ag.f_id_dest and ad_id=1) as name,
1592 ag_title,
1593 dt_value,
1594 ag_ref,
1595 ag_priority,
1596 ag_state,
1597
1598 coalesce((select p_name from profile where p_id=ag_dest),'Aucun groupe') as dest
1599 from action_gestion as ag
1600 join document_type on (ag.ag_type=dt_id)
1601 join document_state on(ag.ag_state=s_id)
1602 where true $p_search order by ag.ag_timestamp,ag.ag_id";
1603 $ret=$this->db->exec_sql($sql);
1604
1605 if (Database::num_row($ret)==0)
1606 return;
1607 $this->db->query_to_csv($ret, array(
1608 array("title"=>"doc id", "type"=>"string"),
1609 array("title"=>"date", "type"=>"date"),
1610 array("title"=>"rappel", "type"=>"date"),
1611 array("title"=>"date dernier commentaire", "type"=>"date"),
1612 array("title"=>"tags", "type"=>"string"),
1613 array("title"=>"nom", "type"=>"string"),
1614 array("title"=>"titre", "type"=>"string"),
1615 array("title"=>"type document", "type"=>"string"),
1616 array("title"=>"ref", "type"=>"string"),
1617 array("title"=>"priorite", "type"=>"string"),
1618 array("title"=>"etat", "type"=>"string"),
1619 array("title"=>"profil", "type"=>"string")
1620 )
1621 );
1622 }
1623 /**
1624 * @brief export to CSV the detailled actions (tags, comment, related operations...),
1625 * it could be a query in $p_array * task #0002035
1626 * @see create_query
1627 * @param array $p_array
1628 */
1630 {
1631
1632
1633 $p_search=self::create_query($this->db, $p_array);
1634 $sql="
1635select ag_id,
1636 to_char(ag_timestamp,'DD.MM.YYYY') as my_date,
1637 to_char(ag_remind_date,'DD.MM.YYYY') as my_remind,
1638 to_char(coalesce((select max(agc_date)
1639 from action_gestion_comment as agc
1640 where agc.ag_id=ag.ag_id),ag.ag_timestamp),'DD.MM.YY HH24:MI') as last_comment,
1641 array_to_string((select array_agg(t1.t_tag)
1642 from action_tags as a1 join tags as t1 on (a1.t_id=t1.t_id)
1643 where a1.ag_id=ag.ag_id ),',') as tags,
1644 array_to_string((select array_agg(coalesce(jrn1.jr_pj_number,jrn1.jr_internal))
1645 from action_gestion_operation ago join jrn jrn1 using (jr_id)
1646 where ago.ag_id=ag.ag_id),',') as related_operation,
1647 array_to_string((select array_agg(agc2.agc_comment order by agc2.agc_date desc)
1648 from action_gestion_comment agc2 where agc2.ag_id=ag.ag_id ),'|') as action_comment,
1649 array_to_string((select array_agg(followup_id) from (select agr1.aga_least followup_id
1650 from action_gestion_related agr1
1651 where agr1.aga_greatest = ag.ag_id
1652 union
1653 select agr2.aga_greatest
1654 from
1655 action_gestion_related agr2
1656 where agr2.aga_least=ag.ag_id) as followup),',') follow_up,
1657 (select ad_value from fiche_Detail where f_id=ag.f_id_dest and ad_id=1) as name,
1658 ag_title,
1659 dt_value,
1660 ag_ref,
1661 ag_priority,
1662 ag_state,
1663 coalesce((select p_name from profile where p_id=ag_dest),'Aucun groupe') as dest
1664from action_gestion as ag
1665join document_type on (ag.ag_type=dt_id)
1666join document_state on(ag.ag_state=s_id)
1667where
1668 true $p_search order by ag.ag_timestamp,ag.ag_id";
1669 $ret=$this->db->exec_sql($sql);
1670
1671 $nb_record=Database::num_row($ret);
1672 $export_csv=new Noalyss_Csv('action_gestion_detail');
1673 $export_csv->send_header();
1674 $export_csv->write_header([
1675 _("Document id"),
1676 _("Date"),
1677 _("Date rappel"),
1678 _("Destinataire"),
1679 _("Référence "),
1680 _("Titre "),
1681 _("Commentaires "),
1682 _("Date dernier commentaire "),
1683 _("Etiquette "),
1684 _("Priorité "),
1685 _("Etat "),
1686 _("Opérations"),
1687 _("Autres actions"),
1688 _("Type action"),
1689 _("Groupe "),
1690 ]);
1691 for ($i=0;$i<$nb_record;$i++)
1692 {
1694 $export_csv->add($row['ag_id']);
1695 $export_csv->add($row['my_date']);
1696 $export_csv->add($row['my_remind']);
1697 $export_csv->add($row['name']);
1698 $export_csv->add($row['ag_ref']);
1699 $export_csv->add($row['ag_title']);
1700 $export_csv->add($row['action_comment']);
1701 $export_csv->add($row['last_comment']);
1702 $export_csv->add($row['tags']);
1703 $export_csv->add($row['ag_priority']);
1704 $export_csv->add($row['ag_state']);
1705 $export_csv->add($row['related_operation']);
1706 $export_csv->add($row['follow_up']);
1707 $export_csv->add($row['dt_value']);
1708 $export_csv->add($row['dest']);
1709
1710 $export_csv->write();
1711 }
1712 if ($nb_record==0)
1713 return;
1714 }
1715
1716 static function get_all_operation($p_jr_id)
1717 {
1718 global $cn;
1719 $array=$cn->get_array("
1720 select ag_id,ag_ref,ago_id,
1721 ag_title
1722 from action_gestion
1723 join action_gestion_operation using(ag_id)
1724 where
1725 jr_id=$1", array($p_jr_id));
1726 return $array;
1727 }
1728
1729 /**
1730 * @brief get the tags of the current objet
1731 * @return an array idx [ag_id,t_id,at_id,t_tag]
1732 */
1733 function tag_get()
1734 {
1735 if ($this->ag_id==0)
1736 return;
1737 $sql='select b.ag_id,b.t_id,b.at_id,a.t_tag,a.t_color'
1738 .' from '
1739 .' tags as a join action_tags as b on (a.t_id=b.t_id)'
1740 .' where ag_id=$1 '
1741 .' order by a.t_tag';
1742 $array=$this->db->get_array($sql, array($this->ag_id));
1743 return $array;
1744 }
1745
1746 /**
1747 * @brief show the tags of the current objet
1748 * normally used by ajax. The same tag cannot be added twice
1749 *
1750 */
1751 function tag_add($p_t_id)
1752 {
1753 if ($this->ag_id==0)
1754 return;
1755 $count=$this->db->get_value('select count(*) from action_tags'.
1756 ' where ag_id=$1 and t_id=$2', array($this->ag_id, $p_t_id));
1757 if ($count>0)
1758 return;
1759 $sql=' insert into action_tags (ag_id,t_id) values ($1,$2)';
1760 $this->db->exec_sql($sql, array($this->ag_id, $p_t_id));
1761 }
1762
1763 /**
1764 * @brief remove the tags of the current objet
1765 * normally used by ajax
1766 */
1767 function tag_remove($p_t_id)
1768 {
1769 if ($this->ag_id==0)
1770 return;
1771 $sql=' delete from action_tags where ag_id=$1 and t_id=$2';
1772 $this->db->exec_sql($sql, array($this->ag_id, $p_t_id));
1773 }
1774
1775 /**
1776 * @brief show the cell content in Display for the tags
1777 * called also by ajax
1778 */
1779 function tag_cell($p_view='UPD')
1780 {
1781 global $g_user;
1782 $a_tag=$this->tag_get();
1783 $c=count($a_tag);
1784 for ($e=0; $e<$c; $e++)
1785 {
1786 echo '<span class="tagcell tagcell-color'.$a_tag[$e]['t_color'].'">';
1787 echo $a_tag[$e]['t_tag'];
1788 if ($g_user->can_write_action($this->ag_id)==true && $p_view != 'READ')
1789 {
1790 $js_remove=sprintf("action_tag_remove('%s','%s','%s')", dossier::id(), $this->ag_id, $a_tag[$e]['t_id']);
1791 echo Icon_Action::trash(uniqid(), $js_remove);
1792 }
1793 echo '</span>';
1794 echo '&nbsp;';
1795 echo '&nbsp;';
1796 }
1797
1798 if ($p_view != 'READ' && $g_user->can_write_action($this->ag_id)==true)
1799 {
1800 $js=sprintf("onclick=\"action_tag_select('%s','%s')\"", dossier::id(), $this->ag_id);
1801 echo HtmlInput::button('tag_bt', _('Ajout étiquette'), $js, 'smallbutton');
1802 }
1803 }
1804
1806 {
1807 global $g_user;
1808 $mag_id=$p_array['mag_id'];
1809 $remtag=$p_array['remtag'];
1810 for ($i=0; $i<count($mag_id); $i++)
1811 {
1812 if ($g_user->can_write_action($mag_id[$i])==false)
1813 continue;
1814 for ($e=0; $e<count($remtag); $e++)
1815 {
1816 $a=new Follow_Up($cn, $mag_id[$i]);
1817 $a->tag_remove($remtag[$e]);
1818 }
1819 }
1820 }
1821
1822 static function action_tag_add($cn, $p_array)
1823 {
1824 global $g_user;
1825 $mag_id=$p_array['mag_id'];
1826 $addtag=$p_array['addtag'];
1827 for ($i=0; $i<count($mag_id); $i++)
1828 {
1829 if ($g_user->can_write_action($mag_id[$i])==false)
1830 continue;
1831 for ($e=0; $e<count($addtag); $e++)
1832 {
1833 $a=new Follow_Up($cn, $mag_id[$i]);
1834 $a->tag_add($addtag[$e]);
1835 }
1836 }
1837 }
1838
1840 {
1841 global $g_user;
1842 $mag_id=$p_array['mag_id'];
1843 for ($i=0; $i<count($mag_id); $i++)
1844 {
1845 if ($g_user->can_write_action($mag_id[$i])==false)
1846 continue;
1847 $a=new Follow_Up($cn, $mag_id[$i]);
1848 $a->tag_clear();
1849 }
1850 }
1851
1852 static function action_print($cn, $p_array)
1853 {
1854 global $g_user;
1855 $mag_id=$p_array['mag_id'];
1856 for ($i=0; $i<count($mag_id); $i++)
1857 {
1858 if ($g_user->can_read_action($mag_id[$i])==false)
1859 continue;
1860 $a=new Follow_Up($cn, $mag_id[$i]);
1861 $a->get();
1862 echo '<div class="content">';
1863 echo $a->Display("READ", false, "");
1864 echo '</div>';
1865 echo '<P id="breakhere"> - - </p>';
1866 }
1867 }
1868
1869 function tag_clear()
1870 {
1871 $this->db->exec_sql('delete from action_tags where ag_id=$1', array($this->ag_id));
1872 }
1873
1875 {
1876
1877 global $g_user;
1878 $mag_id=$p_array['mag_id'];
1879 $state=$p_array['ag_state'];
1880 for ($i=0; $i<count($mag_id); $i++)
1881 {
1882 if ($g_user->can_write_action($mag_id[$i])==false)
1883 continue;
1884 $cn->exec_sql('update action_gestion set ag_state=$1 where ag_id=$2', array($state, $mag_id[$i]));
1885 }
1886 }
1887
1888 static function action_remove($cn, $p_array)
1889 {
1890 global $g_user;
1891
1892 $mag_id=$p_array['mag_id'];
1893 for ($i=0; $i<count($mag_id); $i++)
1894 {
1895 if ($g_user->can_write_action($mag_id[$i])==false)
1896 continue;
1897 $cn->exec_sql('delete from action_gestion where ag_id=$1', array($mag_id[$i]));
1898 }
1899 }
1900
1901 /**
1902 * Verify that data are correct
1903 * @throws Exception
1904 */
1905 function verify()
1906 {
1907 if ($this->dt_id==-1)
1908 {
1909 throw new Exception(_('Type action invalide'), 10);
1910 }
1911 if (isDate($this->ag_timestamp)!=$this->ag_timestamp)
1912 throw new Exception(_('Date invalide'), 20);
1913 if (isDate($this->ag_remind_date)!=$this->ag_remind_date)
1914 throw new Exception(_('Date invalide'), 30);
1915 if ($this->f_id_dest==0)
1916 $this->f_id_dest=null;
1917 }
1918
1919
1920 /**
1921 * @brief display a small form to enter a new event
1922 *
1923 */
1924 function display_short()
1925 {
1926 $cn=$this->db;
1927 include NOALYSS_TEMPLATE.'/action_display_short.php';
1928 }
1929 /**
1930 * Add an event , with the minimum of informations,
1931 * used in Dashboard and Scheduler
1932 */
1933 function save_short()
1934 {
1935 global $g_user;
1936 // check if we can add
1937 if ($g_user->can_add_action($this->ag_dest) == FALSE )
1938 {
1939 throw new Exception(_('SECURITE : Ajout impossible'));
1940 }
1941
1942
1943
1944 // Get The sequence id,
1945 $seq_name="seq_doc_type_".$this->dt_id;
1946 $str_file="";
1947 $add_file='';
1948
1949
1950 $this->ag_id=$this->db->get_next_seq('action_gestion_ag_id_seq');
1951
1952 // Create the reference
1953 $ag_ref=$this->db->get_value('select dt_prefix from document_type '
1954 . 'where dt_id=$1', array($this->dt_id))
1955 .'-'.$this->db->get_next_seq($seq_name);
1956
1957 $this->ag_ref=$ag_ref;
1958 /**
1959 * If ag_ref already exist then compute a new one
1960 */
1961
1962 // save into the database
1963 $sql="insert into action_gestion".
1964 "(ag_id,ag_timestamp,ag_type,ag_title,f_id_dest,ag_ref, "
1965 . "ag_dest, ".
1966 " ag_priority,ag_owner,ag_state,ag_remind_date,ag_hour) ".
1967 " values "
1968 . "($1,to_date($2,'DD.MM.YYYY'),$3,$4,$5,$6,"
1969 . "$7,"
1970 . "$8,$9,$10,to_date($11,'DD.MM.YYYY'),$12)";
1971
1972 $this->db->exec_sql($sql, array(
1973 $this->ag_id, /* 1 */
1974 $this->ag_timestamp, /* 2 */
1975 $this->dt_id, /* 3 */
1976 $this->ag_title, /* 4 */
1977 $this->f_id_dest, /* 5 */
1978 $ag_ref, /* 6 */
1979 $this->ag_dest, /* 7 */
1980 $this->ag_priority, /* 8 */
1981 $_SESSION[SESSION_KEY.'g_user'], /* 9 */
1982 $this->ag_state, /* 10 */
1983 $this->ag_remind_date, /* 11 */
1984 $this->ag_hour /* 12 */
1985 )
1986 );
1987
1988 if (trim($this->ag_comment??"")!='')
1989 {
1990 $this->db->exec_sql("insert into action_gestion_comment (ag_id,tech_user,agc_comment) values ($1,$2,$3)"
1991 , array($this->ag_id, $_SESSION[SESSION_KEY.'g_user'], $this->ag_comment));
1992 }
1993 }
1994 /**
1995 * @brief Return the first parent of the event tree, or -1 if not found. The parent is an action with a lower id,
1996 * so it can happen than an action has several ones
1997 * @return arrary of integer (ag_id)
1998 */
1999 function get_parent() {
2000 $value=$this->db->get_array('
2001 with recursive t (aga_least,aga_greatest,depth) as (
2002 select aga_least,aga_greatest , 1
2003 from
2004 action_gestion_related
2005 where aga_greatest=$1
2006 union all
2007 select p2.aga_least,p2.aga_greatest,depth + 1
2008 from
2009 t as p1, action_gestion_related as p2
2010 where
2011 p2.aga_greatest is not null and
2012 p2.aga_greatest = p1.aga_least
2013 ) select aga_least,aga_greatest,depth from t order by depth desc,aga_least asc
2014 ' , array($this->ag_id)
2015 );
2016 if ( ! empty($value ) )
2017 return $value;
2018 else
2019 return -1;
2020 }
2021 /**
2022 * Compute an array of the complete tree depending of $p_id
2023 * @param $p_id ag_id
2024 * @return array
2025 * key index :
2026 * - uniq value , path
2027 * - aga_least
2028 * - aga_greatest
2029 * - depth
2030 */
2032 // retrieve parent
2033 // Get information
2034 $sql = "with recursive t (key_path, aga_least,aga_greatest,depth) as (
2035 select
2036 aga_least::text||'-'||aga_greatest::text as key_path ,
2037 aga_least,aga_greatest , 1
2038 from
2039 action_gestion_related
2040 where aga_least=$1 or aga_greatest = $1
2041 union all
2042 select key_path||'-'||p2.aga_greatest::text,
2043 p2.aga_least,p2.aga_greatest,depth + 1
2044 from
2045 t as p1, action_gestion_related as p2
2046 where
2047 p1.aga_greatest is not null and
2048 p1.aga_greatest = p2.aga_least
2049 )
2050 select key_path,aga_greatest,ag_title as title,depth ,to_char(ag_timestamp,'DD/MM/YY') as str_date,ag_ref||' '||dt_value as action_ref
2051 from
2052 action_gestion join t on (ag_id=aga_greatest)
2053 join document_type on (ag_type=dt_id)
2054 order by key_path
2055";
2056 $ret_array=$this->db->get_array($sql,array($p_id));
2057 // Empty returns
2058 if ( empty($ret_array)) return array();
2059
2060
2061 return $ret_array;
2062 }
2063
2064 /**
2065 * @brief Display the tree of childrens of the current Action + related parents
2066 * @return return the tree of children in a unordered list , HTML string
2067 */
2068 function display_children($p_view, $p_base)
2069 {
2070 /*
2071 * First we retrieve the parent
2072 */
2073 $parent_id=$this->db->get_value("select min( get_follow_up_tree) from comptaproc.get_follow_up_tree($1)",[$this->ag_id]);
2074 $http=new HttpInput();
2075 $base=HtmlInput::request_to_string(array("gDossier", "ac", "sb", "sc",
2076 "f_id"))."&amp;sa=detail";
2077 $parent=array();
2078 if (empty($parent_id))
2079 {
2080 echo _('Principal');
2081 $parent_id= $this->ag_id;
2082 }
2083
2084
2085 $fu_parent=new Follow_Up($this->db, $parent_id);
2086 $fu_parent->get();
2087 echo'<span class="highlight">';
2088 $xaction=sprintf('view_action(%d,%d,%d)', $fu_parent->ag_id,
2089 Dossier::id(), 1);
2090 $showAction='<a class="line" href="javascript:'.$xaction.'">';
2091 echo $showAction.
2092 $fu_parent->ag_timestamp," ",
2093 h($fu_parent->ag_title),
2094 '('.h($fu_parent->ag_ref).')',
2095 '</a>';
2096
2097 echo "</span>";
2098 echo '<ul style="padding-left:10px;list-style-type: none;">';
2099
2100 $action=$this->get_children($parent_id);
2101 for ($o=0; $o<count($action); $o++)
2102 {
2103 $class=($this->ag_id == $action[$o]['aga_greatest'])?' class="highlight" ':'';
2104
2105 // Count the number of direct parents
2106 $count_parent =$this->db->get_value('select count(*) from action_gestion_related where aga_greatest = $1',array($action[$o]['aga_greatest']));
2107 $direct_parent=($count_parent > 1 ) ? _('direct parent ').$count_parent:"";
2108
2109 $margin=($action[$o]['depth']>1 )?str_repeat("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;",$action[$o]['depth']-1)."&#8680;":"";
2110 if ($p_view!='READ'&&$p_base!='ajax')
2111 {
2112 $rmAction=sprintf("return confirm_box(null,'"._('Voulez-vous effacer cette action ')."', function () {remove_action('%s','%s','%s');});",
2113 dossier::id(), $action[$o]['aga_greatest'],
2114 $http->request('ag_id',"number"));
2115 $showAction='<a class="line" href="'.$base."&ag_id=".$action[$o]['aga_greatest'].'">';
2116 $js=Icon_Action::trash("acact".$action[$o]['aga_greatest'], $rmAction);
2117 echo '<li '.$class.' id="act'.$action[$o]['aga_greatest'].'">'.$margin.$showAction.$action[$o]['str_date'].
2118 h($action[$o]['title']).'('.h($action[$o]['action_ref']).')'.$direct_parent.'</a>'." "
2119 .$js.'</li>';
2120 }
2121 else
2122 /*
2123 * Display detail requested from Ajax Div
2124 */
2125 if ($p_base=='ajax')
2126 {
2127 $xaction=sprintf('view_action(%d,%d,%d)', $action[$o]['aga_greatest'],
2128 Dossier::id(), 1);
2129 $showAction='<a class="line" href="javascript:'.$xaction.'">';
2130 echo '<li '.$class.' >'.$margin.$showAction.$action[$o]['str_date']." ".
2131 h($action[$o]['title']).'('.h($action[$o]['action_ref']).')'.$direct_parent.'</a>'." "
2132 .'</li>';
2133 }
2134 /*
2135 * READ ONLY
2136 */
2137 else
2138 {
2139 $showAction='<a class="line" href="'.$base."&ag_id=".$action[$o]['aga_greatest'].'">';
2140 echo '<li '.$class.' >'.$margin.$showAction.$action[$o]['str_date']." ".
2141 h($action[$o]['title']).'('.h($action[$o]['action_ref']).')'.$direct_parent.'</a>'." "
2142 .'</li>';
2143 }
2144 }
2145 echo '</ul>';
2146
2147 }
2148 /**
2149 * @brief Display the list of parent of the current Follow_Up
2150 * \param $p_view form will be in readonly mode (value: READ, UPD or NEW )
2151 * \param $p_base is the ac parameter
2152 * \see Follow_Up::Display
2153 * \return None display the HTML list
2154 */
2155 function display_parent($p_view,$p_base)
2156 {
2157 $a_parent=$this->db->get_array(
2158 "
2159 select ag1.ag_id
2160 ,ag1.ag_title as title
2161 ,to_char(ag1.ag_timestamp,'DD/MM/YY') as str_date
2162 ,ag1.ag_ref||' '||dt_value as action_ref
2163 from
2164 action_gestion ag1
2165 join document_type on (ag_type=dt_id)
2166 join (select distinct get_follow_up_tree from comptaproc.get_follow_up_tree($1)) tree_ag
2167 on (tree_ag.get_follow_up_tree=ag1.ag_id)
2168order by ag_id
2169 ", array($this->ag_id)
2170 );
2171 if ( empty($a_parent ) ) return;
2172 echo '<ul style="padding-left:10px;list-style-type: none;">';
2173 $base=HtmlInput::request_to_string(array("gDossier", "ac", "sa", "sb", "sc",
2174 "f_id"));
2175 $http=new HttpInput();
2176 for ($o=0; $o<count($a_parent); $o++)
2177 {
2178 $class=($this->ag_id == $a_parent[$o]['ag_id'])?' class="highlight" ':'';
2179
2180 if ($p_view!='READ'&&$p_base!='ajax')
2181 {
2182 $rmAction=sprintf("return confirm_box(null,'"._('Voulez-vous effacer cette action ')."', function () {remove_action('%s','%s','%s');});",
2183 dossier::id(), $a_parent[$o]['ag_id'],
2184 $http->request('ag_id',"number"));
2185 $showAction='<a class="line" href="'.$base."&ag_id=".$a_parent[$o]['ag_id'].'">';
2186
2187 $js=\Icon_Action::trash('acact'.$a_parent[$o]['ag_id'],$rmAction);
2188
2189 echo '<li '.$class.' id="act'.$a_parent[$o]['ag_id'].'">'.$showAction.$a_parent[$o]['str_date'].
2190 h($a_parent[$o]['title']).'('.h($a_parent[$o]['action_ref']).')'.'</a>'." "
2191 .$js.'</li>';
2192 }
2193 else
2194 /*
2195 * Display detail requested from Ajax Div
2196 */
2197 if ($p_base=='ajax')
2198 {
2199 $xaction=sprintf('view_action(%d,%d,%d)', $a_parent[$o]['ag_id'],
2200 Dossier::id(), 1);
2201 $showAction='<a class="line" href="javascript:'.$xaction.'">';
2202 echo '<li '.$class.' >'.$showAction.$a_parent[$o]['str_date']." ".
2203 h($a_parent[$o]['title']).'('.h($a_parent[$o]['action_ref']).')'.'</a>'." "
2204 .'</li>';
2205 }
2206 /*
2207 * READ ONLY
2208 */
2209 else
2210 {
2211 $showAction='<a class="line" href="'.$base."&ag_id=".$a_parent[$o]['ag_id'].'">';
2212 echo '<li '.$class.' >'.$showAction.$a_parent[$o]['str_date']." ".
2213 h($a_parent[$o]['sub_title']).'('.h($a_parent[$o]['action_ref']).')'.'</a>'." "
2214 .'</li>';
2215 }
2216 }
2217 echo '</ul>';
2218 }
2219
2220}
format_date($p_date, $p_from_format='YYYY-MM-DD', $p_to_format='DD.MM.YYYY')
format the date, when taken from the database the format is MM-DD-YYYY
Definition: ac_common.php:852
h2($p_string, $p_class="", $raw="")
Definition: ac_common.php:68
isNumber($p_int)
Definition: ac_common.php:215
th($p_string, $p_extra='', $raw='')
Definition: ac_common.php:58
isDate($p_date)
Definition: ac_common.php:236
noalyss_strlentrim($p_string)
Definition: ac_common.php:1549
record_log($p_message)
Record an error message into the log file of the server.
Definition: ac_common.php:1342
sql_string($p_string)
Fix the problem with the quote char for the database.
Definition: ac_common.php:511
td($p_string='', $p_extra='')
surround the string with td
Definition: ac_common.php:83
noalyss_trim($p_string)
Definition: ac_common.php:1545
$supl_hidden
global $g_user
if no group available , then stop
$retour
Definition: action.inc.php:27
$base
Definition: action.inc.php:56
else $num
$href
Definition: adm.inc.php:31
catch(Exception $exc) if(! $g_user->can_write_action($ag_id)) $r
$op
Definition: ajax_admin.php:38
h( $row[ 'oa_description'])
$url
catch(Exception $ex) $doc_type
global $doc
$_REQUEST['ac']
$fl ag_id
foreach($array as $idx=> $m) $w
$filter
$input_from id
Definition: balance.inc.php:63
$_GET['qcode']
$class
static fetch_all($ret)
wrapper for the function pg_fetch_all
static escape_string($p_string)
wrapper for the function pg_escape_string
static fetch_array($ret, $p_indice=0, $p_mode=PGSQL_ASSOC)
wrapper for the function pg_fetch_array
static num_row($ret)
wrapper for the function pg_num_rows
Description of class_default_menu.
static can_add_comment($p_id)
Returns true if we can add a comment , or false if it is not possible.
static is_enable_comment($p_document_type)
returns true if comment are available otherwise false
Class Document corresponds to the table document.
static id()
return the 'gDossier' value after a check
define Class fiche and fiche def, those class are using class attribut. When adding or modifing new c...
Definition: fiche.class.php:38
get_by_qcode($p_qcode=null, $p_all=true)
Retrieve a card thx his quick_code complete the object,, set the id member of the object or set it to...
Follow_Up Details are the details for an actions, it means the details of an order,...
verify()
Verify that data are correct.
static filter_by_tag($cn, $p_array=null)
Create a subquery to filter thanks the selected tag.
static display_saved_search()
display a form with the saved search
static show_action_add($pa_param)
Show a button for adding follow-up action, display the FORM.
view_list($query, $extra_sql="")
display list of followup , used with card
update()
Update the data into the database, the field ag_description could contain some HTML tags and must be ...
remove_operation_deprecated()
remove a related operation
display($p_view, $p_gen, $p_base, $retour="")
Display the object, the tags for the FORM are in the caller.
get_parent()
Return the first parent of the event tree, or -1 if not found.
export_csv($p_array)
export to CSV the query the p_array has
$action
$action string related action
static action_tag_remove($cn, $p_array)
static sql_security_filter($cn, $p_mode)
Create a filter based on the current user,.
static short_list($cn, $p_sql)
Show the result of a search in an inner windows, the result is limited to 25.
save()
Save the document and propose to save the generated document or to upload one, the data are included ...
static action_remove($cn, $p_array)
get_late()
get the action where the remind day is today
static SQL_list_action()
return the SQL to make a list of actions Colum :
export_csv_detail($p_array)
export to CSV the detailled actions (tags, comment, related operations...), it could be a query in $p...
save_short()
Add an event , with the minimum of informations, used in Dashboard and Scheduler.
$ag_id
Follow_Up.ag_id.
static action_set_state($cn, $p_array)
$operation
$operation string related operation
get_children($p_id)
Compute an array of the complete tree depending of $p_id.
__construct($p_cn, $p_id=0)
constructor
$aAction_detail
Array of action details.
display_short()
display a small form to enter a new event
display_parent($p_view, $p_base)
Display the list of parent of the current Follow_Up.
fromArray($p_array)
put an array in the variable member, the indice is the member name
myList($p_base, $p_filter="", $p_search="")
myList($p_base, $p_filter = "", $p_search = "") Show list of action by default if sorted on date
static get_all_operation($p_jr_id)
tag_remove($p_t_id)
remove the tags of the current objet normally used by ajax
static show_action_list($cn, $p_base)
show a list of documents
static create_query($cn, $p_array=null)
Get date from $_GET and create the sql stmt for the query.
get_today()
get the action where the remind day is today
tag_add($p_t_id)
show the tags of the current objet normally used by ajax.
display_children($p_view, $p_base)
Display the tree of childrens of the current Action + related parents.
tag_cell($p_view='UPD')
show the cell content in Display for the tags called also by ajax
static action_tag_clear($cn, $p_array)
get_last($p_limit)
return the last p_limit operation into an array, there is a security on user
insert_operation()
insert a related operation
static action_print($cn, $p_array)
tag_get()
get the tags of the current objet
static display_search($cn, $inner=false)
Display only a search box for searching an action.
static action_tag_add($cn, $p_array)
insert_action()
Insert a related action into the table action_gestion_related.
generate_document($md_id, $p_array)
generate the document and add it to the action
static get_to_string($array, $start="?")
transform $_GET data to string
static request_to_hidden(array $array)
transform $_REQUEST data to hidden
static filter_table($p_table_id, $p_col, $start_row)
filter the rows in a table and keep the colored row in alternance
static button($p_name, $p_value, $p_javascript="", $p_class="smallbutton")
static request_to_string($array, $start="?")
transform $_REQUEST data to string
static hidden($p_name, $p_value, $p_id="")
static array_to_hidden($array, $global_array)
transform request data to hidden
static submit($p_name, $p_value, $p_javascript="", $p_class="smallbutton")
manage the http input (get , post, request) and extract from an array
Html Input.
Input HTML for the card show buttons, in the file, you have to add card.js How to use :
Html Input.
static javascript_set_range($p_name)
Before calling this function , you must set a range with the function set_range.
Html Input.
Html Input : Input a date format dd.mm.yyyy The property title should be set to indicate what it is e...
Definition: idate.class.php:34
Html Input for uploading file, must be in a form with enctype="multipart/form-data".
Definition: ifile.class.php:31
Html Input.
This class handles only the numeric input, the input will call a javascript to change comma to period...
Definition: inum.class.php:42
Html Input , create a tag <SELECT> ... </SELECT> if readonly == true then display the label correspon...
Html Input.
Definition: ispan.class.php:32
Html Input.
Definition: itext.class.php:30
static trash($p_id, $p_javascript)
Display the icon of a trashbin.
Manage the CSV : manage files and write CSV record.
Description of class_syn_sort_table.
Tag operations or actions to linked them together.
Definition: tag.class.php:32
const NOTFOUND(!defined("SYSINFO_DISPLAY"))
Definition: constant.php:131
const ATTR_DEF_NAME
Definition: constant.php:216
const ATTR_DEF_FIRST_NAME
Definition: constant.php:238
const ATTR_DEF_QUICKCODE
Definition: constant.php:237
$_POST['ac']
Definition: do.php:310
$Res
$count
$SecUser db
$str
Definition: fiche.inc.php:91
print
Type of printing.
if( $delta< 0) elseif( $delta==0)
$ord
Definition: menu.inc.php:115
$table
Definition: menu.inc.php:103
$str_file
Definition: menu_detail.php:11
< tr id="row_currency">< td style="border:1px solid "><?=$default_currency-> get_code()?></td >< td style $iconcerned
for($i=0;$i< count($aHeading);$i++) $sort
navigation_bar($p_offset, $p_line, $p_size=0, $p_page=1, $p_javascript="")
Create a navigation_bar (pagesize)
Definition: user_common.php:76
$content
Definition: xml.php:17