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