Version 4.1 by admin on 2026/06/07 17:49

Hide last authors
pugachevskaya_elena 1.1 1 Часто бывает полезно выявить неактивные пропуска, то есть пропуска, по которым давно не было никаких событий доступа. Для решения этой задачи в Платформе НЕЙРОСС реализован скрипт автоматизации, позволяет автоматически обнаружить неактивные пропуска и поместить их в отдельную группу, а также, при необходимости, — выполнить бессрочную приостановку пропуска.
2
3 Контролируются не все пропуска, а только пропуска выбранных владельцев.
4
5 Посредством настройки свойств скрипта автоматизации вы можете:
6
7 * задать имя группы для помещения пропусков;
8 * определить, требуется ли автоматически выполнять изъятие пропусков, либо решение будет принимать оператор бюро пропусков;
9 * задать период неактивности — временной интервал в днях, по истечении которого при отсутствии событий доступа пропуск считается неактивным;
10 * указать, требуется ли учитывать факт изменения пропуска совместно с событием доступа — пропуск будет считаться неактивным, если за заданный период не было ни события доступа, ни факта изменения пропуска оператором бюро пропусков;
11 * пометить, что пропуск приостановлен скриптом автоматизации.
12
13 {{info}}
14 Задание автоматизации может запускаться оператором вручную, по расписанию (например, раз в неделю по воскресеньям), либо по какому-либо событию/системному действию.
15 {{/info}}
16
17 **Пример: Найти пропуска, по которым не было событий доступа в течение 60 дней и поместить их в группу «Устаревшие пропуска»**
18
19 Задание автоматизации запускается автоматически ежедневно в 23:00, производится поиск за интервал в 60 дне. Найденные неактивные пропуска не приостанавливаются, остаются действительными и принадлежащими «своим» группам, но дополнительно помещаются в группу «Устаревшие пропуска». Анализируются только события доступа, факт изменения пропуска оператором АРМ Доступ не анализируется.
20
21 [[image:attach:card_inactivity_scrypt.png]]
22
23 \\
24
25 === {{id name="Контрольактивностипропуска-НастройкиСКУД"/}}Настройки СКУД ===
26
27 Вам потребуется:
28
29 1. Создать пользовательское свойство владельца пропуска для указания перечня лиц, для которых требуется проводить контроль активности пропуска.
30 1. Добавить свойство на форму владельца пропуска и задать в значение true для владельцев, чьи пропуска требуется анализировать.
31 1. Создать пользовательское свойство пропуска для пометок о том, что пропуск приостановлен скриптом.
32 1. Добавить свойство на форму пропуска.
33
34 Порядок действий:
35
36 |=(((
37 Задача
38 )))|=(((
39 Комментарий
40 )))
41 |(((
42 Создание пользовательского свойства
43 )))|(((
44 (% class="content-wrapper" %)
45 (((
46 В разделе **Настройки СКУД** АРМ НЕЙРОСС Доступ:
47
48 1. На вкладке **Свойства владельца пропуска** добавьте новое свойство, задайте название и ключ свойства, укажите тип «Переключатель».
49 [[image:attach:card_inactivity_appprp.png||height="250"]]
admin 4.1 50 1. На вкладке **Свойства пропуска** добавьте новое свойство, задайте название и ключ свойства, укажите тип «Переключатель».
pugachevskaya_elena 1.1 51 [[image:attach:PausedByScrypt_addprp.png||height="250"]]
52
53 [[doc:neyross.Настройка Платформы НЕЙРОСС.Настройка функций контроля доступа.Добавление пользовательских свойств.WebHome]]
54 )))
55 )))
56 |(((
57 Изменение формы владельца пропуска
58 )))|(((
59 (% class="content-wrapper" %)
60 (((
admin 4.1 61 В разделе **Персонал** АРМ НЕЙРОСС Доступ выберите группу пропусков, для которой нужно настроить контроль активности, перейдите к вкладке **Настройки группы**:
pugachevskaya_elena 1.1 62
admin 4.1 63 1. На вкладке (%%)**Форма ввода: Владелец пропуска** добавьте поле **Контроль активности** (название может быть любым) на форму владельца пропуска.
64 1. На вкладке **Форма ввода: Пропуск добавьте** поле **Приостановлен скриптом** (название может быть любым) на форму пропуска.
pugachevskaya_elena 1.1 65
66 {{info}}
67 Рекомендуем использовать Конструктор форм. При использовании нестандартных форм, обратитесь к специалистам компании ИТРИУМ за услугой по доработке формы.
68 {{/info}}
69
70 [[doc:neyross.Настройка Платформы НЕЙРОСС.Настройка функций контроля доступа.Настройка форм ввода данных.WebHome]]
71
admin 4.1 72 При необходимости вывода информации в таблице пропусков, на вкладке **Настройка таблицы** добавьте вывод данных свойств.
pugachevskaya_elena 1.1 73
admin 4.1 74 [[doc:neyross.Настройка Платформы НЕЙРОСС.Настройка функций контроля доступа.Настройка таблицы пропусков.WebHome]]
pugachevskaya_elena 1.1 75 )))
76 )))
77 |(((
78 Включение необходимости контроля активности пропуска
79 )))|(((
80 (% class="content-wrapper" %)
81 (((
82 Выберите владельцев, для которых требуется проводить контроль активности пропуска, и в режиме редактирования пропуска / группы пропусков в поле **Контроль активности** установите переключатель в положение [[image:attach:ui.Параметры узла.WebHome@fa-on.png||thumbnail="true" height="18"]]**Включено**. Сохраните данные владельца.
83
84 [[image:attach:card_inactivity_person_form.png||width="500"]]
85
86 [[doc:neyross.АРМ НЕЙРОСС Доступ.Управление пропусками.WebHome]]
87 )))
88 )))
89 |(((
90 Просмотр результатов работы скрипта
91 )))|(((
92 Дождитесь выполнения условия запуска задания (в нашем примере это 23:00 текущего дня).
93 )))
94
95 == {{id name="Контрольактивностипропуска-Настройкиавтоматизации"/}}Настройки автоматизации ==
96
admin 4.1 97 Скопируйте приведённый ниже код скрипта (% class="auto-cursor-target" style="color: rgb(23, 43, 77); color: rgb(23, 43, 77)" %)и создайте файл с произвольным именем и расширением **JSON**, например: (%%)//задание_автоматизации_Контроль_устаревших пропусков.json//(% class="auto-cursor-target" style="color: rgb(23, 43, 77); color: rgb(23, 43, 77)" %). Для этого удобно использовать простые текстовые редакторы типа Блокнот или Notepad++. Вы также можете обратиться к специалистам компании ИТРИУМ, мы вышлем подготовленный файл.
pugachevskaya_elena 1.1 98
admin 2.1 99 {{code language="java"}}
pugachevskaya_elena 1.1 100
101 import play.api.libs.json.Format
102 import beans.pacs.{PacsFolderBean, PassBean}
103 import extensions.automation.scripts.AutomationActionScript
104 import extensions.automation.signals.AutomationSignal
105 import models.common.UserIdentity
106 import models.neyross.{Pass, PassComponent}
107 import models.pacs.{PacsFolder, PacsFolderComponent}
108 import dto.pacs.PacsFolderMovementDto
109 import services.logging.web.{LoggerWithWeb => Logger}
110 import play.api.libs.json.{JsObject, Json}
111 import proto.neyross.PassProto
112 import services.common.{SystemLogService, SystemLogTag}
113 import services.neyross.NeyrossEmbedApiService
114 import slick.dbio.DBIOAction
115 import utils.TableExtension
116 import utils.bootstrap.CustomPostgresProfile
117 import utils.common.ScalaUtils
118
119 import java.time.OffsetDateTime
120 import java.util.UUID
121 import scala.concurrent.Future
122
123 class ObsoletePassControlAutomationScript extends AutomationActionScript {
124
125 val logger = Logger("ObsoletePassControlAutomationScript")
126
127 private val postgresProfile = ctx.dbConfig.profile.asInstanceOf[CustomPostgresProfile]
128
129 import postgresProfile.api._
130
131 implicit val ec = ctx.executionContext
132 private val neyrossEmbedApi = ctx.injector.instanceOf[NeyrossEmbedApiService]
133 private val pacsFolderBean = ctx.injector.instanceOf[PacsFolderBean]
134 private val systemLogService = ctx.injector.instanceOf[SystemLogService]
135 private val passBean = ctx.injector.instanceOf[PassBean]
136
137 private val folders = new PacsFolderComponent()(ctx.dbConfig)
138 private val passes = new PassComponent()(ctx.dbConfig, neyrossEmbedApi, ec)
139
140 // @parameter { "type": "string", "title": "Название группы для устаревших пропусков", "key": "workingFolder" }
141 val workingFolder = "Устаревшие пропуска"
142
143 // @parameter { "type": "string", "title": "Идентификатор свойства-признака контроля", "key": "shouldControlOutdateProperty", "description": "Контролироваться будут пропуска только тех владельцев, которые имеют данное свойство" }
144 val shouldControlOutdateProperty = "inactivity"
145
146 // @parameter { "type": "string", "title": "Значение свойства-признака контроля", "key": "shouldControlOutdatePropertyValue", "description": "Контролироваться будут пропуска только тех владельцев, которые имеют указанное значение данного свойства (true означает Да)" }
147 val shouldControlOutdatePropertyValue = "true"
148
149 // @parameter { "type": "select", "title": "Режим работы", "key": "mode", "options": [ { "value": "default", "label": "Помещение устаревших пропусков группу" }, { "value": "withStopping", "label": "Приостановка и помещение устаревших пропусков в группу" } ] }
150 val mode = "withStopping"
151
152 // @parameter { "type": "number", "title": "Максимальный период неактивности, дней", "key": "inactivityPeriod" }
153 val inactivityPeriod = 1
154
155 // @parameter { "type": "boolean", "title": "Анализировать время изменения пропуска", "key": "isUpdateTimeAnalysisEnabled", "description": "Если флаг установлен, при расчёте активности пропуска будут учитываться также события изменения пропуска оператором бюро пропусков. В противном случае будет анализироваться только время последнего прохода по данному пропуску" }
156 val isUpdateTimeAnalysisEnabled = false
157
158 // @parameter { "type": "string", "title": "Идентификатор свойства-маркера контроля", "key": "scriptMarkPropertyKey", "description": "При автоматической приостановке пропуска к нему будет добавлено свойство с данным идентификатором и значением true (Да). Вы можете вынести данное свойство на форму пропуска или в таблицу пропусков, при необходимости" }
159 val scriptMarkPropertyKey = "PausedByScrypt"
160
161 val modeLocalization: Map[String, String] =
162 Map(
163 "default" -> "Помещение устаревших пропусков в группу",
164 "withStopping" -> "Приостановка и помещение устаревших пропусков в группу"
165 )
166
167 logger.debug(s"mode: ${modeLocalization.getOrElse(mode, "")}")
168 logger.debug(s"modification time analysing: $isUpdateTimeAnalysisEnabled")
169 logger.debug(s"inactivity period: $inactivityPeriod")
170
171 override def onSignal(signal: AutomationSignal): Future[Unit] = {
172 workingFolder.trim match {
173 case "" =>
174 logger.warn("working folder name is empty. do nothing")
175 Future.unit
176 case nonEmptyFolderName =>
177 runWithNonEmptyFolderName(nonEmptyFolderName)
178 }
179 }
180
181 private def createFolderWithNameAndParent(name: String, parent: Option[String]) = {
182 val uuid = UUID.randomUUID().toString
183 val folder = PacsFolder(
184 id = None,
185 uuid = Some(uuid),
186 name = Some(name),
187 parent = parent,
188 isDefault = false,
189 templates = None,
190 defaultValues = None,
191 settings = None,
192 created = OffsetDateTime.now(),
193 deleted = false
194 )
195 folders.insert(folder).map(_ => Some(uuid))
196 }
197
198 private def getFolderUuidByName(folderName: String) = {
199 folders.folders
200 .filter(f => f.name === folderName && !f.deleted)
201 .result
202 .headOption
203 .flatMap({
204 case Some(folder) =>
205 DBIOAction.successful(folder.uuid)
206 case _ =>
207 folders
208 .findDefault()
209 .flatMap({
210 case Some(defaultFolder) if defaultFolder.uuid.nonEmpty =>
211 createFolderWithNameAndParent(folderName, defaultFolder.uuid)
212 case _ =>
213 logger.warn("there is no valid default folder. wtf?")
214 DBIOAction.successful(None)
215 })
216 })
217 }
218
219 private def isOutdated(timestamp: OffsetDateTime): Boolean = {
220 val threshold = OffsetDateTime.now().minusDays(inactivityPeriod)
221 logger.trace(s"checking if chosen timestamp $timestamp is older than threshold $threshold")
222 threshold.isAfter(timestamp)
223 }
224
225 private def isStoppedOrInOutdatedFolder(
226 pass: Pass,
227 outdatedFolderUuid: String,
228 passFolders: List[String]
229 ): Boolean = {
230 pass.getState.contains(PassProto.Pass.State.sSTOPPED) || passFolders.contains(outdatedFolderUuid)
231 }
232
233 private def isOutdatedPassRecord(record: PassRecord): Boolean = {
234 // from all pass times, choose latest one and check if it outdated
235 val lastAccessGrantedAtOption = record._2
236 val created = record._3
237 val lastUpdatedAtOption = record._4
238 logger.trace(s"last access granted: $lastAccessGrantedAtOption, created: $created, last updated: $lastUpdatedAtOption")
239 // in any cases, pass has "created" time
240 var latestTimeToCheck: OffsetDateTime = created
241 if (
242 lastAccessGrantedAtOption.isDefined &&
243 lastAccessGrantedAtOption.get.isAfter(latestTimeToCheck)
244 ) {
245 // last access event was later than created time - using it
246 latestTimeToCheck = lastAccessGrantedAtOption.get
247 }
248 if (isUpdateTimeAnalysisEnabled) {
249 if (
250 lastUpdatedAtOption.isDefined &&
251 lastUpdatedAtOption.get.isAfter(latestTimeToCheck)
252 ) {
253 // last update event was later than created time and last access time - using it
254 latestTimeToCheck = lastUpdatedAtOption.get
255 }
256 }
257 isOutdated(latestTimeToCheck)
258 }
259
260 private def getPassesToMove(records: Seq[PassRecord], outdatedFolderUuid: String): Seq[Pass] = {
261 records
262 .filter(record => {
263 logger.trace(s"pass ${record._5.uuid} handling")
264 !isStoppedOrInOutdatedFolder(record._5, outdatedFolderUuid, record._1.getOrElse(Nil)) &&
265 isOutdatedPassRecord(record)
266 })
267 .map(_._5)
268 }
269
270 type PassFolders = Option[List[String]]
271 type LastAccessGrantedAt = Option[OffsetDateTime]
272 type Created = OffsetDateTime
273 type LastUpdatedAt = Option[OffsetDateTime]
274 type PassRecord = (PassFolders, LastAccessGrantedAt, Created, LastUpdatedAt, Pass)
275
276 type PersonUUID = String
277 type PersonFolders = Option[Seq[String]]
278 type PersonRecord = (PersonUUID, PersonFolders)
279
280 private def personToControlHandler(
281 outdatedFolderUuid: String,
282 personRecord: PersonRecord
283 ): Future[Seq[String]] = {
284 val dbAction =
285 passes
286 .extendedPasses4(
287 TableExtension.folders(ctx.dbConfig),
288 TableExtension.lastAccessGrantedAt(ctx.dbConfig),
289 TableExtension.created(ctx.dbConfig),
290 TableExtension.lastUpdatedAt(ctx.dbConfig)
291 )
292 .filter(r => r.person === personRecord._1 && !r.deleted)
293 .result
294
295 ctx
296 .dbRun(dbAction)
297 .flatMap(result => {
298 logger.trace(s"found passes of person ${personRecord._1}: ${result.map(_._5.uuid)}")
299 val passesToMove = getPassesToMove(result, outdatedFolderUuid)
300 logger.trace(s"found outdated passes of person ${personRecord._1}: ${passesToMove.map(_.uuid)}")
301 if (passesToMove.nonEmpty) {
302 val isPersonInOutdatedFolder = personRecord._2.exists(_.contains(outdatedFolderUuid))
303 val personsToMove = Option.when(!isPersonInOutdatedFolder)(personRecord._1).toList
304 val dto = PacsFolderMovementDto(personsToMove, passesToMove.map(_.uuid))
305 pacsFolderBean.copyToFolder(outdatedFolderUuid, dto)(ui = null, None).map(_ => passesToMove.map(_.uuid))
306 } else {
307 Future.successful(Nil)
308 }
309 })
310 }
311
312 private def getPersonsToControl: Future[Vector[PersonRecord]] = {
313 val personsToControl =
314 sql"""
315 SELECT DISTINCT uuid, folders
316 FROM
317 neyross_person,
318 jsonb_to_recordset((person_json->>'properties'):: jsonb) AS props(key text, value text)
319 WHERE
320 key = '#${shouldControlOutdateProperty}' AND
321 value = '#${shouldControlOutdatePropertyValue}' AND
322 neyross_person.deleted = false
323 """.as[PersonRecord]
324
325 ctx.dbRun(personsToControl)
326 }
327
328 case class Property(key: String, value: String, index: Option[Long] = None)
329
330 object Property {
331 implicit val jsonFormat: Format[Property] = Json.format[Property]
332 }
333
334 private def stopPassesWithUuid(uuids: Seq[String]): Future[Unit] = {
335 ctx
336 .dbRun(passes.findByUuids(uuids))
337 .flatMap(updatedPasses => {
338 ScalaUtils
339 .sequentialTraverse(updatedPasses)(updatedPass => {
340 logger.trace(s"stopping pass ${updatedPass.uuid}; setting property $scriptMarkPropertyKey and disabled_from fields")
341 val passJson = updatedPass.toFullJson.asOpt[JsObject].get
342 val passProperties = (passJson \ "properties").asOpt[List[Property]].getOrElse(Nil)
343
344 val newPassProperties = passProperties.filter(p => {
345 p.key != scriptMarkPropertyKey
346 }) :+ Property(
347 scriptMarkPropertyKey,
348 "true"
349 )
350 val newPassJson = passJson ++ Json.obj(
351 "disabled_from" -> OffsetDateTime.now().toInstant.getEpochSecond.toInt,
352 "properties" -> Json.toJson(newPassProperties)
353 )
354 logger.trace(s"new pass json is: $newPassJson")
355 passBean
356 .updateV2(updatedPass.uuid, newPassJson)(UserIdentity.getFakeUserIdentityFor("Автоматизация"), None)
357 })
358 .map(_ => ())
359 })
360 }
361
362 private def runWithNonEmptyFolderName(folderName: String): Future[Unit] = {
363 systemLogService
364 .log(
365 SystemLogTag.NORMAL,
366 SystemLogTag.AUTOMATION
367 )(s"Запущен процесс контроля устаревших пропусков")
368 .map(_ => ())
369 ctx
370 .dbRun(getFolderUuidByName(folderName))
371 .flatMap({
372 case Some(folderUUID) =>
373 logger.debug(s"working folder is $folderName ($folderUUID)")
374 getPersonsToControl
375 .flatMap(persons => {
376 logger.debug(s"found persons to control: $persons")
377 ScalaUtils.sequentialTraverse(persons)(personToControlHandler(folderUUID, _))
378 })
379 .flatMap(uuids => {
380 val flatUuidsList = uuids.flatten.distinct
381 if (flatUuidsList.nonEmpty) {
382 val stopping = if (mode == "withStopping") {
383 stopPassesWithUuid(flatUuidsList)
384 } else {
385 Future.unit
386 }
387 stopping.flatMap(_ => {
388 val yesOrNo = Option
389 .when(isUpdateTimeAnalysisEnabled)("да")
390 .getOrElse("нет")
391 logger.debug(s"were moved ${flatUuidsList.size} passes")
392 val message =
393 s"""В группу '$folderName' было помещено ${flatUuidsList.size} пропусков.
394 |Режим работы: ${modeLocalization.getOrElse(mode, "")}.
395 |Анализировать время изменения пропуска: $yesOrNo
396 |Максимальный период неактивности: $inactivityPeriod дней""".stripMargin
397 systemLogService
398 .log(
399 SystemLogTag.NORMAL,
400 SystemLogTag.AUTOMATION
401 )(
402 message = message,
403 data = Some(Json.toJson(flatUuidsList))
404 )
405 .map(_ => ())
406 })
407 } else {
408 logger.debug("not found persons with obsolete persons or passes")
409 systemLogService
410 .log(
411 SystemLogTag.NORMAL,
412 SystemLogTag.AUTOMATION
413 )(s"Не найдено владельцев для контроля устаревших пропусков, либо все пропуска таких владельцев не являются устаревшими")
414 .map(_ => ())
415 }
416 })
417 case _ =>
418 Future.unit
419 })
420 Future.unit
421 }
422 }
423
424 new ObsoletePassControlAutomationScript
425 {{/code}}
426
427 (% class="auto-cursor-target" style="color: rgb(23, 43, 77); color: rgb(23, 43, 77)" %)Добавьте задание автоматизации
428
admin 1.3 429 1. (% class="auto-cursor-target" style="color: rgb(23, 43, 77); color: rgb(23, 43, 77)" %)В разделе **Автоматизация** нажмите на кнопку  **Добавить новое задание [[image:attach:ui.Параметры узла.WebHome@btn_add_new.png||thumbnail="true" height="18"]]**, нажмите на кнопку **Импорт** и укажите путь к подготовленному на предыдущем этапе файлу ~[[[Автоматизация>>doc:ui.Параметры узла.Автоматизация.WebHome||style="" shape="rect"]]].
pugachevskaya_elena 1.1 430 1. В блоке **Параметры сигнала** выберите **По расписанию**, настройте расписание (например, 0 23 * * * для ежедневного запуска, или 0 23 * * 1 для запуска раз в неделю по воскресеньям).
431 1. (((
432 В блоке **Параметры действия** настройте параметры задания автоматизации согласно таблице ниже.
433
434 |=(((
435 Параметр
436 )))|=(((
437 Комментарий
438 )))
439 |(((
440 Название группы устаревших пропусков
441 )))|(((
442 Название группы. При запуске скрипта проверяется наличие группы с указанным именем в группе **Все**. При отсутствии, — она будет создана. В эту группу помещаться все найденные пропуска и их владельцы. Если название пустое, задание не выполняется.
443 )))
444 |(((
445 Идентификатор свойства — признака контроля
446 )))|(((
447 Уникальный идентификатор пользовательского свойства владельца пропуска, созданный на этапе [[#Настройки СКУД>>doc:||anchor="Контрольактивностипропуска-НастройкиСКУД"]]. В нашем примере: inactivity
448 )))
449 |(((
450 Значение свойства — признака контроля
451 )))|(((
452 (% class="content-wrapper" %)
453 (((
454 * true — если требуется проверять пропуска, для владельцев которого в поле **Контроль пропусков** переключатель установлен в положение [[image:attach:ui.Параметры узла.WebHome@fa-on.png||thumbnail="true" height="18"]] **Включено**.
455 * false — если требуется проверять пропуска, для владельцев которого в поле **Контроль пропусков** переключатель установлен в положение [[image:attach:ui.Параметры узла.WebHome@fa-off.png||thumbnail="true" height="18"]] **Выключено**.
456
457 В нашем примере: true
458 )))
459 )))
460 |(((
461 Режим работы
462 )))|(((
463 Выберите из раскрывающегося списка требуемые действия с пропусками:  требуется ли просто помещать пропуска в дополнительную группу для принятия решения оператором о дальнейших действиях с пропуском, либо необходимо приостанавливать действие найденных пропусков и помещать в группу.
464
465 * Помещение устаревших пропусков в группу — просто помещать пропуска в дополнительную группу для принятия решения оператором о дальнейших действиях с пропуском. Пропуск остаётся действительным. Доступ по нему возможен.
admin 4.1 466 * Приостановка и помещение устаревших пропусков в группу — приостанавливать пропуск и помещать в дополнительную группу. Пропуск не удаляется из контроллеров доступа, но доступ блокируется.
pugachevskaya_elena 1.1 467 )))
468 |(((
469 Максимальный период неактивности, дней
470 )))|(((
471 Укажите временной интервал в днях (количество дней), по истечению которого пропуск без событий доступа считается устаревшим.
472 )))
473 |(((
474 Анализировать время изменения пропуска
475 )))|(((
476 Установите флаг в поле, если, помимо событий доступа при расчёте активности пропуска требуется учитывать не только события доступа, но и события изменения пропуска оператором бюро пропусков.
477 )))
478 |(((
admin 4.1 479 Идентификатор свойства-маркера контроля
pugachevskaya_elena 1.1 480 )))|(((
481 Уникальный идентификатор пользовательского свойства пропуска, значение которого будет устанавливаться в true для пропусков, которые приостановлены данным скриптом. В нашем примере: PausedByScrypt
482 )))
483
484 === {{id name="Контрольактивностипропуска-Алгоритмработы"/}}Алгоритм работы ===
485
486 (% class="wiki-list0" %)
487 1. Поиск владельцев, для которых в поле с указанным идентификатором задано указанное значение.
488 1. Поиск активных пропусков для найденных владельцев (если пропуск уже приостановлен или находится в группе устаревших пропусков операции с ним не выполняются).
489 1. Поиск времени «активизации пропуска»:
490 (% class="wiki-list0" %)
491 11. Если флаг в поле **Анализировать время изменения пропуска** установлен, то выбирается наиболее позднее из времени последнего редактирования и времени последнего прохода по пропуску
492 11. Если флаг не установлен, выбирается время последнего прохода по пропуску.
493 1. Если «время активизации» раньше чем (% class="inline-code" %)##текущее время минус **Максимальный период неактивности**,##(%%) пропуск дополнительно помещается в группу устаревших пропусков.
494 1. Если указан режим работы «Приостановка и перемещение устаревших пропусков в группу», все найденные пропуска бессрочно приостанавливаются. В поле** Приостановлен с** задаётся текущее время.
495 )))
496 1. Нажмите на кнопку **Сохранить задание**.
497
498 {{error}}
499 **ВАЖНО**
500
admin 4.1 501 В НЕЙРОСС пропуск не «привязывается» жёстко к одной группе. Принадлежность пропуска группе пропусков является просто свойством пропуска. Пропуск может принадлежать нескольким группам одновременно. При помещении пропуска в группу **Устаревшие пропуска**, пропуск остаётся также и в групе, в которой он располагался до запуска скрипта. Изъятие пропуска из группы осуществляется оператором АРМ Доступ с помощью команды (% style="text-align: left;" %)**Другие действия** (% style="text-align: left;" %)**> Действие с группами > Изъять из текущей группы.**
pugachevskaya_elena 1.1 502 {{/error}}
503
504 === {{id name="Контрольактивностипропуска-Запускзадания"/}}Запуск задания ===
505
admin 4.1 506 Дождитесь выполнения условия запуска задания или запустите задание вручную. Для ручного запуска в поле **Тип сигнала** выберите значение **По HTTP-запросу**, сохраните задание и нажмите отправить запрос(%%).
pugachevskaya_elena 1.1 507
508 [[image:attach:task_run_manually.png||height="205"]]
509
510 Вы можете отслеживать процедуру инициализации и выполнения задания в Журнале аудита ~[[[doc:ui.Журнал аудита.WebHome]]].
511
512 [[image:attach:card_inactivity_scrypt_log.png||width="900"]]
513
514 Запуск и выполненные скриптом действия фиксируются в системном журнале ~[[[doc:ui.Системный журнал.WebHome]]].
515
516 [[image:attach:card_inactivity_journal.png]]
517
518 Если в поле** Режим работы** задана необходимость приостановки пропуска. В системном журнале отражается факт блокировки действия на контроллерах и задания срока приостановки с текущего времени:
519
520 [[image:attach:card_inactivity_journal1.png]]
521
522 Пропуска приостанавливаются с текущего времени, свойство **Приостановлен скриптом** у приостановленных пропусков устанавливается в значение **Да** (true).
523
524 [[image:attach:card_inactivity_card_form.png||height="250"]]

Платформа НЕЙРОСС