/** * Сайт SharePoint, где живут списки данных портала. * Портал (web part) может размещаться на другом сайте (например, на главной), * поэтому клиент PnPjs всегда нацеливаем на этот адрес явно. * * TODO: при необходимости вынести в свойство web part (property pane), * чтобы не хардкодить и переключать между dev/prod-сайтами. */ export const DATA_SITE_URL = 'https://tnsukz.sharepoint.com/sites/requests'; /** * Инструкция пользователя по порталу (docx на сайте базы знаний) — ссылка в * боковом меню (см. components/RequestPortal.tsx), открывается в новой вкладке. */ export const USER_GUIDE_URL = 'https://tnsukz.sharepoint.com/:w:/r/sites/knowledge/DocLib8/%D0%98%D0%BD%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%86%D0%B8%D0%B8%20%D0%BA%20IT%20%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0%D0%BC/%D0%98%D0%BD%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%86%D0%B8%D1%8F%20-%20%D0%9F%D0%BE%D1%80%D1%82%D0%B0%D0%BB%20%D0%B7%D0%B0%D1%8F%D0%B2%D0%BE%D0%BA.docx?d=wce77e8a0d19d49b5b2fcdf13828e8bb3&csf=1&web=1&e=p9V3hU'; /** * Страница портала в SharePoint — ссылка «Открыть портал в браузере» в * объявлении для Teams (см. components/TeamsBrowserNotice). Внутри Teams * портал свой адрес не знает (вкладка Teams — служебная страница), поэтому задан явно. */ export const PORTAL_PAGE_URL = `${DATA_SITE_URL}/SitePages/${encodeURIComponent('Портал-Заявок')}.aspx`; /** * Внешний approval-route API (маршруты согласования по ролям). * Авторизация — AadHttpClient (SSO текущего пользователя) по clientId * зарегистрированного AAD-приложения. Разрешение объявлено в * config/package-solution.json (webApiPermissionRequests) и одобряется * в Центре администрирования SharePoint (API access) при развёртывании. */ export const APPROVAL_API_CLIENT_ID = '9232d9e2-9807-4753-808f-07250e5474b0'; /** Прод — то же самое значение, что default в свойстве approvalApiBaseUrl веб-части. */ export const APPROVAL_API_BASE_URL_PROD = 'https://api.tnsu.kz/approval-route'; /** Локальный backend — порт из tnsu-approval-route/backend/.../launchSettings.json. */ export const APPROVAL_API_BASE_URL_LOCAL = 'http://localhost:5080'; // Настраивается свойством веб-части approvalApiBaseUrl (селект в панели свойств, // см. RequestPortalWebPart.render) — тот же приём, что и у debugUserQuery/ // setImpersonatedIdentity (shared/impersonation.ts): модульный синглтон, а не // проброс параметром через все вызовы approvalRoute.service.ts, потому что эти // вызовы разбросаны по формам и не имеют общего входа, через который можно // было бы прокинуть контекст. let _approvalApiBaseUrl = APPROVAL_API_BASE_URL_PROD; export function setApprovalApiBaseUrl(url: string): void { _approvalApiBaseUrl = url || APPROVAL_API_BASE_URL_PROD; } export function getApprovalApiBaseUrl(): string { return _approvalApiBaseUrl; } /** * ЭДО (TANSU ЭДО) — подписание документов. Токен берётся для того же AAD-приложения, что и * у approval-route и справочников: бэкенд ЭДО принимает токены сотрудников этого приложения * (Auth:Entra:Audience). Если ЭДО переедет на своё приложение — поменять только эту константу * и объявить доступ в package-solution.json (webApiPermissionRequests). */ export const EDO_API_CLIENT_ID = APPROVAL_API_CLIENT_ID; /** Локальный бэкенд ЭДО — порт из launchSettings.json (https). */ export const EDO_API_BASE_URL_LOCAL = 'https://localhost:7016'; /** Стейджинг ЭДО. Сертификат самоподписанный: браузер должен ему доверять, иначе запрос не уйдёт. */ export const EDO_API_BASE_URL_STAGE = 'https://10.0.1.225:8443'; /** Прод ЭДО — значение по умолчанию. */ export const EDO_API_BASE_URL_PROD = 'https://edo.tnsu.kz'; // Настраивается свойством веб-части edoApiBaseUrl (селект в панели свойств) — тот же // модульный синглтон, что и approvalApiBaseUrl выше. let _edoApiBaseUrl = EDO_API_BASE_URL_PROD; export function setEdoApiBaseUrl(url: string): void { // Хвостовые слэши отбрасываем: адрес склеивается с путём «/api/...», а в панели // свойств его могли вписать с «/» на конце. _edoApiBaseUrl = (url || EDO_API_BASE_URL_PROD).trim().replace(/\/+$/, ''); } export function getEdoApiBaseUrl(): string { return _edoApiBaseUrl; } /** * Отправка согласованного заявления на отпуск на подпись в ЭДО (forms/Vacation/VacationView). * Временно выключена: решение последнего согласующего применяется без обращения к ЭДО. * Чтобы вернуть — поставить true, остальной код отправки на месте. */ export const VACATION_EDO_SIGNING_ENABLED = false; // Уведомления согласующим (поток Power Automate, см. approval/notify.service.ts). // Настраивается свойствами веб-части notificationsEnabled / notifyOnlyTo — тот // же модульный синглтон, что и у approvalApiBaseUrl выше. // enabled — false выключает рассылку целиком; // onlyTo — непустой адрес: письма уходят ТОЛЬКО если активный шаг назначен // на него (обкатка рассылки); пусто — всем. let _notificationsEnabled = true; let _notifyOnlyTo = ''; export function setNotificationSettings(enabled: boolean, onlyTo: string): void { _notificationsEnabled = enabled; _notifyOnlyTo = (onlyTo || '').trim(); } export function getNotificationsEnabled(): boolean { return _notificationsEnabled; } export function getNotifyOnlyTo(): string { return _notifyOnlyTo; } /** * Справочники (Dictionary API) — тот же gateway api.tnsu.kz и тот же AAD-app * (APPROVAL_API_CLIENT_ID), но другой путь/сервис. Используется, например, для * GET /Dictionary/Departments. */ export const DICTIONARY_API_BASE_URL = 'https://api.tnsu.kz'; /** * Проходы СКУД (Hikvision) текущего пользователя — тот же gateway и AAD-app, * что у справочников. Сотрудника API определяет по токену, e-mail не передаём. * Используется формой «Объяснительная по СКУД» (forms/SkudExplanation). */ export const SKUD_EVENTS_PATH = '/Hikvision/Events/CurrentUser'; /** * Значения параметра `source` внешней ссылки (см. shared/routing, sourceSystem) — * из какой системы открыли форму и, значит, куда отвечать ссылкой на заявку. * Без source (или с неизвестным значением) — ссылка пришла из Dataverse. */ export const EXTERNAL_SOURCE = { /** КПС: positionId — id позиции акта дефектов, ответ — в Inventory API. */ kps: 'kps' } as const; /** * Inventory API (КПС) — приём ссылки на заявку «СЗ на перемещение ТМЦ» для * позиции акта дефектов: POST {DICTIONARY_API_BASE_URL}<путь> с телом { url }. * {partId} = positionId из внешней ссылки с source=kps. Тот же gateway * api.tnsu.kz — авторизация та же, что у справочников (APPROVAL_API_CLIENT_ID). */ export const INVENTORY_TMC_TRANSFER_PATH = '/inventory/api/defect-acts/parts/{partId}/tmc-transfer'; /** * Производственный календарь (праздничные выходные) — SP-список на корневом * сайте, где живёт главная страница портала (portal-main-page читает его же). * Недоступен — календарь СКУД просто не красит праздники. */ export const HOLIDAYS_SITE_URL = 'https://tnsukz.sharepoint.com'; export const HOLIDAYS_LIST_TITLE = 'Производственный Календарь'; /** * Power Automate: поток оповещения согласующего/исполнителя. * Триггер «When an HTTP request is received» защищён Entra («любой пользователь * тенанта»), поэтому URL без подписи (`sig`), а вызываем через AadHttpClient с * ресурсом Flow Service (обычный fetch → 401; так же решается CORS). Разрешение * «Microsoft Flow Service / Flows.Read.All» объявлено в package-solution.json и * одобряется в Центре администрирования SharePoint (API access) при развёртывании. * Шлём тело `{ RowID: }` — поток сам находит по * строке согласующего, статус и заявку и уведомляет. (Паттерн из kps-ct-form.) */ export const FLOW_RESOURCE = 'https://service.flow.microsoft.com/'; export const FLOW_NOTIFY_URL = 'https://eab3d2815f2beb42bf2e7ec1731708.92.environment.api.powerplatform.com:443/powerautomate/automations/direct/cu/07/workflows/b21516edf8a14287a65a39e4116dfe4f/triggers/manual/paths/invoke?api-version=1'; /** * Power Automate: поток оповещения о новом сообщении в чате заявки (shared/chat). * Тот же механизм вызова, что у FLOW_NOTIFY_URL (Entra-триггер, AadHttpClient с * ресурсом FLOW_RESOURCE), но тело другое — получателей поток НЕ ищет сам, их * передаёт портал (см. shared/chat/chatNotify.ts): * отмеченным через «@» — «Вас упомянули в чате по заявке №…», * инициатору (если его не отметили) — «Новое сообщение в чате по вашей заявке №…». */ export const FLOW_CHAT_NOTIFY_URL = 'https://eab3d2815f2beb42bf2e7ec1731708.92.environment.api.powerplatform.com:443/powerautomate/automations/direct/cu/07/workflows/325d735d32de4e6989f4f06fc347e833/triggers/manual/paths/invoke?api-version=1'; // Чат заявки, режим проверки (свойство веб-части chatSelfNotify): письма уходят и // о СВОИХ сообщениях, и себя можно отметить через «@». По умолчанию выключен — // писать самому себе в обычной работе незачем. let _chatSelfNotify = false; export function setChatSelfNotify(enabled: boolean): void { _chatSelfNotify = enabled; } export function getChatSelfNotify(): boolean { return _chatSelfNotify; } /** * Microsoft Dataverse (Power Platform) — рабочая среда «По умолчанию» * (org95ca17d6.crm4.dynamics.com). NB: таблица cree9_demandline существует и в * другой среде (tansu.crm5, из проекта stroy-bot) — писать нужно ИМЕННО в эту. * Авторизация через AadHttpClient (SSO текущего пользователя): ресурс = URL * среды, разрешение объявлено в package-solution.json (webApiPermissionRequests, * scope user_impersonation) и одобряется в Центре администрирования SharePoint * (API access) при развёртывании — тот же механизм, что у approval-route API. * * Используется формой «СЗ на перемещение ТМЦ»: после отправки на согласование * в строку-источник (таблица cree9_demandline) записывается ссылка на заявку * портала — см. shared/dataverse/demandLine.service.ts. */ export const DATAVERSE_RESOURCE_URL = 'https://org95ca17d6.crm4.dynamics.com'; export const DATAVERSE_API_VERSION = 'v9.2'; /** * EntitySetName таблицы «Строка заявки» (LogicalName cree9_demandline). * NB: значение выведено по конвенции Dataverse (logical + 's') — проверить в * проде через EntityDefinitions(LogicalName='cree9_demandline')?$select=EntitySetName. */ export const DATAVERSE_DEMANDLINE_ENTITY_SET = 'cree9_demandlines'; /** * Колонка, куда пишем ссылку на заявку портала (создана вручную в Dataverse, * отображаемое имя «cree9_tmctransferurl», однострочный текст). Указана владельцами * внешней системы; прежняя URL-колонка cr498_portalrequesturl больше не используется. * NB: логическое имя с префиксом cr498_ (издатель среды org95ca17d6.crm4 по * умолчанию) — так сгенерировалось при создании колонки. * Ссылка на заявку ~200+ символов (кириллица в пути страницы кодируется), поэтому * макс. длина колонки должна быть не меньше 500 — иначе PATCH отклонится. */ export const DATAVERSE_DEMANDLINE_LINK_FIELD = 'cr498_cree9_tmctransferurl'; /** * Колонка «ID позиции ЛЗК» на «Строке заявки» — GUID строки cree9_lzkposition * ХРАНИТСЯ ТЕКСТОМ (не lookup-связью), поэтому её нельзя $expand'нуть — только * читать значение и адресовать таблицу lzk position отдельным запросом. * Используется для определения проекта-получателя («Куда») в форме «СЗ на * перемещение ТМЦ» — см. shared/dataverse/lzkPosition.service.ts. */ export const DATAVERSE_DEMANDLINE_LZKPOSITION_FIELD = 'cree9_lzkpositionid'; /** * EntitySetName таблицы «lzk position» (LogicalName cree9_lzkposition) — выведено * по той же конвенции (logical + 's'), что и DATAVERSE_DEMANDLINE_ENTITY_SET. */ export const DATAVERSE_LZKPOSITION_ENTITY_SET = 'cree9_lzkpositions'; /** Lookup-поле на lzk position, ссылающееся на родительскую запись LZK. */ export const DATAVERSE_LZKPOSITION_LZK_LOOKUP_FIELD = 'cree9_lzkid'; /** EntitySetName таблицы «LZK» (LogicalName cree9_lzk). */ export const DATAVERSE_LZK_ENTITY_SET = 'cree9_lzks'; /** Колонка «project id» на LZK — GUID проекта текстом, совпадает по формату с oid из /Project. */ export const DATAVERSE_LZK_PROJECT_FIELD = 'cree9_projectid'; /** * Сайт сравнительных таблиц (СТ): списки «Сравнительная таблица», «Позиции СТ», * «Оценка поставщиков», «Критерии», «Поставщики», «Курс Валют» живут здесь, а не * на сайте данных портала. Читаем их из «Заявки на оплату» (forms/PaymentRequest). */ export const CT_SITE_URL = 'https://tnsukz.sharepoint.com/sites/sed';