Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
88.75% |
505 / 569 |
|
80.43% |
37 / 46 |
CRAP | |
0.00% |
0 / 1 |
Process | |
88.75% |
505 / 569 |
|
80.43% |
37 / 46 |
162.32 | |
0.00% |
0 / 1 |
getQueryNewProcessId | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 | |||
getLockProcessId | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
addJoin | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
addJoinAvailability | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 | |||
addJoinScope | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
1 | |||
getEntityMapping | |
100.00% |
61 / 61 |
|
100.00% |
1 / 1 |
1 | |||
addCountValue | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
addConditionHasTelephone | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 | |||
addConditionProcessDeleteInterval | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
1 | |||
addConditionProcessExpiredIPTimeStamp | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 | |||
addConditionProcessReminderInterval | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
1 | |||
addConditionProcessMailReminder | |
100.00% |
44 / 44 |
|
100.00% |
1 / 1 |
1 | |||
addConditionProcessId | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
1 | |||
addConditionProcessIdFollow | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 | |||
addConditionIgnoreSlots | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 | |||
addConditionScopeId | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 | |||
addConditionQueueNumber | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
addConditionWorkstationId | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 | |||
addConditionTime | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
addConditionTimeframe | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
addConditionAuthKey | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
1 | |||
addConditionAssigned | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
addConditionStatus | |
97.18% |
69 / 71 |
|
0.00% |
0 / 1 |
16 | |||
addConditionIsReserved | |
100.00% |
12 / 12 |
|
100.00% |
1 / 1 |
1 | |||
addConditionSearch | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
2 | |||
addConditionName | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
2 | |||
addConditionMail | |
62.50% |
5 / 8 |
|
0.00% |
0 / 1 |
2.21 | |||
addConditionCustomTextfield | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
6 | |||
addConditionAmendment | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
addConditionRequestId | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
1 | |||
addConditionDeallocate | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
1 | |||
addValuesNewProcess | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
2 | |||
addValuesUpdateProcess | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
3 | |||
addValuesIPAdress | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
addValuesFollowingProcessData | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
3 | |||
addValuesAppointmentData | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
2 | |||
addValuesScopeData | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
addValuesStatusData | |
87.50% |
28 / 32 |
|
0.00% |
0 / 1 |
14.38 | |||
addValuesClientData | |
95.24% |
20 / 21 |
|
0.00% |
0 / 1 |
16 | |||
addProcessingTimeData | |
30.43% |
14 / 46 |
|
0.00% |
0 / 1 |
79.98 | |||
addValuesQueueData | |
100.00% |
16 / 16 |
|
100.00% |
1 / 1 |
11 | |||
addValuesWaitingTimeData | |
33.33% |
3 / 9 |
|
0.00% |
0 / 1 |
16.67 | |||
addValuesWayTimeData | |
60.00% |
3 / 5 |
|
0.00% |
0 / 1 |
3.58 | |||
postProcess | |
100.00% |
31 / 31 |
|
100.00% |
1 / 1 |
7 | |||
removeDuplicates | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
addRequiredJoins | |
100.00% |
12 / 12 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | |
3 | namespace BO\Zmsdb\Query; |
4 | |
5 | /** |
6 | * @SuppressWarnings(Methods) |
7 | * @SuppressWarnings(Complexity) |
8 | */ |
9 | class Process extends Base implements MappingInterface |
10 | { |
11 | /** |
12 | * * @var String TABLE mysql table reference |
13 | */ |
14 | const TABLE = 'buerger'; |
15 | |
16 | const QUERY_DEREFERENCED = "UPDATE `buerger` process LEFT JOIN `standort` s USING(StandortID) |
17 | SET |
18 | process.Anmerkung = ?, |
19 | process.custom_text_field = ?, |
20 | process.StandortID = 0, |
21 | process.AbholortID = 0, |
22 | process.Abholer = 0, |
23 | process.Name = 'dereferenced', |
24 | process.IPadresse = '', |
25 | process.IPTimeStamp = 0, |
26 | process.NutzerID = 0, |
27 | process.vorlaeufigeBuchung = 0, |
28 | process.bestaetigt = 1, |
29 | process.absagecode = 'deref!0', |
30 | process.EMail = '', |
31 | process.NutzerID = 0 |
32 | WHERE |
33 | (process.BuergerID = ? AND process.absagecode = ?) |
34 | OR process.istFolgeterminvon = ? |
35 | "; |
36 | |
37 | const QUERY_CANCELED = " |
38 | UPDATE `buerger` process LEFT JOIN `standort` s USING(StandortID) |
39 | SET |
40 | process.Anmerkung = CONCAT( |
41 | 'Abgesagter Termin gebucht am: ', |
42 | FROM_UNIXTIME(process.IPTimeStamp,'%d.%m.%Y, %H:%i'),' Uhr | ', |
43 | IFNULL(process.Anmerkung,'') |
44 | ), |
45 | process.Name = '(abgesagt)', |
46 | process.IPadresse = '', |
47 | process.IPTimeStamp = :canceledTimestamp + (IFNULL(s.loeschdauer, 15) * 60), |
48 | process.NutzerID = 0, |
49 | process.vorlaeufigeBuchung = 1, |
50 | process.absagecode = RIGHT(MD5(CONCAT(process.absagecode, 'QUERY_CANCELED')), 4) |
51 | WHERE |
52 | (process.BuergerID = :processId AND process.absagecode = :authKey) |
53 | OR process.istFolgeterminvon = :processId |
54 | "; |
55 | |
56 | const QUERY_DELETE = "DELETE FROM `buerger` |
57 | WHERE |
58 | BuergerID = ? |
59 | OR istFolgeterminvon = ? |
60 | "; |
61 | |
62 | const QUERY_REASSIGN_PROCESS_CREDENTIALS = "UPDATE `buerger` process |
63 | SET |
64 | process.BuergerID = :newProcessId, |
65 | process.absagecode = :newAuthKey |
66 | WHERE BuergerID = :processId |
67 | "; |
68 | |
69 | const QUERY_REASSIGN_PROCESS_REQUESTS = "UPDATE `buergeranliegen` requests |
70 | SET |
71 | requests.BuergerID = :newProcessId |
72 | WHERE BuergerID = :processId |
73 | "; |
74 | |
75 | const QUERY_REASSIGN_FOLLWING_PROCESS = "UPDATE `buerger` process |
76 | SET process.istFolgeterminvon = :newProcessId |
77 | WHERE istFolgeterminvon = :processId |
78 | "; |
79 | |
80 | const QUERY_UPDATE_FOLLOWING_PROCESS = "UPDATE buerger |
81 | SET vorlaeufigeBuchung = :reserved |
82 | WHERE istFolgeterminvon = :processID |
83 | "; |
84 | |
85 | public function getQueryNewProcessId() |
86 | { |
87 | $random = rand(20, 999); |
88 | return 'SELECT pseq.processId AS `nextid` |
89 | FROM process_sequence pseq |
90 | WHERE pseq.processId = ( |
91 | SELECT ps.processID FROM `process_sequence` ps LEFT JOIN `' . self::getTablename() . '` p |
92 | ON ps.processId = p.BuergerID |
93 | WHERE p.`BuergerID` IS NULL |
94 | LIMIT ' . $random . ',1) |
95 | FOR UPDATE'; |
96 | } |
97 | |
98 | public function getLockProcessId() |
99 | { |
100 | return 'SELECT p.`BuergerID` FROM `' . self::getTablename() . '` p WHERE p.`BuergerID` = :processId FOR UPDATE'; |
101 | } |
102 | |
103 | public function addJoin() |
104 | { |
105 | return [ |
106 | $this->addJoinAvailability(), |
107 | $this->addJoinScope(), |
108 | ]; |
109 | } |
110 | |
111 | /** |
112 | * Add Availability to the dataset |
113 | */ |
114 | protected function addJoinAvailability() |
115 | { |
116 | $this->leftJoin( |
117 | new Alias(Availability::TABLE, 'availability'), |
118 | Availability::getJoinExpression('`process`', '`availability`') |
119 | ); |
120 | $joinQuery = new Availability($this, $this->getPrefixed('appointments__0__availability__')); |
121 | return $joinQuery; |
122 | } |
123 | |
124 | /** |
125 | * Add Scope to the dataset |
126 | */ |
127 | protected function addJoinScope() |
128 | { |
129 | $this->leftJoin( |
130 | new Alias(Scope::TABLE, 'scope'), |
131 | self::expression( |
132 | 'IF(`process`.`AbholortID`, |
133 | `process`.`AbholortID`, |
134 | `process`.`StandortID` |
135 | )' |
136 | ), |
137 | '=', |
138 | 'scope.StandortID' |
139 | ); |
140 | $joinQuery = new Scope($this, $this->getPrefixed('scope__')); |
141 | return $joinQuery; |
142 | } |
143 | |
144 | public function getEntityMapping() |
145 | { |
146 | $status_expression = self::expression( |
147 | 'CASE |
148 | WHEN process.Name = "(abgesagt)" |
149 | THEN "deleted" |
150 | WHEN process.StandortID = 0 AND process.AbholortID = 0 |
151 | THEN "blocked" |
152 | WHEN process.vorlaeufigeBuchung = 1 AND process.bestaetigt = 0 |
153 | THEN "reserved" |
154 | WHEN process.nicht_erschienen != 0 |
155 | THEN "missed" |
156 | WHEN process.parked != 0 |
157 | THEN "parked" |
158 | WHEN process.Abholer != 0 AND process.AbholortID != 0 AND process.NutzerID = 0 |
159 | THEN "pending" |
160 | WHEN process.AbholortID != 0 AND process.NutzerID != 0 |
161 | THEN "pickup" |
162 | WHEN process.AbholortID = 0 AND process.aufruferfolgreich != 0 AND process.NutzerID != 0 |
163 | THEN "processing" |
164 | WHEN process.aufrufzeit != "00:00:00" AND process.NutzerID != 0 AND process.AbholortID = 0 |
165 | THEN "called" |
166 | WHEN process.Uhrzeit = "00:00:00" |
167 | THEN "queued" |
168 | WHEN process.vorlaeufigeBuchung = 0 AND process.bestaetigt = 0 |
169 | THEN "preconfirmed" |
170 | WHEN process.vorlaeufigeBuchung = 0 AND process.bestaetigt = 1 |
171 | THEN "confirmed" |
172 | ELSE "free" |
173 | END' |
174 | ); |
175 | return [ |
176 | 'amendment' => 'process.Anmerkung', |
177 | 'id' => 'process.BuergerID', |
178 | 'appointments__0__date' => self::expression( |
179 | 'CONCAT(`process`.`Datum`, " ", `process`.`Uhrzeit`)' |
180 | ), |
181 | 'scope__id' => self::expression( |
182 | 'IF(`process`.`AbholortID`, |
183 | `process`.`AbholortID`, |
184 | `process`.`StandortID` |
185 | )' |
186 | ), |
187 | 'appointments__0__scope__id' => 'process.StandortID', |
188 | // 'appointments__0__slotCount' => 'process.hatFolgetermine', |
189 | 'appointments__0__slotCount' => self::expression('process.hatFolgetermine + 1'), |
190 | 'authKey' => 'process.absagecode', |
191 | 'clients__0__email' => 'process.EMail', |
192 | 'clients__0__emailSendCount' => 'process.EMailverschickt', |
193 | 'clients__0__familyName' => 'process.Name', |
194 | 'clients__0__notificationsSendCount' => 'process.SMSverschickt', |
195 | 'clients__0__surveyAccepted' => 'process.zustimmung_kundenbefragung', |
196 | 'clients__0__telephone' => self::expression( |
197 | 'IF(`process`.`telefonnummer_fuer_rueckfragen`!="", |
198 | `process`.`telefonnummer_fuer_rueckfragen`, |
199 | `process`.`Telefonnummer` |
200 | )' |
201 | ), |
202 | 'customTextfield' => 'process.custom_text_field', |
203 | 'createIP' => 'process.IPAdresse', |
204 | 'createTimestamp' => 'process.IPTimeStamp', |
205 | 'lastChange' => 'process.updateTimestamp', |
206 | 'showUpTime' => 'process.showUpTime', |
207 | 'processingTime' => 'process.processingTime', |
208 | 'timeoutTime' => 'process.timeoutTime', |
209 | 'finishTime' => 'process.finishTime', |
210 | 'status' => $status_expression, |
211 | 'queue__status' => $status_expression, |
212 | 'queue__arrivalTime' => self::expression( |
213 | 'CONCAT( |
214 | `process`.`Datum`, |
215 | " ", |
216 | IF(`process`.`wsm_aufnahmezeit`, `process`.`wsm_aufnahmezeit`, `process`.`Uhrzeit`) |
217 | )' |
218 | ), |
219 | 'queue__callCount' => 'process.AnzahlAufrufe', |
220 | 'queue__callTime' => 'process.aufrufzeit', |
221 | 'queue__lastCallTime' => 'process.Timestamp', |
222 | 'queue__number' => self::expression( |
223 | 'IF(`process`.`wartenummer`, |
224 | `process`.`wartenummer`, |
225 | `process`.`BuergerID` |
226 | )' |
227 | ), |
228 | 'queue__destination' => self::expression( |
229 | 'IF(`process`.`AbholortID`, |
230 | `processscope`.`ausgabeschaltername`, |
231 | `processuser`.`Arbeitsplatznr` |
232 | )' |
233 | ), |
234 | 'queue__destinationHint' => 'processuser.aufrufzusatz', |
235 | 'queue__waitingTime' => 'process.wartezeit', |
236 | 'queue__wayTime' => 'process.wegezeit', |
237 | 'queue__withAppointment' => self::expression( |
238 | 'IF(`process`.`wartenummer`, |
239 | "0", |
240 | "1" |
241 | )' |
242 | ), |
243 | 'reminderTimestamp' => 'process.Erinnerungszeitpunkt', |
244 | '__clientsCount' => 'process.AnzahlPersonen', |
245 | ]; |
246 | } |
247 | |
248 | public function addCountValue() |
249 | { |
250 | $this->query->select([ |
251 | 'processCount' => self::expression('COUNT(*)'), |
252 | ]); |
253 | return $this; |
254 | } |
255 | |
256 | public function addConditionHasTelephone() |
257 | { |
258 | $this->query->where(function (\Solution10\SQL\ConditionBuilder $condition) { |
259 | $condition |
260 | ->andWith('process.telefonnummer_fuer_rueckfragen', '!=', '') |
261 | ->orWith('process.Telefonnummer', '!=', ''); |
262 | }); |
263 | return $this; |
264 | } |
265 | |
266 | public function addConditionProcessDeleteInterval(\DateTimeInterface $expirationDate) |
267 | { |
268 | $this->query->where(function (\Solution10\SQL\ConditionBuilder $query) use ($expirationDate) { |
269 | $query->andWith( |
270 | self::expression( |
271 | 'CONCAT(`process`.`Datum`, " ", `process`.`Uhrzeit`)' |
272 | ), |
273 | '<=', |
274 | $expirationDate->format('Y-m-d H:i:s') |
275 | ); |
276 | }); |
277 | $this->query->orderBy('appointments__0__date', 'ASC'); |
278 | return $this; |
279 | } |
280 | |
281 | public function addConditionProcessExpiredIPTimeStamp(\DateTimeInterface $expirationDate) |
282 | { |
283 | $this->query->where(function (\Solution10\SQL\ConditionBuilder $query) use ($expirationDate) { |
284 | $query->andWith('process.IPTimeStamp', '<=', $expirationDate->getTimestamp()); |
285 | }); |
286 | $this->query->orderBy('appointments__0__date', 'ASC'); |
287 | return $this; |
288 | } |
289 | |
290 | public function addConditionProcessReminderInterval(\DateTimeInterface $dateTime) |
291 | { |
292 | $this->query->where(function (\Solution10\SQL\ConditionBuilder $query) use ($dateTime) { |
293 | $query |
294 | ->andWith('process.Erinnerungszeitpunkt', '<=', $dateTime->getTimestamp()) |
295 | ->andWith('process.Erinnerungszeitpunkt', '>=', $dateTime->modify("-5 Minutes")->getTimestamp()); |
296 | }); |
297 | $this->query->orderBy('reminderTimestamp', 'ASC'); |
298 | return $this; |
299 | } |
300 | |
301 | public function addConditionProcessMailReminder( |
302 | \DateTimeInterface $now, |
303 | \DateTimeInterface $lastRun, |
304 | $defaultReminderInMinutes |
305 | ) { |
306 | $this->query |
307 | ->where(function (\Solution10\SQL\ConditionBuilder $query) use ($now, $lastRun, $defaultReminderInMinutes) { |
308 | $query |
309 | ->andWith( |
310 | self::expression( |
311 | 'CONCAT(`process`.`Datum`, " ", `process`.`Uhrzeit`)' |
312 | ), |
313 | '>', |
314 | $lastRun->format('Y-m-d H:i:s') |
315 | ) |
316 | ->andWith( |
317 | self::expression( |
318 | 'CONCAT(`process`.`Datum`, " ", `process`.`Uhrzeit`)' |
319 | ), |
320 | '>', |
321 | $now->format('Y-m-d H:i:s') |
322 | ) |
323 | ->andWith( |
324 | 'scopemail.send_reminder', |
325 | '=', |
326 | 1 |
327 | ) |
328 | ->andWith( |
329 | 'process.EMail', |
330 | '<>', |
331 | "" |
332 | ) |
333 | ->andWith( |
334 | 'process.EMailverschickt', |
335 | '=', |
336 | 0 |
337 | ) |
338 | ->andWith( |
339 | self::expression( |
340 | 'DATE_SUB(CONCAT(`process`.`Datum`, " ", `process`.`Uhrzeit`), INTERVAL ' |
341 | . 'IFNULL(scopemail.send_reminder_minutes_before, ' . $defaultReminderInMinutes |
342 | . ') MINUTE)' |
343 | ), |
344 | '<=', |
345 | $now->format('Y-m-d H:i:s') |
346 | ); |
347 | }); |
348 | $this->query->orderBy('appointments__0__date', 'ASC'); |
349 | return $this; |
350 | } |
351 | |
352 | public function addConditionProcessId($processId) |
353 | { |
354 | $this->query->where('process.BuergerID', '=', $processId); |
355 | $this->query->where(function (\Solution10\SQL\ConditionBuilder $condition) { |
356 | $condition |
357 | ->andWith('process.istFolgeterminvon', 'IS', null) |
358 | ->orWith('process.istFolgeterminvon', '=', 0); |
359 | }); |
360 | return $this; |
361 | } |
362 | |
363 | public function addConditionProcessIdFollow($processId) |
364 | { |
365 | $this->query->where(function (\Solution10\SQL\ConditionBuilder $condition) use ($processId) { |
366 | $condition |
367 | ->andWith('process.BuergerID', '=', $processId) |
368 | ->orWith('process.istFolgeterminvon', '=', $processId); |
369 | }); |
370 | return $this; |
371 | } |
372 | |
373 | public function addConditionIgnoreSlots() |
374 | { |
375 | $this->query->where(function (\Solution10\SQL\ConditionBuilder $condition) { |
376 | $condition |
377 | ->andWith('process.istFolgeterminvon', 'IS', null) |
378 | ->orWith('process.istFolgeterminvon', '=', 0); |
379 | }); |
380 | return $this; |
381 | } |
382 | |
383 | public function addConditionScopeId($scopeId) |
384 | { |
385 | $this->query->where(function (\Solution10\SQL\ConditionBuilder $query) use ($scopeId) { |
386 | $query |
387 | ->andWith('process.StandortID', '=', $scopeId) |
388 | ->orWith('process.AbholortID', '=', $scopeId); |
389 | }); |
390 | return $this; |
391 | } |
392 | |
393 | public function addConditionQueueNumber($queueNumber, $queueLimit = 10000) |
394 | { |
395 | ($queueLimit > $queueNumber) |
396 | ? $this->query->where('process.wartenummer', '=', $queueNumber) |
397 | : $this->query->where('process.BuergerID', '=', $queueNumber); |
398 | return $this; |
399 | } |
400 | |
401 | public function addConditionWorkstationId($workstationId) |
402 | { |
403 | $this->query->where(function (\Solution10\SQL\ConditionBuilder $query) use ($workstationId) { |
404 | $query->andWith('process.NutzerID', '=', $workstationId); |
405 | $query->andWith('process.StandortID', '>', 0); |
406 | }); |
407 | return $this; |
408 | } |
409 | |
410 | public function addConditionTime($dateTime) |
411 | { |
412 | $this->query->where('process.Datum', '=', $dateTime->format('Y-m-d')); |
413 | return $this; |
414 | } |
415 | |
416 | /** |
417 | * Identify processes between two dates |
418 | */ |
419 | public function addConditionTimeframe(\DateTimeInterface $startDate, \DateTimeInterface $endDate) |
420 | { |
421 | $this->query->where(function (\Solution10\SQL\ConditionBuilder $condition) use ($startDate, $endDate) { |
422 | $condition |
423 | ->andWith('process.Datum', '<=', $endDate->format('Y-m-d')) |
424 | ->andWith('process.Datum', '>=', $startDate->format('Y-m-d')); |
425 | }); |
426 | return $this; |
427 | } |
428 | |
429 | public function addConditionAuthKey($authKey) |
430 | { |
431 | $authKey = urldecode($authKey); |
432 | $this->query |
433 | ->where(function (\Solution10\SQL\ConditionBuilder $condition) use ($authKey) { |
434 | $condition |
435 | ->andWith('process.absagecode', '=', $authKey) |
436 | ->orWith('process.Name', '=', $authKey); |
437 | }); |
438 | return $this; |
439 | } |
440 | |
441 | public function addConditionAssigned() |
442 | { |
443 | $this->query->where('process.StandortID', '!=', "0"); |
444 | return $this; |
445 | } |
446 | |
447 | public function addConditionStatus($status, $scopeId = 0) |
448 | { |
449 | $this->query->where(function (\Solution10\SQL\ConditionBuilder $query) use ($status, $scopeId) { |
450 | if ('deleted' == $status) { |
451 | $query |
452 | ->andWith('process.Name', '=', '(abgesagt)'); |
453 | } |
454 | if ('blocked' == $status) { |
455 | $query |
456 | ->andWith('process.StandortID', '=', 0) |
457 | ->andWith('process.AbholortID', '=', 0); |
458 | } |
459 | if ('reserved' == $status) { |
460 | $query |
461 | ->andWith('process.name', '!=', '(abgesagt)') |
462 | ->andWith('process.vorlaeufigeBuchung', '=', 1) |
463 | ->andWith('process.StandortID', '!=', 0) |
464 | ->andWith('process.istFolgeterminvon', 'is', null); |
465 | } |
466 | if ('missed' == $status) { |
467 | $query->andWith('process.nicht_erschienen', '!=', 0) |
468 | ->andWith('process.StandortID', '!=', 0); |
469 | } |
470 | if ('parked' == $status) { |
471 | $query |
472 | ->andWith('process.parked', '!=', 0) |
473 | ->andWith('process.StandortID', '!=', 0); |
474 | } |
475 | if ('pending' == $status) { |
476 | $query |
477 | ->andWith('process.StandortID', '!=', 0) |
478 | ->andWith('process.Abholer', '!=', 0) |
479 | ->andWith('process.NutzerID', '=', 0); |
480 | if (0 != $scopeId) { |
481 | $query->andWith('process.AbholortID', '=', $scopeId); |
482 | } else { |
483 | $query->andWith('process.AbholortID', '!=', 0); |
484 | } |
485 | } |
486 | if ('processing' == $status) { |
487 | $query |
488 | ->andWith('process.aufruferfolgreich', '!=', 0) |
489 | ->andWith('process.NutzerID', '!=', 0) |
490 | ->andWith('process.StandortID', '!=', 0); |
491 | } |
492 | if ('pickup' == $status) { |
493 | $query |
494 | ->andWith('process.StandortID', '!=', 0) |
495 | ->andWith('process.NutzerID', '!=', 0); |
496 | if (0 != $scopeId) { |
497 | $query->andWith('process.AbholortID', '=', $scopeId); |
498 | } else { |
499 | $query->andWith('process.AbholortID', '!=', 0); |
500 | } |
501 | } |
502 | if ('called' == $status) { |
503 | $query |
504 | ->andWith('process.aufrufzeit', '!=', '00:00:00') |
505 | ->andWith('process.NutzerID', '!=', 0) |
506 | ->andWith('process.StandortID', '!=', 0) |
507 | ->andWith('process.AbholortID', '=', 0); |
508 | } |
509 | if ('queued' == $status) { |
510 | $query->andWith('process.Uhrzeit', '=', '00:00:00') |
511 | ->andWith('process.StandortID', '!=', 0) |
512 | ->andWith('process.AbholortID', '=', 0); |
513 | ; |
514 | } |
515 | if ('confirmed' == $status) { |
516 | $query |
517 | ->andWith('process.vorlaeufigeBuchung', '=', 0) |
518 | ->andWith('process.Abholer', '=', 0) |
519 | ->andWith('process.Uhrzeit', '!=', '00:00:00') |
520 | ->andWith('process.bestaetigt', '=', 1) |
521 | ->andWith('process.IPTimeStamp', '!=', 0); |
522 | } |
523 | if ('preconfirmed' == $status) { |
524 | $query |
525 | ->andWith('process.vorlaeufigeBuchung', '=', 0) |
526 | ->andWith('process.Abholer', '=', 0) |
527 | ->andWith('process.StandortID', '!=', 0) |
528 | ->andWith('process.Uhrzeit', '!=', '00:00:00') |
529 | ->andWith('process.bestaetigt', '=', 0) |
530 | ->andWith('process.IPTimeStamp', '!=', 0); |
531 | if (0 != $scopeId) { |
532 | $query |
533 | ->andWith('process.StandortID', '=', $scopeId); |
534 | } |
535 | } |
536 | }); |
537 | return $this; |
538 | } |
539 | |
540 | public function addConditionIsReserved() |
541 | { |
542 | $this->query->where('process.name', 'NOT IN', array( |
543 | 'dereferenced', |
544 | '(abgesagt)' |
545 | )) |
546 | ->where('process.vorlaeufigeBuchung', '=', 1) |
547 | ->where('process.StandortID', '>', 0); |
548 | $this->query->where(function (\Solution10\SQL\ConditionBuilder $condition) { |
549 | $condition |
550 | ->andWith('process.istFolgeterminvon', 'IS', null) |
551 | ->orWith('process.istFolgeterminvon', '=', 0); |
552 | }); |
553 | return $this; |
554 | } |
555 | |
556 | public function addConditionSearch($queryString, $orWhere = false) |
557 | { |
558 | $condition = function (\Solution10\SQL\ConditionBuilder $query) use ($queryString) { |
559 | $queryString = trim($queryString); |
560 | $query->orWith('process.Name', 'LIKE', "%$queryString%"); |
561 | $query->orWith('process.EMail', 'LIKE', "%$queryString%"); |
562 | $query->orWith('process.Telefonnummer', 'LIKE', "%$queryString%"); |
563 | $query->orWith('process.telefonnummer_fuer_rueckfragen', 'LIKE', "%$queryString%"); |
564 | }; |
565 | if ($orWhere) { |
566 | $this->query->orWhere($condition); |
567 | } else { |
568 | $this->query->where($condition); |
569 | } |
570 | return $this; |
571 | } |
572 | |
573 | public function addConditionName($name, $exactMatching = false) |
574 | { |
575 | if ($exactMatching) { |
576 | $this->query->where(function (\Solution10\SQL\ConditionBuilder $query) use ($name) { |
577 | $query->andWith('process.Name', '=', $name); |
578 | }); |
579 | } else { |
580 | $this->query->where(function (\Solution10\SQL\ConditionBuilder $query) use ($name) { |
581 | $query->andWith('process.Name', 'LIKE', "%$name%"); |
582 | }); |
583 | } |
584 | return $this; |
585 | } |
586 | |
587 | public function addConditionMail($mailAddress, $exactMatching = false) |
588 | { |
589 | if ($exactMatching) { |
590 | $this->query->where(function (\Solution10\SQL\ConditionBuilder $query) use ($mailAddress) { |
591 | $query->andWith('process.Email', '=', $mailAddress); |
592 | }); |
593 | } else { |
594 | $this->query->where(function (\Solution10\SQL\ConditionBuilder $query) use ($mailAddress) { |
595 | $query->andWith('process.Email', 'LIKE', "%$mailAddress%"); |
596 | }); |
597 | } |
598 | return $this; |
599 | } |
600 | |
601 | public function addConditionCustomTextfield($customText, $exactMatching = false) |
602 | { |
603 | if ($exactMatching) { |
604 | $this->query->where(function (\Solution10\SQL\ConditionBuilder $query) use ($customText) { |
605 | $query->andWith('process.custom_text_field', '=', $customText); |
606 | }); |
607 | } else { |
608 | $this->query->where(function (\Solution10\SQL\ConditionBuilder $query) use ($customText) { |
609 | $query->andWith('process.custom_text_field', 'LIKE', "%$customText%"); |
610 | }); |
611 | } |
612 | return $this; |
613 | } |
614 | |
615 | public function addConditionAmendment($amendment) |
616 | { |
617 | $this->query->where(function (\Solution10\SQL\ConditionBuilder $query) use ($amendment) { |
618 | $query->andWith('process.Anmerkung', 'LIKE', "%$amendment%"); |
619 | }); |
620 | return $this; |
621 | } |
622 | |
623 | /** |
624 | * Add Requests Join |
625 | */ |
626 | public function addConditionRequestId($requestId) |
627 | { |
628 | $this->leftJoin( |
629 | new Alias("buergeranliegen", 'buergeranliegen'), |
630 | 'buergeranliegen.BuergerID', |
631 | '=', |
632 | 'process.BuergerID' |
633 | ); |
634 | $this->query->where('buergeranliegen.AnliegenID', '=', $requestId); |
635 | return $this; |
636 | } |
637 | |
638 | /** |
639 | * add condition to get process if deallocation time < now |
640 | */ |
641 | public function addConditionDeallocate($now) |
642 | { |
643 | $this->query->where(function (\Solution10\SQL\ConditionBuilder $query) use ($now) { |
644 | $query |
645 | ->andWith('process.Name', '=', '(abgesagt)') |
646 | ->andWith('process.IPTimeStamp', '<', $now->getTimestamp()); |
647 | }); |
648 | $this->query->orderBy('process.IPTimeStamp', 'ASC'); |
649 | return $this; |
650 | } |
651 | |
652 | public function addValuesNewProcess(\BO\Zmsentities\Process $process, $parentProcess = 0, $childProcessCount = 0) |
653 | { |
654 | $values = [ |
655 | 'BuergerID' => $process->id, |
656 | 'IPTimeStamp' => $process->createTimestamp, |
657 | 'absagecode' => $process->authKey, |
658 | 'hatFolgetermine' => $childProcessCount, |
659 | 'istFolgeterminvon' => $parentProcess, |
660 | 'wartenummer' => $process->queue['number'] |
661 | ]; |
662 | if ($process->toProperty()->apiclient->apiClientID->isAvailable()) { |
663 | $values['apiClientID'] = $process->apiclient->apiClientID; |
664 | } |
665 | $this->addValues($values); |
666 | } |
667 | |
668 | public function addValuesUpdateProcess( |
669 | \BO\Zmsentities\Process $process, |
670 | \DateTimeInterface $dateTime, |
671 | $parentProcess = 0, |
672 | $previousStatus = null |
673 | ) { |
674 | $this->addValuesIPAdress($process); |
675 | $this->addValuesStatusData($process, $dateTime); |
676 | if (0 === $parentProcess) { |
677 | $this->addValuesClientData($process); |
678 | $this->addProcessingTimeData($process, $dateTime, $previousStatus); |
679 | $this->addValuesQueueData($process); |
680 | $this->addValuesWaitingTimeData($process, $previousStatus); |
681 | $this->addValuesWayTimeData($process); |
682 | } |
683 | if ($process->isWithAppointment()) { |
684 | $this->addValuesFollowingProcessData($process, $parentProcess); |
685 | } |
686 | } |
687 | |
688 | public function addValuesIPAdress($process) |
689 | { |
690 | $data = array(); |
691 | $data['IPAdresse'] = $process['createIP']; |
692 | $this->addValues($data); |
693 | } |
694 | |
695 | public function addValuesFollowingProcessData($process, $parentProcess) |
696 | { |
697 | $data = array(); |
698 | if (0 === $parentProcess) { |
699 | $data['hatFolgetermine'] = (1 <= $process->getFirstAppointment()->getSlotCount()) ? |
700 | $process->getFirstAppointment()->getSlotCount() - 1 : |
701 | 0; |
702 | } else { |
703 | $data['Name'] = '(Folgetermin)'; |
704 | } |
705 | $this->addValues($data); |
706 | } |
707 | |
708 | public function addValuesAppointmentData( |
709 | \BO\Zmsentities\Process $process |
710 | ) { |
711 | $data = array(); |
712 | $appointment = $process->getFirstAppointment(); |
713 | if (null !== $appointment) { |
714 | $datetime = $appointment->toDateTime(); |
715 | $data['Datum'] = $datetime->format('Y-m-d'); |
716 | $data['Uhrzeit'] = $datetime->format('H:i:s'); |
717 | } |
718 | $this->addValues($data); |
719 | } |
720 | |
721 | public function addValuesScopeData( |
722 | \BO\Zmsentities\Process $process |
723 | ) { |
724 | $data = array(); |
725 | $data['StandortID'] = $process->getScopeId(); |
726 | $this->addValues($data); |
727 | } |
728 | |
729 | public function addValuesStatusData($process, \DateTimeInterface $dateTime) |
730 | { |
731 | $data = array(); |
732 | $data['vorlaeufigeBuchung'] = ($process['status'] == 'reserved') ? 1 : 0; |
733 | $data['aufruferfolgreich'] = ($process['status'] == 'processing') ? 1 : 0; |
734 | if ($process->status == 'called') { |
735 | $data['parked'] = 0; |
736 | $data['nicht_erschienen'] = 0; |
737 | } |
738 | if ($process->status == 'pending') { |
739 | $data['AbholortID'] = $process->scope['id']; |
740 | $data['Abholer'] = 1; |
741 | $data['nicht_erschienen'] = 0; |
742 | $data['parked'] = 0; |
743 | } |
744 | if ($process->status == 'pickup') { |
745 | $data['AbholortID'] = $process->scope['id']; |
746 | $data['Abholer'] = 1; |
747 | $data['Timestamp'] = 0; |
748 | $data['nicht_erschienen'] = 0; |
749 | $data['parked'] = 0; |
750 | } |
751 | if ($process->status == 'queued') { |
752 | $data['nicht_erschienen'] = 0; |
753 | $data['parked'] = 0; |
754 | if ( |
755 | $process->hasArrivalTime() && |
756 | (isset($process->queue['withAppointment']) && $process->queue['withAppointment']) |
757 | ) { |
758 | $data['wsm_aufnahmezeit'] = $dateTime->format('H:i:s'); |
759 | } |
760 | } |
761 | if ($process->status == 'missed') { |
762 | $data['nicht_erschienen'] = 1; |
763 | } |
764 | if ($process->status == 'parked') { |
765 | $data['parked'] = 1; |
766 | } |
767 | if ($process->status == 'confirmed') { |
768 | $data['bestaetigt'] = 1; |
769 | } |
770 | if ($process->status == 'preconfirmed') { |
771 | $data['bestaetigt'] = 0; |
772 | } |
773 | |
774 | $this->addValues($data); |
775 | } |
776 | |
777 | protected function addValuesClientData($process) |
778 | { |
779 | $data = array(); |
780 | $client = $process->getFirstClient(); |
781 | if ($client && $client->hasFamilyName()) { |
782 | $data['Name'] = $client->familyName; |
783 | } |
784 | if ($client && $client->hasEmail()) { |
785 | $data['EMail'] = $client->email; |
786 | } |
787 | if ($client && $client->offsetExists('telephone')) { |
788 | $data['telefonnummer_fuer_rueckfragen'] = $client->telephone; |
789 | $data['Telefonnummer'] = $client->telephone; // to stay compatible with ZMS1 |
790 | } |
791 | if ($client && $client->offsetExists('emailSendCount')) { |
792 | $data['EMailverschickt'] = ('-1' == $client->emailSendCount) ? 0 : $client->emailSendCount; |
793 | } |
794 | if ($client && $client->offsetExists('notificationsSendCount')) { |
795 | $data['SMSverschickt'] = ('-1' == $client->notificationsSendCount) ? 0 : $client->notificationsSendCount; |
796 | } |
797 | if ($process->getAmendment()) { |
798 | $data['Anmerkung'] = $process->getAmendment(); |
799 | } |
800 | if ($process->getCustomTextfield()) { |
801 | $data['custom_text_field'] = $process->getCustomTextfield(); |
802 | } |
803 | $data['zustimmung_kundenbefragung'] = ($client->surveyAccepted) ? 1 : 0; |
804 | $data['Erinnerungszeitpunkt'] = $process->getReminderTimestamp(); |
805 | $data['AnzahlPersonen'] = $process->getClients()->count(); |
806 | $this->addValues($data); |
807 | } |
808 | |
809 | protected function addProcessingTimeData($process, \DateTimeInterface $dateTime, $previousStatus = null) |
810 | { |
811 | $data = array(); |
812 | $timeoutTime = null; |
813 | $showUpTime = null; |
814 | $finishTime = null; |
815 | |
816 | if ( |
817 | isset($previousStatus) && |
818 | (($process->status == 'called' && $previousStatus == 'called') || |
819 | ($process->status == 'processing' && $previousStatus == 'processing')) |
820 | ) { |
821 | $timeoutTime = $dateTime->format('Y-m-d H:i:s'); |
822 | $data['timeoutTime'] = $timeoutTime; |
823 | } elseif ($process->status == 'processing') { |
824 | $showUpTime = $dateTime->format('Y-m-d H:i:s'); |
825 | $data['showUpTime'] = $showUpTime; |
826 | } elseif ($process->status == 'finished') { |
827 | $finishTime = $dateTime->format('Y-m-d H:i:s'); |
828 | $data['finishTime'] = $finishTime; |
829 | } |
830 | |
831 | |
832 | if (isset($finishTime) && isset($process->showUpTime)) { |
833 | $showUpDateTime = new \DateTime($process->showUpTime); |
834 | $finishTime = new \DateTime($finishTime); |
835 | |
836 | $processingTimeStr = $process->getProcessingTime(); |
837 | $previousProcessingTimeInSeconds = 0; // Default to 0 if not set |
838 | |
839 | if (!empty($processingTimeStr)) { |
840 | // Assume the format is HH:MM:SS and parse it |
841 | list($hours, $minutes, $seconds) = explode(':', $processingTimeStr); |
842 | // Convert hours, minutes, and seconds to total seconds |
843 | $previousProcessingTimeInSeconds = (int)$hours * 3600 + (int)$minutes * 60 + (int)$seconds; |
844 | } |
845 | |
846 | $interval = $showUpDateTime->diff($finishTime); |
847 | $totalSeconds = ($interval->days * 24 * 60 * 60) + ($interval->h * 60 * 60) + ($interval->i * 60) + $interval->s; |
848 | |
849 | $totalSeconds += $previousProcessingTimeInSeconds; |
850 | |
851 | $hours = intdiv($totalSeconds, 3600); |
852 | $minutes = intdiv($totalSeconds % 3600, 60); |
853 | $seconds = $totalSeconds % 60; |
854 | |
855 | $data['processingTime'] = sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds); |
856 | } elseif (isset($timeoutTime) && isset($process->showUpTime)) { |
857 | $showUpDateTime = new \DateTime($process->showUpTime); |
858 | $timeoutDateTime = new \DateTime($timeoutTime); |
859 | $processingTimeStr = $process->getProcessingTime(); |
860 | |
861 | $previousProcessingTimeInSeconds = 0; // Default to 0 if not set |
862 | if (!empty($processingTimeStr)) { |
863 | // Assume the format is HH:MM:SS and parse it |
864 | list($hours, $minutes, $seconds) = explode(':', $processingTimeStr); |
865 | // Convert hours, minutes, and seconds to total seconds |
866 | $previousProcessingTimeInSeconds = (int)$hours * 3600 + (int)$minutes * 60 + (int)$seconds; |
867 | } |
868 | $interval = $showUpDateTime->diff($timeoutDateTime); |
869 | $totalSeconds = ($interval->days * 24 * 60 * 60) + ($interval->h * 60 * 60) + ($interval->i * 60) + $interval->s; |
870 | |
871 | $totalSeconds += $previousProcessingTimeInSeconds; |
872 | |
873 | $hours = intdiv($totalSeconds, 3600); |
874 | $minutes = intdiv($totalSeconds % 3600, 60); |
875 | $seconds = $totalSeconds % 60; |
876 | |
877 | $data['processingTime'] = sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds); |
878 | } |
879 | |
880 | $this->addValues($data); |
881 | } |
882 | |
883 | protected function addValuesQueueData($process) |
884 | { |
885 | $data = array(); |
886 | $appointmentTime = $process->getFirstAppointment()->toDateTime()->format('H:i:s'); |
887 | |
888 | if (isset($process->queue['callCount']) && $process->queue['callCount']) { |
889 | $data['AnzahlAufrufe'] = $process->queue['callCount']; |
890 | } |
891 | if (isset($process->queue['callTime']) && $process->queue['callTime']) { |
892 | $data['aufrufzeit'] = (new \DateTimeImmutable()) |
893 | ->setTimestamp($process->queue['callTime'])->format('H:i:s'); |
894 | } |
895 | if (isset($process->queue['lastCallTime']) && $process->queue['lastCallTime']) { |
896 | $data['Timestamp'] = (new \DateTimeImmutable()) |
897 | ->setTimestamp($process->queue['lastCallTime'])->format('H:i:s'); |
898 | } |
899 | if (isset($process->queue['arrivalTime']) && $process->queue['arrivalTime']) { |
900 | $data['wsm_aufnahmezeit'] = (new \DateTimeImmutable()) |
901 | ->setTimestamp($process->queue['arrivalTime'])->format('H:i:s'); |
902 | } |
903 | if (isset($data['wsm_aufnahmezeit']) && $data['wsm_aufnahmezeit'] == $appointmentTime) { |
904 | // Do not save arrivalTime if it is an appointment |
905 | $data['wsm_aufnahmezeit'] = 0; |
906 | } |
907 | $this->addValues($data); |
908 | } |
909 | |
910 | protected function addValuesWaitingTimeData($process, $previousStatus = null) |
911 | { |
912 | $data = array(); |
913 | if (($previousStatus == 'queued' || $previousStatus == 'missed' || $previousStatus == 'confirmed') && $process['status'] == 'called') { |
914 | // Retrieve waiting time in seconds |
915 | $wartezeitInSeconds = $process->getWaitedSeconds(); |
916 | |
917 | // Check if there is any waiting time; if not, default to 0 seconds |
918 | $wartezeitInSeconds = $wartezeitInSeconds > 0 ? $wartezeitInSeconds : 0; |
919 | |
920 | // Convert total seconds into HH:MM:SS format |
921 | $hours = intdiv($wartezeitInSeconds, 3600); |
922 | $minutes = intdiv($wartezeitInSeconds % 3600, 60); |
923 | $seconds = $wartezeitInSeconds % 60; |
924 | |
925 | // Format and store the time in HH:MM:SS |
926 | $data['wartezeit'] = sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds); |
927 | } |
928 | $this->addValues($data); |
929 | } |
930 | |
931 | protected function addValuesWayTimeData($process) |
932 | { |
933 | $data = array(); |
934 | if ($process['status'] == 'processing') { |
935 | $wegezeit = $process->getWayMinutes(); |
936 | $data['wegezeit'] = $wegezeit > 0 ? $wegezeit : 0; |
937 | } |
938 | $this->addValues($data); |
939 | } |
940 | |
941 | public function postProcess($data) |
942 | { |
943 | $data[$this->getPrefixed("appointments__0__date")] = |
944 | strtotime($data[$this->getPrefixed("appointments__0__date")]); |
945 | if ('00:00:00' != $data[$this->getPrefixed("queue__callTime")]) { |
946 | $time = explode(':', $data[$this->getPrefixed("queue__callTime")]); |
947 | $data[$this->getPrefixed("queue__callTime")] = (new \DateTimeImmutable()) |
948 | ->setTimestamp($data[$this->getPrefixed("appointments__0__date")]) |
949 | ->setTime($time[0], $time[1], $time[2]) |
950 | ->getTimestamp(); |
951 | } else { |
952 | $data[$this->getPrefixed("queue__callTime")] = 0; |
953 | } |
954 | if ('00:00:00' != $data[$this->getPrefixed("queue__lastCallTime")]) { |
955 | $time = explode(':', $data[$this->getPrefixed("queue__lastCallTime")]); |
956 | $data[$this->getPrefixed("queue__lastCallTime")] = (new \DateTimeImmutable()) |
957 | ->setTimestamp($data[$this->getPrefixed("appointments__0__date")]) |
958 | ->setTime($time[0], $time[1], $time[2]) |
959 | ->getTimestamp(); |
960 | } else { |
961 | $data[$this->getPrefixed("queue__lastCallTime")] = 0; |
962 | } |
963 | $data[$this->getPrefixed("queue__arrivalTime")] = |
964 | strtotime($data[$this->getPrefixed("queue__arrivalTime")]); |
965 | if ( |
966 | isset($data[$this->getPrefixed('scope__provider__data')]) |
967 | && $data[$this->getPrefixed('scope__provider__data')] |
968 | ) { |
969 | $data[$this->getPrefixed('scope__provider__data')] = |
970 | json_decode($data[$this->getPrefixed('scope__provider__data')], true); |
971 | } |
972 | if (isset($data[$this->getPrefixed('__clientsCount')])) { |
973 | $clientsCount = $data[$this->getPrefixed('__clientsCount')]; |
974 | unset($data[$this->getPrefixed('__clientsCount')]); |
975 | while (--$clientsCount > 0) { |
976 | $data[$this->getPrefixed('clients__' . $clientsCount . '__familyName')] = 'Unbekannt'; |
977 | } |
978 | } |
979 | $data[$this->getPrefixed("lastChange")] = |
980 | (new \DateTimeImmutable($data[$this->getPrefixed("lastChange")] . |
981 | \BO\Zmsdb\Connection\Select::$connectionTimezone))->getTimestamp(); |
982 | return $data; |
983 | } |
984 | |
985 | public function removeDuplicates() |
986 | { |
987 | $this->query->groupBy('process.BuergerID'); |
988 | return $this; |
989 | } |
990 | |
991 | protected function addRequiredJoins() |
992 | { |
993 | $this->leftJoin( |
994 | new Alias(Useraccount::TABLE, 'processuser'), |
995 | 'process.NutzerID', |
996 | '=', |
997 | 'processuser.NutzerID' |
998 | ); |
999 | |
1000 | $this->leftJoin( |
1001 | new Alias(Scope::TABLE, 'processscope'), |
1002 | 'process.StandortID', |
1003 | '=', |
1004 | 'processscope.StandortID' |
1005 | ); |
1006 | } |
1007 | } |