1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
workflowusertable.php
См. документацию.
1<?php
2
3namespace Bitrix\Bizproc\Workflow\Entity;
4
5use Bitrix\Main\Application;
6use Bitrix\Main\ORM\Data\DataManager;
7use Bitrix\Main\ORM\Fields\IntegerField;
8use Bitrix\Main\ORM\Fields\StringField;
9use Bitrix\Main\ORM\Fields\DatetimeField;
10use Bitrix\Main\ORM\Fields\Relations\Reference;
11use Bitrix\Main\ORM\Query\Join;
12use Bitrix\Main\Type\DateTime;
13use Bitrix\Bizproc\Integration\Push\WorkflowPush;
14
32{
33 public const WORKFLOW_STATUS_ACTIVE = 0;
34 public const WORKFLOW_STATUS_COMPLETED = 1;
35
36 public const TASK_STATUS_NONE = 0;
37 public const TASK_STATUS_COMPLETED = 1;
38 public const TASK_STATUS_ACTIVE = 2;
39
40
41 public static function getTableName()
42 {
43 return 'b_bp_workflow_user';
44 }
45
46 public static function getMap()
47 {
48 return [
49 (new IntegerField('USER_ID'))
50 ->configurePrimary()
51 ,
52 (new StringField('WORKFLOW_ID'))
53 ->configureSize(32)
54 ->configurePrimary()
55 ,
56 (new IntegerField('IS_AUTHOR'))
57 ->configureNullable(false)
58 ,
59 (new IntegerField('WORKFLOW_STATUS'))
60 ->configureNullable(false)
61 ,
62 (new IntegerField('TASK_STATUS'))
63 ->configureNullable(false)
64 ,
65 (new DatetimeField('MODIFIED'))
66 ->configureNullable(false)
67 ,
68 (new Reference(
69 'FILTER',
70 WorkflowFilterTable::class,
71 Join::on('this.WORKFLOW_ID', 'ref.WORKFLOW_ID')
72 ))
73 ->configureJoinType(Join::TYPE_INNER)
74 ,
75 (new Reference(
76 'COMMENTS',
77 WorkflowUserCommentTable::class,
78 Join::on('this.WORKFLOW_ID', 'ref.WORKFLOW_ID')
79 ->whereColumn('this.USER_ID', 'ref.USER_ID')
80 )),
81 ];
82 }
83
84 public static function syncOnWorkflowUpdated(\CBPWorkflow $workflow, int $status): void
85 {
86 $workflowId = $workflow->getInstanceId();
87 $users = static::getTaskUsers($workflowId);
88 $hasUsers = !empty($users) || static::hasStoredUsers($workflowId);
89
90 if (!$hasUsers && !static::isLiveFeedProcess($workflow->getDocumentId()))
91 {
92 return;
93 }
94
95 $authorId = $workflow->getStartedBy();
97 ? static::WORKFLOW_STATUS_COMPLETED
98 : static::WORKFLOW_STATUS_ACTIVE
99 ;
100
101 if ($authorId)
102 {
103 $users[$authorId]['IS_AUTHOR'] ??= 1;
104 }
105
106 foreach ($users as $id => $user)
107 {
108 $users[$id]['WORKFLOW_STATUS'] = $workflowStatus;
109 $users[$id]['IS_AUTHOR'] ??= 0;
110 }
111
112 static::syncUsers($workflowId, $users);
113 }
114
115 public static function syncOnTaskUpdated(string $workflowId): array
116 {
117 $users = static::getTaskUsers($workflowId);
118
119 return static::syncUsers($workflowId, $users);
120 }
121
122 public static function getUserIdsByWorkflowId(string $workflowId): array
123 {
124 $result = static::getList([
125 'select' => ['USER_ID'],
126 'filter' => ['=WORKFLOW_ID' => $workflowId],
127 ])->fetchAll();
128
129 $ids = array_column($result, 'USER_ID');
130 return array_map(
131 static fn($id) => (int)$id,
132 $ids,
133 );
134 }
135
136 public static function touchWorkflowUsers(string $workflowId, array $userIds): void
137 {
138 static::updateOnSync(
139 $workflowId,
140 array_fill_keys($userIds, [/* MODIFIED = new DateTime() */])
141 );
142 }
143
144 private static function isLiveFeedProcess(array $documentId): bool
145 {
146 return ($documentId[0] ?? '') === 'lists' && ($documentId[1] ?? '') === 'BizprocDocument';
147 }
148
149 private static function getTaskUsers(string $workflowId): array
150 {
151 $taskUsers = \CBPTaskService::getWorkflowUsers($workflowId);
152 $users = [];
153
154 foreach ($taskUsers as $id => $taskStatus)
155 {
156 $users[$id] = [
157 'TASK_STATUS' => $taskStatus === \CBPTaskUserStatus::Waiting
158 ? static::TASK_STATUS_ACTIVE
159 : static::TASK_STATUS_COMPLETED
160 ,
161 ];
162 }
163
164 $authorId = static::getAuthorId($workflowId);
165 if ($authorId && !isset($users[$authorId]))
166 {
167 $users[$authorId] = [
168 'TASK_STATUS' => static::TASK_STATUS_NONE,
169 ];
170 }
171
172 return $users;
173 }
174
175 private static function syncUsers(string $workflowId, array $users): array
176 {
177 $stored = static::getStoredUsers($workflowId);
178
179 $toDelete = array_diff_key($stored, $users);
180 $toAdd = array_diff_key($users, $stored);
181 $toUpdate = array_intersect_key($users, $stored);
182
183 self::deleteOnSync($workflowId, $toDelete);
184 self::addOnSync($workflowId, $toAdd);
185 self::updateOnSync($workflowId, $toUpdate, $stored);
186
187 return [array_keys($toAdd), array_keys($toUpdate), array_keys($toDelete)];
188 }
189
190 private static function getAuthorId(string $workflowId): int
191 {
192 $result = static::getList([
193 'select' => ['USER_ID'],
194 'filter' => [
195 '=WORKFLOW_ID' => $workflowId,
196 '=IS_AUTHOR' => 1,
197 ],
198 ])->fetch();
199
200 return (int)($result['USER_ID'] ?? 0);
201 }
202
203 private static function deleteOnSync(string $workflowId, array $toDelete): void
204 {
205 if (!$toDelete)
206 {
207 return;
208 }
209
210 $deleted = array_keys($toDelete);
211 foreach ($deleted as $userId)
212 {
213 static::delete([
214 'USER_ID' => $userId,
215 'WORKFLOW_ID' => $workflowId,
216 ]);
217 }
218
220 WorkflowPush::pushDeleted($workflowId, $deleted);
221 }
222
223 private static function addOnSync(string $workflowId, array $toAdd): void
224 {
225 if (!$toAdd)
226 {
227 return;
228 }
229
230 foreach ($toAdd as $userId => $user)
231 {
232 static::add([
233 'USER_ID' => $userId,
234 'WORKFLOW_ID' => $workflowId,
235 'IS_AUTHOR' => $user['IS_AUTHOR'] ?? 0,
236 'WORKFLOW_STATUS' => $user['WORKFLOW_STATUS'] ?? static::WORKFLOW_STATUS_ACTIVE,
237 'TASK_STATUS' => $user['TASK_STATUS'] ?? static::TASK_STATUS_NONE,
238 'MODIFIED' => new DateTime(),
239 ]);
240 }
241
242 WorkflowPush::pushAdded($workflowId, array_keys($toAdd));
243 }
244
245 private static function updateOnSync(string $workflowId, array $toUpdate, ?array $stored = null): void
246 {
247 if (!$toUpdate)
248 {
249 return;
250 }
251
252 $modified = new DateTime();
253
254 foreach ($toUpdate as $userId => $user)
255 {
256 if (
257 isset($stored[$userId])
258 && $user['TASK_STATUS'] !== static::TASK_STATUS_ACTIVE
259 && static::isEqualUser($user, $stored[$userId])
260 )
261 {
262 unset($toUpdate[$userId]);
263 continue;
264 }
265
266 $user['MODIFIED'] ??= $modified;
267
268 static::update(
269 [
270 'USER_ID' => $userId,
271 'WORKFLOW_ID' => $workflowId,
272 ],
273 $user
274 );
275 }
276
277 WorkflowPush::pushUpdated($workflowId, array_keys($toUpdate));
278 }
279
280 private static function isEqualUser(array $userA, array $userB): bool
281 {
282 return (
283 ($userA['IS_AUTHOR'] ?? null) === ($userB['IS_AUTHOR'] ?? null)
284 && ($userA['WORKFLOW_STATUS'] ?? null) === ($userB['WORKFLOW_STATUS'] ?? null)
285 && ($userA['TASK_STATUS'] ?? null) === ($userB['TASK_STATUS'] ?? null)
286 );
287 }
288
289 private static function getStoredUsers(string $workflowId): array
290 {
291 $result = static::getList([
292 'select' => ['USER_ID', 'IS_AUTHOR', 'WORKFLOW_STATUS', 'TASK_STATUS'],
293 'filter' => ['=WORKFLOW_ID' => $workflowId],
294 ]);
295
296 $users = [];
297
298 while ($row = $result->fetch())
299 {
300 $users[(int)$row['USER_ID']] = [
301 'IS_AUTHOR' => (int)$row['IS_AUTHOR'],
302 'WORKFLOW_STATUS' => (int)$row['WORKFLOW_STATUS'],
303 'TASK_STATUS' => (int)$row['TASK_STATUS'],
304 ];
305 }
306
307 return $users;
308 }
309
310 private static function hasStoredUsers(string $workflowId): bool
311 {
312 return static::getCount(['=WORKFLOW_ID' => $workflowId]) > 0;
313 }
314
315 public static function deleteByWorkflow(string $workflowId): array
316 {
317 $stored = static::getStoredUsers($workflowId);
318 self::deleteOnSync($workflowId, $stored);
319
320 return array_keys($stored);
321 }
322
323 public static function onDocumentDelete(array $docId): void
324 {
325 $stateIds = WorkflowStateTable::getIdsByDocument($docId, 1000);
326
327 if (!$stateIds)
328 {
329 return;
330 }
331
332 $connection = Application::getConnection();
333 $sqlHelper = $connection->getSqlHelper();
334 $tableName = $sqlHelper->forSql(static::getTableName());
335 $sqlQuery = sprintf(
336 'DELETE from %s WHERE WORKFLOW_ID IN(%s)',
337 $tableName,
338 implode(',', array_map(fn($id) => "'{$id}'", $stateIds))
339 );
340
341 $connection->queryExecute($sqlQuery);
342 }
343
344 public static function convertUserProcesses(int $userId): void
345 {
346 $connection = Application::getConnection();
347
348 if ($connection->getType() !== 'mysql')
349 {
350 return;
351 }
352
353 //truncate first
354 $connection->query(
355 <<<SQL
356 DELETE FROM b_bp_workflow_user WHERE USER_ID = {$userId}
357 SQL
358 );
359
360 // convert user "Live Feed" workflows (lists + BizprocDocument)
361 $connection->query(
362 <<<SQL
363 INSERT INTO b_bp_workflow_user
364 (USER_ID, WORKFLOW_ID, IS_AUTHOR, WORKFLOW_STATUS, MODIFIED)
365 (
366 select wt.STARTED_BY, wt.ID, 1, case when wi.id is null then 1 else 0 end, wt.MODIFIED
367 from b_bp_workflow_state wt
368 left join b_bp_workflow_instance wi on (wt.id = wi.id)
369 where wt.STARTED_BY = {$userId} and wt.MODULE_ID = 'lists' and wt.ENTITY = 'BizprocDocument'
370 )
371 ON DUPLICATE KEY UPDATE IS_AUTHOR = 1, WORKFLOW_STATUS = VALUES(WORKFLOW_STATUS), MODIFIED = VALUES(MODIFIED)
372 SQL
373 );
374
375 // convert my active tasks
376 $connection->query(
377 <<<SQL
378 INSERT INTO b_bp_workflow_user
379 (USER_ID, WORKFLOW_ID, IS_AUTHOR, WORKFLOW_STATUS, TASK_STATUS, MODIFIED)
380 (
381 select tu.USER_ID, t.WORKFLOW_ID, 0, 0, 2,
382 case when tu.DATE_UPDATE is null then now() else tu.DATE_UPDATE end
383 from b_bp_task_user tu
384 inner join b_bp_task t on (t.ID = tu.TASK_ID)
385 where tu.USER_ID = {$userId} and tu.STATUS = '0'
386 )
387 ON DUPLICATE KEY UPDATE TASK_STATUS = VALUES(TASK_STATUS), MODIFIED = VALUES(MODIFIED)
388 SQL
389 );
390
391 //convert other tasks
392 \Bitrix\Bizproc\Worker\Task\UserToWorkflowStepper::bindUser($userId);
393 }
394}
return select
Определения access_edit.php:440
$connection
Определения actionsdefinitions.php:38
if(!is_object($USER)||! $USER->IsAuthorized()) $userId
Определения check_mail.php:18
static pushDeleted(mixed $itemId,... $userIds)
Определения basepush.php:28
static pushAdded(mixed $itemId,... $userIds)
Определения basepush.php:18
static pushUpdated(mixed $itemId,... $userIds)
Определения basepush.php:23
static getIdsByDocument(array $documentId, ?int $limit=null)
Определения workflowstate.php:141
static deleteUsersByWorkflow(array $userIds, string $workflowId)
Определения workflowusercommenttable.php:197
static onDocumentDelete(array $docId)
Определения workflowusertable.php:323
static getUserIdsByWorkflowId(string $workflowId)
Определения workflowusertable.php:122
static syncOnWorkflowUpdated(\CBPWorkflow $workflow, int $status)
Определения workflowusertable.php:84
static deleteByWorkflow(string $workflowId)
Определения workflowusertable.php:315
static convertUserProcesses(int $userId)
Определения workflowusertable.php:344
static touchWorkflowUsers(string $workflowId, array $userIds)
Определения workflowusertable.php:136
static syncOnTaskUpdated(string $workflowId)
Определения workflowusertable.php:115
static getWorkflowUsers(string $workflowId)
Определения taskservice.php:196
const Waiting
Определения constants.php:273
Определения workflow.php:9
getDocumentId()
Определения workflow.php:61
getStartedBy()
Определения workflow.php:76
getInstanceId()
Определения workflow.php:26
static isFinished(int $status)
Определения constants.php:115
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
hidden mSiteList<?=htmlspecialcharsbx(serialize( $siteList))?><?=htmlspecialcharsbx( $siteList[ $j]["ID"])?> _Propery<? if(((COption::GetOptionString( $module_id, "different_set", "N")=="Y") &&( $j !=0))||(COption::GetOptionString( $module_id, "different_set", "N")=="N")) echo "display: none;"?> top adm detail content cell l top adm detail content cell r heading center center ID left
Определения options.php:768
$result
Определения get_property_values.php:14
$status
Определения session.php:10
$user
Определения mysql_to_pgsql.php:33