Аддоны: различия между версиями
Arhidiman (обсуждение | вклад) |
Arhidiman (обсуждение | вклад) |
||
| Строка 489: | Строка 489: | ||
[[Файл:Check-user-rights.png|frame]] | [[Файл:Check-user-rights.png|frame]] | ||
Проверяет права доступа пользователя к определённым ресурсам (объекты анализа, методики, записи ЛЖ). Отображает таблицу с типами доступа (чтение, запись и т.д.) и наличием прав по каждому ресурсу. | Проверяет права доступа пользователя к определённым ресурсам (объекты анализа, методики, записи ЛЖ). Отображает таблицу с типами доступа (чтение, запись и т.д.) и наличием прав по каждому ресурсу. | ||
<div class="mw-collapsible mw-collapsed"> | |||
<div style="display: flex; align-items: center; gap: 2px;"> | |||
<strong>Просмотр кода</strong> | |||
<span class="mw-collapsible-toggle-placeholder"></span> | |||
</div> | |||
<div class="mw-collapsible-content"> | |||
<syntaxhighlight lang="typescript"> | |||
import { getDataFromDialog } from "../../src/gui/api" | |||
import { apiInstance } from "../../src/servivces/worker/api/interactors/ApiInstance" | |||
import { | |||
PermissionController, | |||
PermissionResource, | |||
PermissionRwAccess | |||
} from "../../src/servivces/worker/api/controllers/permisson" | |||
import { TableBuilder } from "../../src/gui/builder" | |||
import type { DialogType, TableConfig } from "@triteia/types-integration-gui" | |||
import type { JournalRecordRouteDto } from "../../src/servivces/worker/api/controllers/journal-records" | |||
const accessNamesMap = { | |||
[PermissionRwAccess.EXEC]: 'Выполнение', | |||
[PermissionRwAccess.READ]: 'Чтение', | |||
[PermissionRwAccess.WRITE]: 'Запись', | |||
} | |||
const requiredResources = [ | |||
PermissionResource.ANALYSIS_OBJECT, | |||
PermissionResource.METHODOLOGY, | |||
PermissionResource.JOURNAL_RECORD | |||
] | |||
const resourcesNamesMap = { | |||
[PermissionResource.ANALYSIS_OBJECT]: 'Объекты анализа', | |||
[PermissionResource.METHODOLOGY]: 'Методики', | |||
[PermissionResource.JOURNAL_RECORD]: 'Записи ЛЖ' | |||
} | |||
const getAccessRightsTable = async (tableBuilder: TableBuilder, permissionController: PermissionController): Promise<TableConfig> => { | |||
const rows = (await Promise.all(requiredResources.map(async (source: PermissionResource) => { | |||
const sourceCombinations = await Promise.all(Object.keys(PermissionRwAccess).map(async (action) => { | |||
const access = await permissionController.getSourcePermission(source, PermissionRwAccess[action]) | |||
return { source: resourcesNamesMap[source], action: accessNamesMap[PermissionRwAccess[action]], access: access.hasPermission } | |||
})) | |||
return sourceCombinations | |||
} | |||
))).flat() | |||
const table = tableBuilder | |||
.name('simpleTable') | |||
.label('Таблица') | |||
.isAddable(false) | |||
.actionsCol(false) | |||
.addColumn('Ресурс', 'source', false) | |||
.config('input', { name: 'source', rules: [{ required: true }] }, { placeholder: '', disabled: false }) | |||
.next() | |||
.addColumn('Тип доступа', 'action', false) | |||
.config('input', { name: 'action' }, { type: 'string', placeholder: '', disabled: false }) | |||
.next() | |||
.addColumn('Доступ', 'access', false) | |||
.config('checkbox', { name: 'access' }, { type: 'boolean', placeholder: '', disabled: false }) | |||
.next() | |||
.setRows(rows) | |||
.build(); | |||
return table | |||
} | |||
const messages = { | |||
socketNotFound: 'Отсутствует соединение с клиентом. Дальнейшее выполнение аддона невозможно', | |||
queryParamsNotFound: 'Отсутствуют необходимые параметры для выполнения аддона. Дальнейшее выполнение невозможно', | |||
route: (routes: JournalRecordRouteDto[], recordId: number) => `Маршрут пробы: ${routes.map(r => `"${r.stageName}"`).join(' -> ')}. Id записи ЛЖ: ${recordId}`, | |||
notMoved: (recordId: number) => `Движение пробы не происходило. Id записи ЛЖ: ${recordId}`, | |||
} | |||
const errorHandlers = { | |||
queryParamsError: () => { | |||
throw new Error(messages.queryParamsNotFound) | |||
}, | |||
socketError: () => { | |||
throw new Error(messages.socketNotFound) | |||
} | |||
} | |||
const getConfig = (type: DialogType, title: string, message) => { | |||
return { | |||
type, | |||
config: { | |||
title, | |||
message | |||
} | |||
} | |||
} | |||
const getSocketId = (queryParams: any) => { | |||
const socketId = Array.isArray(queryParams?.socketId) && queryParams?.socketId?.length ? queryParams?.socketId[0] : ''; | |||
if (!queryParams) errorHandlers.queryParamsError() | |||
if (!socketId) errorHandlers.socketError() | |||
return socketId | |||
} | |||
const showErrorMessage = async (message: string, socketId) => getDataFromDialog(getConfig('confirm', 'Ошибка', message), socketId); | |||
const showTable = async (builder: TableBuilder, controller: PermissionController, socketId: string) => | |||
await getDataFromDialog({ type: 'input-data', config: [await getAccessRightsTable(builder, controller)] }, socketId) | |||
async function main({ queryParams }) { | |||
if (!queryParams) errorHandlers.queryParamsError() | |||
const socketId = getSocketId(queryParams) | |||
try { | |||
await showTable(new TableBuilder, new PermissionController(apiInstance), socketId) | |||
} catch (err) { | |||
await showErrorMessage(err.message, socketId) | |||
return { error: err.message } | |||
} | |||
} | |||
module.exports = { main } | |||
</syntaxhighlight> | |||
</div> | |||
</div> | |||
== Заполнение атрибутов записи ЛЖ. <code>fill-record-fields</code> == | == Заполнение атрибутов записи ЛЖ. <code>fill-record-fields</code> == | ||
Версия от 01:38, 2 апреля 2026
Список демонстрационных аддонов, показывающих возможности интеграционного сервиса.
Проверка даты регистрации. check-registration-date

Проверяет, не истёк ли срок регистрации пробы. Сравнивает дату регистрации из указанного поля с текущей датой. Если прошло более заданного количества дней (по умолчанию — 10), выдаёт ошибку. В противном случае показывает сообщение об успешной проверке.
Просмотр кода
import { JournalRecordManager } from "../../src/servivces/worker/api/interactors"
import { MessageBoxResults } from "@triteia/types-integration-gui"
import { getDataFromDialog } from "../../src/gui/api"
import { DialogType } from "@triteia/types-integration-gui"
const config = {
dateField: 'Дата регистрации',
expirationLimit: 10,
journalRecordId: 201, // Лаб. воздуха / Анализы завершены
integrationResult: { message: 'Срок регистрации пробы не истёк !'}
}
const messages = {
queryParamsNotFound: 'Отсутствуют необходимые параметры для выполнения аддона. Дальнейшее выполнение невозможно',
socketNotFound: 'Отсутствует соединение с клиентом. Дальнейшее выполнение аддона невозможно',
success: (recordId) => `Срок регистрации пробы не истёк ! Id записи ${recordId}`,
expired: (limit, recordId) => `Срок регистрации пробы истёк!\nПрошло более ${ limit } дней с момента регистрации. Id записи: ${recordId}`,
dateField: (dateField, stageName, journalRecordId) => [
`Не заполнено либо отсутствует поле "${dateField}"`,
`в этапе "${stageName || ''}".\nId записи: ${journalRecordId}`
].join(' ')
}
const errorHandlers = {
queryParamsError: () => {
throw new Error(messages.queryParamsNotFound)
},
socketError: () => {
throw new Error(messages.socketNotFound)
},
dateError: (dateField, stageName, journalRecordId) => {
throw new Error(messages.dateField(dateField, stageName, journalRecordId))
},
expirationError: () => {
throw new Error(messages.expired(config.expirationLimit, config.journalRecordId))
}
}
const getSocketId = (queryParams: any) => {
const socketId = Array.isArray(queryParams?.socketId) && queryParams?.socketId?.length ? queryParams?.socketId[0] : '';
if (!queryParams) errorHandlers.queryParamsError()
if (!socketId) errorHandlers.socketError()
return socketId
}
const getDaysByDate = (date: Date) => {
const dayMs = 60 * 60 * 24 * 1000
const timestamp = date.getTime()
return timestamp/dayMs
}
const getConfig = (type: DialogType, title: string, message) => {
return {
type,
config: {
title,
message
}
}
}
const getExpirationOffset = (registrationDate: string) => {
const regDate = new Date(registrationDate)
const today = new Date()
return getDaysByDate(today) - getDaysByDate(regDate)
}
const showErrorMessage = async (message: string, socketId) => getDataFromDialog(getConfig('confirm', 'Ошибка', message), socketId);
const showSuccessMessage = async (message: string, socketId) => getDataFromDialog(getConfig('confirm', 'Внимание', message), socketId);
async function main({ queryParams }) {
const socketId = getSocketId(queryParams)
try {
const journalRecordManager = await JournalRecordManager(config.journalRecordId)
const date = journalRecordManager.getFieldValue(config.dateField)
if (!date) errorHandlers.dateError(config.dateField, journalRecordManager?.data?.stage?.stage?.name, config.journalRecordId)
const expirationOffset = getExpirationOffset(date as string)
if (expirationOffset >= config.expirationLimit) errorHandlers.expirationError()
await showSuccessMessage(messages.success(config.journalRecordId), socketId)
return config.integrationResult
} catch (err) {
await showErrorMessage(err.message, socketId)
return { error: err.message }
}
}
module.exports = { main }
Проверка заполненности полей показателей. check-indicator-fields-filled

Проверяет заполненность полей показателей в записи журнала по настраиваемому списку. Проверяет наличие определённых показателей (например, "Аммоний-ион") и заполненность у них таких полей, как исполнители, методики, средний результат и др. Выдаёт ошибку, если показатели отсутствуют или не все поля заполнены.
Просмотр кода
import { JournalRecordManager } from "../../src/servivces/worker/api/interactors"
import { getDataFromDialog } from "../../src/gui/api"
import type { DialogType } from "@triteia/types-integration-gui"
import type { JournalRecordIndicatorResponse } from "../../src/servivces/worker/api/controllers/journal-records"
import type { IJournalRecordManager } from "../../src/servivces/worker/api/interactors/JournalRecordManager/interface"
type IndicatorProp = { label: string, get: () => unknown }
type IndicatorPropsConfig = Record<string, IndicatorProp>
const indicatorPropsConfig = (indicator): IndicatorPropsConfig => {
return {
executors: {
label: 'Исполнители',
get: () => indicator?.result?.executors
},
methodic: {
label: 'Методики',
get: () => indicator?.methodics
},
averageResult: {
label: 'Средний результат',
get: () => indicator?.result?.averageValue
},
averageRoundedValue: {
label: 'Средний округлённый результат',
get: () => indicator?.result?.averageRoundedValue
}
}
}
const config = {
requiredFields: [
'Источник',
'Место отбора',
'Дата регистрации',
'Шифр пробы',
'Время регистрации'
],
indicatorsList: [
'Аммоний-ион'
],
journalRecordId: 144, // Мк / Тест_Ушакова
integrationResult: { message: 'Все поля заполнены!' }
}
const messages = {
socketNotFound: 'Отсутствует соединение с клиентом. Дальнейшее выполнение аддона невозможно',
queryParamsNotFound: 'Отсутствуют необходимые параметры для выполнения аддона. Дальнейшее выполнение невозможно',
success: 'Все необходимые поля заполнены!',
emptyIndicators: (recordId) => `в записи с Id ${recordId} отсутствуют показатели`,
emptyFieldsError: (fields, recordId) => `Поля ${fields.map(f => `"${f}"`).join(', ')} не заполнены в записи с ID ${recordId}`,
indicators: (indicators: string[], recordId) => `Показатели ${indicators.map(f => `"${f}"`).join(', ')} отсутствуют в записи с ID ${recordId}`,
emptyIndicatorsProps: (props: Record<string, string[]>, recordId) => {
const propsString = Object.keys(props).map(prop => !isEmptyArray(props[prop]) ? `${prop}: ${props[prop].map(p => `"${p}"`).join(', ')}` : '').join('; ')
return `В записи с Id ${recordId} отсутствуют либо не заполнены следующие поля у показателей: ${propsString}`
}
}
const errorHandlers = {
queryParamsError: () => {
throw new Error(messages.queryParamsNotFound)
},
fieldsError: (emptyFields, recordId) => {
throw new Error(messages.emptyFieldsError(emptyFields, recordId))
},
socketError: () => {
throw new Error(messages.socketNotFound)
},
indicatorsError: (recordId) =>{
throw new Error(messages.emptyIndicators(recordId))
},
notFoundIndicators: (indicators: string[], recordId: number) => {
throw new Error(messages.indicators(indicators, recordId))
},
notFilledIndicatorProps: (props: Record<string, string[]>) => {
throw new Error(messages.emptyIndicatorsProps(props, config.journalRecordId))
}
}
const getConfig = (type: DialogType, title: string, message) => {
return {
type,
config: {
title,
message
}
}
}
const getSocketId = (queryParams: any) => {
const socketId = Array.isArray(queryParams?.socketId) && queryParams?.socketId?.length ? queryParams?.socketId[0] : '';
if (!queryParams) errorHandlers.queryParamsError()
if (!socketId) errorHandlers.socketError()
return socketId
}
const showErrorMessage = async (message: string, socketId) => getDataFromDialog(getConfig('confirm', 'Ошибка', message), socketId);
const showSuccessMessage = async (message: string, socketId) => getDataFromDialog(getConfig('confirm', 'Внимание', message), socketId);
const isEmptyArray = (arr: unknown[]) => {
return Array.isArray(arr) && arr.length === 0
}
const hasIndicators = (journalRecordManager: IJournalRecordManager) => {
const indicators = journalRecordManager?.data?.indicators
return Array.isArray(indicators) && indicators.length > 0
}
const getNotFoundIndicators = (indicators: JournalRecordIndicatorResponse[], indicatorsList = config.indicatorsList) => {
return indicatorsList.filter(ind => indicators.every(ljInd => ljInd?.indicator?.name?.toLowerCase() !== ind.toLocaleLowerCase()))
}
const getNotFilledResultsFields = (indicators: JournalRecordIndicatorResponse[]): Record<string, string[]> => {
return indicators.reduce((acc, indicator) => {
const config = indicatorPropsConfig(indicator)
return {
...acc,
[indicator?.indicator?.name]: Object.keys(config).reduce((acc, prop) => {
if (!config[prop].get()) return [...acc, config[prop].label]
return acc
}, [] as string[])
}
}, {}) as Record<string, string[]>
}
const hasNotFilledProps = (indicatorsProps: Record<string, string[]>) => {
return Object.keys(indicatorsProps).some(indicator => !isEmptyArray(indicatorsProps[indicator]))
}
const hasNotFoundIndicators = (indicators: string[]) => !isEmptyArray(indicators)
async function main({ queryParams }) {
if (!queryParams) errorHandlers.queryParamsError()
const socketId = getSocketId(queryParams)
try {
const journalRecordManager = await JournalRecordManager(config.journalRecordId)
if (!hasIndicators(journalRecordManager)) {
errorHandlers.indicatorsError(journalRecordManager.journalRecordId)
}
const indicators = journalRecordManager?.data?.indicators
const notFoundIndicators = getNotFoundIndicators(indicators)
if (hasNotFoundIndicators(notFoundIndicators)) {
errorHandlers.notFoundIndicators(notFoundIndicators, journalRecordManager.journalRecordId)
}
const emptyIndicatorProps = getNotFilledResultsFields(indicators)
if (hasNotFilledProps(emptyIndicatorProps)) {
errorHandlers.notFilledIndicatorProps(emptyIndicatorProps)
}
showSuccessMessage(messages.success, socketId)
} catch (err) {
await showErrorMessage(err.message, socketId)
return { error: err.message }
}
}
module.exports = { main }
Проверка заполненности атрибутов записи ЛЖ. check-record-fields-filled

Проверяет заполненность заданных полей в записи журнала (например, "Источник", "Место отбора", "Дата регистрации" и др.). Если какое-либо из обязательных полей не заполнено, выдаётся соответствующая ошибка.
Просмотр кода
import { JournalRecordManager } from "../../src/servivces/worker/api/interactors"
import { getDataFromDialog } from "../../src/gui/api"
import { DialogType } from "@triteia/types-integration-gui"
import { IJournalRecordManager } from "../../src/servivces/worker/api/interactors/JournalRecordManager/interface"
const config = {
requiredFields: [
'Источник',
'Список. Целое число',
'Строка',
'Целое число',
'Вещественное число',
'Логический тип',
'Дата',
'Время',
],
journalRecordId: 144, // Мк / Тест_Ушакова
integrationResult: { message: 'Все поля заполнены!' }
}
const messages = {
socketNotFound: 'Отсутствует соединение с клиентом. Дальнейшее выполнение аддона невозможно',
queryParamsNotFound: 'Отсутствуют необходимые параметры для выполнения аддона. Дальнейшее выполнение невозможно',
success: 'Все необходимые поля заполнены!',
emptyFieldsError: (fields, recordId) => `Поля ${fields.map(f => `"${f}"`).join(', ')} не заполнены в записи с ID ${recordId}`,
}
const errorHandlers = {
queryParamsError: () => {
throw new Error(messages.queryParamsNotFound)
},
fieldsError: (emptyFields, recordId) => {
throw new Error(messages.emptyFieldsError(emptyFields, recordId))
},
socketError: () => {
throw new Error(messages.socketNotFound)
}
}
const getConfig = (type: DialogType, title: string, message) => {
return {
type,
config: {
title,
message
}
}
}
const getSocketId = (queryParams: any) => {
const socketId = Array.isArray(queryParams?.socketId) && queryParams?.socketId?.length ? queryParams?.socketId[0] : '';
if (!queryParams) errorHandlers.queryParamsError()
if (!socketId) errorHandlers.socketError()
return socketId
}
const showErrorMessage = async (message: string, socketId) => getDataFromDialog(getConfig('confirm', 'Ошибка', message), socketId);
const showSuccessMessage = async (message: string, socketId) => getDataFromDialog(getConfig('confirm', 'Внимание', message), socketId);
const isEmptyArray = (arr: unknown[]) => {
return arr.length === 0
}
const getNotFilledFields = (fields: string[], journalRecordsManager: IJournalRecordManager) => {
console.log(journalRecordsManager.data.attributes, 'data.attributes')
return fields.filter(f => !journalRecordsManager.getFieldValue(f))
}
async function main({ queryParams }) {
if (!queryParams) errorHandlers.queryParamsError()
const socketId = getSocketId(queryParams)
try {
const journalRecordManager = await JournalRecordManager(config.journalRecordId)
const emptyFields = getNotFilledFields(config.requiredFields, journalRecordManager)
if (isEmptyArray(emptyFields)) {
showSuccessMessage(messages.success, socketId)
return config.integrationResult
} else errorHandlers.fieldsError(emptyFields, config.journalRecordId)
} catch (err) {
await showErrorMessage(err.message, socketId)
return { error: err.message }
}
}
module.exports = { main }
Проверка движения пробы. check-sample-moving

Проверяет маршрут движения пробы по этапам. Получает историю перемещений записи и определяет, происходило ли движение (нахождение более чем на одном этапе). Отображает маршрут или сообщает, что движение не происходило.
Просмотр кода
import { getDataFromDialog } from "../../src/gui/api"
import { JournalsRecordRouteController } from "../../src/servivces/worker/api/controllers/journals-record-route"
import { apiInstance } from "../../src/servivces/worker/api/interactors/ApiInstance"
import type { DialogType } from "@triteia/types-integration-gui"
import type { JournalRecordRouteDto } from "../../src/servivces/worker/api/controllers/journal-records"
const config = {
journalRecordId: 114 // Лаб. воздуха / Анализы завершены
}
const messages = {
socketNotFound: 'Отсутствует соединение с клиентом. Дальнейшее выполнение аддона невозможно',
queryParamsNotFound: 'Отсутствуют необходимые параметры для выполнения аддона. Дальнейшее выполнение невозможно',
route: (routes: JournalRecordRouteDto[], recordId: number) => `Машрут пробы: ${routes.map(r => `"${r.stageName}"`).join(' -> ')}. Id записи ЛЖ: ${recordId}`,
notMoved: (recordId: number) => `Движение пробы не происходило. Id записи ЛЖ: ${recordId}`,
}
const errorHandlers = {
queryParamsError: () => {
throw new Error(messages.queryParamsNotFound)
},
socketError: () => {
throw new Error(messages.socketNotFound)
}
}
const getConfig = (type: DialogType, title: string, message) => {
return {
type,
config: {
title,
message
}
}
}
const getSocketId = (queryParams: any) => {
const socketId = Array.isArray(queryParams?.socketId) && queryParams?.socketId?.length ? queryParams?.socketId[0] : '';
if (!queryParams) errorHandlers.queryParamsError()
if (!socketId) errorHandlers.socketError()
return socketId
}
const showErrorMessage = async (message: string, socketId) => getDataFromDialog(getConfig('confirm', 'Ошибка', message), socketId);
const showSuccessMessage = async (message: string, socketId) => getDataFromDialog(getConfig('confirm', 'Внимание', message), socketId);
const isSampleMoved = (moves: JournalRecordRouteDto[]) => {
return Array.isArray(moves) && moves.length > 1
}
async function main({ queryParams }) {
if (!queryParams) errorHandlers.queryParamsError()
const socketId = getSocketId(queryParams)
try {
const journalsRecordRouteController = new JournalsRecordRouteController(apiInstance)
const sampleMoves = await journalsRecordRouteController.getJournalRecordRoute(config.journalRecordId)
if (isSampleMoved(sampleMoves)) {
showSuccessMessage(messages.route(sampleMoves, config.journalRecordId), socketId)
} else {
showSuccessMessage(messages.notMoved(config.journalRecordId), socketId)
}
} catch (err) {
await showErrorMessage(err.message, socketId)
return { error: err.message }
}
}
module.exports = { main }
Проверка прав пользователя. check-user-rights

Проверяет права доступа пользователя к определённым ресурсам (объекты анализа, методики, записи ЛЖ). Отображает таблицу с типами доступа (чтение, запись и т.д.) и наличием прав по каждому ресурсу.
Просмотр кода
import { getDataFromDialog } from "../../src/gui/api"
import { apiInstance } from "../../src/servivces/worker/api/interactors/ApiInstance"
import {
PermissionController,
PermissionResource,
PermissionRwAccess
} from "../../src/servivces/worker/api/controllers/permisson"
import { TableBuilder } from "../../src/gui/builder"
import type { DialogType, TableConfig } from "@triteia/types-integration-gui"
import type { JournalRecordRouteDto } from "../../src/servivces/worker/api/controllers/journal-records"
const accessNamesMap = {
[PermissionRwAccess.EXEC]: 'Выполнение',
[PermissionRwAccess.READ]: 'Чтение',
[PermissionRwAccess.WRITE]: 'Запись',
}
const requiredResources = [
PermissionResource.ANALYSIS_OBJECT,
PermissionResource.METHODOLOGY,
PermissionResource.JOURNAL_RECORD
]
const resourcesNamesMap = {
[PermissionResource.ANALYSIS_OBJECT]: 'Объекты анализа',
[PermissionResource.METHODOLOGY]: 'Методики',
[PermissionResource.JOURNAL_RECORD]: 'Записи ЛЖ'
}
const getAccessRightsTable = async (tableBuilder: TableBuilder, permissionController: PermissionController): Promise<TableConfig> => {
const rows = (await Promise.all(requiredResources.map(async (source: PermissionResource) => {
const sourceCombinations = await Promise.all(Object.keys(PermissionRwAccess).map(async (action) => {
const access = await permissionController.getSourcePermission(source, PermissionRwAccess[action])
return { source: resourcesNamesMap[source], action: accessNamesMap[PermissionRwAccess[action]], access: access.hasPermission }
}))
return sourceCombinations
}
))).flat()
const table = tableBuilder
.name('simpleTable')
.label('Таблица')
.isAddable(false)
.actionsCol(false)
.addColumn('Ресурс', 'source', false)
.config('input', { name: 'source', rules: [{ required: true }] }, { placeholder: '', disabled: false })
.next()
.addColumn('Тип доступа', 'action', false)
.config('input', { name: 'action' }, { type: 'string', placeholder: '', disabled: false })
.next()
.addColumn('Доступ', 'access', false)
.config('checkbox', { name: 'access' }, { type: 'boolean', placeholder: '', disabled: false })
.next()
.setRows(rows)
.build();
return table
}
const messages = {
socketNotFound: 'Отсутствует соединение с клиентом. Дальнейшее выполнение аддона невозможно',
queryParamsNotFound: 'Отсутствуют необходимые параметры для выполнения аддона. Дальнейшее выполнение невозможно',
route: (routes: JournalRecordRouteDto[], recordId: number) => `Маршрут пробы: ${routes.map(r => `"${r.stageName}"`).join(' -> ')}. Id записи ЛЖ: ${recordId}`,
notMoved: (recordId: number) => `Движение пробы не происходило. Id записи ЛЖ: ${recordId}`,
}
const errorHandlers = {
queryParamsError: () => {
throw new Error(messages.queryParamsNotFound)
},
socketError: () => {
throw new Error(messages.socketNotFound)
}
}
const getConfig = (type: DialogType, title: string, message) => {
return {
type,
config: {
title,
message
}
}
}
const getSocketId = (queryParams: any) => {
const socketId = Array.isArray(queryParams?.socketId) && queryParams?.socketId?.length ? queryParams?.socketId[0] : '';
if (!queryParams) errorHandlers.queryParamsError()
if (!socketId) errorHandlers.socketError()
return socketId
}
const showErrorMessage = async (message: string, socketId) => getDataFromDialog(getConfig('confirm', 'Ошибка', message), socketId);
const showTable = async (builder: TableBuilder, controller: PermissionController, socketId: string) =>
await getDataFromDialog({ type: 'input-data', config: [await getAccessRightsTable(builder, controller)] }, socketId)
async function main({ queryParams }) {
if (!queryParams) errorHandlers.queryParamsError()
const socketId = getSocketId(queryParams)
try {
await showTable(new TableBuilder, new PermissionController(apiInstance), socketId)
} catch (err) {
await showErrorMessage(err.message, socketId)
return { error: err.message }
}
}
module.exports = { main }
Заполнение атрибутов записи ЛЖ. fill-record-fields

Автоматически заполняет заданные поля в записи журнала (например, даты, место отбора, шифр пробы и др.). Есть возможность использования ключевых слов для сопоставления полей, если точные названия не совпадают.
Деление данных. copy-journal-record

Создаёт копию записи журнала на заданном этапе маршрута. Выводит сообщение с ID новой записи.