3namespace Bitrix\Bizproc\Api\Service;
5use Bitrix\Bizproc\Api\Data\WorkflowStateService\WorkflowStateToGet;
6use Bitrix\Bizproc\Api\Request\WorkflowAccessService\CanViewTimelineRequest;
7use Bitrix\Bizproc\Api\Request\WorkflowStateService\GetAverageWorkflowDurationRequest;
8use Bitrix\Bizproc\Api\Request\WorkflowStateService\GetExecutionTimeRequest;
9use Bitrix\Bizproc\Api\Request\WorkflowStateService\GetEfficiencyDataRequest;
10use Bitrix\Bizproc\Api\Request\WorkflowStateService\GetTimelineRequest;
11use Bitrix\Bizproc\Api\Response\Error;
12use Bitrix\Bizproc\Api\Response\WorkflowStateService\GetAverageWorkflowDurationResponse;
13use Bitrix\Bizproc\Api\Response\WorkflowStateService\GetExecutionTimeResponse;
14use Bitrix\Bizproc\Api\Response\WorkflowStateService\GetEfficiencyDataResponse;
15use Bitrix\Bizproc\Api\Response\WorkflowStateService\GetFullFilledListResponse;
16use Bitrix\Bizproc\Api\Response\WorkflowStateService\GetListResponse;
17use Bitrix\Bizproc\Api\Response\WorkflowStateService\GetTimelineResponse;
18use Bitrix\Bizproc\Workflow\Entity\EO_WorkflowState_Collection;
19use Bitrix\Bizproc\Workflow\Entity\WorkflowDurationStatTable;
20use Bitrix\Bizproc\Workflow\Entity\WorkflowInstanceTable;
21use Bitrix\Bizproc\Workflow\Entity\WorkflowStateTable;
22use Bitrix\Bizproc\Workflow\Entity\WorkflowUserTable;
23use Bitrix\Bizproc\Workflow\Task\EO_Task_Collection;
24use Bitrix\Bizproc\Workflow\Task\TaskTable;
25use Bitrix\Bizproc\Workflow\Timeline;
26use Bitrix\Bizproc\Workflow\WorkflowState;
27use Bitrix\Main\SystemException;
28use Bitrix\Main\Type\DateTime;
32 private const CONVERTER_VERSION = 2;
34 private const THREE_DAYS_IN_SECONDS = 259200;
43 $query = WorkflowUserTable::query()
44 ->addSelect(
'WORKFLOW_ID')
45 ->addSelect(
'MODIFIED')
56 $query->registerRuntimeField($runtimeField);
59 $queryResult =
$query->exec();
63 $response->setTotalCount($queryResult->getCount());
65 $workflowStates = $queryResult->fetchAll();
66 $ids = array_column($workflowStates,
'WORKFLOW_ID');
67 $mods = array_column($workflowStates,
'MODIFIED');
72 if (
count($ids) === 1)
74 $query->where(
'ID',
'=', $ids[0]);
78 $query->whereIn(
'ID', $ids);
81 $collection =
$query->exec()->fetchCollection();
83 foreach ($ids as
$k => $id)
85 $workflowState = $collection->getByPrimary($id);
88 $responseCollection->add($workflowState);
90 $workflowTasks = $this->getWorkflowTasks($workflowState, $toGet);
91 if (isset($workflowTasks))
93 $response->setWorkflowTasks($id, $workflowTasks);
99 return $response->setWorkflowStatesCollection($responseCollection);
107 $activeTasksQuery = TaskTable::query()
108 ->setSelect($taskFields)
110 '=WORKFLOW_ID' => $workflowState->getId(),
114 ->setOrder([
'ID' =>
'DESC'])
118 if (isset($taskLimit))
120 $activeTasksQuery->setLimit($taskLimit);
123 $userActiveTasks = $activeTasksQuery->exec()->fetchCollection();
125 $remainingTasksCount =
null;
126 if (isset($taskLimit))
128 $remainingTasksCount = $taskLimit - $userActiveTasks->count();
131 if (isset($remainingTasksCount) && $remainingTasksCount <= 0)
133 return $userActiveTasks;
136 $workflowTasksQuery = TaskTable::query()
137 ->setSelect($taskFields)
139 '=WORKFLOW_ID' => $workflowState->getId(),
146 ->setOrder([
'ID' =>
'DESC'])
149 if (isset($remainingTasksCount))
151 $workflowTasksQuery->setLimit($remainingTasksCount);
154 return $userActiveTasks->merge($workflowTasksQuery->exec()->fetchCollection());
165 $getListResult = $this->
getList($toGet);
166 $collection = $getListResult->getWorkflowStatesCollection();
169 return $response->setWorkflowStatesList([]);
172 $fullFilledList = [];
174 foreach ($collection as $stateElement)
176 $tasksInfo = $stateElement->getTasksInfo();
177 foreach ($tasksInfo as $task)
179 if (!empty($task[
'TASK_USERS']))
181 foreach ($task[
'TASK_USERS'] as $row)
183 $userIds[$row[
'USER_ID']] =
true;
184 $userIds[$row[
'ORIGINAL_USER_ID']] =
true;
189 $fullFilledList[] = [
190 'ID' => $stateElement->getId(),
191 'STARTED' => $stateElement->getStarted(),
192 'MODIFIED' => $stateElement->getModified(),
193 'STATE_INFO' => $stateElement->getStateInfo(),
194 'DOCUMENT_INFO' => $this->getDocumentInfo($stateElement->getComplexDocumentId()),
195 'STARTED_USER_INFO' => [
196 'ID' => $stateElement->getStartedBy(),
198 'TASKS_INFO' => $tasksInfo,
199 'WORKFLOW_TEMPLATE_ID' => $stateElement->getWorkflowTemplateId(),
200 'TEMPLATE_NAME' => $stateElement->getTemplate()?->getName(),
201 'META' => $stateElement->getMeta()?->collectValues() ?? [],
204 $userIds[$stateElement->getStartedBy()] =
true;
209 ->setWorkflowStatesList($fullFilledList)
210 ->setMembersInfo($this->getMembersInfo(array_keys($userIds)))
218 return GetTimelineResponse::createError(
Error::fromCode(Error::WORKFLOW_NOT_FOUND));
221 $isAdmin = (new \CBPWorkflowTemplateUser(
$request->userId))->isAdmin();
228 $accessResponse = $accessService->canViewTimeline($accessRequest);
229 if (!$accessResponse->isSuccess())
235 $timeline = Timeline::createByWorkflowId(
$request->workflowId);
239 return GetTimelineResponse::createError(
Error::fromCode(Error::WORKFLOW_NOT_FOUND));
242 return GetTimelineResponse::createOk([
'timeline' => $timeline->setUserId(
$request->userId)]);
245 private function getDocumentInfo(
array $complexDocumentId):
array
247 $documentService = \CBPRuntime::getRuntime()->getDocumentService();
252 $complexDocumentType = $documentService->getDocumentType($complexDocumentId);
253 if ($complexDocumentType)
255 $key = $complexDocumentId[0] .
'@' . $complexDocumentId[1] .
'@' . $complexDocumentType[2];
260 $complexDocumentType =
null;
266 $cache[
$key] = $documentService->getDocumentTypeCaption($complexDocumentType);
268 $typeCaption =
$key ? $cache[
$key] :
'';
271 'COMPLEX_ID' => $complexDocumentId,
272 'COMPLEX_TYPE' => $complexDocumentType,
273 'NAME' => $documentService->getDocumentName($complexDocumentId),
274 'TYPE_CAPTION' => $typeCaption,
278 private function getMembersInfo(
array $ids):
array
285 $userFields = [
'ID',
'NAME',
'SECOND_NAME',
'LAST_NAME',
'LOGIN',
'TITLE',
'EMAIL',
'PERSONAL_PHOTO'];
287 $users = \CUser::GetList(
290 [
'ID' => implode(
'|', $ids)],
291 [
'FIELDS' => $userFields]
295 while (
$user = $users->Fetch())
297 $fullName = \CUser::FormatName(\CSite::GetNameFormat(
false),
$user,
true,
false);
298 $personalPhoto = (int)
$user[
'PERSONAL_PHOTO'];
301 'ID' => (int)(
$user[
'ID'] ?? 0),
302 'FULL_NAME' => $fullName,
303 'PERSONAL_PHOTO' => $personalPhoto,
310 private function convertProcesses(
int $userId)
317 $converterVersion = \CUserOptions::getOption(
319 'processes_converted',
324 if ($converterVersion === self::CONVERTER_VERSION)
329 WorkflowUserTable::convertUserProcesses(
$userId);
331 \CUserOptions::setOption(
333 'processes_converted',
334 self::CONVERTER_VERSION,
354 $averageDuration = WorkflowDurationStatTable::getAverageDurationByTemplateId(
$request->templateId);
355 if ($averageDuration !==
null)
357 $response->setAverageDuration($averageDuration);
368 if (
$request->workflowStarted ===
null)
370 return $response->addError(
new Error(
'incorrect workflowStarted'));
373 $startedTimestamp =
$request->workflowStarted?->getTimestamp();
374 if (WorkflowInstanceTable::exists(
$request->workflowId))
376 $currentTimestamp = (
new DateTime())->getTimestamp();
378 return $response->setExecutionTime($currentTimestamp - $startedTimestamp);
381 $modifiedTimestamp =
$request->workflowModified->getTimestamp();
383 return $response->setExecutionTime($modifiedTimestamp - $startedTimestamp);
388 $workflow = WorkflowStateTable::query()
393 'WORKFLOW_TEMPLATE_ID',
396 '=ID' => $workflowId,
397 '=STATE' =>
'Completed',
407 workflowId: $workflow->getId(),
408 workflowStarted: $workflow->getStarted(),
409 workflowModified: $workflow->getModified()
411 )->getRoundedExecutionTime();
414 templateId: $workflow->getWorkflowTemplateId(),
416 )->getRoundedAverageDuration();
418 executionTime: $executionTime,
419 averageDuration: $averageDuration ?? $executionTime
435 $averageDuration =
$request->averageDuration;
436 $currentDuration =
$request->executionTime;
438 $efficiency =
'stopped';
439 if (
null === $averageDuration)
441 $efficiency =
'first';
443 elseif ($currentDuration <= $averageDuration)
445 $efficiency =
'fast';
447 elseif ($currentDuration <= ($averageDuration + self::THREE_DAYS_IN_SECONDS))
449 $efficiency =
'slow';
if(!Loader::includeModule('catalog')) if(!AccessController::getCurrent() ->check(ActionDictionary::ACTION_PRICE_EDIT)) if(!check_bitrix_sessid()) $request
if(!is_object($USER)||! $USER->IsAuthorized()) $userId
setSelectAllFields(bool $flag=true)
getTimeline(GetTimelineRequest $request)
getEfficiencyData(GetEfficiencyDataRequest $request)
getExecutionTime(GetExecutionTimeRequest $request)
getList(WorkflowStateToGet $toGet)
getAverageWorkflowDuration(GetAverageWorkflowDurationRequest $request)
getCompletedWorkflowEfficiency(string $workflowId)
getFullFilledList(WorkflowStateToGet $toGet)
static fromCode(string $code, $customData=null)
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
if($NS['step']==6) if( $NS[ 'step']==7) if(COption::GetOptionInt('main', 'disk_space', 0) > 0) $info
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
if(empty($signedUserToken)) $key
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"