24 private const WORKFLOW_FIELDS = [
'ID',
'STARTED',
'STARTED_BY',
'MODIFIED',
'META.START_DURATION'];
25 private const TASK_FIELDS = [
'ID',
'WORKFLOW_ID',
'MODIFIED',
'STATUS',
'CREATED_DATE'];
26 private const COMPLETED_TASK_LIMIT = 2;
27 private const RUNNING_TASK_LIMIT = 3;
35 $this->accessService = $accessService;
42 return GetDataResponse::createError(
new Error(
'empty workflowId'));
47 $canViewResponse = $this->accessService->canViewFaces(
51 max(
$request->currentUserId ?? 0, 0),
54 if (!$canViewResponse->isSuccess())
56 return GetDataResponse::createError($this->accessService::getViewAccessDeniedError());
61 WorkflowStateTable::query()
62 ->setSelect(self::WORKFLOW_FIELDS)
69 return GetDataResponse::createError(
71 'workflow does not exist',
72 self::WORKFLOW_DOES_NOT_EXIST_ERROR_CODE
79 ->setAuthorId($workflow->getStartedBy() ?? 0)
80 ->setWorkflowStarted($workflow->getStarted())
83 $response->setWorkflowIsFinished(\CBPHelper::isWorkflowFinished(
$request->workflowId));
87 '=WORKFLOW_ID' =>
$request->workflowId,
94 ? $this->getCompletedTasks(
$request->workflowId)
104 $response->setTasksUserIds($this->getTasksUserIds($completedTasks, $runningTasks,
$request->taskUsersLimit));
106 $runningTask = current($runningTasks);
112 $completedTask = current($completedTasks);
114 if (
$response->getWorkflowIsFinished() &&
count($completedTasks) > 1)
116 $doneTask = $completedTask;
117 $completedTask = next($completedTasks);
125 $response->setCompletedTask($completedTask);
128 $authorDuration = $workflow->getMeta()?->getStartDuration() ?? 0;
132 : $this->getRunningDuration($workflow, $runningTask ?:
null, $completedTask ?:
null)
134 $completedDuration = $this->getCompletedDuration($workflow, $completedTask ?:
null);
137 ? $this->getDoneDuration($workflow, $completedTask ?:
null)
141 $response->setDurations(
new StepDurations($authorDuration, $runningDuration, $completedDuration, $doneDuration));
146 private function getCompletedTasks(
string $workflowId):
array
149 [
'MODIFIED' =>
'DESC'],
152 [
'nTopCount' => self::COMPLETED_TASK_LIMIT],
155 $completedTasks = [];
156 while ($task = $completedTasksIterator->getNext())
158 $completedTasks[$task[
'ID']] = $task;
161 return $completedTasks;
164 private function getRunningTasks(
string $workflowId, ?
int $runningTaskId =
null):
array
166 $isTaskIdCorrect = $runningTaskId && $runningTaskId > 0;
175 [
'nTopCount' => self::RUNNING_TASK_LIMIT],
180 while ($task = $runningTasksIterator->getNext())
183 if ($isTaskIdCorrect && ($runningTaskId === (
int)$task[
'ID']))
185 $runningTask = $task;
190 $runningTasks[$task[
'ID']] = $task;
194 if ($hasTasks && $isTaskIdCorrect && !$runningTask)
197 [], [
'ID' => $runningTaskId],
false,
false, self::TASK_FIELDS
202 $runningTask = $task;
208 $runningTasks = [$runningTask[
'ID'] => $runningTask] + $runningTasks;
211 return $runningTasks;
214 private function getTasksUserIds(
array $completedTasks,
array $runningTasks,
int $usersLimit):
array
216 $taskIds = array_merge(array_keys($runningTasks), array_keys($completedTasks));
217 $taskUsers = $taskIds ? \CBPTaskService::getTaskUsers($taskIds) : [];
219 $taskUserIdsMap = [];
220 foreach ($taskUsers as $taskId => $users)
222 $ids = array_slice(array_column($users,
'USER_ID'), 0, $usersLimit);
223 Collection::normalizeArrayValuesByInt($ids,
false);
224 $taskUserIdsMap[$taskId] = $ids;
227 return $taskUserIdsMap;
230 private function getRunningDuration(WorkflowState $workflow, ?
array $runningTask, ?
array $completedTask): int
232 $currentTimestamp = time();
235 $startTaskTimestamp = $this->getDateTimeTimestamp($runningTask[
'CREATED_DATE'] ??
null);
236 if (!$startTaskTimestamp)
238 $startTaskTimestamp = $this->getDateTimeTimestamp($runningTask[
'MODIFIED'] ??
null);
241 return $startTaskTimestamp ? $currentTimestamp - $startTaskTimestamp : 0;
246 $finishTaskTimestamp = $this->getDateTimeTimestamp($completedTask[
'MODIFIED'] ??
null);
248 return $finishTaskTimestamp ? $currentTimestamp - $finishTaskTimestamp : 0;
251 $startWorkflowTimestamp = $this->getDateTimeTimestamp($workflow->getStarted());
253 return $startWorkflowTimestamp ? ($currentTimestamp - $startWorkflowTimestamp) : 0;
256 private function getCompletedDuration(WorkflowState $workflow, ?
array $completedTask): int
258 $startWorkflowTimestamp = $this->getDateTimeTimestamp($workflow->getStarted());
260 $finishTaskTimestamp = (
261 $completedTask ? $this->getDateTimeTimestamp($completedTask[
'MODIFIED'] ??
null) : null
264 return $startWorkflowTimestamp && $finishTaskTimestamp ? ($finishTaskTimestamp - $startWorkflowTimestamp) : 0;
267 private function getDoneDuration(WorkflowState $workflow, ?
array $completedTask): int
269 $finishWorkflowTimestamp = $this->getDateTimeTimestamp($workflow->getModified());
272 $finishTaskTimestamp = $this->getDateTimeTimestamp($completedTask[
'MODIFIED'] ??
null);
275 $finishWorkflowTimestamp && $finishTaskTimestamp && ($finishWorkflowTimestamp > $finishTaskTimestamp)
276 ? $finishWorkflowTimestamp - $finishTaskTimestamp
281 $startWorkflowTimestamp = $this->getDateTimeTimestamp($workflow->getStarted());
284 $finishWorkflowTimestamp && $startWorkflowTimestamp
285 ? ($finishWorkflowTimestamp - $startWorkflowTimestamp)
290 private function getDateTimeTimestamp($datetime): ?int
292 if ($datetime instanceof DateTime)
294 return $datetime->getTimestamp();
297 if (is_string($datetime) && DateTime::isCorrect($datetime))
299 return DateTime::createFromUserTime($datetime)->getTimestamp();
305 public function getDataBySteps(GetDataRequest
$request): GetDataByStepsResponse
307 $response =
new GetDataByStepsResponse();
310 if (!
$data->isSuccess())
316 ->setIsWorkflowFinished(
$data->getWorkflowIsFinished())
317 ->setAuthorStep($this->createAuthorStep(
$data))
318 ->setFirstStep(
$response->getAuthorStep())
321 $completedTasksCount =
$data->getCompletedTasksCount();
322 if ($completedTasksCount > 0)
326 ProgressBox::calculateProgressTasksCount($completedTasksCount,
$data->getWorkflowIsFinished())
331 if (
$data->getCompletedTask())
334 ->setCompletedStep($this->createCompletedStep(
$data))
335 ->setSecondStep(
$response->getCompletedStep())
339 if (
$data->getWorkflowIsFinished())
364 private function createAuthorStep(GetDataResponse
$data): Step
366 $authorId =
$data->getAuthorId();
367 $duration =
$data->getDurations();
370 (
new Step(WorkflowFacesStep::Author))
371 ->setAvatars($authorId > 0 ? [$authorId] : [])
372 ->setDuration((
int)($duration?->getRoundedAuthorDuration()))
376 private function createCompletedStep(GetDataResponse
$data): Step
378 $completedTask =
$data->getCompletedTask();
379 $completedTaskId = (int)$completedTask[
'ID'];
380 $duration =
$data->getDurations();
383 (
new Step(WorkflowFacesStep::Completed))
384 ->setAvatars(
$data->getTaskUserIds($completedTaskId))
385 ->setDuration((
int)($duration?->getRoundedCompletedDuration()))
386 ->setSuccess(
$data->isCompletedTaskStatusSuccess())
387 ->setTaskId($completedTaskId)
391 private function createDoneStep(GetDataResponse
$data): Step
393 $doneTask =
$data->getDoneTask();
394 $doneTaskId = $doneTask ? (int)$doneTask[
'ID'] : null;
395 $duration =
$data->getDurations();
398 (
new Step(WorkflowFacesStep::Done))
399 ->setAvatars($doneTaskId ?
$data->getTaskUserIds($doneTaskId) : [])
400 ->setDuration((
int)($duration?->getRoundedDoneDuration()))
401 ->setSuccess(!$doneTask ||
$data->isDoneTaskStatusSuccess())
402 ->setTaskId($doneTaskId ?: 0)
406 private function createRunningStep(GetDataResponse
$data): Step
408 $runningTask =
$data->getRunningTask();
409 $runningTaskId = $runningTask ? $runningTask[
'ID'] :
null;
410 $duration =
$data->getDurations();
413 (
new Step(WorkflowFacesStep::Running))
414 ->setAvatars($runningTaskId ?
$data->getTaskUserIds($runningTaskId) : [])
415 ->setDuration((
int)($duration?->getRoundedRunningDuration()))
416 ->setTaskId($runningTaskId ? : 0)
420 private function createTimeStep(GetDataResponse
$data): Step
422 if (
$data->getWorkflowIsFinished())
424 $durations =
$data->getDurations();
426 ($durations?->getRoundedAuthorDuration() ?? 0)
427 + ($durations?->getRoundedCompletedDuration() ?? 0)
428 + ($durations?->getRoundedDoneDuration() ?? 0)
432 (
new Step(WorkflowFacesStep::TimeFinal))
434 DurationFormatter::roundTimeInSeconds($totalDuration)
439 $timestamp =
$data->getWorkflowStarted()?->getTimestamp();
442 (
new Step(WorkflowFacesStep::TimeInWork))
444 DurationFormatter::roundTimeInSeconds($timestamp ? time() - $timestamp : 0)
451 $step = WorkflowFacesStep::tryFrom($id);
453 return $step ?
new Step($step) :
null;