Visit::getImmutableAcquisitionDate()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
nc 1
nop 0
dl 0
loc 2
c 0
b 0
f 0
cc 1
rs 10
1
<?php
2
/**
3
 Copyright (C) 2018-2020 KANOUN Salim
4
 This program is free software; you can redistribute it and/or modify
5
 it under the terms of the Affero GNU General Public v.3 License as published by
6
 the Free Software Foundation;
7
 This program is distributed in the hope that it will be useful,
8
 but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
 Affero GNU General Public Public for more details.
11
 You should have received a copy of the Affero GNU General Public Public along
12
 with this program; if not, write to the Free Software Foundation, Inc.,
13
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14
 */
15
16
/**
17
 * Access visit data
18
 */
19
20
class Visit {
21
    
22
	private $linkpdo;
23
	public $id_visit;
24
	public $creatorName;
25
	public $creationDate;
26
	public $qcStatus;
27
	public $reviewStatus;
28
	public $statusDone;
29
	public $reasonForNotDone;
30
	public $uploadStatus;
31
	public $uploadDate;
32
	public $uploaderUsername;
33
	public $acquisitionDate;
34
	public $stateInvestigatorForm;
35
	public $stateQualityControl;
36
	public $formQualityControl;
37
	public $imageQualityControl;
38
	public $newSeriesUpload;
39
	public $investigatorFormIsCorrected;
40
	public $otherCorrectiveAction;
41
	public $correctiveActionDecision;
42
	public $formQualityComment;
43
	public $imageQualityComment;
44
	public $controllerUsername;
45
	public $controlDate;
46
	public $correctiveActionUsername;
47
	public $correctiveActionDate;
48
	public $visitTypeId;
49
	public $study;
50
	public $patientCode;
51
	public $visitType;
52
	public $reviewAvailable;
53
	public $reviewConclusionDate;
54
	public $reviewConclusion;
55
	public $reviewTargetLesions;
56
	public $lastReminderUpload;
57
	public $deleted;
58
    
59
	public $studyDicomObject;
60
	public $visitGroupObject;
61
    
62
	const QC_NOT_DONE="Not Done";
63
	const QC_ACCEPTED="Accepted";
64
	const QC_REFUSED="Refused";
65
	const QC_WAIT_DEFINITVE_CONCLUSION="Wait Definitive Conclusion";
66
	const QC_CORRECTIVE_ACTION_ASKED="Corrective Action Asked";
67
    
68
	const LOCAL_FORM_NOT_DONE="Not Done";
69
	const LOCAL_FORM_DRAFT="Draft";
70
	const LOCAL_FORM_DONE="Done";
71
    
72
	const DONE="Done";
73
	const NOT_DONE="Not Done";
74
    
75
	const UPLOAD_PROCESSING="Processing";
76
77
	const REVIEW_NOT_DONE='Not Done';
78
	const REVIEW_ONGOING='Ongoing';
79
	const REVIEW_WAIT_ADJUDICATION='Wait Adjudication';
80
	const REVIEW_DONE='Done';
81
    
82
	public function __construct($id_visit, PDO $linkpdo) {
83
		$this->linkpdo=$linkpdo;
84
		$this->id_visit=$id_visit;
85
        
86
		$this->refreshVisitData();
87
        
88
	}
89
    
90
	/**
91
	 * Refresh this current object proprieties from database
92
	 */
93
	private function refreshVisitData() {
94
        
95
		$visitQuery=$this->linkpdo->prepare('SELECT * FROM visits WHERE id_visit=:idVisit');
96
        
97
		$visitQuery->execute(array('idVisit' => $this->id_visit));
98
		$visitDbData=$visitQuery->fetch(PDO::FETCH_ASSOC);
99
        
100
		$this->creatorName=$visitDbData['creator_name'];
101
		$this->creationDate=$visitDbData['creation_date'];
102
        
103
		$this->qcStatus=$visitDbData['state_quality_control'];
104
		$this->controllerUsername=$visitDbData['controller_username'];
105
		$this->controlDate=$visitDbData['control_date'];
106
        
107
		$this->formQualityControl=$visitDbData['form_quality_control'];
108
		$this->imageQualityControl=$visitDbData['image_quality_control'];
109
		$this->formQualityComment=$visitDbData['form_quality_comment'];
110
		$this->imageQualityComment=$visitDbData['image_quality_comment'];
111
        
112
		$this->statusDone=$visitDbData['status_done'];
113
		$this->reasonForNotDone=$visitDbData['reason_for_not_done'];
114
		$this->visitTypeId=$visitDbData['visit_type_id'];
115
		$this->patientCode=$visitDbData['patient_code'];
116
        
117
		$this->uploadStatus=$visitDbData['upload_status'];
118
		$this->acquisitionDate=$visitDbData['acquisition_date'];
119
		$this->stateInvestigatorForm=$visitDbData['state_investigator_form'];
120
		$this->stateQualityControl=$visitDbData['state_quality_control'];
121
122
		$this->newSeriesUpload=$visitDbData['corrective_action_new_upload'];
123
		$this->investigatorFormIsCorrected=$visitDbData['corrective_action_investigator_form'];
124
		$this->otherCorrectiveAction=$visitDbData['corrective_action_other'];
125
		$this->correctiveActionDecision=$visitDbData['corrective_action_decision'];
126
		$this->reviewAvailable=$visitDbData['review_available'];
127
		$this->reviewStatus=$visitDbData['review_status'];
128
		$this->reviewConclusionDate=$visitDbData['review_conclusion_date'];
129
		$this->reviewTargetLesions=$visitDbData['review_target_lesions'];
130
		$this->reviewConclusion=$visitDbData['review_conclusion_value'];
131
		$this->correctiveActionUsername=$visitDbData['corrective_action_username'];
132
		$this->correctiveActionDate=$visitDbData['corrective_action_date'];
133
		$this->deleted=$visitDbData['deleted'];
134
		$this->lastReminderUpload=$visitDbData['last_reminder_upload'];
135
        
136
137
		//Get VisitType detail
138
		$this->visitTypeObject=new Visit_Type($this->linkpdo, $this->visitTypeId);
0 ignored issues
show
Bug Best Practice introduced by
The property visitTypeObject does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
139
		$this->visitType=$this->visitTypeObject->name;
140
		//Get VisitGroup details
141
		$this->visitGroupObject=new Visit_Group($this->linkpdo, $this->visitTypeObject->groupId);
142
		$this->study=$this->visitGroupObject->studyName;
143
        
144
		if ($this->uploadStatus == Visit::DONE) {
145
			$studyDicomObject=$this->getStudyDicomDetails();
146
			$this->uploaderUsername=$studyDicomObject->uploaderUsername;
147
			$this->uploadDate=$studyDicomObject->uploadDate;
148
		}
149
        
150
	}
151
152
	public function getImmutableAcquisitionDate() {
153
		return new DateTimeImmutable($this->acquisitionDate);
154
	}
155
156
	/**
157
	 * return Patient Object of this visit
158
	 * @return Patient
159
	 */
160
	public function getPatient() {
161
		return new Patient($this->patientCode, $this->linkpdo);
162
	}
163
    
164
	/**
165
	 * Update upload status of this visit
166
	 * if upload set to done, eventually skip local form/ QC and trgger upload notification method
167
	 * @param string $uploadStatus
168
	 * @param string $username
169
	 */
170
	public function changeUploadStatus(string $uploadStatus, ?string $username=null) {
171
172
		$changeStatusUpload=$this->linkpdo->prepare('UPDATE visits SET upload_status= :statusDone WHERE id_visit = :idvisit');
173
		$changeStatusUpload->execute(array(
174
			'statusDone'=>$uploadStatus,
175
			'idvisit'=> $this->id_visit)
176
			);
177
178
		//Update status in this object
179
		$this->refreshVisitData();
180
        
181
		if ($uploadStatus == Visit::DONE) {
182
			$this->skipQcIfNeeded();
183
			$this->sendUploadedVisitEmailToController($username);
184
		}
185
	}
186
187
	public function updateLastReminderUpload() {
188
189
		$changeReminderUpload=$this->linkpdo->prepare('UPDATE visits SET last_reminder_upload= :lastReminderDateTime WHERE id_visit = :idvisit');
190
		$changeReminderUpload->execute(array(
191
			'lastReminderDateTime'=> date("Y-m-d H:i:s"),
192
			'idvisit'=> $this->id_visit)
193
			);
194
	}
195
    
196
	/**
197
	 * If Form and / or QC not needed skip these step by writing done in database for each status
198
	 */
199
	private function skipQcIfNeeded() {
200
        
201
		$visitType=$this->getVisitCharacteristics();
202
        
203
		if (!$visitType->localFormNeeded || !$visitType->qcNeeded) {
204
205
			//If QC Not needed validate it
206
			if (!$visitType->qcNeeded) {
207
				$this->editQc(true, true, null, null, Visit::QC_ACCEPTED, null);
208
                
209
			}
210
			//If form Not Needed put investigator form to Done
211
			if (!$visitType->localFormNeeded) {
212
				$this->changeVisitStateInvestigatorForm(Visit::DONE);
213
			}
214
            
215
		}
216
        
217
	}
218
    
219
	/**
220
	 * Reset QC and corrective action of the visit
221
	 */  
222
	public function resetQC() {
223
		$update=$this->linkpdo->prepare('UPDATE visits
224
								SET state_quality_control = "Not Done",
225
								controller_username=NULL,
226
								control_date=NULL,
227
								image_quality_control=0,
228
								form_quality_control=0,
229
								image_quality_comment=NULL,
230
								form_quality_comment=NULL,
231
								corrective_action_investigator_form=NULL,
232
								corrective_action_date=NULL,
233
								corrective_action_username=NULL,
234
								corrective_action_other=NULL,
235
								corrective_action_decision=NULL,
236
								corrective_action_new_upload=0
237
								WHERE (id_visit = :id_visit AND deleted=0)');
238
        
239
		$update->execute(array('id_visit' => $this->id_visit));
240
		//Set visit to not review available (include a refresh of the current object)
241
        $this->changeReviewAvailability(false);
242
        
243
	}
244
    
245
	/**
246
	 * Return visit type object related to this visit
247
	 * @return Visit_Type
248
	 */
249
	public function getVisitCharacteristics() : Visit_Type {
250
		return $this->visitTypeObject;  
251
	}
252
253
	/**
254
	 * Return visit group object related to this visit
255
	 */
256
	public function getVisitGroup() : Visit_Group {
257
		return $this->visitGroupObject;
258
	}
259
    
260
	/**
261
	 * Retrun series Orthanc ID of this visit
262
	 * @param bool $deletedSeries
263
	 * @return String[]
264
	 */
265
	public function getSeriesOrthancID(bool $deletedSeries=false) {
266
        
267
		$seriesObjects=$this->getSeriesDetails($deletedSeries);
268
        
269
		$orthancSeriesIDs=[];
270
        
271
		foreach ($seriesObjects as $seriesObject) {
272
				$orthancSeriesIDs[]=$seriesObject->seriesOrthancID;
273
		}
274
        
275
		return $orthancSeriesIDs;
276
        
277
	}
278
    
279
	/**
280
	 * Return study details of this visit (only one if calling non deleted)
281
	 * @param bool $deletedStudies
282
	 * @return Study_Details|Study_Details[]
283
	 */
284
	public function getStudyDicomDetails(bool $deletedStudies=false) {
285
    	
286
		$idFetcher=$this->linkpdo->prepare("SELECT Study_Orthanc_ID FROM orthanc_studies
287
										WHERE deleted=:deleted
288
										AND id_visit=:idVisit");
289
		$idFetcher->execute(array(
290
				"idVisit" => $this->id_visit,
291
				 "deleted"=>intval($deletedStudies)
292
		));
293
294
		$orthancStudyIDs=$idFetcher->fetchAll(PDO::FETCH_COLUMN);
295
296
		$studyDetails=[];
297
		foreach ($orthancStudyIDs as $studyOrthancId) {
298
			$studyDetails[]=new Study_Details($studyOrthancId, $this->linkpdo);
299
		}
300
    	
301
		if (!$deletedStudies && !empty($studyDetails)) {
302
			return $studyDetails[0];
303
		}
304
    	
305
		return $studyDetails;
306
    	
307
	}
308
    
309
	/**
310
	 * Return series details of this visit
311
	 * @param bool $deletedSeries
312
	 * @return Series_Details[]
313
	 */
314
	public function getSeriesDetails(bool $deletedSeries=false) {
315
        
316
		$orthancSeriesObjects=[];
317
        
318
		$studyDicomObject=$this->getStudyDicomDetails();
319
        
320
		if (!empty($studyDicomObject)) {
321
			$childSeriesObjects=$studyDicomObject->getChildSeries();
322
			foreach ($childSeriesObjects as $seriesObject) {
323
				if ($seriesObject->deleted == $deletedSeries) {
324
					$orthancSeriesObjects[]=$seriesObject;
325
				}
326
			}
327
		}
328
        
329
		return $orthancSeriesObjects;
330
        
331
	}
332
    
333
    
334
	/**
335
	 * Return reviews (local or reviewer) of this visit
336
	 * @param bool $local
337
	 * @return Review|Review[]
338
	 */
339
	public function getReviewsObject(bool $local, bool $onlyValidated=false) {
340
        if(!$onlyValidated){
341
			$reviewQuery=$this->linkpdo->prepare('SELECT id_review FROM reviews WHERE id_visit=:idVisit AND deleted=0 AND is_local=:isLocal');
342
        
343
		}else{
344
			$reviewQuery=$this->linkpdo->prepare('SELECT id_review FROM reviews WHERE id_visit=:idVisit AND deleted=0 AND validated=1 AND is_local=:isLocal');
345
        
346
		}
347
		
348
		$reviewQuery->execute(array('idVisit' => $this->id_visit, 'isLocal'=>intval($local)));
349
		$reviewResults=$reviewQuery->fetchAll(PDO::FETCH_COLUMN);
350
351
		if (empty($reviewResults)) {
352
			throw new Exception('No Review Found');
353
		}
354
        
355
		if ($local && sizeof($reviewResults) == 1) {
356
			return new Review($reviewResults[0], $this->linkpdo);
357
		}
358
		//Else put review object in an Array
359
		$reviewObjects=[];
360
		foreach ($reviewResults as $reviewID) {
361
			$reviewObjects[]=new Review($reviewID, $this->linkpdo);
362
		}
363
        
364
		return $reviewObjects;
365
        
366
	}
367
    
368
    
369
	/**
370
	 * return the existing reviewer review for this visit
371
	 * @throws Exception if not available review for reviewer
372
	 */
373
	public function queryExistingReviewForReviewer($username) {
374
        
375
		$reviewsObjects=$this->getReviewsObject(false);
376
		$filteredReview=array_filter($reviewsObjects, function($review) use ($username) {
377
			if ($review->username == $username) {
378
				return true;
379
			}else {
380
				return false;
381
			}
382
		});
383
		$filteredReview=array_values($filteredReview);
384
		if (sizeof($filteredReview) == 1) return $filteredReview[0];
385
		else throw new Exception('No review for reviwer');
386
387
	}
388
389
	/**
390
	 * Check that no activated visit exsits for this visit
391
	 * @return boolean
392
	 */
393
	private function isNoOtherActivatedVisit() {
394
		$visitQuery=$this->linkpdo->prepare('SELECT id_visit FROM visits
395
                                        WHERE visit_type_id=:visitTypeID AND patient_code=:patientCode AND deleted=0;
396
                                    ');
397
		$visitQuery->execute(array('visitTypeID' => $this->visitTypeId,
398
				'patientCode'=>$this->patientCode));
399
    	
400
		$dataVisits=$visitQuery->fetchAll(PDO::FETCH_COLUMN);
401
    	
402
		if (empty($dataVisits)) {
403
			return true;
404
		}else {
405
			return false;
406
		}
407
    	
408
	}
409
    
410
	/**
411
	 * Update quality control data
412
	 * @param bool $formAccepted
413
	 * @param bool $imageAccepted
414
	 * @param $formComment
415
	 * @param $imageComment
416
	 * @param $controlDecision
417
	 * @param $usernameController
418
	 */
419
	public function editQc(bool $formAccepted, bool $imageAccepted, $formComment, $imageComment, $controlDecision, $usernameController) {
420
        
421
		$req_update=$this->linkpdo->prepare('UPDATE visits
422
                                        SET form_quality_control = :form,
423
                                        image_quality_control = :image,
424
                                        form_quality_comment = :form_comment,
425
                                        image_quality_comment = :image_comment,
426
                                        state_quality_control= :decision,
427
                                        controller_username=:username,
428
                                        control_date=:date
429
                                        WHERE id_visit = :id_visit');
430
        
431
		$req_update->execute(array(
432
			'id_visit' => $this->id_visit,
433
			'form' => intval($formAccepted),
434
			'image' => intval($imageAccepted),
435
			'form_comment' => $formComment,
436
			'image_comment' => $imageComment,
437
			'decision' =>$controlDecision,
438
			'username'=>$usernameController,
439
			'date'=>date("Y-m-d H:i:s")
440
		));
441
        
442
		$this->refreshVisitData();
443
        
444
		if ($controlDecision == Visit::QC_ACCEPTED) {
445
			if ($this->getVisitCharacteristics()->reviewNeeded) {
446
				//If review needed make it available for reviewers
447
				$this->changeReviewAvailability(true);
448
			}else if( ! $this->getVisitCharacteristics()->qcNeeded) {
449
				//The visit is QC accepted and will not go further as Review is not needed
450
				//Inform supervisors that the visit is well recieved
451
				//Do this only if QC is not needed as supervisor will get QC notification otherwise (avoid dual mail)
452
				$this->sendUploadNotificationToSupervisor();
453
			}
454
		}else if ($controlDecision == Visit::QC_REFUSED){
455
			$this->changeReviewAvailability(false);
456
		}
457
        
458
	}
459
    
460
	/**
461
	 * update corrective action data
462
	 * @param bool $newSeries
463
	 * @param bool $formCorrected
464
	 * @param bool $correctiveActionDecision
465
	 * @param string $otherComment
466
	 * @param string $username
467
	 */
468
	public function setCorrectiveAction(bool $newSeries, bool $formCorrected, bool $correctiveActionDecision, string $otherComment, string $username) {
469
		//Write in the database
470
		$req_update=$this->linkpdo->prepare('UPDATE visits
471
                                          SET corrective_action_username=:username,
472
											  corrective_action_date=:date,
473
											  corrective_action_new_upload = :new_series,
474
                                              corrective_action_other = :other_comment,
475
                                              corrective_action_investigator_form = :invest_form,
476
											  corrective_action_decision=:corrective_action,
477
											  state_quality_control="Wait Definitive Conclusion"
478
                                          WHERE visits.id_visit = :id_visit' );
479
        
480
		$req_update->execute(array(
481
			'username'=>$username,
482
			'date'=>date("Y-m-d H:i:s"),
483
			'id_visit' => $this->id_visit,
484
			'new_series' => intval($newSeries),
485
			'other_comment' => $otherComment,
486
			'invest_form' => intval($formCorrected),
487
			'corrective_action'=>intval($correctiveActionDecision)
488
		));
489
        
490
		$this->refreshVisitData();
491
	}
492
    
493
	/**
494
	 * Delete / reactivate visit
495
	 * @param bool $delete
496
	 * @return boolean
497
	 */
498
	public function changeDeletionStatus(bool $delete) {
499
    	
500
		//If reactivation of Visit check that not other same activated visit type exist in the DB for this patient
501
		if ($delete == false && !$this->isNoOtherActivatedVisit()) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
502
			return false;
503
		}
504
    	
505
		$connecter=$this->linkpdo->prepare('UPDATE visits SET deleted=:deletion WHERE id_visit = :idvisit');
506
		$connecter->execute(array(
507
			"idvisit" => $this->id_visit,
508
			"deletion"=>intval($delete)
509
		));
510
        
511
		$this->refreshVisitData();
512
        
513
		return true;
514
	}
515
    
516
	/**
517
	 * Update the Local Investigator Form status
518
	 * If Done inform controller that visit await QC (sent if Form and upload done and QC not done)
519
	 * @param string $status see visit constant (Not Done, Draft or Done)
520
	 * @param string $username
521
	 */
522
	public function changeVisitStateInvestigatorForm(string $status, ?string $username=null) {
523
		//Update Visit table
524
		$update=$this->linkpdo->prepare('UPDATE visits SET
525
                                        state_investigator_form = :formStatus WHERE id_visit = :id_visit');
526
        
527
		$update->execute(array('formStatus'=>$status, 'id_visit' => $this->id_visit));
528
        
529
		//Update data in this object
530
		$this->refreshVisitData();
531
        
532
		if ($status == Visit::LOCAL_FORM_DONE) {
533
			$this->sendUploadedVisitEmailToController($username);
534
		}
535
	}
536
    
537
	/**
538
	 * Update the review availability status according to boolean argument
539
	 * @param boolean $available
540
	 */
541
	public function changeReviewAvailability(bool $available) {
542
		$dbStatus=$this->linkpdo->prepare('UPDATE visits SET review_available =:available WHERE visits.id_visit = :idVisit');
543
		$dbStatus->execute(array('idVisit'=>$this->id_visit, 'available'=>intval($available)));
544
        
545
		$this->refreshVisitData();
546
        
547
		if ($available) {
548
			//If available notify reviewers of this study by email
549
			$this->sendAvailableReviewMail();
550
		}
551
	}
552
    
553
	/**
554
	 * Update review conclusion
555
	 * @param string $reviewStatus
556
	 * @param $conclusionValue
557
	 */
558
	public function changeVisitValidationStatus(string $reviewStatus, $conclusionValue=null) {
559
        
560
		if ($reviewStatus == Visit::DONE) {
561
			$date=date("Y-m-d H:i:s");
562
		}
563
        
564
		$dbStatus=$this->linkpdo->prepare('UPDATE visits SET 
565
                                            review_status = :conclusionStatus, 
566
                                            review_conclusion_value=:conclusionValue, 
567
                                            review_conclusion_date=:conclusionDate 
568
                                            WHERE visits.id_visit = :id_visit');
569
		$dbStatus->execute(array(
570
			'id_visit' => $this->id_visit,
571
			'conclusionStatus'=> $reviewStatus,
572
			'conclusionDate'=>isset($date) ? $date : null,
573
			'conclusionValue'=>isset($conclusionValue) ? $conclusionValue : null
574
		));
575
        
576
		$this->refreshVisitData();
577
        
578
	}
579
580
	/**
581
	 * Store final target lesions in database
582
	 */
583
	public function changeReviewTargetLesions(?array $targetLesions) : void {
584
		$dbStatus=$this->linkpdo->prepare('UPDATE visits SET 
585
                                            review_target_lesions = :reviewTargetLesions
586
                                            WHERE visits.id_visit = :id_visit');
587
		$dbStatus->execute(array(
588
			'id_visit' => $this->id_visit,
589
			'reviewTargetLesions'=> json_encode($targetLesions),
590
		));
591
        
592
		$this->refreshVisitData();
593
	}
594
595
	/**
596
	 * Get the final target lesion for this visit
597
	 */
598
	public function getReviewTargetLesionsArray() {
599
		return $this->reviewTargetLesions !=null ? json_decode($this->reviewTargetLesions, true) : null;
600
	}
601
    
602
	/**
603
	 * Return the object sepecific instance for this visit to manage users form data
604
	 * @param boolean $local
605
	 * @param string $username
606
	 * @return Form_Processor
607
	 */
608
	public function getFromProcessor(bool $local, string $username) {
609
		//Destination of the specific post processing POO
610
		$modality=$this->visitGroupObject->groupModality;
611
		$specificObjectFile=$_SERVER["DOCUMENT_ROOT"].'/data/form/'.$this->study.'/Poo/'.$modality."_".$this->study."_".$this->visitType.".php";
612
        
613
		$formProcessor=null;
0 ignored issues
show
Unused Code introduced by
The assignment to $formProcessor is dead and can be removed.
Loading history...
614
        
615
		if (is_file($specificObjectFile)) {
616
			require_once($specificObjectFile);
617
			$objectName=$modality."_".$this->study."_".$this->visitType;
618
			$formProcessor=new $objectName($this, $local, $username, $this->linkpdo);
619
		}else {
620
			throw new Exception('Missing From Processor for this visit');
621
		}
622
    	
623
		return $formProcessor;
624
    	
625
	}
626
    
627
	/**
628
	 * Send uploaded confirmation to supervisors and uploader
629
	 * will send email only if uploaded dicom and local form done and QC Not Done
630
	 * @param string $username
631
	 * @return boolean
632
	 */
633
	private function sendUploadedVisitEmailToController(?string $username) {
634
        
635
		if ($this->uploadStatus == Visit::DONE 
636
			&& $this->stateInvestigatorForm == Visit::DONE 
637
			&& $this->stateQualityControl == Visit::NOT_DONE) {
638
			//Inform Controllers that Visit is uploaded and awaiting QC
639
			$emailObject=new Send_Email($this->linkpdo);
640
			$emailObject->addGroupEmails($this->study, User::CONTROLLER)
641
						->addGroupEmails($this->study, User::MONITOR)
642
						->addGroupEmails($this->study, User::SUPERVISOR);
643
			
644
			if ($username != null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $username of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
645
				$emailObject->addEmail($emailObject->getUserEmails($username));
646
			}
647
			$emailObject->sendUploadedVisitMessage($this->study, $this->patientCode, $this->visitType);
648
649
			return true;
650
            
651
		}else {
652
			return false;
653
		}
654
	}
655
    
656
	/**
657
	 * Send emails to reviewers saying the visit is available for review
658
	 */
659
	private function sendAvailableReviewMail() {
660
		$emailObject=new Send_Email($this->linkpdo);
661
		$emailObject->addEmailsReviewerWithNoReview($this->study, $this->id_visit);
662
		$emailObject->sendReviewReadyMessage($this->study, $this->patientCode, $this->visitType);    
663
	}
664
    
665
	/**
666
	 * Send emails to supervisors when visit recieved and QC done and does not need review process
667
	 */
668
	private function sendUploadNotificationToSupervisor() {
669
		$emailObject=new Send_Email($this->linkpdo);
670
		$emailObject->addGroupEmails($this->study, User::SUPERVISOR);
671
		$emailObject->sendUploadedVisitMessage($this->study, $this->patientCode, $this->visitType);     
672
	}
673
    
674
	/**
675
	 * Return study object associated with this visit
676
	 * @return Study
677
	 */
678
	public function getParentStudyObject() {
679
		return new Study($this->study, $this->linkpdo);
680
	}
681
    
682
	/**
683
	 * Return if the review is awaiting a review form for a specific reviewer
684
	 * @param string $username
685
	 * @return boolean
686
	 */
687
	public function isAwaitingReviewForReviewerUser(string $username) {
688
689
		try {
690
			$reviewObject=$this->queryExistingReviewForReviewer($username);
691
		}catch (Exception $e) {
692
			//User does not have any review, so visit still awaiting it's review
693
			return true;
694
		}
695
696
		//If found look at validation status.
697
		//not awaiting review if form already validated
698
		if ($reviewObject->validated) {
699
			return false;
700
		}else {
701
			return true;
702
		}
703
        
704
705
	}
706
    
707
	/**
708
	 * Create a new visit
709
	 * @param $visitName
710
	 * @param $study
711
	 * @param $patientCode
712
	 * @param $statusDone
713
	 * @param $reasonNotDone
714
	 * @param $acquisitionDate
715
	 * @param $username
716
	 * @param $linkpdo
717
	 * @return string
718
	 */
719
	public static function createVisit($visitName, $visitGroupId, $patientCode, $statusDone, $reasonNotDone, $acquisitionDate, $username, PDO $linkpdo) {
720
        
721
		$visitType=Visit_Type::getVisitTypeByName($visitGroupId, $visitName, $linkpdo);
722
        
723
		//Add visit verifying that this visit doesn't already have an active visite registered
724
		$insertion=$linkpdo->prepare('INSERT INTO visits(visit_type_id, status_done, patient_code, reason_for_not_done, acquisition_date, creator_name, creation_date)
725
      										SELECT :visitTypeId, :status_done, :patient_code, :reason, :acquisition_date, :creator_name, :creation_date FROM DUAL
726
											WHERE NOT EXISTS (SELECT id_visit FROM visits WHERE patient_code=:patient_code AND visit_type_id=:visitTypeId AND deleted=0) ' );
727
        
728
		$insertion->execute(array(
729
			'visitTypeId'=>$visitType->id,
730
			'status_done' => $statusDone,
731
			'patient_code' => $patientCode,
732
			'reason' => $reasonNotDone,
733
			'acquisition_date' => $acquisitionDate,
734
			'creator_name' => $username,
735
			'creation_date' => date("Y-m-d H:i:s")
736
		));
737
        
738
		$createdId=$linkpdo->lastInsertId();
739
        
740
		return new Visit($createdId, $linkpdo);
0 ignored issues
show
Bug Best Practice introduced by
The expression return new Visit($createdId, $linkpdo) returns the type Visit which is incompatible with the documented return type string.
Loading history...
741
	}
742
    
743
}