9 Commits

Author SHA1 Message Date
Александр Кондратов 0866814a74 Pull request #17: feat(короткая заявка): TEAMOPRS-87 [ОНБ_МСБ] добавляет короткую заявку
Merge in MCB_FE/eco-onboarding-short from feature-teamoprs-87-new2 to develop

* commit '290e4d0ba6047b92ccbb1cca1a12e48c93d97aaf':
  fix(назначение звонка): TEAMMSBDAY-2340 [ОНБ_МСБ] убирает full route
  fix(назначение звонка): TEAMMSBDAY-2222 [ОНБ_МСБ] при пропуске значения не будут отправляться
  fix(тарифы): TEAMMSBDAY-2221 [ОНБ_МСБ] тариф за месяц будет выбран по-умолчанию
  feat(короткая заявка): TEAMMSBDAY-2309 [ОНБ_МСБ] добавил скроллер на фрактале
  feat(короткая заявка): TEAMOPRS-87 [ОНБ_МСБ] добавляет короткую заявку
2025-07-23 13:41:33 +03:00
Александр Кондратов d5caa03cdf Pull request #16: Feature classic onboarding
Merge in MCB_FE/eco-onboarding-short from feature-classic-onboarding to develop

* commit '7ebc753713cfad98a9f17155ba9935ab13f90721':
  feat(короткая заявка): TEAMOPRS-50 [ОНБ_МСБ] adds old repository
2025-07-23 13:41:02 +03:00
akondratov 290e4d0ba6 fix(назначение звонка): TEAMMSBDAY-2340 [ОНБ_МСБ] убирает full route 2025-07-23 13:34:31 +03:00
Александр Кондратов 1436c85846 Pull request #18: Feature teamoprs 2309 new
Merge in MCB_FE/eco-onboarding-short from feature-teamoprs-2309-new to feature-teamoprs-87-new2

* commit '19e0ade8aa78da8b9f9ec9889a0c2eea9c00440f':
  fix(назначение звонка): TEAMMSBDAY-2222 [ОНБ_МСБ] при пропуске значения не будут отправляться
  fix(тарифы): TEAMMSBDAY-2221 [ОНБ_МСБ] тариф за месяц будет выбран по-умолчанию
  feat(короткая заявка): TEAMMSBDAY-2309 [ОНБ_МСБ] добавил скроллер на фрактале
2025-07-23 12:32:42 +03:00
Valeev Bulat 19e0ade8aa fix(назначение звонка): TEAMMSBDAY-2222 [ОНБ_МСБ] при пропуске значения не будут отправляться 2025-07-23 12:22:35 +03:00
Valeev Bulat 8ab7ae9511 fix(тарифы): TEAMMSBDAY-2221 [ОНБ_МСБ] тариф за месяц будет выбран по-умолчанию
Также задача: TEAMMSBDAY-2223
2025-07-23 12:09:29 +03:00
Valeev Bulat 41cabd0853 feat(короткая заявка): TEAMMSBDAY-2309 [ОНБ_МСБ] добавил скроллер на фрактале 2025-07-23 12:09:28 +03:00
akondratov 3a3edc50a3 feat(короткая заявка): TEAMOPRS-87 [ОНБ_МСБ] добавляет короткую заявку 2025-07-23 11:58:32 +03:00
akondratov 7ebc753713 feat(короткая заявка): TEAMOPRS-50 [ОНБ_МСБ] adds old repository 2025-07-23 11:18:38 +03:00
1517 changed files with 120434 additions and 543 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ module.exports = {
...require('@eco/cz-config'),
scopes: [
{
name: 'скроллер',
name: 'физ.лица',
},
],
};
+5
View File
@@ -1,3 +1,8 @@
module.exports = {
extends: ['@eco'],
rules: {
'@eco/no-services-imports': 'off',
'import/no-deprecated': 'off',
'react-hooks/exhaustive-dep': 'off',
},
};
+3 -1
View File
@@ -1 +1,3 @@
module.exports = require('@eco/lint-staged-config');
module.exports = {
'(src|lib|tests|__tests__|__mocks__)/**/*.{js,jsx,ts,tsx}': ['eslint --fix'],
};
-8
View File
@@ -1,11 +1,3 @@
# 1.0.0 (2025-07-21)
### Features
* TEAMOPRS-177 настройка репозитория 53cf82a
* Первый релиз baeaaf5
# 3.3.0 (2025-07-07)
+12 -3
View File
@@ -1,5 +1,14 @@
# Пример стрима `@eco/stream-example`
# Короткая заявка / Короткий Онбординг `@eco/onboarding-short`
Образец стрима и основных подходов.
## Запуск
```sh
# Запуск клиентской части.
npm start
# Запуск банковской части.
npm run start:admin
```
Стрим доступен по относительному пути `/onboarding-short`
Master Commit
File diff suppressed because it is too large Load Diff
-3
View File
@@ -1,3 +0,0 @@
{
"scroller.title": "Stage 2.27.1"
}
+2
View File
@@ -0,0 +1,2 @@
'use strict';
module.exports = 'div';
+5
View File
@@ -2,4 +2,9 @@ module.exports = {
testEnvironment: 'jsdom',
preset: './node_modules/@platform/services/configs/jest/stream.config',
setupFiles: ['<rootDir>/test-setup.ts'],
moduleNameMapper: {
'^.+\\.(svg|png)$': '<rootDir>/file-import-mock.js',
},
collectCoverage: true,
collectCoverageFrom: ['<rootDir>/src/**/*.{ts,tsx}', '!<rootDir>/src/**/__tests__/*.(ts|tsx)'],
};
+394 -399
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@eco/onboarding-short",
"version": "1.0.0",
"version": "3.1.0",
"main": "export",
"files": [
"client",
@@ -0,0 +1,10 @@
import type { onboardingArchiveRequestsService } from 'services';
import type { errorHandler } from 'utils';
import type { IActionServiceContext, IBaseContext } from '@platform/services';
/** Тип контекста экзекьютора архивной заявки на открытие первого счёта. */
export type ArchiveRequestsExecutorContext = IActionServiceContext<typeof onboardingArchiveRequestsService> &
IBaseContext & {
/** Общий обработчик ошибок. */
errorHandler: typeof errorHandler;
};
@@ -0,0 +1,14 @@
import { onboardingArchiveRequestsService } from 'services';
import { errorHandler } from 'utils';
import type { IExecuter } from '@platform/core';
import { createExecuter } from '@platform/core';
import { createContext } from '@platform/services';
import type { ArchiveRequestsExecutorContext } from './archive-requests-executor-context';
/** Создает экзекьютер для архивных заявок. */
export const createArchiveRequestsExecutor = (): IExecuter<ArchiveRequestsExecutorContext> =>
createExecuter({
...createContext(),
service: onboardingArchiveRequestsService,
errorHandler,
});
@@ -0,0 +1,2 @@
export * from './archive-requests-executor-context';
export * from './create-archive-requests-executor';
+2
View File
@@ -0,0 +1,2 @@
export * from './onboarding';
export * from './archive-requests';
+70
View File
@@ -0,0 +1,70 @@
// Чтоб разрешить циклические зависимости.
import { showAddDocumentDialog } from 'components/modals/add-document-dialog';
import { showDownloadDocumentsDialog } from 'components/modals/download-documents-dialog';
import { showConfirmNeedToReplaceDialog } from 'components/modals/need-to-replace-dialog';
import { showServerErrorDialog } from 'components/modals/server-error-dialog';
import { showSnackbarMessage } from 'components/snackbar-provider';
import type { OnboardingRequestDto, OriginalDocumentDto } from 'interfaces';
import type { DepartureHistoryDto } from 'interfaces/admin';
import { showAddDepartureRecordDialog } from 'pages/admin/manage-request/modals';
import { showAddCallDialog } from 'pages/admin/manage-request/views/calls-tab/add-call-dialog'; // Циклическая ссылка
import type { IOnboardingAdminService } from 'services';
import { onboardingAdminService } from 'services';
import type { STATUS } from 'stream-constants';
import { STATUSES_WITHOUT_COMMENTS } from 'stream-constants';
import { errorHandler } from 'utils';
import { createExecuter } from '@platform/core';
import type { IExecuter } from '@platform/core';
import { showAdminHistoryChangesDialog, createContext, getChangeStatusDialog } from '@platform/services';
import type { IActionServiceContext, IBaseContext, IChangeStatusFormState, IStatusOption } from '@platform/services';
import { dialog } from '@platform/ui';
/** Тип контекста экзекьютора заявки на открытие первого счёта. */
export interface IOnboardingAdminContext extends IBaseContext, IActionServiceContext<IOnboardingAdminService> {
showChangeStatusDialog(currentStatus: IStatusOption, availableStatuses: IStatusOption[]): Promise<IChangeStatusFormState>;
showAddDepartureRecordDialog(doc: OnboardingRequestDto): Promise<DepartureHistoryDto>;
showAddCallDialog: typeof showAddCallDialog;
showConfirmNeedToReplaceDialog(names: string[]): Promise<void>;
showAddDocumentDialog(): Promise<OriginalDocumentDto>;
showDownloadDocumentsDialog: typeof showDownloadDocumentsDialog;
errorHandler: typeof errorHandler;
showServerErrorDialog: typeof showServerErrorDialog;
showSnackbarMessage: typeof showSnackbarMessage;
}
/** Контекст экзекьютора заявки на открытие первого счёта. */
export const OnboardingAdminContext: IOnboardingAdminContext = {
...createContext(),
service: onboardingAdminService,
showAddDepartureRecordDialog,
showChangeStatusDialog: (currentStatus, availableStatuses) =>
new Promise((resolve, reject) =>
dialog.show(
'changeStatus',
getChangeStatusDialog(availableStatuses),
{
currentStatus,
onSelectStatus: resolve,
commentForBankMaxLength: 10_000,
commentForClientMaxLength: 10_000,
hiddenBankComment: STATUSES_WITHOUT_COMMENTS.includes(currentStatus.value as STATUS),
hiddenClientComment: STATUSES_WITHOUT_COMMENTS.includes(currentStatus.value as STATUS),
},
() => reject(true)
)
),
showAddCallDialog,
showConfirmNeedToReplaceDialog,
showAddDocumentDialog,
showDownloadDocumentsDialog,
showAdminHistoryDialog: showAdminHistoryChangesDialog,
errorHandler,
showServerErrorDialog,
showSnackbarMessage,
};
/** Тип экзекьютора заявки на открытие первого счёта. */
export type IOnboardingExecutor = IExecuter<IOnboardingAdminContext>;
/** Экзекьютор заявки на открытие первого счёта. */
export const onboardingAdminExecutor: IOnboardingExecutor = createExecuter(OnboardingAdminContext);
+1
View File
@@ -0,0 +1 @@
export * from './onboarding';
+36
View File
@@ -0,0 +1,36 @@
// Чтоб разрешить циклические зависимости.
import { showExportDocumentsDialog } from 'components/modals/export-documents-dialog';
import { showServerErrorDialog } from 'components/modals/server-error-dialog';
import { showSnackbarMessage } from 'components/snackbar-provider';
import type { IOnboardingClientService } from 'services';
import { onboardingClientService } from 'services';
import { errorHandler } from 'utils';
import type { IExecuter } from '@platform/core';
import { createExecuter } from '@platform/core';
import type { IActionServiceContext, IBaseContext } from '@platform/services';
import { createContext } from '@platform/services';
/** Тип контекста экзекьютора заявки на открытие первого счёта. */
export interface IOnboardingContext extends IBaseContext, IActionServiceContext<IOnboardingClientService> {
/** Обработчик запросов сервиса открытия первого счёта. */
errorHandler: typeof errorHandler;
showExportDocumentsDialog: typeof showExportDocumentsDialog;
showServerErrorDialog: typeof showServerErrorDialog;
showSnackbarMessage: typeof showSnackbarMessage;
}
/** Контекст экзекьютора заявки на открытие первого счёта. */
export const OnboardingContext: IOnboardingContext = {
...createContext(),
service: onboardingClientService,
errorHandler,
showExportDocumentsDialog,
showServerErrorDialog,
showSnackbarMessage,
};
/** Тип экзекьютора заявки на открытие первого счёта. */
export type IOnboardingExecutor = IExecuter<IOnboardingContext>;
/** Экзекьютор заявки на открытие первого счёта. */
export const onboardingExecutor: IOnboardingExecutor = createExecuter(OnboardingContext);
@@ -0,0 +1,76 @@
import type { ShowConfirmModalType } from 'components';
import type { ActiveRequestsValidationResultDto, ICreateRequestParams } from 'interfaces';
import { locale } from 'localization';
import { ACTIVE_REQUEST_RESULT, REQUEST_SOURCE } from 'stream-constants';
import { singleAction, to } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { COMMON_STREAM_URL, isClientScope } from '@platform/services';
import type { CommonOnboardingContextFractal } from './hooks/use-onboarding-executor';
/** Результат работы проверки на наличие активных заявок. */
export interface CheckActiveRequestActionResult {
/** Ответ от сервера при проверкезаявки. */
result: ActiveRequestsValidationResultDto;
/** Действие пользователя. */
userAction: 'cancel' | 'createNew' | 'navigateToRequest' | 'none';
}
/**
* Проверка на отсутствие у пользователя активных заявок по клиенту при создании заявки.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=42668532 1
*/
export const checkActiveRequestBeforeCreateFractal: IActionConfig<CommonOnboardingContextFractal, CheckActiveRequestActionResult> = {
action:
({ fatal, addSucceeded, done }, { service, router, showLoader, hideLoader }) =>
async ([doc]: [ICreateRequestParams], showConfirmModal: ShowConfirmModalType) => {
showLoader();
const [result] = await to(service.checkActiveRequestBeforeCreate({ inn: doc.inn, kpp: doc.kpp }));
hideLoader();
fatal(result?.code);
const resultData = result!.data;
if (resultData.result === ACTIVE_REQUEST_RESULT.INVALID) {
await new Promise<void>(resolve =>
showConfirmModal({
size: 'M',
type: 'warning',
header: locale.common.warning,
content: locale.dialog.activeRequest.content,
confirmButtonText: locale.dialog.activeRequest.primaryButton,
cancelButtonText: locale.dialog.activeRequest.secondaryButton,
onConfirm: () => {
addSucceeded({ userAction: 'createNew', result: resultData });
resolve();
},
onCancel: () => {
// Переход на уже созданную заявку.
const baseUrl =
!isClientScope() && resultData.activeRequestSource === REQUEST_SOURCE.DOCUMENT_PACKAGE
? `${COMMON_STREAM_URL.ONBOARDING}/archive`
: COMMON_STREAM_URL.ONBOARDING;
router.push(`${baseUrl}/${resultData.activeRequestId}`);
addSucceeded({ userAction: 'navigateToRequest', result: resultData });
resolve();
},
onCloseButtonClick: () => {
addSucceeded({ userAction: 'cancel', result: resultData });
resolve();
},
})
);
done();
} else {
addSucceeded({ userAction: 'none', result: resultData });
done();
}
},
guardians: [singleAction],
};
@@ -0,0 +1,25 @@
import type { IOnboardingContext } from 'action-executers';
import type { IOnboardingAdminContext } from 'action-executers/admin';
import type { ShowConfirmModalType } from 'components';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS, DOCUMENT_TYPE_CODE } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { inStatuses } from '../actions/guardians';
import { printReportFractal } from './print-report-fractal';
/**
* Клиент/Банк. Функция формирования ПФ уведомления об открытии счетов.
* Осуществляет скачивание документа.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=84458398
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=93294020
*/
export const downloadAccountOpenedNotificationFractal: IActionConfig<IOnboardingAdminContext | IOnboardingContext, void> = {
action:
(...args) =>
async (doc: [OnboardingRequestDto], _, showModal: ShowConfirmModalType) => {
await printReportFractal.action(...args)(doc, DOCUMENT_TYPE_CODE.ONB_CM_1_1_21, showModal);
},
guardians: [singleAction, inStatuses([STATUS.EXECUTED])],
};
@@ -0,0 +1,55 @@
import type { CommonOnboardingContextFractal } from 'actions-fractal';
import { canDownloadCommissionPaymentDocument } from 'actions/admin/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { locale } from 'localization';
import { onboardingCommonService } from 'services';
import { DOCUMENT_TYPE_CODE } from 'stream-constants';
import { getFilenameFromTemplate, getOnbConfig } from 'utils';
import { to } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { attachmentService, DOCUMENT_EXPORT_FORMAT, showFile, type IPrintResponseDoc } from '@platform/services';
/** Загрузка документа об оплате из filestorage(замена paymentReceiptDownload). */
export const downloadReceipt = async (requestId: string, clientId: string) => {
const { downloadDocsFromFs } = getOnbConfig();
if (!downloadDocsFromFs) {
return onboardingCommonService.paymentReceiptDownload(requestId, clientId);
}
const attachmentInfo = await onboardingCommonService.exportPaymentReceipt(requestId, clientId);
const attachment = await attachmentService.downloadOneTimeData(attachmentInfo.id, attachmentInfo.accessToken);
return { content: attachment.data, fileName: attachment.fileName };
};
/**
* Банк: Функция сформировать документ об оплате комиссии.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=111248654
*/
export const downloadCommissionPaymentFractal: IActionConfig<CommonOnboardingContextFractal, IPrintResponseDoc> = {
action:
({ done, fatal }, { showLoader, hideLoader }) =>
async ([doc]: [OnboardingRequestDto]) => {
const format = DOCUMENT_EXPORT_FORMAT.PDF;
showLoader();
const [value, err] = await to(downloadReceipt(doc.id, doc.bankClient.clientId));
hideLoader();
fatal(err);
if (value) {
const fileName = getFilenameFromTemplate(doc, DOCUMENT_TYPE_CODE.ONB_CM_1_1_23);
showFile(value.content, fileName, format);
}
done();
},
guardians: [canDownloadCommissionPaymentDocument],
fatalHandler: ({ showServerErrorModal }) => showServerErrorModal({ header: locale.errorDialog.downloadError }),
};
@@ -0,0 +1,55 @@
import type { CommonOnboardingContextFractal } from 'actions-fractal';
import type { OnboardingRequestDto } from 'interfaces';
import { locale } from 'localization';
import { onboardingCommonService } from 'services';
import { DOCUMENT_TYPE_CODE } from 'stream-constants';
import { getFilenameFromTemplate, getOnbConfig } from 'utils';
import { to } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { attachmentService, DOCUMENT_EXPORT_FORMAT, showFile, type IPrintResponseDoc } from '@platform/services';
/** Загрузка QR кода из filestorage(замена qrCodeDownload). */
export const downloadQrCodeFromFs = async (requestId: string, clientId: string) => {
const { downloadDocsFromFs } = getOnbConfig();
if (!downloadDocsFromFs) {
return onboardingCommonService.qrCodeDownload(requestId, clientId);
}
const attachmentInfo = await onboardingCommonService.exportQrCode(requestId, clientId);
const attachment = await attachmentService.downloadOneTimeData(attachmentInfo.id, attachmentInfo.accessToken);
return { content: attachment.data, fileName: attachment.fileName };
};
/**
* Функция сформировать QR-код с информацией о тарифе и сумме комиссии.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138996317
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138996417
*/
export const downloadQrCodeFractal: IActionConfig<CommonOnboardingContextFractal, IPrintResponseDoc> = {
action:
({ done, fatal }, { showLoader, hideLoader }) =>
async ([doc]: [OnboardingRequestDto]) => {
const format = DOCUMENT_EXPORT_FORMAT.PDF;
showLoader();
const [value, err] = await to(downloadQrCodeFromFs(doc.id, doc.bankClient.clientId));
hideLoader();
fatal(err);
if (value) {
const fileName = getFilenameFromTemplate(doc, DOCUMENT_TYPE_CODE.ONB_CM_1_1_27);
showFile(value.content, fileName, format);
}
done();
},
guardians: [],
fatalHandler: ({ showServerErrorModal }) => showServerErrorModal({ header: locale.errorDialog.downloadError }),
};
@@ -0,0 +1,35 @@
import type { IOnboardingContext } from 'action-executers';
import type { NewPersonContact, OnboardingRequestDto } from 'interfaces';
import { transformValidation } from 'services/onboarding-common';
import { to } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import type { ISaveResponse } from '@platform/services';
/**
* Изменение контактных данных.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=134219656
*/
export const editContactsDataFractal: IActionConfig<IOnboardingContext, ISaveResponse<OnboardingRequestDto>> = {
action:
({ fatal, addSucceeded, done }, { service }) =>
async ([{ request, contact }]: [{ request: OnboardingRequestDto; contact: NewPersonContact }]) => {
const [result, err] = await to(service.editContactsData(request.id, contact));
fatal(err);
if ('error' in result!) {
fatal(result.error?.code);
}
if (result?.data) {
const { payload, validationResult } = result.data;
const resultWithValidation = transformValidation({ data: payload || request, validationResult });
addSucceeded(resultWithValidation);
}
done();
},
};
@@ -0,0 +1,55 @@
import { useMemo } from 'react';
import { useServerErrorModal, useAlertModal, useHeadOfFarmWarningModal, showServerErrorDialog } from 'components';
import { locale } from 'localization';
import { useNotFoundSparkModal } from 'pages/select-organization-fractal/modals/not-found-in-spark';
import { ERROR as CUSTOM_ERROR } from 'stream-constants';
import { ERROR, errorHandler as baseErrorHandler } from '@platform/services';
/** Обработчик ошибок. */
export const useErrorHandler = () => {
const showServerErrorModal = useServerErrorModal();
const showNotFoundSparkModal = useNotFoundSparkModal();
const showAlertModal = useAlertModal();
const showHeadOfFarmWarningModal = useHeadOfFarmWarningModal();
const errorHandler = useMemo(
() =>
baseErrorHandler({
/** Организация не найдена в СПАРК. */
[CUSTOM_ERROR.SPARK_NOT_FOUND_ORG]: showNotFoundSparkModal,
/** Самозанятый не найден в СПАРК. */
[CUSTOM_ERROR.SPARK_NOT_FOUND_IP]: () => showNotFoundSparkModal(true),
/** Ошибка сервера. */
[ERROR.UNEXPECTED_SYSTEM_ERROR]: () => showServerErrorModal({ header: locale.errorDialog.serverError }),
/** Сервис недоступен для глав крестьянских (фермерских) хозяйств. (ОКОПФ 50101). */
[CUSTOM_ERROR.HEAD_OF_FARM]: showHeadOfFarmWarningModal,
/** Вы не сможете создать новую заявку, пока не завершите работу с заявкой в ЕСК. */
[CUSTOM_ERROR.REQUEST_115_IS_FOUND_IN_ESK]: () =>
showAlertModal({ header: locale.modals.found115InEsk.header, content: locale.modals.found115InEsk.message, type: 'warning' }),
/** Найден действующий счёт. */
[CUSTOM_ERROR.REQUEST_RKO_IS_FOUND_IN_ESK]: () => {
showAlertModal({
header: locale.dialog.activeRkoRequests.header,
content: locale.dialog.activeRkoRequests.content,
type: 'warning',
preventSimpleClose: true,
});
},
[CUSTOM_ERROR.TECH_REQ_CREATING_FAILED]: () => showServerErrorDialog({ title: locale.dialog.techReqError.header }),
[ERROR.OPTIMISTIC_LOCK]: () =>
showAlertModal({
header: locale.common.error,
content: locale.common.lockError,
type: 'warning',
}),
[ERROR.BAD_REQUEST]: () =>
showAlertModal({
header: locale.common.saveError,
type: 'error',
}),
}),
[showAlertModal, showHeadOfFarmWarningModal, showNotFoundSparkModal, showServerErrorModal]
);
return { errorHandler };
};
@@ -0,0 +1,91 @@
import { useMemo } from 'react';
import type { showServerErrorDialog } from 'components';
import { useServerErrorModal, useConfirmModal } from 'components';
import { showExportDocumentsDialog } from 'components/modals/export-documents-dialog';
import { showSnackbarMessage } from 'components/snackbar-provider';
import type { IOnboardingAdminService, IOnboardingClientService, IOnboardingCommmonService } from 'services';
import { onboardingAdminService, onboardingClientService } from 'services';
import type { IExecuter } from '@platform/core';
import { createExecuter } from '@platform/core';
import type { IActionServiceContext, IBaseContext } from '@platform/services';
import { createContext, isClientScope } from '@platform/services';
import { useErrorHandler } from './use-error-handler';
/** Общий контекст экзекьютора. */
export interface CommonOnboardingContext<T = IOnboardingCommmonService> extends IActionServiceContext<T>, IBaseContext {
errorHandler: ReturnType<typeof useErrorHandler>['errorHandler'];
showServerErrorDialog: typeof showServerErrorDialog;
showSnackbarMessage: typeof showSnackbarMessage;
}
/** Общий контекст экзекьютора для фрактальных экранов. */
export interface CommonOnboardingContextFractal<T = IOnboardingCommmonService> extends CommonOnboardingContext<T> {
showServerErrorModal: ReturnType<typeof useServerErrorModal>;
showConfirmModal: ReturnType<typeof useConfirmModal>;
}
/** Контекст клиентского экзекьютора для фрактальных экранов. */
export interface OnboardingContext extends CommonOnboardingContextFractal<IOnboardingClientService> {
showExportDocumentsDialog: typeof showExportDocumentsDialog;
}
/** Контекст админского экзекьютора для фрактальных экранов. */
export type OnboardingAdminContext = CommonOnboardingContextFractal<IOnboardingAdminService>;
/** Контекст экзекьютора для фрактальных экранов. */
export type ExecutorContext = OnboardingAdminContext | OnboardingContext;
/** Экзекьютора заявки на открытие первого счёта для фрактальных экранов. */
export type IOnboardingExecutor = IExecuter<ExecutorContext>;
/** Клиентский экзекьютор заявки на открытие первого счёта для фрактальных экранов. */
export type ClientExecutor = IExecuter<OnboardingContext>;
/** Админский экзекьютор заявки на открытие первого счёта для фрактальных экранов. */
export type AdminExecutor = IExecuter<OnboardingAdminContext>;
/** Хук получения экзекьютор заявки на открытие первого счёта. */
export const useOnboardingExecutor = (context?: Partial<OnboardingContext>) => {
const { errorHandler } = useErrorHandler();
const showServerErrorModal = useServerErrorModal();
const showConfirmModal = useConfirmModal();
const commonContext = useMemo(
() => ({
...createContext(),
errorHandler,
showServerErrorModal,
showConfirmModal,
// Для совместимости экшнов подставляем вызов фрактальной модалки
showServerErrorDialog: ({ title }: { title?: string }) => showServerErrorModal({ header: title }),
showSnackbarMessage,
}),
[errorHandler, showConfirmModal, showServerErrorModal]
);
const clientContext: OnboardingContext = useMemo(
() => ({
...commonContext,
showExportDocumentsDialog,
...context,
service: onboardingClientService,
}),
[commonContext, context]
);
const adminContext: OnboardingAdminContext = useMemo(
() => ({
...commonContext,
...context,
service: onboardingAdminService,
}),
[commonContext, context]
);
const executor = useMemo<IOnboardingExecutor>(
() => createExecuter(isClientScope() ? clientContext : adminContext),
[adminContext, clientContext]
);
return { executor };
};
@@ -0,0 +1,65 @@
import { useMemo } from 'react';
import type { CommonOnboardingContextFractal } from 'actions-fractal';
import { useConfirmModal, useServerErrorModal } from 'components';
import { showExportDocumentsDialog } from 'components/modals/export-documents-dialog';
import { showSnackbarMessage } from 'components/snackbar-provider';
import type { IOnboardingShortClientService } from 'services/onboarding-short-client';
import { onboardingShortClientService } from 'services/onboarding-short-client';
import { createExecuter, type IExecuter } from '@platform/core';
import { createContext } from '@platform/services';
import { useErrorHandler } from './use-error-handler';
/** Контекст клиентского экзекьютора для фрактальных экранов. */
export interface ShortOnboardingContext extends CommonOnboardingContextFractal<IOnboardingShortClientService> {
showExportDocumentsDialog: typeof showExportDocumentsDialog;
}
/** Экзекьютора заявки на открытие первого счёта для фрактальных экранов. */
export type IShortOnboardingExecutor = IExecuter<ShortOnboardingContext>;
/** Хук получения экзекьютор короткой заявки на открытие первого счёта. */
export const useShortOnboardingExecutor = (context?: Partial<ShortOnboardingContext>) => {
const { errorHandler } = useErrorHandler();
const showServerErrorModal = useServerErrorModal();
const showConfirmModal = useConfirmModal();
const commonContext = useMemo(
() => ({
...createContext(),
errorHandler,
showServerErrorModal,
showConfirmModal,
// Для совместимости экшнов подставляем вызов фрактальной модалки
showServerErrorDialog: ({ title }: { title?: string }) => showServerErrorModal({ header: title }),
showSnackbarMessage,
}),
[errorHandler, showConfirmModal, showServerErrorModal]
);
const clientContext: ShortOnboardingContext = useMemo(
() => ({
...commonContext,
showExportDocumentsDialog,
...context,
service: onboardingShortClientService,
}),
[commonContext, context]
);
// const adminContext: OnboardingAdminContext = useMemo(
// () => ({
// ...commonContext,
// ...context,
// service: onboardingAdminService,
// }),
// [commonContext, context]
// );
const executor = useMemo<IShortOnboardingExecutor>(
// () => createExecuter(isClientScope() ? clientContext : adminContext),
() => createExecuter(clientContext),
[clientContext]
);
return { executor };
};
+18
View File
@@ -0,0 +1,18 @@
export * from './use-delete';
export * from './use-edit';
export * from './use-edit';
export * from './use-export';
export * from './use-fix';
export * from './use-view';
export * from './hooks/use-onboarding-executor';
export * from './hooks/use-error-handler';
export * from './hooks/use-short-onboarding-executor';
export * from './utils';
export * from './interfaces';
export * from './check-active-request-before-create-fractal';
export * from './print-account-opened-notification-fractal';
export * from './download-account-opened-notification-fractal';
export * from './update-request-fractal';
export * from './parse-fns-archive-fractal';
export * from './download-qr-code-fractal';
export * from './update-short-request-fractal';
+22
View File
@@ -0,0 +1,22 @@
import type { ReactNode } from 'react';
import type { Guardian } from '@platform/core';
/** Описание простого экшена. */
export type SimpleAction<T> = (data: T) => void;
/** Описание экшена с принимаемым контекстом. */
export type ActionWithContext<T, C> = (context: C) => SimpleAction<T>;
/** Общее описание экшенов. */
export type Action<T, C> = C extends undefined ? SimpleAction<T> : ActionWithContext<T, C>;
/** Интерфейс возращаемого объекта хука экшена. */
export interface IHookActionReturn<T, C = undefined> {
/** Экшен. */
action: Action<T, C>;
/** Список гардинов. */
guardians?: Guardian[];
/** UI экшена в jsx представлении, обычно модальное окно. */
jsx?: ReactNode;
}
/** Интерфейс хука с описаным экшеном. */
export type IHookAction<T, C = undefined> = () => IHookActionReturn<T, C>;
@@ -0,0 +1,36 @@
import type { OriginalDocumentDto } from 'interfaces';
import type { DOCUMENT_TYPE_CODE } from 'stream-constants';
import { createRequestFatalHandler } from 'utils';
import { singleAction, to } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import type { CommonOnboardingContext } from './hooks/use-onboarding-executor';
/**
* Клиент/Банк. Функция распарсивания архива ФНС.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=93306020
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=93310120
*/
export const parseFNSArchive: IActionConfig<CommonOnboardingContext, OriginalDocumentDto[] | string> = {
action:
({ fatal, addSucceeded, done, addFailed }, { service }) =>
async ([{ requestId, zipFileId, docType }]: [{ requestId: string; zipFileId: string; docType: DOCUMENT_TYPE_CODE }]) => {
const [response, error] = await to(service.parseFNSZip(requestId, zipFileId, docType));
fatal(error);
const { data, error: serverError } = response!;
if (serverError) {
addFailed(serverError.message);
}
if (data) {
addSucceeded(data);
}
done();
},
fatalHandler: createRequestFatalHandler,
guardians: [singleAction],
};
@@ -0,0 +1,46 @@
import type { IOnboardingContext } from 'action-executers';
import type { IOnboardingAdminContext } from 'action-executers/admin';
import type { ShowConfirmModalType } from 'components';
import type { OnboardingRequestDto } from 'interfaces';
import { locale } from 'localization';
import { STATUS, DOCUMENT_TYPE_CODE } from 'stream-constants';
import { goToFilePreview } from 'utils';
import { singleAction, to } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { DOCUMENT_EXPORT_FORMAT } from '@platform/services';
import { inStatuses } from '../actions/guardians';
import { downloadPrintForm } from './print-report-fractal';
/**
* Клиент/ Банк. Функция формирования ПФ уведомления об открытии счетов.
* Открывает пф на просмотр и печать.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=84458398
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=93294020
*/
export const printAccountOpenedNotificationFractal: IActionConfig<IOnboardingAdminContext | IOnboardingContext, void> = {
action:
({ done }, { showLoader, hideLoader }) =>
async ([doc]: [OnboardingRequestDto], _, showModal: ShowConfirmModalType) => {
showLoader();
const [response, err] = await to(downloadPrintForm(doc.id, DOCUMENT_EXPORT_FORMAT.PDF, DOCUMENT_TYPE_CODE.ONB_CM_1_1_21));
hideLoader();
if (err) {
showModal({
header: locale.action.printNotificationErrorText,
type: 'error',
confirmButtonText: locale.action.ok,
cancelButtonText: '',
});
done();
}
await goToFilePreview(response!.content, response!.fileName);
done();
},
guardians: [singleAction, inStatuses([STATUS.EXECUTED])],
};
@@ -0,0 +1,80 @@
import type { IOnboardingContext } from 'action-executers';
import type { IOnboardingAdminContext } from 'action-executers/admin';
import type { ShowConfirmModalType } from 'components';
import type { OnboardingRequestDto } from 'interfaces';
import { locale } from 'localization';
import { onboardingCommonService } from 'services';
import type { DOCUMENT_TYPE_CODE, ExtendedDocumentExportFormat } from 'stream-constants';
import { APPROVED_STATUSES, STATUS, IN_PROGRESS_STATUSES } from 'stream-constants';
import { getFilenameFromTemplate, getOnbConfig } from 'utils';
import { singleAction, to } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { showFile, DOCUMENT_EXPORT_FORMAT, attachmentService } from '@platform/services';
import { inStatuses } from '../actions/guardians';
/** Загрузка печатной формы из filestorage по настройке(замена printReport). */
export const downloadPrintForm = async (id: string, format: ExtendedDocumentExportFormat, template: string) => {
const { downloadDocsFromFs } = getOnbConfig();
if (!downloadDocsFromFs) {
return onboardingCommonService.printReport(id, format, template);
}
const attachmentInfo = await onboardingCommonService.exportPrintReport(id, format, template);
const attachment = await attachmentService.downloadOneTimeData(attachmentInfo.id, attachmentInfo.accessToken);
return { content: attachment.data, fileName: attachment.fileName };
};
// TODO используется не только по основному назначение, но и как утилита
/**
* Клиент/Банк. Функция экспорта ПФ. Осуществляет скачивание документа.
* Меняя параметр "template" можно использовать для формирования других документов.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=51820214
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=84447739
*/
export const printReportFractal: IActionConfig<IOnboardingAdminContext | IOnboardingContext, void> = {
action:
({ done }, { showLoader, hideLoader }) =>
async ([doc]: [OnboardingRequestDto], template: DOCUMENT_TYPE_CODE, showModal: ShowConfirmModalType) => {
const format = DOCUMENT_EXPORT_FORMAT.PDF;
showLoader();
const [value, err] = await to(downloadPrintForm(doc.id, format, template));
hideLoader();
if (err) {
showModal({
header: locale.action.printNotificationErrorText,
type: 'error',
confirmButtonText: locale.action.ok,
cancelButtonText: '',
});
done();
}
if (value) {
const fileName = getFilenameFromTemplate(doc, template, value.fileName);
showFile(value.content, fileName, format);
}
done();
},
guardians: [
singleAction,
inStatuses([
STATUS.FORMED,
STATUS.APPROVED,
STATUS.DELIVERED,
STATUS.EXECUTED,
STATUS.WAITING_RESTRICTION,
...IN_PROGRESS_STATUSES,
...APPROVED_STATUSES,
]),
],
};
@@ -0,0 +1,42 @@
import type { CommonOnboardingContextFractal } from 'actions-fractal';
import type { OnboardingRequestDto, SaveResponseWithRawValidationResults } from 'interfaces';
import { singleAction, to } from '@platform/core';
import type { IActionConfig } from '@platform/core';
/**
* Обновление данных заявки.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=328081
*/
export const updateRequestFractal: IActionConfig<
CommonOnboardingContextFractal,
SaveResponseWithRawValidationResults<OnboardingRequestDto> | number
> = {
action:
({ addFailed, addSucceeded, done, fatal }, { service, showLoader, hideLoader }) =>
async ([doc]: [OnboardingRequestDto]) => {
showLoader();
const [res, err] = await to(service.update(doc.id, doc));
hideLoader();
fatal(err);
if (res?.code) {
addFailed(res.code);
}
if (res?.data) {
addSucceeded(res);
}
done();
},
failedHandler: ({ errorHandler }, code) => {
const response = { data: { errorInfo: { code } } };
errorHandler({ response });
},
guardians: [singleAction],
};
@@ -0,0 +1,42 @@
import type { CommonOnboardingContextFractal } from 'actions-fractal';
import type { SaveResponseWithRawValidationResults } from 'interfaces';
import type { ShortOnboardingRequestDto } from 'pages/onboarding-short/interfaces';
import type { IOnboardingShortClientService } from 'services/onboarding-short-client';
import type { IActionConfig } from '@platform/core';
import { singleAction, to } from '@platform/core';
/**
* Обновление данных заявки.
*/
export const updateShortRequestFractal: IActionConfig<
CommonOnboardingContextFractal<IOnboardingShortClientService>,
SaveResponseWithRawValidationResults<ShortOnboardingRequestDto> | number
> = {
action:
({ addFailed, addSucceeded, done, fatal }, { service, showLoader, hideLoader }) =>
async ([doc]: [ShortOnboardingRequestDto]) => {
showLoader();
const [res, err] = await to(service.update(doc));
hideLoader();
fatal(err);
if (res?.code) {
addFailed(res.code);
}
if (res?.data) {
addSucceeded(res);
}
done();
},
failedHandler: ({ errorHandler }, code) => {
const response = { data: { errorInfo: { code } } };
errorHandler({ response });
},
guardians: [singleAction],
};
+55
View File
@@ -0,0 +1,55 @@
import { useCallback } from 'react';
import { useSnackbar } from '@fractal-ui/overlays';
import { inStatuses } from 'actions/guardians';
import { useConfirmModal } from 'components';
import type { OnboardingRequestDto } from 'interfaces';
import { locale } from 'localization';
import { onboardingClientService } from 'services';
import { STATUS } from 'stream-constants';
import type { IHookAction } from './interfaces';
/** Статусы, при которых доступна функция удаления заявки. */
const DELETE_ACTIONS = [STATUS.DRAFT, STATUS.COMPLETED, STATUS.DOCS_LOAD];
/** Интерфейс параметров. */
interface DeleteActionParams {
/** Документ. */
doc: OnboardingRequestDto;
/** Колбэк на успешное удаление. */
onSuccessRemove(): void;
}
/**
* Функция удаления заявки.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=42679028
*/
export const useDelete: IHookAction<DeleteActionParams> = () => {
const showConfirmModal = useConfirmModal();
const { showSnackbarMessage } = useSnackbar();
const action = useCallback(
({ doc, onSuccessRemove }: DeleteActionParams) => {
showConfirmModal({
content: locale.dialog.removeRequest.text,
type: 'warning',
header: locale.dialog.removeRequest.header,
confirmButtonText: locale.yes,
onConfirm: async () => {
await onboardingClientService.delete(doc.id);
showSnackbarMessage({ type: 'success', message: locale.snake.removeRequest.success });
onSuccessRemove();
},
cancelButtonText: locale.no,
preventSimpleClose: true,
});
},
[showConfirmModal, showSnackbarMessage]
);
return {
action,
guardians: [inStatuses(DELETE_ACTIONS)],
};
};
+28
View File
@@ -0,0 +1,28 @@
import { useCallback } from 'react';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { useHistory } from 'react-router-dom';
import { CLIENT_EDIT_STATUSES } from 'stream-constants';
import { COMMON_STREAM_URL } from '@platform/services';
import type { IHookAction } from './interfaces';
/**
* Функция редактирования заявки.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=42679027
*/
export const useEdit: IHookAction<OnboardingRequestDto> = () => {
const { push } = useHistory();
const action = useCallback(
(doc: OnboardingRequestDto) => {
push(`${COMMON_STREAM_URL.ONBOARDING}/${doc.id}`);
},
[push]
);
return {
action,
guardians: [inStatuses(CLIENT_EDIT_STATUSES)],
};
};
+94
View File
@@ -0,0 +1,94 @@
import { useCallback } from 'react';
import { canExportDocument } from 'actions/guardians';
import { showExportDocumentsDialog } from 'components';
import type { IOnboardingAppConfigClient, OnboardingRequestDto } from 'interfaces';
import { onboardingClientService } from 'services';
import type { ExtendedDocumentExportFormat } from 'stream-constants';
import { STATUS } from 'stream-constants';
import { errorHandler, getExportedFilesFilename, getOnbConfig } from 'utils';
import { to } from '@platform/core';
import type { IDownloadedAttachment } from '@platform/services';
import { DOCUMENT_EXPORT_FORMAT, attachmentService, showFile } from '@platform/services';
import type { IHookAction } from './interfaces';
/** Интерфейс входных параметров. */
interface ExportActionParams {
/** Интерфейс документа. */
doc: OnboardingRequestDto;
/** Колбэк на успешный экспорт. */
onSuccessExport(): void;
/** Показать лоадер. */
showLoader(): void;
/** Скрыть лоадер. */
hideLoader(): void;
}
/**
* Функция экспорта ПФ.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=42679029
*/
export const useExport: IHookAction<ExportActionParams> = () => {
const action = useCallback(async ({ doc, onSuccessExport, showLoader, hideLoader }: ExportActionParams) => {
let format: ExtendedDocumentExportFormat = [STATUS.FORMED, STATUS.REJECTED].includes(doc.status)
? getOnbConfig().onboarding_client_printFormat_docPackExportFormat
: getOnbConfig().onboarding_client_printFormat_exportFormat;
if (!format || format === DOCUMENT_EXPORT_FORMAT.USER_CHOICE) {
const [dialogResult, dialogCancel] = await to(showExportDocumentsDialog({ extraSmall: true }));
if (dialogCancel) {
return;
}
if (dialogResult?.format) {
format = dialogResult.format;
}
}
showLoader();
const templatesData = doc.formedDocuments?.map(({ additionalParameter, systemFileName }) => ({
linkedEntityId: additionalParameter,
template: systemFileName,
}));
const exportPrintFormsFromFileStorage = getOnbConfig<IOnboardingAppConfigClient>().onboarding?.exportPrintFormsFromFileStorage;
let value: IDownloadedAttachment | null;
let err: unknown;
if (exportPrintFormsFromFileStorage) {
const [attachmentInfo, attachmentErr] = await to(onboardingClientService.exportPrintForms(doc.id, format, templatesData));
if (attachmentErr) {
errorHandler(attachmentErr);
}
const { id, accessToken } = attachmentInfo!;
[value, err] = await to(attachmentService.downloadOneTimeData(id, accessToken));
} else {
[value, err] = await to(onboardingClientService.exportReportToZip(doc.id, format, templatesData));
}
hideLoader();
if (err) {
errorHandler(err);
}
if (value) {
showFile(value.data, getExportedFilesFilename(doc), value.type);
onSuccessExport();
return doc;
}
}, []);
return {
action,
guardians: [canExportDocument([STATUS.FORMED, STATUS.WAITING_FOR_ESK_ACCOUNTS, STATUS.REJECTED])],
};
};
+31
View File
@@ -0,0 +1,31 @@
import { useCallback } from 'react';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { useHistory } from 'react-router-dom';
import { STATUS } from 'stream-constants';
import { COMMON_STREAM_URL } from '@platform/services';
import type { IHookAction } from './interfaces';
/** Статусы, при которых доступна функция редактирования заявки. */
const FIX_STATUSES = [STATUS.REPLACING_DOCS];
/**
* Функция редактирования заявки (Исправление).
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=42679027
*/
export const useFix: IHookAction<OnboardingRequestDto> = () => {
const { push } = useHistory();
const action = useCallback(
(doc: OnboardingRequestDto) => {
push(`${COMMON_STREAM_URL.ONBOARDING}/${doc.id}/edit`);
},
[push]
);
return {
action,
guardians: [inStatuses(FIX_STATUSES)],
};
};
+34
View File
@@ -0,0 +1,34 @@
import { useCallback } from 'react';
import { notInStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { useHistory } from 'react-router-dom';
import { STATUS } from 'stream-constants';
import { COMMON_STREAM_URL } from '@platform/services';
import type { IHookAction } from './interfaces';
/** Статусы, при которых функция просмотра заявки не доступна клиенту.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=42677578, 3.3 в блоке "Кнопки ЭФ".
*/
const VIEW_STATUSES_EXCLUDED = [STATUS.DRAFT, STATUS.COMPLETED, STATUS.DOCS_LOAD, STATUS.DATA_ERROR, STATUS.REPLACING_DOCS];
/**
* Функция просмотра заявки.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=42679025
*/
export const useView: IHookAction<OnboardingRequestDto> = () => {
const { push } = useHistory();
const action = useCallback(
(doc: OnboardingRequestDto) => {
push(`${COMMON_STREAM_URL.ONBOARDING}/${doc.id}`);
},
[push]
);
return {
action,
guardians: [notInStatuses(VIEW_STATUSES_EXCLUDED)],
};
};
+31
View File
@@ -0,0 +1,31 @@
import { useCallback } from 'react';
import type { Guardian } from '@platform/core';
import { useAuth } from '@platform/services';
/**
* Функция проверки того, что действие может быть выполнено с заданными параметрами.
*/
export const validateGuardians = <T>(guardians: Guardian[], doc: T): boolean => {
for (const guard of guardians) {
try {
guard([doc]);
} catch {
return false;
}
}
return true;
};
/** Хук с утилитами для работы с экшенами. */
export const useActionUtils = () => {
const { accessCheck } = useAuth();
const getAvailableActions = useCallback(
<T extends { authorities: string[]; guardians?: Guardian[] }, D>(actions: T[], doc: D): T[] =>
actions.filter(item => accessCheck(...item.authorities) && validateGuardians<D>(item.guardians || [], doc)),
[accessCheck]
);
return { getAvailableActions };
};
+38
View File
@@ -0,0 +1,38 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import type { OnboardingRequestDto } from 'interfaces';
import { locale } from 'localization';
import { onboardingAdminService } from 'services';
import { to, singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
/**
* Банк: Функция сохранения результатов выезда менеджера.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=42679054
*/
export const addDepartureRecord: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action:
({ done, fatal, addSucceeded }, { showAddDepartureRecordDialog, showLoader, hideLoader }) =>
async ([doc]: [OnboardingRequestDto]) => {
const [dialogResult, dialogCancel] = await to(showAddDepartureRecordDialog(doc));
if (dialogCancel) {
done();
return;
}
showLoader();
const [res, err] = await to(onboardingAdminService.addDepartureRecord(dialogResult!));
hideLoader();
fatal(err);
addSucceeded(res!);
done();
},
succeededHandler: ({ showSuccess }) => showSuccess('', locale.successMessage.dataSaved),
guardians: [singleAction],
};
+37
View File
@@ -0,0 +1,37 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { to } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { inStatuses } from '../guardians';
/**
* Функция "Добавить документ в список".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=42679048
*/
export const addDocumentAction: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action:
({ done, fatal, addSucceeded }, { service, showAddDocumentDialog, showLoader, hideLoader }) =>
async ([doc]: [OnboardingRequestDto]) => {
const [newDoc, cancel] = await to(showAddDocumentDialog());
if (cancel) {
done();
return;
}
showLoader();
const [result, err] = await to(service.addOriginDoc(doc.id, doc.version, newDoc!));
hideLoader();
fatal(err);
addSucceeded(result!);
done();
},
guardians: [inStatuses([STATUS.EXPORT_TO_ESK_ERROR, STATUS.PROCESSING_TESSA_COMMENTS])],
};
@@ -0,0 +1,2 @@
export * from './open';
export * from './view-history';
@@ -0,0 +1,15 @@
import type { OnboardingRequestArchiveBankScrollerDto } from 'interfaces/admin';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import type { IBaseContext } from '@platform/services';
import { open as openAction } from '@platform/services';
/**
* Банк: Функция просмотра архивной заявки.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=121101069
*/
export const open: IActionConfig<IBaseContext, OnboardingRequestArchiveBankScrollerDto> = {
...openAction(({ id }) => `/onboarding/archive/${id}`),
guardians: [singleAction],
};
@@ -0,0 +1,14 @@
import type { ArchiveRequestsExecutorContext } from 'action-executers/admin';
import { ARCHIVE_REQUEST_STATUS_LABEL } from 'stream-constants/admin';
import type { IActionConfig } from '@platform/core';
import type { BankHistoryDialogData } from '@platform/services';
import { action } from '@platform/services/admin';
/**
* Банк: Функция просмотра истории архивной заявки.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=149424301
*/
export const viewHistory: IActionConfig<ArchiveRequestsExecutorContext, BankHistoryDialogData> = action.getBankHistoryAction({
getStatusLabel: status => ARCHIVE_REQUEST_STATUS_LABEL[status],
});
+51
View File
@@ -0,0 +1,51 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { showServerErrorDialog, showWarningDialog } from 'components/modals';
import type { OnboardingRequestDto } from 'interfaces';
import type { OnboardingRequestBankScrollerDto } from 'interfaces/admin';
import { locale } from 'localization';
import { to } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { canAssignResponsibleForCall, checkOnbConfig, currentUserIsNotResponsible } from './guardians';
/**
* Банк: Функция назначить ответственного за обзвон Клиентов по заявке.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=151817959
*/
export const assignResponsible: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action:
({ done, fatal, addSucceeded }, { service, showLoader, hideLoader }) =>
async ([doc]: [OnboardingRequestBankScrollerDto | OnboardingRequestDto]) => {
const { isRequestEditing, responsibleBankUserFio, id } = doc;
if (isRequestEditing) {
showWarningDialog({
header: locale.dialog.takeRequestResponsibleError.header,
content: responsibleBankUserFio
? locale.dialog.takeRequestResponsibleError.content({ responsibleBankUserFio })
: locale.dialog.requestIsEditing.content,
buttonText: locale.action.ok,
});
done();
return;
}
showLoader();
const [result, err] = await to(service.assignResponsible(id));
hideLoader();
fatal(err);
addSucceeded(result!.data);
done();
},
fatalHandler: () => showServerErrorDialog({ title: locale.errorDialog.serverError }),
guardians: [
currentUserIsNotResponsible,
checkOnbConfig(({ assignResponsibleEnabled }) => assignResponsibleEnabled),
canAssignResponsibleForCall,
],
};
@@ -0,0 +1,35 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import type { OnboardingRequestDto, OriginalDocumentDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { groupAction, to } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { requiredAttachmentReplaceValue, inStatuses } from '../guardians';
/**
* Функция снять с замены.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=42679048
*/
export const cancelNeedToReplaceAction: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action:
({ done, fatal, addSucceeded }, { service }) =>
async ([doc, originalDocuments]: [OnboardingRequestDto, OriginalDocumentDto[]]) => {
const data = originalDocuments.map(originalDocument => ({
...originalDocument,
requiredReplace: false,
}));
const [result, err] = await to(service.requireReplace(doc.id, doc.version, data));
fatal(err);
addSucceeded(result!);
done();
},
guardians: [
groupAction,
requiredAttachmentReplaceValue(true),
inStatuses([STATUS.EXPORT_TO_ESK_ERROR, STATUS.PROCESSING_TESSA_COMMENTS]),
],
};
+328
View File
@@ -0,0 +1,328 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import type { OnboardingRequestDto } from 'interfaces';
import { locale } from 'localization';
import { STATUS, UNABLE_TO_CHANGE_STATUS } from 'stream-constants';
import { CANCEL_STATUSES } from 'stream-constants/admin';
import { getChangeStatusOption, getChangeStatusOptions } from 'utils';
import { to, singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { UserType } from '@platform/services/admin';
import { dateTime } from '@platform/ui';
import { canChangeStatus, inStatusesForChangeStatusExtended } from './guardians';
import {
APPROVED_AVAILABLE_STATUSES,
changeToApprovedStatus,
changeToCompletedStatus,
changeToCompletedStatusBankUserType,
changeToDataErrorStatus,
changeToDeletedStatus,
changeToDeletedStatusBankUserType,
changeToDeliveredStatus,
changeToDetailsErrorStatus,
changeToDocsLoadStatus,
changeToDraftStatus,
changeToDraftStatusBankUserType,
changeToEditingCompletedStatus,
changeToEditingDocsLoadStatus,
changeToEditingDraftStatus,
changeToEditingReplacingDocsStatus,
changeToExecutedByEskStatus,
changeToExecutedByTessaStatus,
changeToExecutedStatus,
changeToExportedToEskStatus,
changeToExportToEskErrorStatus,
changeToExportToEskStatus,
changeToExportToTessaStatus,
changeToFormedStatus,
changeToFormedStatusBankUserType,
changeToProcessingTessaCommentsStatus,
changeToRefusedStatus,
changeToRejectedStatus,
changeToReplacingDocsStatus,
changeToWaitingForEskAccountsStatus,
changeToWaitingForEskDecisionStatus,
changeToWaitingRestrictionStatus,
COMPLETED_AVAILABLE_STATUSES_BANK_USER_TYPE,
DATA_ERROR_AVAILABLE_STATUSES,
DELETED_AVAILABLE_STATUSES,
DELETED_AVAILABLE_STATUSES_BANK_USER_TYPE,
DELIVERED_AVAILABLE_STATUSES,
DETAILS_ERROR_AVAILABLE_STATUSES,
DOCS_LOAD_AVAILABLE_STATUSES,
DRAFT_AVAILABLE_STATUSES,
DRAFT_AVAILABLE_STATUSES_BANK_USER_TYPE,
EDITING_COMPLETED_AVAILABLE_STATUSES,
EDITING_DOCS_LOAD_AVAILABLE_STATUSES,
EDITING_DRAFT_AVAILABLE_STATUSES,
EDITING_REPLACING_DOCS_AVAILABLE_STATUSES,
EXECUTED_AVAILABLE_STATUSES,
EXECUTED_BY_ESK_AVAILABLE_STATUSES,
EXECUTED_BY_TESSA_AVAILABLE_STATUSES,
EXPORTED_TO_ESK_AVAILABLE_STATUSES,
EXPORT_TO_ESK_AVAILABLE_STATUSES,
EXPORT_TO_ESK_ERROR_AVAILABLE_STATUSES,
EXPORT_TO_TESSA_AVAILABLE_STATUSES,
EXPORT_TO_TESSA_ERROR_AVAILABLE_STATUSES,
FORMED_AVAILABLE_STATUSES,
FORMED_AVAILABLE_STATUSES_BANK_USER_TYPE,
PROCESSING_TESSA_COMMENTS_AVAILABLE_STATUSES,
REFUSED_AVAILABLE_STATUSES,
REJECTED_AVAILABLE_STATUSES,
REPLACING_DOCS_AVAILABLE_STATUSES,
WAITING_FOR_ESK_ACCOUNTS_AVAILABLE_STATUSES,
WAITING_FOR_ESK_DECISION_AVAILABLE_STATUSES,
WAITING_RESTRICTION_AVAILABLE_STATUSES,
} from './processing/bank-admin';
import { reverse } from './reverse';
/** Статусы, при которых доступна функция изменения статуса заявки. */
const CHANGE_STATUS_STATUSES = [
STATUS.DRAFT,
STATUS.COMPLETED,
STATUS.DOCS_LOAD,
STATUS.FORMED,
STATUS.REPLACING_DOCS,
STATUS.EDITING_DRAFT,
STATUS.EDITING_COMPLETED,
STATUS.EDITING_DOCS_LOAD,
STATUS.REPLACING_DOCS,
STATUS.EDITING_REPLACING_DOCS,
STATUS.DELIVERED,
STATUS.RECEIVED,
STATUS.EXPORT_TO_ESK,
STATUS.EXPORTED_TO_ESK,
STATUS.EXPORT_TO_ESK_ERROR,
STATUS.EXECUTED_BY_ESK,
STATUS.EXPORT_TO_TESSA,
STATUS.EXPORT_TO_TESSA_ERROR,
STATUS.EXECUTED_BY_TESSA,
STATUS.WAITING_FOR_ESK_DECISION,
STATUS.WAITING_RESTRICTION,
STATUS.PROCESSING_TESSA_COMMENTS,
STATUS.APPROVED,
STATUS.WAITING_FOR_ESK_ACCOUNTS,
STATUS.DATA_ERROR,
STATUS.REFUSED,
STATUS.DETAILS_ERROR,
];
/** Статусы, при которых доступна функция изменения статуса заявки при типе пользователя BANK. */
const CHANGE_STATUS_STATUSES_BANK_USER_TYPE = [STATUS.DRAFT, STATUS.COMPLETED, STATUS.FORMED];
/**
* Ключ - в какой статус доступен переход
* statuses - из каких статусов доступен переход.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049
*/
const STATUS_MAP: Record<string, { statuses: STATUS[]; action: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> }> = {
[STATUS.DRAFT]: {
statuses: DRAFT_AVAILABLE_STATUSES,
action: changeToDraftStatus,
},
[STATUS.COMPLETED]: {
statuses: COMPLETED_AVAILABLE_STATUSES_BANK_USER_TYPE,
action: changeToCompletedStatus,
},
[STATUS.DELETED]: {
statuses: DELETED_AVAILABLE_STATUSES,
action: changeToDeletedStatus,
},
[STATUS.EDITING_DRAFT]: {
statuses: EDITING_DRAFT_AVAILABLE_STATUSES,
action: changeToEditingDraftStatus,
},
[STATUS.DOCS_LOAD]: {
statuses: DOCS_LOAD_AVAILABLE_STATUSES,
action: changeToDocsLoadStatus,
},
[STATUS.FORMED]: {
statuses: FORMED_AVAILABLE_STATUSES,
action: changeToFormedStatus,
},
[STATUS.EDITING_DOCS_LOAD]: {
statuses: EDITING_DOCS_LOAD_AVAILABLE_STATUSES,
action: changeToEditingDocsLoadStatus,
},
[STATUS.DELIVERED]: {
statuses: DELIVERED_AVAILABLE_STATUSES,
action: changeToDeliveredStatus,
},
[STATUS.DATA_ERROR]: {
statuses: DATA_ERROR_AVAILABLE_STATUSES,
action: changeToDataErrorStatus,
},
[STATUS.REPLACING_DOCS]: {
statuses: REPLACING_DOCS_AVAILABLE_STATUSES,
action: changeToReplacingDocsStatus,
},
[STATUS.EDITING_COMPLETED]: {
statuses: EDITING_COMPLETED_AVAILABLE_STATUSES,
action: changeToEditingCompletedStatus,
},
[STATUS.EDITING_REPLACING_DOCS]: {
statuses: EDITING_REPLACING_DOCS_AVAILABLE_STATUSES,
action: changeToEditingReplacingDocsStatus,
},
[STATUS.PROCESSING_TESSA_COMMENTS]: {
statuses: PROCESSING_TESSA_COMMENTS_AVAILABLE_STATUSES,
action: changeToProcessingTessaCommentsStatus,
},
[STATUS.EXECUTED]: {
statuses: EXECUTED_AVAILABLE_STATUSES,
action: changeToExecutedStatus,
},
[STATUS.DETAILS_ERROR]: {
statuses: DETAILS_ERROR_AVAILABLE_STATUSES,
action: changeToDetailsErrorStatus,
},
[STATUS.EXPORT_TO_ESK]: {
statuses: EXPORT_TO_ESK_AVAILABLE_STATUSES,
action: changeToExportToEskStatus,
},
[STATUS.EXPORT_TO_TESSA]: {
statuses: EXPORT_TO_TESSA_AVAILABLE_STATUSES,
action: changeToExportToTessaStatus,
},
[STATUS.EXPORTED_TO_ESK]: {
statuses: EXPORTED_TO_ESK_AVAILABLE_STATUSES,
action: changeToExportedToEskStatus,
},
[STATUS.EXPORT_TO_ESK_ERROR]: {
statuses: EXPORT_TO_ESK_ERROR_AVAILABLE_STATUSES,
action: changeToExportToEskErrorStatus,
},
[STATUS.EXECUTED_BY_ESK]: {
statuses: EXECUTED_BY_ESK_AVAILABLE_STATUSES,
action: changeToExecutedByEskStatus,
},
[STATUS.APPROVED]: {
statuses: APPROVED_AVAILABLE_STATUSES,
action: changeToApprovedStatus,
},
[STATUS.REJECTED]: {
statuses: REJECTED_AVAILABLE_STATUSES,
action: changeToRejectedStatus,
},
[STATUS.EXPORT_TO_TESSA_ERROR]: {
statuses: EXPORT_TO_TESSA_ERROR_AVAILABLE_STATUSES,
action: changeToExportToTessaStatus,
},
[STATUS.EXECUTED_BY_TESSA]: {
statuses: EXECUTED_BY_TESSA_AVAILABLE_STATUSES,
action: changeToExecutedByTessaStatus,
},
[STATUS.WAITING_FOR_ESK_DECISION]: {
statuses: WAITING_FOR_ESK_DECISION_AVAILABLE_STATUSES,
action: changeToWaitingForEskDecisionStatus,
},
[STATUS.WAITING_RESTRICTION]: {
statuses: WAITING_RESTRICTION_AVAILABLE_STATUSES,
action: changeToWaitingRestrictionStatus,
},
[STATUS.WAITING_FOR_ESK_ACCOUNTS]: {
statuses: WAITING_FOR_ESK_ACCOUNTS_AVAILABLE_STATUSES,
action: changeToWaitingForEskAccountsStatus,
},
[STATUS.REFUSED]: {
statuses: REFUSED_AVAILABLE_STATUSES,
action: changeToRefusedStatus,
},
};
/**
* Ключ - в какой статус доступен переход
* statuses - из каких статусов доступен переход.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049
*/
const STATUS_MAP_BANK_USER_TYPE: Record<
string,
{ statuses: STATUS[]; action: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> }
> = {
[STATUS.DRAFT]: {
statuses: DRAFT_AVAILABLE_STATUSES_BANK_USER_TYPE,
action: changeToDraftStatusBankUserType,
},
[STATUS.COMPLETED]: {
statuses: COMPLETED_AVAILABLE_STATUSES_BANK_USER_TYPE,
action: changeToCompletedStatusBankUserType,
},
[STATUS.DELETED]: {
statuses: DELETED_AVAILABLE_STATUSES_BANK_USER_TYPE,
action: changeToDeletedStatusBankUserType,
},
[STATUS.FORMED]: {
statuses: FORMED_AVAILABLE_STATUSES_BANK_USER_TYPE,
action: changeToFormedStatusBankUserType,
},
};
/**
* Банк: Функция изменения статуса заявки (Расширенная).
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049
*/
export const changeStatusActionExtended: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action:
({ done, fatal, execute, addSucceeded, addFailed }, { service, showChangeStatusDialog }) =>
async ([doc]: [OnboardingRequestDto]) => {
const map = doc.userType === UserType.BANK ? STATUS_MAP_BANK_USER_TYPE : STATUS_MAP;
if (doc.status === STATUS.REFUSED && doc.userType === UserType.CLIENT) {
// согласно https://confluence.gboteam.ru/pages/viewpage.action?pageId=42679042
// делаем запрос истории изменения заявки и извлекаем статус, предшествующий REFUSED
const [historyResult, historyError] = await to(service.getHistory(doc.id));
fatal(historyError);
const sortedHistory = historyResult!.sort((a, b) =>
// сортируем элементы по убыванию дат
dateTime(b.changedIn).diff(dateTime(a.changedIn), 'millisecond')
);
// и тогда берем ближайший статус, попадающий в CANCEL_STATUSES
const prevRefusedStatusIndex = sortedHistory.findIndex(x => CANCEL_STATUSES.includes(x.status));
const prevRefusedStatus = historyResult![prevRefusedStatusIndex].status;
map[STATUS.REFUSED].statuses = [prevRefusedStatus];
map[prevRefusedStatus].action = reverse;
}
const currentStatus = getChangeStatusOption(doc.status);
const availableStatuses = map[doc.status].statuses;
const [result, cancel] = await to(showChangeStatusDialog(currentStatus, getChangeStatusOptions(availableStatuses)));
if (cancel) {
done();
return;
}
const { action } = map[result?.newStatus || ''];
if (!action) {
fatal();
}
const executeResult = await execute(action, [doc], result?.commentForBank, result?.commentForClient);
addSucceeded(...executeResult.succeeded);
addFailed(...executeResult.failed);
fatal(executeResult.error);
done();
},
fatalHandler({ showError }, { error }) {
if (error && error.message === UNABLE_TO_CHANGE_STATUS) {
showError(locale.errorDialog.title, locale.action.sendToDataOriginals.noReplacementError);
}
},
guardians: [
singleAction,
inStatusesForChangeStatusExtended(CHANGE_STATUS_STATUSES, CHANGE_STATUS_STATUSES_BANK_USER_TYPE),
canChangeStatus,
],
};
+154
View File
@@ -0,0 +1,154 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import type { OnboardingRequestDto } from 'interfaces';
import { locale } from 'localization';
import { STATUS, UNABLE_TO_CHANGE_STATUS } from 'stream-constants';
import { CANCEL_STATUSES } from 'stream-constants/admin';
import { getChangeStatusOption, getChangeStatusOptions } from 'utils';
import { to, singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { dateTime } from '@platform/ui';
import { inStatuses } from '../guardians';
import { canChangeStatus } from './guardians';
import {
approve,
APPROVE_STATUSES,
changeToExecutedByTessa,
changeToProcessingTessaComments,
executeDoc,
CHANGE_TO_EXECUTED_BY_TESSA_STATUSES,
EXECUTE_DOC_STATUSES,
PROCESSING_TESSA_COMMENTS_STATUSES,
reject,
REJECT_STATUSES,
sendToDataOriginals,
sendToDataRevision,
SEND_TO_DATA_ORIGINALS_STATUSES,
SEND_TO_DATA_REVISION_STATUSES,
} from './processing';
import { reverse } from './reverse';
/** Статусы, при которых доступна функция изменения статуса заявки. */
const CHANGE_STATUS_STATUSES = [
STATUS.DATA_ERROR,
STATUS.EDITING_DRAFT,
STATUS.EDITING_COMPLETED,
STATUS.EDITING_DOCS_LOAD,
STATUS.REPLACING_DOCS,
STATUS.EDITING_REPLACING_DOCS,
STATUS.EXPORT_TO_ESK_ERROR,
STATUS.EXPORT_TO_TESSA_ERROR,
STATUS.WAITING_FOR_ESK_DECISION,
STATUS.PROCESSING_TESSA_COMMENTS,
STATUS.WAITING_FOR_ESK_ACCOUNTS,
STATUS.DETAILS_ERROR,
STATUS.REFUSED,
];
/**
* Ключ - в какой статус доступен переход
* statuses - из каких статусов доступен переход.
*
* Согласно https://confluence.gboteam.ru/pages/viewpage.action?pageId=42679900 ручной перевод в EXPORT_TO_ESK невозможен.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=42679042
*/
const MAP: Record<string, { statuses: STATUS[]; action: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> }> = {
[STATUS.APPROVED]: {
statuses: APPROVE_STATUSES,
action: approve,
},
[STATUS.DATA_ERROR]: {
statuses: SEND_TO_DATA_REVISION_STATUSES,
action: sendToDataRevision,
},
[STATUS.REJECTED]: {
statuses: REJECT_STATUSES,
action: reject,
},
[STATUS.REPLACING_DOCS]: {
statuses: SEND_TO_DATA_ORIGINALS_STATUSES,
action: sendToDataOriginals,
},
[STATUS.EXECUTED]: {
statuses: EXECUTE_DOC_STATUSES,
action: executeDoc,
},
[STATUS.PROCESSING_TESSA_COMMENTS]: {
statuses: PROCESSING_TESSA_COMMENTS_STATUSES,
action: changeToProcessingTessaComments,
},
[STATUS.EXECUTED_BY_TESSA]: {
statuses: CHANGE_TO_EXECUTED_BY_TESSA_STATUSES,
action: changeToExecutedByTessa,
},
};
/**
* Банк: Функция изменения статуса заявки.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=42679042
*/
export const changeStatusAction: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action:
({ done, fatal, execute, addSucceeded, addFailed }, { service, showChangeStatusDialog }) =>
async ([doc]: [OnboardingRequestDto]) => {
let map = MAP;
if (doc.status === STATUS.REFUSED) {
// согласно https://confluence.gboteam.ru/pages/viewpage.action?pageId=42679042
// делаем запрос истории изменения заявки и извлекаем статус, предшествующий REFUSED
const [historyResult, historyError] = await to(service.getHistory(doc.id));
fatal(historyError);
const sortedHistory = historyResult!.sort((a, b) =>
// сортируем элементы по убыванию дат
dateTime(b.changedIn).diff(dateTime(a.changedIn), 'millisecond')
);
// и тогда берем ближайший статус, попадающий в CANCEL_STATUSES
const prevRefusedStatusIndex = sortedHistory.findIndex(x => CANCEL_STATUSES.includes(x.status));
const prevRefusedStatus = historyResult![prevRefusedStatusIndex].status;
map = {
...MAP,
[prevRefusedStatus]: {
statuses: [STATUS.REFUSED],
action: reverse,
},
};
}
const currentStatus = getChangeStatusOption(doc.status);
const availableStatuses = Object.keys(map).filter(key => map[key].statuses.includes(doc.status)) as STATUS[];
const [result, cancel] = await to(showChangeStatusDialog(currentStatus, getChangeStatusOptions(availableStatuses)));
if (cancel) {
done();
return;
}
const { action } = map[result?.newStatus || ''];
if (!action) {
fatal();
}
const executeResult = await execute(action, [doc], result?.commentForBank, result?.commentForClient);
addSucceeded(...executeResult.succeeded);
addFailed(...executeResult.failed);
fatal(executeResult.error);
done();
},
fatalHandler({ showError }, { error }) {
if (error && error.message === UNABLE_TO_CHANGE_STATUS) {
showError(locale.errorDialog.title, locale.action.sendToDataOriginals.noReplacementError);
}
},
guardians: [singleAction, inStatuses(CHANGE_STATUS_STATUSES), canChangeStatus],
};
+30
View File
@@ -0,0 +1,30 @@
import type { CheckUserBlockByOrganisationQuery, CheckUserBlockByOrganisationResponse } from 'interfaces';
import { createRequestFatalHandler } from 'utils';
import { to, singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import type { IOnboardingContext } from '../../action-executers';
/**
* [ОНБ_2021] Группа контролей №1, №2.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=42681829
*/
export const checkUserBlockByOrganisation: IActionConfig<IOnboardingContext, CheckUserBlockByOrganisationResponse> = {
action:
({ done, addSucceeded }, { service, showLoader, hideLoader }) =>
async (data: CheckUserBlockByOrganisationQuery) => {
showLoader();
const [res] = await to(service.checkUserBlockByOrganisation(data));
if (res) {
addSucceeded(res);
}
hideLoader();
done();
},
fatalHandler: () => createRequestFatalHandler,
guardians: [singleAction],
};
+32
View File
@@ -0,0 +1,32 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { to, singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { inStatuses } from '../guardians';
/** Статусы, при которых доступна функция закрытия задания в ТЕССА. */
const TESSA_TASK_CLOSABLE_STATUSES = [STATUS.EXPORT_TO_TESSA_ERROR, STATUS.PROCESSING_TESSA_COMMENTS];
/**
* Банк: Функция закрытия задания в ТЕССА.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=42679053
*/
export const closeTessaTask: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action:
({ done, fatal, addSucceeded }, { service, showLoader, hideLoader }) =>
async ([doc]: [OnboardingRequestDto]) => {
showLoader();
const [result, err] = await to(service.manualTessaFinishTask(doc.id));
hideLoader();
fatal(err);
addSucceeded(result!);
done();
},
guardians: [singleAction, inStatuses(TESSA_TASK_CLOSABLE_STATUSES)],
};
@@ -0,0 +1,30 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import type { ShowModalFn } from 'components';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { callStreamAction } from '@platform/services';
import { inStatuses, isVmCreateRequestEnabled } from '../guardians';
/**
* Вызов функции создания заявки на выезд менеджера.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=42665231
* */
export const createDepartureRequestFractal = (openModalFn: ShowModalFn): IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> => ({
action:
({ done }, { showLoader, hideLoader }) =>
async ([doc]: [OnboardingRequestDto]) => {
await callStreamAction('manager', 'showCreateDepartureRequestFractal', {
requestId: doc.id,
accountType: doc.accountTypeCode,
showModal: openModalFn,
showLoader,
hideLoader,
});
done();
},
guardians: [singleAction, isVmCreateRequestEnabled, inStatuses([STATUS.APPROVED, STATUS.WAITING_FOR_ESK_ACCOUNTS])],
});
@@ -0,0 +1,26 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { callStreamAction } from '@platform/services';
import { inStatuses, isVmCreateRequestEnabled } from '../guardians';
/**
* Вызов функции создания заявки на выезд менеджера.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=42665231
* */
export const createDepartureRequest: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action:
({ done }) =>
async ([doc]: [OnboardingRequestDto]) => {
await callStreamAction('manager', 'showCreateDepartureRequest', {
requestId: doc.id,
accountType: doc.accountTypeCode,
});
done();
},
guardians: [singleAction, isVmCreateRequestEnabled, inStatuses([STATUS.APPROVED, STATUS.WAITING_FOR_ESK_ACCOUNTS])],
};
+32
View File
@@ -0,0 +1,32 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { showWarningDialog } from 'components';
import { locale } from 'localization';
import { to, singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { isCreateTechReqEnabled } from './guardians';
/**
* Банк: Временная функция создания технической заявки.
* Будет удалена, когда будет готов ЖЦ.
*/
export const createTechReq: IActionConfig<IOnboardingAdminContext, void> = {
action:
({ done, fatal }, { service }) =>
async (data: { id: string }) => {
const { id } = data;
const [_, err] = await to(service.createTechReq(id));
fatal(err);
showWarningDialog({
// eslint-disable-next-line @eco/no-missing-localization
content: 'Техническая заявка создана',
// eslint-disable-next-line @eco/no-missing-localization
header: 'Внимание',
buttonText: locale.action.ok,
});
done();
},
guardians: [singleAction, isCreateTechReqEnabled],
};
@@ -0,0 +1,24 @@
import { onboardingAdminExecutor, type IOnboardingAdminContext } from 'action-executers/admin';
import { showServerErrorDialog } from 'components/modals/server-error-dialog';
import type { OnboardingRequestDto } from 'interfaces';
import { locale } from 'localization';
import { DOCUMENT_TYPE_CODE } from 'stream-constants';
import type { IActionConfig } from '@platform/core';
import type { IPrintResponseDoc } from '@platform/services';
import { printReport } from '../print-report';
import { canDownloadCommissionPaymentDocument } from './guardians';
/**
* Банк: Функция сформировать документ об оплате комиссии.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=111248654
*/
export const downloadCommissionPayment: IActionConfig<IOnboardingAdminContext, IPrintResponseDoc> = {
action:
() =>
async ([doc]: [OnboardingRequestDto]) => {
await onboardingAdminExecutor.execute(printReport, [doc], DOCUMENT_TYPE_CODE.ONB_CM_1_1_23);
},
guardians: [canDownloadCommissionPaymentDocument],
fatalHandler: () => showServerErrorDialog({ title: locale.errorDialog.downloadError }),
};
+66
View File
@@ -0,0 +1,66 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { showServerErrorDialog } from 'components/modals/server-error-dialog';
import type { FormedDocumentDto, OnboardingRequestDto, OriginalDocumentDto } from 'interfaces';
import { locale } from 'localization';
import type { ExtendedDocumentExportFormat } from 'stream-constants';
import { DOCUMENT_EXPORT_FORMAT_EXTENSION, DOWNLOAD_DOCUMENT_STATUSES } from 'stream-constants';
import { getOnbConfig } from 'utils';
import { to } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import type { IDownloadedAttachment } from '@platform/services';
import { attachmentService, showFile } from '@platform/services';
import { documentsGroupAction, inStatuses } from '../guardians';
/**
* Банк: Функция экспорта ПФ и сканов.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=42679044
*/
export const download: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action:
({ done, fatal }, { showLoader, hideLoader, service, showDownloadDocumentsDialog }) =>
async ([doc, originalDocuments, formedDocuments]: [OnboardingRequestDto, OriginalDocumentDto[], FormedDocumentDto[]]) => {
let format: ExtendedDocumentExportFormat = DOCUMENT_EXPORT_FORMAT_EXTENSION.DOCX_TO_PDF;
const { downloadDocsFromFs } = getOnbConfig();
const originDocsIds = originalDocuments.map(x => x.id);
const formedDocsIds = formedDocuments.map(x => x.id);
if (formedDocsIds.length > 0) {
const [formValues, cancel] = await to(showDownloadDocumentsDialog());
if (cancel) {
done();
}
format = formValues!.format;
}
showLoader();
let result: IDownloadedAttachment | null;
let err: unknown;
if (downloadDocsFromFs) {
const [attachmentInfo, attachmentErr] = await to(service.exportDocsByIds(formedDocsIds, originDocsIds, doc.id, format));
fatal(attachmentErr);
const { id, accessToken } = attachmentInfo!;
[result, err] = await to(attachmentService.downloadOneTimeData(id, accessToken));
} else {
[result, err] = await to(service.download(formedDocsIds, originDocsIds, doc.id, format));
}
hideLoader();
fatal(err);
showFile(result!.data, result!.fileName, result!.type);
done();
},
guardians: [documentsGroupAction, inStatuses(DOWNLOAD_DOCUMENT_STATUSES)],
fatalHandler: () => showServerErrorDialog({ title: locale.errorDialog.downloadError }),
};
+124
View File
@@ -0,0 +1,124 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { showServerErrorDialog, showConfirmDialog } from 'components/modals';
import type { OnboardingRequestDto } from 'interfaces';
import type { OnboardingRequestBankScrollerDto } from 'interfaces/admin';
import { locale } from 'localization';
import { REQUEST_STEP, STATUS, streamUrl, UNABLE_TO_CHANGE_STATUS } from 'stream-constants';
import { getOnbConfig } from 'utils';
import { to, singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { UserType } from '@platform/services';
import { getUserItem } from '@platform/services/admin';
import { canEditRequest } from './guardians';
import { setRequestEditing } from './set-request-editing';
/**
* Банк: Функция редактирования заявки.
* Вызывается на скроллере, управлении заявкой и ЭФ "документы сформированы".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=42679039
*/
export const edit: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto | undefined> = {
action:
({ done, fatal, addSucceeded, execute }, { service, router, showLoader, hideLoader }) =>
async ([doc]: [OnboardingRequestBankScrollerDto | OnboardingRequestDto]) => {
const { status, id, isRequestEditing = false, responsibleBankUserFio, responsibleBankUserId = '', userId, userType } = doc;
const user = getUserItem('user');
const routerState = { prevPathname: window.location.pathname };
const isRequestOwner = userId === user.userId && (!responsibleBankUserId || responsibleBankUserId === user.userId);
const isRequestResponsibleUser = userId !== user.userId && responsibleBankUserId === user.userId;
// Для заявок созданных на стороне банка в статусах [STATUS.DRAFT, STATUS.COMPLETED] не надо изменять статус, достаточно проставить флаг isRequestEditing.
const bankRequest = userType === UserType.BANK;
const notUpdatableStatusesInBankRequest = [STATUS.DRAFT, STATUS.COMPLETED];
const statusUpdateIsNotNeeded = bankRequest && notUpdatableStatusesInBankRequest.includes(status);
if (statusUpdateIsNotNeeded && (isRequestOwner || isRequestResponsibleUser)) {
if (!isRequestEditing) {
const { succeeded, error } = await execute(setRequestEditing, { requestId: id, isEditing: true });
if (error) {
fatal(error);
}
if (succeeded.length > 0) {
addSucceeded(succeeded[0]);
}
}
router.push(streamUrl.getRequestUrl(id), routerState);
done();
}
const callEdit = async () => {
showLoader();
const [result, error] = await to(service.edit(id));
hideLoader();
fatal(error);
if (result) {
addSucceeded(result);
}
router.push(streamUrl.getRequestUrl(id), routerState);
};
const switchToDraft = async () => {
showLoader();
// Экшен может вызываться со скроллера, поэтом получим полную информация о заявке
const [fullRequestInfo, fullRequestError] = await to(service.get(id));
fatal(fullRequestError);
const [result, error] = await to(
service.update(id, {
...fullRequestInfo!,
status: STATUS.DRAFT,
step: getOnbConfig()['acc-open-first-115on'] ? REQUEST_STEP.SERVICES_FORMS : REQUEST_STEP.BANKSIGNER,
})
);
hideLoader();
fatal(error);
if (result?.data.status === status) {
throw new Error(UNABLE_TO_CHANGE_STATUS);
}
if (result?.data) {
addSucceeded(result.data);
}
router.push(streamUrl.getRequestUrl(id), routerState);
};
if (status === STATUS.FORMED) {
await switchToDraft();
}
if (isRequestEditing && responsibleBankUserId !== user.userId) {
showConfirmDialog({
header: locale.manageRequest.requestHasAlreadyEditing.header,
content: locale.manageRequest.requestHasAlreadyEditing.message({ responsibleBankUserFio }),
confimType: 'PRIMARY',
cancelButtonText: locale.action.cancel,
onConfirm: async () => {
// Бек переназначит ответственного за заявку
await callEdit();
},
});
} else {
await callEdit();
}
done();
},
fatalHandler: () => showServerErrorDialog({ title: locale.errorDialog.title }),
guardians: [singleAction, canEditRequest],
};
+79
View File
@@ -0,0 +1,79 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { showWarningDialog } from 'components/modals';
import type { OnboardingRequestDto } from 'interfaces';
import type { OnboardingRequestBankScrollerDto } from 'interfaces/admin';
import { locale } from 'localization';
import { DOWNLOAD_DOCUMENT_STATUSES, STATUS } from 'stream-constants';
import { getOnbConfig } from 'utils';
import { groupAction, to } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import type { IDownloadedAttachment } from '@platform/services';
import { attachmentService, showFile } from '@platform/services';
import { inStatuses } from '../guardians';
import { canExportDocuments } from './guardians';
/**
* Функция экспорта ПФ и сканов.
* Вызывается на скроллере и управлении заявкой.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=42679044
*/
export const exportDocuments: IActionConfig<IOnboardingAdminContext, OnboardingRequestBankScrollerDto | OnboardingRequestDto> = {
action:
({ fatal, addSucceeded, done }, { service, showLoader, hideLoader, showDownloadDocumentsDialog }) =>
async ([doc]: [OnboardingRequestBankScrollerDto | OnboardingRequestDto]) => {
if (doc.status === STATUS.REFUSED) {
showLoader();
const [prevStatus, statusErr] = await to(service.getPreviousStatus(doc.id));
hideLoader();
fatal(statusErr);
if ([STATUS.DRAFT, STATUS.DOCS_LOAD].includes(prevStatus as STATUS)) {
showWarningDialog({ content: locale.exportDocumentsDialog.exportDisallowed });
done();
}
}
const [dialogResult, dialogCancel] = await to(showDownloadDocumentsDialog());
if (dialogCancel) {
done();
return;
}
showLoader();
const { downloadDocsFromFs } = getOnbConfig();
let value: IDownloadedAttachment | null;
let err: unknown;
if (downloadDocsFromFs) {
const [attachmentInfo, attachmentErr] = await to(service.exportAllDocs(doc.id, dialogResult!.format));
fatal(attachmentErr);
const { id, accessToken } = attachmentInfo!;
[value, err] = await to(attachmentService.downloadOneTimeData(id, accessToken));
} else {
[value, err] = await to(service.exportAllToZip(doc.id, dialogResult!.format));
}
hideLoader();
fatal(err);
if (value) {
showFile(value.data, value.fileName, value.type);
addSucceeded(doc);
}
done();
},
guardians: [groupAction, inStatuses(DOWNLOAD_DOCUMENT_STATUSES), canExportDocuments],
};
+27
View File
@@ -0,0 +1,27 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { showServerErrorDialog } from 'components/modals/server-error-dialog';
import type { OnboardingRequestDto } from 'interfaces';
import { EXPORT_TYPE } from 'interfaces';
import { locale } from 'localization';
import { FILE_EXTENSIONS } from 'stream-constants';
import { groupAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { exportDoc } from '@platform/services';
const DEFAULT_EXPORT_SETTINGS = {
extension: FILE_EXTENSIONS.XLS,
splitReport: true,
selectedValue: EXPORT_TYPE.DOCUMENTS_LIST,
};
/**
* Функция экспорта.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=42680365
*/
export const exportList: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
...exportDoc.withoutDialog(DEFAULT_EXPORT_SETTINGS),
failedHandler: () => showServerErrorDialog({ title: locale.errorDialog.exportError }),
fatalHandler: () => showServerErrorDialog({ title: locale.errorDialog.exportError }),
guardians: [groupAction],
};
@@ -0,0 +1,94 @@
import { type IOnboardingAdminContext } from 'action-executers/admin';
import { showAccessRightsErrorDialog, showConfirmDialog } from 'components/modals';
import type { IOnboardingAppConfigAdmin } from 'interfaces';
import type { OnboardingRequestBankScrollerDto } from 'interfaces/admin';
import { locale } from 'localization';
import { STATUS } from 'stream-constants';
import { getOnbConfig } from 'utils';
import { to, groupAction } from '@platform/core';
import type { IActionConfig } from '@platform/services';
import { atLeastOneRequestWithAccessGrantedError } from './guardians';
/**
* Функция массовой повторной выдачи прав доступа и запроса отправки инвайтов для потенциальных УЛ с ошибками.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=136385422
*/
export const groupRepeatAccessRightsGrant: IActionConfig<IOnboardingAdminContext, OnboardingRequestBankScrollerDto> = {
action:
({ done, addSucceeded, addFailed, fatal }, { service, showLoader, hideLoader }) =>
async (docs: OnboardingRequestBankScrollerDto[]) => {
const { showAccessRightsAndInviteSuccessInfo, revokeOrgDuplicateInvitesEnbaled } = getOnbConfig<IOnboardingAppConfigAdmin>();
const repeat = async (ids: string[]) => {
showLoader();
const [result, err] = await to(service.repeatAccessRightsGrantBulk(ids));
hideLoader();
fatal(err);
const { errorRequestsIds } = result!.data;
if (errorRequestsIds.length > 0) {
const failed = docs.filter(doc => errorRequestsIds.includes(doc.id));
addFailed(...failed);
} else {
addSucceeded(...docs);
}
};
const docsWithErrors = docs.filter(
doc =>
doc.hasAccessGrantedInviteSentError &&
(!revokeOrgDuplicateInvitesEnbaled || [STATUS.APPROVED, STATUS.WAITING_FOR_ESK_ACCOUNTS].includes(doc.status))
);
let inProgress = false;
if (showAccessRightsAndInviteSuccessInfo && docsWithErrors.length !== docs.length) {
const ids = docsWithErrors.map(doc => doc.id);
await new Promise<void>(resolve =>
showConfirmDialog({
header: locale.action.groupRepeatAccessRightsGrant.dialogHeader({ count: docsWithErrors.length, total: docs.length }),
content: locale.action.groupRepeatAccessRightsGrant.dialogContent,
confimType: 'PRIMARY',
confirmButtonText: locale.action.continue,
cancelButtonText: locale.action.cancel,
onConfirm: async () => {
inProgress = true;
await repeat(ids);
inProgress = false;
resolve();
},
onClose: () => {
if (inProgress) {
return;
}
resolve();
},
})
);
done();
} else {
const ids = docs.map(doc => doc.id);
await repeat(ids);
done();
}
},
succeededHandler: ({ showSuccess }) =>
showSuccess(locale.action.repeatAccessRightsGrant.successHeader, locale.action.successfullyCompleted, {
okButtonText: locale.action.good,
}),
failedHandler: (_, docs) => {
showAccessRightsErrorDialog({ header: locale.accessRightsErrorDialog.header.grant, requests: docs });
},
guardians: [groupAction, atLeastOneRequestWithAccessGrantedError],
};
@@ -0,0 +1,92 @@
import { type IOnboardingAdminContext } from 'action-executers/admin';
import { showAccessRightsErrorDialog, showConfirmDialog } from 'components/modals';
import type { IOnboardingAppConfigAdmin } from 'interfaces';
import type { OnboardingRequestBankScrollerDto } from 'interfaces/admin';
import { locale } from 'localization';
import { STATUS } from 'stream-constants';
import { getOnbConfig } from 'utils';
import { to, groupAction } from '@platform/core';
import type { IActionConfig } from '@platform/services';
import { atLeastOneRequestWithAccessRevokeError } from './guardians';
/**
* Функция массового повторного отзыва прав доступа и запроса аннулирования инвайтов для потенциальных УЛ с ошибками.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=136385410
*/
export const groupRepeatAccessRightsRevoke: IActionConfig<IOnboardingAdminContext, OnboardingRequestBankScrollerDto> = {
action:
({ done, addSucceeded, addFailed, fatal }, { service, showLoader, hideLoader }) =>
async (docs: OnboardingRequestBankScrollerDto[]) => {
const { showAccessRightsAndInviteSuccessInfo, revokeOrgDuplicateInvitesEnbaled } = getOnbConfig<IOnboardingAppConfigAdmin>();
const repeat = async (ids: string[]) => {
showLoader();
const [result, err] = await to(service.repeatAccessRightsRevokeBulk(ids));
hideLoader();
fatal(err);
const { errorRequestsIds } = result!.data;
if (errorRequestsIds.length > 0) {
const failed = docs.filter(doc => errorRequestsIds.includes(doc.id));
addFailed(...failed);
} else {
addSucceeded(...docs);
}
};
const docsWithErrors = docs.filter(
doc => doc.hasAccessRevokeError && (!revokeOrgDuplicateInvitesEnbaled || [STATUS.REFUSED, STATUS.REJECTED].includes(doc.status))
);
let inProgress = false;
if (showAccessRightsAndInviteSuccessInfo && docsWithErrors.length !== docs.length) {
const ids = docsWithErrors.map(doc => doc.id);
await new Promise<void>(resolve =>
showConfirmDialog({
header: locale.action.groupRepeatAccessRightsRevoke.dialogHeader({ count: docsWithErrors.length, total: docs.length }),
content: locale.action.groupRepeatAccessRightsRevoke.dialogContent,
confimType: 'PRIMARY',
confirmButtonText: locale.action.continue,
cancelButtonText: locale.action.cancel,
onConfirm: async () => {
inProgress = true;
await repeat(ids);
inProgress = false;
resolve();
},
onClose: () => {
if (inProgress) {
return;
}
resolve();
},
})
);
done();
} else {
const ids = docs.map(doc => doc.id);
await repeat(ids);
done();
}
},
succeededHandler: ({ showSuccess }) =>
showSuccess(locale.action.repeatAccessRightsRevoke.successHeader, locale.action.successfullyCompleted, {
okButtonText: locale.action.good,
}),
failedHandler: (_, docs) => {
showAccessRightsErrorDialog({ header: locale.accessRightsErrorDialog.header.revoke, requests: docs });
},
guardians: [groupAction, atLeastOneRequestWithAccessRevokeError],
};
+441
View File
@@ -0,0 +1,441 @@
import { ACCESS_RIGHT_GRANTING_STATUS } from 'interfaces';
import type { IOnboardingAppConfigAdmin, OnboardingRequestDto } from 'interfaces';
import type { AdminActionAdditionalParams, OnboardingRequestBankScrollerDto } from 'interfaces/admin';
import { APPROVED_STATUSES, STATUS, TESSA_STATUS } from 'stream-constants';
import { UAA_AUTHORITIES } from 'stream-constants/admin';
import { getOnbConfig } from 'utils/configs';
import { inStatuses as oldInStatuses } from '@platform/core';
import { getAuthItem, UserType } from '@platform/services';
import { getUserItem } from '@platform/services/admin';
/**
* Guardian для проверки, что документ возможно редактировать на банке.
*
* @throws Guardian не пройден.
*/
export const canEditRequest = (
[doc]: [OnboardingRequestBankScrollerDto | OnboardingRequestDto],
params: AdminActionAdditionalParams
): void => {
const { userId, status, userType, responsibleBankUserId } = doc;
const user = getUserItem('user');
const isRequestOwner =
userType === UserType.BANK && userId === user.userId && (!responsibleBankUserId || responsibleBankUserId === user.userId);
const isRequestResponsibleUser = userType === UserType.BANK && userId !== user.userId && responsibleBankUserId === user.userId;
// На скроллере поле "isAfterRework" есть, в управлении заявкой прокидывается отдельно
const isAfterRework = !!('isAfterRework' in doc ? doc.isAfterRework : params.isAfterRework) && userType === UserType.CLIENT;
switch (status) {
case STATUS.DRAFT:
case STATUS.COMPLETED:
if (isRequestOwner || isRequestResponsibleUser || isAfterRework) {
return;
}
break;
case STATUS.DOCS_LOAD:
if (isAfterRework) {
return;
}
break;
case STATUS.FORMED:
if (isRequestOwner || isRequestResponsibleUser) {
return;
}
break;
case STATUS.DATA_ERROR:
case STATUS.EDITING_DRAFT:
case STATUS.EDITING_COMPLETED:
case STATUS.EDITING_DOCS_LOAD:
case STATUS.REPLACING_DOCS:
case STATUS.EDITING_REPLACING_DOCS:
return;
default:
throw new Error('GUARD_HAS_NOT_PASSED');
}
throw new Error('GUARD_HAS_NOT_PASSED');
};
/**
* Guardian для проверки, что пользователь может взять заявку в работу.
*
* @throws Пользователь может брать в работу только не свои заявки, созданные в банке.
*/
export const canTakeRequest = ([doc]: [OnboardingRequestDto]): void => {
const { userType, responsibleBankUserId, userId } = doc;
const user = getUserItem('user');
const isNotRequestResponsibleUser =
(userType === UserType.BANK && userId !== user.userId && !responsibleBankUserId) ||
(userType === UserType.BANK && !!responsibleBankUserId && responsibleBankUserId !== user.userId);
if (!isNotRequestResponsibleUser) {
throw new Error('AVAILABLE_ONLY_FOR_NOT_RESPONSIBLE_USERS_ON_BANK');
}
};
/**
* Guardian для проверки что пользователь может скачать документы заявки.
*
* @throws Пользователь не может скачивать документы из статуса "Отменён", если предшествующий статус заявки = "Черновик" или "Загрузка документов".
*/
export const canExportDocuments = ([doc]: [OnboardingRequestDto], { previousStatus }: AdminActionAdditionalParams = {}) => {
if (doc.status === STATUS.REFUSED && [STATUS.DRAFT, STATUS.DOCS_LOAD].includes(previousStatus as STATUS)) {
throw new Error('USER_CANT_EXPORT_FROM_REFUSED_AFTER_DRAFT');
}
};
/**
* Guardian для проверки, что пользователь может открыть заявку.
*
* @throws Пользователь может открыть только заявки, созданные в банке.
*/
export const canOpenBankRequest = ([doc]: [OnboardingRequestDto]): void => {
const { userType } = doc;
if (userType !== UserType.BANK) {
throw new Error('AVAILABLE_ONLY_FOR_BANK_REQUESTS');
}
};
/**
* Guardian для проверки, что пользователь может открыть техническую заявку.
*
* @throws Пользователь может перейти к технической заявке только в случае если у заявки, созданной в банке, есть соответствующая техзаявка.
*/
export const canOpenTechRequest = ([doc]: [OnboardingRequestDto]): void => {
const { userType, lastFoRequest } = doc;
if (userType !== UserType.BANK || !lastFoRequest) {
throw new Error('AVAILABLE_ONLY_IF_BANK_REQUEST_HAS_TECH_REQUESTS');
}
};
/**
* Guardian для проверки, что настройка по открытию технических заявок включена.
*
* @throws Настройка отключена.
*/
export const isTechRequestEnabled = () => {
if (!getOnbConfig<IOnboardingAppConfigAdmin>().open_tech_request_enabled) {
throw new Error('OPEN_TECH_REQUEST_DISABLED');
}
};
/**
* Guardian для проверки, что переданная настройка включена.
*
* @throws Настройка отключена.
*/
export const isCreateTechReqEnabled = () => {
if (!getOnbConfig<IOnboardingAppConfigAdmin>().onbCreateTechReqEnabled) {
throw new Error('CREATE_TECH_REQUEST_DISABLED');
}
};
/**
* Guardian для проверки что пользователь может скачать квитанцию об оплате QRC комиссии.
*
* @throws Настройка отключена.
*/
export const canDownloadCommissionPaymentDocument = (
[_]: [OnboardingRequestDto],
{ hasExecutedCommission }: AdminActionAdditionalParams = {}
) => {
if (!hasExecutedCommission) {
throw new Error('HAS_NO_QRC_TICKET');
}
};
/**
* Guardian для проверки что пользователь может оплатить заявку через QRC.
*
* @throws Заявку нельзя оплатить через QRC.
*/
export const canCreatePayCommission = (
[doc]: [OnboardingRequestDto],
{ hasExecutedCommission, isQrcCommissionFree, hasFeeFreeCommission }: AdminActionAdditionalParams = {}
) => {
const { userType, status } = doc;
const { onboarding } = getOnbConfig<IOnboardingAppConfigAdmin>();
const hasApprovedStatus = APPROVED_STATUSES.includes(status);
const isBank = status === STATUS.FORMED && userType === UserType.BANK;
if (isQrcCommissionFree || hasFeeFreeCommission) {
throw new Error('QRC_IS_NOT_APPLICABLE_FOR_REQUEST');
}
if (
hasExecutedCommission ||
(userType === UserType.BANK && !onboarding.enableCommissionPayForBankRequest) ||
!(hasApprovedStatus || isBank)
) {
throw new Error('QRC_IS_NOT_APPLICABLE_FOR_REQUEST');
}
};
/**
* Guardian для проверки что у оплаченой коммиссии возникла ошибка при загрузки в ТЕССА.
*
* @throws Для заявки не доступна повторная отправка в ТЕССА.
*/
export const canResendToTessa = ([_]: [OnboardingRequestDto], { tessaStatus }: AdminActionAdditionalParams = {}) => {
if (tessaStatus !== TESSA_STATUS.ERROR) {
throw new Error('RESENDING_TO_TESSA_NOT_AVAILABLE');
}
};
/**
* Guardian для проверки наличия признака подключения ГПБ БО.
*
* @throws ГПБ БО не подключено.
*/
export const isGpbBOConnected = ([doc]: [OnboardingRequestDto]) => {
if (!doc.gpbBoConnectionInfo?.connected) {
throw new Error('GBP_BO_NOT_CONNECTED');
}
};
/**
* Guardian для проверки доступности изменения статуса заявки.
*
* @throws Недоступно изменение из статуса "Отменён", если предшествующий статус заявки = "Ожидание информации об открытии счетов".
*/
export const canChangeStatus = ([doc]: [OnboardingRequestDto], { previousStatus }: AdminActionAdditionalParams) => {
if (doc.status === STATUS.REFUSED && previousStatus === STATUS.WAITING_FOR_ESK_ACCOUNTS) {
throw new Error('CANT_CHANGE_BACK_TO_WAITING_FOR_ESK_ACCOUNTS');
}
};
/**
* Guardian для проверки функции изменения стауста заявки при роли BANK_ADMIN на наличие статусов при которых доступна функция.
*
* @param statuses Статусы.
* @param statusesBankUserType Статусы при типе пользователя BANK.
*/
export const inStatusesForChangeStatusExtended =
(statuses: STATUS[], statusesBankUserType: STATUS[]) =>
([doc]: [OnboardingRequestDto]) => {
if (doc.userType === UserType.BANK) {
oldInStatuses(statusesBankUserType, s => s.status)([doc]);
} else if (doc.userType === UserType.CLIENT) {
oldInStatuses(statuses, s => s.status)([doc]);
} else {
throw new Error('IS_AVAILABLE_ONLY_FOR_CLIENT_AND_BANK_REQUESTS');
}
};
/**
* Guardian для проверки наличия в заявке физических лиц имеющих статус выдачи прав доступа и отправки инвайта "Ошибка выдачи прав и запроса на отправку инвайта".
*
* @throws Отсутсвуют физические лица со статусом "Ошибка выдачи прав и запроса на отправку инвайта".
*/
export const hasAccessRightsGrantingError = ([doc]: [OnboardingRequestBankScrollerDto | OnboardingRequestDto]) => {
const errorMessage = 'WRONG_ACCESS_RIGHT_GRANTING_STATUS';
const { revokeOrgDuplicateInvitesEnbaled } = getOnbConfig<IOnboardingAppConfigAdmin>();
const isApprovedOrWaitingForEskAccounts = [STATUS.APPROVED, STATUS.WAITING_FOR_ESK_ACCOUNTS].includes(doc.status);
if (revokeOrgDuplicateInvitesEnbaled && !isApprovedOrWaitingForEskAccounts) {
throw new Error(errorMessage);
}
if ('hasAccessGrantedInviteSentError' in doc) {
if (!doc.hasAccessGrantedInviteSentError) {
throw new Error(errorMessage);
}
} else {
const hasError = doc.persons.some(
person => person.accessRightGrantingStatus === ACCESS_RIGHT_GRANTING_STATUS.ERROR_ACCESS_GRANTED_INVITE_SENT
);
if (!hasError) {
throw new Error(errorMessage);
}
}
};
/**
* Guardian для проверки наличия в заявке физических лиц имеющих статус выдачи прав доступа и отправки инвайта "Ошибка отзыва прав и запроса на аннулирование инвайта".
*
* @throws Отсутсвуют физические лица со статусом "Ошибка отзыва прав и запроса на аннулирование инвайта".
*/
export const hasAccessRightsRevokingError = ([doc]: [OnboardingRequestBankScrollerDto | OnboardingRequestDto]) => {
const errorMessage = 'WRONG_ACCESS_RIGHT_REVOKING_STATUS';
const { revokeOrgDuplicateInvitesEnbaled } = getOnbConfig<IOnboardingAppConfigAdmin>();
const isRefusedOrRejected = [STATUS.REFUSED, STATUS.REJECTED].includes(doc.status);
if (revokeOrgDuplicateInvitesEnbaled && !isRefusedOrRejected) {
throw new Error(errorMessage);
}
if ('hasAccessRevokeError' in doc) {
if (!doc.hasAccessRevokeError) {
throw new Error(errorMessage);
}
} else {
const hasError = doc.persons.some(
person => person.accessRightGrantingStatus === ACCESS_RIGHT_GRANTING_STATUS.ERROR_ACCESS_AND_INVITE_REVOKED
);
if (!hasError) {
throw new Error(errorMessage);
}
}
};
/**
* Guardian для проверки, что профиль создателя заявки доступен.
*
* @throws Настройка отключена.
*/
export const isCreatorProfileAccessible = ([doc]: [OnboardingRequestBankScrollerDto | OnboardingRequestDto]) => {
const { userType } = doc;
const hasAuthority = getAuthItem('hasAuthority');
if (userType === UserType.CLIENT ? !hasAuthority(UAA_AUTHORITIES.CLIENT_USER_VIEW) : !hasAuthority(UAA_AUTHORITIES.BANKUSER_VIEW)) {
throw new Error('CREATOR_PROFILE_NOT_ACCESSSIBLE');
}
};
/**
* Guardian для проверки доступности функции повторной отправки приглашений для физ лиц в заявке.
*
* @throws Нет ни одного физ лица со статусом отправки инвайта "Ошибка" или нет ни одного лица с приглашением.
*/
export const hasInvitesWithError = ([doc]: [OnboardingRequestDto]) => {
if (!doc.persons.some(person => person.accessRightGrantingStatus === ACCESS_RIGHT_GRANTING_STATUS.ERROR_INVITE_SENT)) {
throw new Error('HAS_INVITES_WITH_ERROR');
}
};
/**
* Guardian для проверки наличия настройки ОНБ по колбэку.
*
* @throws Нет значения в конфиге или значение в конфиге не имеет ожидаемого значения.
*/
export const checkOnbConfig = (configChecker: (onbConfig: IOnboardingAppConfigAdmin) => boolean) => () => {
const config = getOnbConfig<IOnboardingAppConfigAdmin>();
if (!configChecker(config)) {
throw new Error('CONFIG_NOT_VALID');
}
};
/**
* Guardian для проверки наличия хотя бы одной заявки среди выбранных, с признаком того, что в заявке есть физические лица имеющие статус выдачи прав доступа и отправки инвайта "Ошибка выдачи прав и запроса на отправку инвайта".
*
* @throws Нет ни одной заявки с признаком.
*/
export const atLeastOneRequestWithAccessGrantedError = (docs: OnboardingRequestBankScrollerDto[]) => {
const { revokeOrgDuplicateInvitesEnbaled } = getOnbConfig<IOnboardingAppConfigAdmin>();
if (
!docs.some(
doc =>
doc.hasAccessGrantedInviteSentError &&
(!revokeOrgDuplicateInvitesEnbaled || [STATUS.APPROVED, STATUS.WAITING_FOR_ESK_ACCOUNTS].includes(doc.status))
)
) {
throw new Error('THERE_ARE_NO_REQUESTS_WITH_ERROR');
}
};
/**
* Guardian для проверки наличия хотя бы одной заявки среди выбранных, с признаком того, что в заявке есть физические лица имеющие статус выдачи прав доступа и отправки инвайта "Ошибка отзыва прав и запроса на аннулирование инвайта".
*
* @throws Нет ни одной заявки с признаком.
*/
export const atLeastOneRequestWithAccessRevokeError = (docs: OnboardingRequestBankScrollerDto[]) => {
const { revokeOrgDuplicateInvitesEnbaled } = getOnbConfig<IOnboardingAppConfigAdmin>();
if (
!docs.some(
doc => doc.hasAccessRevokeError && (!revokeOrgDuplicateInvitesEnbaled || [STATUS.REFUSED, STATUS.REJECTED].includes(doc.status))
)
) {
throw new Error('THERE_ARE_NO_REQUESTS_WITH_ERROR');
}
};
/**
* Guardian для проверки, что текущий пользователь не является ответственным за заявку.
*
* @throws Текущий пользователь является ответственным за заявку.
*/
export const currentUserIsNotResponsible = ([doc]: [OnboardingRequestBankScrollerDto | OnboardingRequestDto]) => {
const user = getUserItem('user');
if (user.userId === doc.responsibleBankUserId) {
throw new Error('CURRENT_USER_IS_RESPONSIBLE_USER');
}
};
/**
* Guardian для проверки доступности назначения ответственного за созвон.
*
* @throws Guardian не пройден.
*/
export const canAssignResponsibleForCall = (
[doc]: [OnboardingRequestBankScrollerDto | OnboardingRequestDto],
params: AdminActionAdditionalParams
): void => {
const { status, userType } = doc;
// На скроллере поле "isAfterRework" есть, в управлении заявкой прокидывается отдельно
const isAfterRework = !!('isAfterRework' in doc ? doc.isAfterRework : params.isAfterRework) && userType === UserType.CLIENT;
switch (status) {
case STATUS.DRAFT:
case STATUS.DOCS_LOAD:
case STATUS.DATA_ERROR:
case STATUS.REPLACING_DOCS:
if (isAfterRework) {
return;
}
break;
case STATUS.WAITING_FOR_ESK_ACCOUNTS:
return;
default:
throw new Error('GUARD_HAS_NOT_PASSED');
}
throw new Error('GUARD_HAS_NOT_PASSED');
};
/**
* Guardian для проверки, что доступно добавление записи в историю звонков.
*
* @throws Не доступно добавление записи в историю звонков.
*/
export const addCallToHistoryAllowed = (
[doc]: [OnboardingRequestBankScrollerDto | OnboardingRequestDto],
params: AdminActionAdditionalParams
) => {
const { responsibleBankUserId } = doc;
const { assignResponsibleEnabled } = getOnbConfig<IOnboardingAppConfigAdmin>();
const user = getUserItem('user');
if (assignResponsibleEnabled) {
if (user.userId === responsibleBankUserId) {
return;
}
try {
canAssignResponsibleForCall([doc], params);
throw new Error('GUARD_HAS_NOT_PASSED');
} finally {
// do nothing
}
}
};
+37
View File
@@ -0,0 +1,37 @@
export * from './export';
export * from './print';
export * from './manage';
export * from './suv-message-history';
export * from './view';
export * from './short-view';
export * from './reform-doc-list';
export * from './repeat-unload';
export * from './close-tessa-task';
export * from './change-status';
export * from './add-departure-record';
export * from './create-departure-request';
export * from './edit';
export * from './open';
export * from './open-techreq';
export * from './take';
export * from './download';
export * from './need-to-replace';
export * from './add-document';
export * from './cancel-need-to-replacement';
export * from './export-documents';
export * from './repeat-unload-list';
export * from './set-request-editing';
export * from './pay-commission';
export * from './open-esign-requests';
export * from './repeat-access-rights-grant';
export * from './repeat-access-rights-revoke';
export * from './payment-receipt-upload';
export * from './send-tech-request';
export * from './open-client-user-profile';
export * from './open-bank-user-profile';
export * from './open-creator-profile';
export * from './group-repeat-access-rights-grant';
export * from './group-repeat-access-rights-revoke';
export * from './resend-invites';
export * from './create-departure-request-fractal';
export * from './assign-responsible';
+15
View File
@@ -0,0 +1,15 @@
import type { OnboardingRequestDto } from 'interfaces';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import type { IBaseContext } from '@platform/services';
import { open } from '@platform/services';
/**
* Функция управления заявкой.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=42679041
*/
export const manage: IActionConfig<IBaseContext, OnboardingRequestDto> = {
...open('/onboarding/manage'),
guardians: [singleAction],
};
+43
View File
@@ -0,0 +1,43 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import type { OnboardingRequestDto, OriginalDocumentDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { groupAction, to } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { inStatuses, requiredAttachmentReplaceValue } from '../guardians';
/**
* Функция "Необходимо заменить".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=42679048
*/
export const needToReplaceAction: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action:
({ done, fatal, addSucceeded }, { service, showConfirmNeedToReplaceDialog }) =>
async ([doc, originalDocuments]: [OnboardingRequestDto, OriginalDocumentDto[]]) => {
const names = originalDocuments.map(({ description }) => description);
const [_, cancel] = await to(showConfirmNeedToReplaceDialog(names));
if (cancel) {
done();
}
const data = originalDocuments.map(originalDocument => ({
...originalDocument,
requiredReplace: true,
}));
const [result, err] = await to(service.requireReplace(doc.id, doc.version, data));
fatal(err);
addSucceeded(result!);
done();
},
guardians: [
groupAction,
requiredAttachmentReplaceValue(false),
inStatuses([STATUS.EXPORT_TO_ESK_ERROR, STATUS.PROCESSING_TESSA_COMMENTS]),
],
};
@@ -0,0 +1,15 @@
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { open as openAction } from '@platform/services';
import type { IBaseContext, IBaseEntity } from '@platform/services';
import { ADMIN_STREAM_URL } from '@platform/services/admin';
/**
* [Профиль] Банк: Функция просмотра пользователя банка.
*
* @see {@link https://confluence.gboteam.ru/pages/viewpage.action?pageId=6357576}
*/
export const openBankUserProfile: IActionConfig<IBaseContext, IBaseEntity> = {
...openAction(({ id }) => `${ADMIN_STREAM_URL.BANK_USERS}/${id}`),
guardians: [singleAction],
};
@@ -0,0 +1,15 @@
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { open as openAction } from '@platform/services';
import type { IBaseContext, IBaseEntity } from '@platform/services';
import { ADMIN_STREAM_URL } from '@platform/services/admin';
/**
* [Профиль] Банк: Функция просмотра пользователя клиента.
*
* @see {@link https://confluence.gboteam.ru/pages/viewpage.action?pageId=6357827}
*/
export const openClientUserProfile: IActionConfig<IBaseContext, IBaseEntity> = {
...openAction(({ id }) => `${ADMIN_STREAM_URL.CLIENT_USERS}/${id}`),
guardians: [singleAction],
};
+50
View File
@@ -0,0 +1,50 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import type { OnboardingRequestDto } from 'interfaces';
import { singleAction, to } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { UserType } from '@platform/services';
import { uaaService } from '@platform/services/admin';
import { isCreatorProfileAccessible } from './guardians';
import { openBankUserProfile } from './open-bank-user-profile';
import { openClientUserProfile } from './open-client-user-profile';
/**
* [Профиль] Банк: Функция просмотра пользователя клиента.
* [Профиль] Банк: Функция просмотра пользователя банка.
*
* @see {@link https://confluence.gboteam.ru/pages/viewpage.action?pageId=6357827}
* @see {@link https://confluence.gboteam.ru/pages/viewpage.action?pageId=6357576}
*/
export const openCreatorProfile: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action:
({ execute, done, fatal }, { showLoader, hideLoader }) =>
async ([doc]: [OnboardingRequestDto]) => {
const { userType, userId } = doc;
showLoader();
if (userType === UserType.BANK) {
const [user, error] = await to(uaaService.bankUser.get(userId));
fatal(error);
if (user) {
void execute(openBankUserProfile, [{ id: user.uaaUser.id }]);
}
} else {
const [user, error] = await to(uaaService.clientUser.getByUaaUserId(userId));
fatal(error);
if (user) {
void execute(openClientUserProfile, [{ id: user.id }]);
}
}
hideLoader();
done();
},
fatalHandler: ({ hideLoader }) => hideLoader(),
guardians: [singleAction, isCreatorProfileAccessible],
};
+48
View File
@@ -0,0 +1,48 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import type { OnboardingRequestDto, PersonDto } from 'interfaces';
import type { AdminActionAdditionalParams } from 'interfaces/admin';
import { ROLE_OF_INDIVIDUALS, STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { COMMON_STREAM_URL } from '@platform/services';
import { inStatuses } from '../guardians';
import { isGpbBOConnected } from './guardians';
/** Удовлетворяющие условию роли физических лиц. */
const ROLES = [
ROLE_OF_INDIVIDUALS.ACCOUNT_SIGNER,
ROLE_OF_INDIVIDUALS.LEADER,
ROLE_OF_INDIVIDUALS.LEADER_MC,
ROLE_OF_INDIVIDUALS.INDIVIDUAL,
ROLE_OF_INDIVIDUALS.INDIVIDUAL_MC,
];
/**
* Банк: Функция Перейти к заявкам на ЭП.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=121083621
*/
export const openESignRequests: IActionConfig<IOnboardingAdminContext, void> = {
action:
({ done }, { router }) =>
async ([doc]: [OnboardingRequestDto], { personsExternalSystemRequisites }: AdminActionAdditionalParams) => {
const {
bankClient: { clientId },
persons,
} = doc;
const personsMap: Record<string, PersonDto> = persons.reduce((acc, person) => ({ ...acc, [person.id]: person }), {});
const eskIds = personsExternalSystemRequisites
?.filter(({ id, personExternalSystemsRequisites }) =>
Boolean(personExternalSystemsRequisites?.eskId && personsMap[id]?.roles.some(role => ROLES.includes(role)))
)
.map(({ personExternalSystemsRequisites }) => personExternalSystemsRequisites!.eskId);
router.push(`${COMMON_STREAM_URL.CERT_ENROLL}/union-request`, { filters: { clientId, eskIds } });
done();
return Promise.resolve();
},
guardians: [singleAction, isGpbBOConnected, inStatuses([STATUS.APPROVED, STATUS.WAITING_FOR_ESK_ACCOUNTS, STATUS.EXECUTED])],
};
+22
View File
@@ -0,0 +1,22 @@
import type { OnboardingRequestDto } from 'interfaces';
import type { OnboardingRequestBankScrollerDto } from 'interfaces/admin';
import { STREAM_ONBOARDING_FO_URL } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import type { IBaseContext } from '@platform/services';
import { open as openAction } from '@platform/services';
import { canOpenTechRequest, isTechRequestEnabled } from './guardians';
/**
* Банк: Функция открытия технической заявки.
* Вызывается на скроллере и управлении заявкой.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=93306619
*/
export const openTechReq: IActionConfig<IBaseContext, OnboardingRequestDto> = {
...openAction(
({ lastFoRequest }: OnboardingRequestBankScrollerDto | OnboardingRequestDto) =>
`${STREAM_ONBOARDING_FO_URL}/${lastFoRequest!.foRequestId}`
),
guardians: [isTechRequestEnabled, singleAction, canOpenTechRequest],
};
+22
View File
@@ -0,0 +1,22 @@
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import type { IBaseContext } from '@platform/services';
import { inStatuses } from '../guardians';
import { open as openAction } from '../open';
import { canOpenBankRequest } from './guardians';
/** Статусы, при которых доступна функция открытия заявки. */
const OPEN_ACTIONS = [STATUS.REJECTED, STATUS.EXECUTED, STATUS.TECH_REQ, STATUS.FORMED];
/**
* Банк: Функция открытия заявки.
* Вызывается на скроллере и управлении заявкой.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=93306619
*/
export const open: IActionConfig<IBaseContext, OnboardingRequestDto | undefined> = {
...openAction,
guardians: [singleAction, canOpenBankRequest, inStatuses(OPEN_ACTIONS)],
};
+15
View File
@@ -0,0 +1,15 @@
import type { OnboardingRequestDto } from 'interfaces';
import type { IActionConfig } from '@platform/core';
import type { IBaseContext } from '@platform/services';
import { openQrc } from '../open-qrc';
import { canCreatePayCommission } from './guardians';
/**
* Банк: Функция "Оплатить комиссию".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=111248648
*/
export const payCommission: IActionConfig<IBaseContext, OnboardingRequestDto> = {
...openQrc,
guardians: [canCreatePayCommission],
};
@@ -0,0 +1,43 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { showAlertDialog } from 'components/modals';
import type { OnboardingRequestDto, QrcCommissionPaymentDto } from 'interfaces';
import type { OnboardingRequestBankScrollerDto } from 'interfaces/admin';
import { locale } from 'localization';
import { defaultFatalHandler } from 'utils';
import { to } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { canResendToTessa } from './guardians';
/**
* Банк: Функция повторения создания и выгрузки ПФ об оплате в ТЕССА.
* Вызывается на управлении заявкой.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=121104195
*/
export const paymentReceiptUpload: IActionConfig<IOnboardingAdminContext, QrcCommissionPaymentDto> = {
action:
({ done, fatal, addSucceeded }, { service, showLoader, hideLoader }) =>
async ([doc]: [OnboardingRequestBankScrollerDto | OnboardingRequestDto]) => {
showLoader({ delay: 500 });
const [result, err] = await to(service.paymentReceiptUpload(doc.id));
hideLoader();
fatal(err);
if (result?.error) {
showAlertDialog({ header: locale.manageRequest.requestInfo.tessaStatus.error, content: result.error.message ?? '', type: 'ERROR' });
done();
}
if (result?.data.onboardingRequestId) {
addSucceeded(result.data);
}
done();
},
fatalHandler: defaultFatalHandler,
failedHandler: ({ showWarning }, docs) => showWarning(locale.action.repeatUnload.failed({ count: docs.length })),
guardians: [canResendToTessa],
};
+52
View File
@@ -0,0 +1,52 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import { showServerErrorDialog } from 'components/modals/server-error-dialog';
import type { OnboardingRequestBankScrollerDto } from 'interfaces/admin';
import { locale } from 'localization';
import { DOCUMENT_EXPORT_FORMAT_EXTENSION, PRINT_ALL_STATUSES } from 'stream-constants';
import { getOnbConfig, goToFilePreview } from 'utils';
import { groupAction, to } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { attachmentService, type IPrintResponseDoc } from '@platform/services';
/**
* Функция печати.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=42680365
*/
export const print: IActionConfig<IOnboardingAdminContext, IPrintResponseDoc> = {
action:
({ done, fatal }, { service, showLoader, hideLoader }) =>
async (docs: OnboardingRequestBankScrollerDto[]) => {
showLoader();
const { downloadDocsFromFs } = getOnbConfig();
const download = async () => {
if (!downloadDocsFromFs) {
return service.print({ requestIds: docs.map(x => x.id), format: DOCUMENT_EXPORT_FORMAT_EXTENSION.DOCX_TO_PDF });
}
const attachmentInfo = await service.exportListAsFile({
requestIds: docs.map(x => x.id),
format: DOCUMENT_EXPORT_FORMAT_EXTENSION.DOCX_TO_PDF,
});
const attachment = await attachmentService.downloadOneTimeData(attachmentInfo.id, attachmentInfo.accessToken);
return { content: attachment.data, fileName: attachment.fileName };
};
const [response, error] = await to(download());
hideLoader();
fatal(error);
await goToFilePreview(response!.content, response!.fileName);
done();
},
failedHandler: () => showServerErrorDialog({ title: locale.errorDialog.printError }),
fatalHandler: () => showServerErrorDialog({ title: locale.errorDialog.printError }),
guardians: [groupAction, inStatuses(PRINT_ALL_STATUSES)],
};
+36
View File
@@ -0,0 +1,36 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS, UNABLE_TO_CHANGE_STATUS } from 'stream-constants';
import { to, singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
/** Статусы, при которых доступна функция "Одобрить заяввку". */
export const APPROVE_STATUSES = [STATUS.WAITING_FOR_ESK_DECISION, STATUS.EXPORT_TO_ESK_ERROR, STATUS.PROCESSING_TESSA_COMMENTS];
/** Действие при котором вызывается функция "Одобрить заявку". */
const approveAction: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto>['action'] =
({ done, fatal, addSucceeded }, { service }) =>
async ([doc]: [OnboardingRequestDto], commentForBank?: string, commentForClient?: string) => {
const [result, err] = await to(service.approve(doc.id, commentForBank, commentForClient));
fatal(err || result?.error);
if (result!.data.status === doc.status) {
throw new Error(UNABLE_TO_CHANGE_STATUS);
}
addSucceeded(result!.data);
done();
};
/**
* Функция "Одобрить заявку" в процессинге.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=42679042
* */
export const approve: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: approveAction,
guardians: [singleAction, inStatuses(APPROVE_STATUSES)],
};
@@ -0,0 +1,28 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { changeStatusBankAdminAction } from './change-status-bank-admin-action';
/** Статусы, при которых доступна функция перевода заявки в статус "Одобрен". */
export const APPROVED_STATUSES = [
STATUS.EXPORT_TO_ESK_ERROR,
STATUS.WAITING_FOR_ESK_DECISION,
STATUS.PROCESSING_TESSA_COMMENTS,
STATUS.WAITING_RESTRICTION,
];
/** Статусы, доступные для перехода со статуса "Одобрен". */
export const APPROVED_AVAILABLE_STATUSES = [STATUS.WAITING_FOR_ESK_ACCOUNTS];
/**
* Функция перевода заявки в статус "Одобрен".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049
*/
export const changeToApprovedStatus: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.APPROVED),
guardians: [singleAction, inStatuses(APPROVED_STATUSES)],
};
@@ -0,0 +1,27 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import type { OnboardingRequestDto } from 'interfaces';
import type { STATUS } from 'stream-constants';
import { UNABLE_TO_CHANGE_STATUS } from 'stream-constants';
import { to } from '@platform/core';
import type { IActionConfig } from '@platform/core';
/**
* Действие "Изменить статус".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049
* */
export const changeStatusBankAdminAction: (status: STATUS) => IActionConfig<IOnboardingAdminContext, OnboardingRequestDto>['action'] =
status =>
({ done, fatal, addSucceeded }, { service }) =>
async ([doc]: [OnboardingRequestDto], commentForBank?: string, commentForClient?: string) => {
const [result, err] = await to(service.changeStatusBankAdmin(doc.id, status, commentForBank, commentForClient));
fatal(err);
if (result!.data.status === doc.status) {
throw new Error(UNABLE_TO_CHANGE_STATUS);
}
addSucceeded(result!.data);
done();
};
@@ -0,0 +1,39 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { changeStatusBankAdminAction } from './change-status-bank-admin-action';
/** Статусы, при которых доступна функция перевода заявки в статус "Заполнен". */
export const COMPLETED_STATUSES = [STATUS.DRAFT, STATUS.DATA_ERROR];
/** Статусы, доступные для перехода со статуса "Заполнен". */
export const COMPLETED_AVAILABLE_STATUSES = [STATUS.DOCS_LOAD, STATUS.FORMED, STATUS.EDITING_DOCS_LOAD];
/**
* Функция перевода заявки в статус "Заполнен".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049.
*/
export const changeToCompletedStatus: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.COMPLETED),
guardians: [singleAction, inStatuses(COMPLETED_STATUSES)],
};
/** Статусы, при которых доступна функция перевода заявки в статус "Заполнен" при типе пользователя BANK. */
export const COMPLETED_STATUSES_BANK_USER_TYPE = [STATUS.DRAFT];
/** Статусы, доступные для перехода со статуса "Заполнен" при типе пользователя BANK. */
export const COMPLETED_AVAILABLE_STATUSES_BANK_USER_TYPE = [STATUS.FORMED];
/**
* Функция перевода заявки в статус "Заполнен" при типе пользователя заявки BANK.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049.
*/
export const changeToCompletedStatusBankUserType: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.COMPLETED),
guardians: [singleAction, inStatuses(COMPLETED_STATUSES_BANK_USER_TYPE)],
};
@@ -0,0 +1,33 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { changeStatusBankAdminAction } from './change-status-bank-admin-action';
/** Статусы, при которых доступна функция перевода заявки в статус "Требуется доработка данных". */
const DATA_ERROR_STATUSES = [
STATUS.DOCS_LOAD,
STATUS.EDITING_DRAFT,
STATUS.EDITING_COMPLETED,
STATUS.EDITING_DOCS_LOAD,
STATUS.EXPORT_TO_ESK_ERROR,
STATUS.WAITING_FOR_ESK_DECISION,
STATUS.PROCESSING_TESSA_COMMENTS,
STATUS.DETAILS_ERROR,
STATUS.REFUSED,
];
/** Статусы, доступные для перехода со статуса "Требуется доработка данных". */
export const DATA_ERROR_AVAILABLE_STATUSES = [STATUS.DRAFT, STATUS.COMPLETED, STATUS.EDITING_DRAFT, STATUS.REPLACING_DOCS, STATUS.REFUSED];
/**
* Функция перевода заявки в статус "Требуется доработка данных".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049
*/
export const changeToDataErrorStatus: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.DATA_ERROR),
guardians: [singleAction, inStatuses(DATA_ERROR_STATUSES)],
};
@@ -0,0 +1,39 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { changeStatusBankAdminAction } from './change-status-bank-admin-action';
/** Статусы, при которых доступна функция перевода заявки в статус "Удалён". */
const DELETED_STATUSES = [STATUS.DRAFT, STATUS.DOCS_LOAD];
/** Статусы, доступные для перехода со статуса "Удален". */
export const DELETED_AVAILABLE_STATUSES = [];
/**
* Функция перевода заявки в статус "Удалён".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049.
*/
export const changeToDeletedStatus: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.DELETED),
guardians: [singleAction, inStatuses(DELETED_STATUSES)],
};
/** Статусы, при которых доступна функция перевода заявки в статус "Удалён" при типе пользователя BANK. */
const DELETED_STATUSES_BANK_USER_TYPE = [STATUS.DRAFT];
/** Статусы, доступные для перехода со статуса "Удален" при типе пользователя BANK. */
export const DELETED_AVAILABLE_STATUSES_BANK_USER_TYPE = [];
/**
* Функция перевода заявки в статус "Удалён" при типе пользователя заявки BANK.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049.
*/
export const changeToDeletedStatusBankUserType: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.DELETED),
guardians: [singleAction, inStatuses(DELETED_STATUSES_BANK_USER_TYPE)],
};
@@ -0,0 +1,23 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { changeStatusBankAdminAction } from './change-status-bank-admin-action';
/** Статусы, при которых доступна функция перевода заявки в статус "Доставлен". */
const DELIVERED_STATUSES = [STATUS.DOCS_LOAD, STATUS.EDITING_DOCS_LOAD, STATUS.REPLACING_DOCS, STATUS.EDITING_REPLACING_DOCS];
/** Статусы, доступные для перехода со статуса "Доставлен". */
export const DELIVERED_AVAILABLE_STATUSES = [STATUS.EXECUTED, STATUS.DETAILS_ERROR];
/**
* Функция перевода заявки в статус "Доставлен".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049
*/
export const changeToDeliveredStatus: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.DELIVERED),
guardians: [singleAction, inStatuses(DELIVERED_STATUSES)],
};
@@ -0,0 +1,23 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { changeStatusBankAdminAction } from './change-status-bank-admin-action';
/** Статусы, при которых доступна функция перевода заявки в статус "Ошибка реквизитов". */
const DETAILS_ERROR_STATUSES = [STATUS.DELIVERED];
/** Статусы, доступные для перехода со статуса "Ошибка реквизитов". */
export const DETAILS_ERROR_AVAILABLE_STATUSES = [STATUS.DATA_ERROR, STATUS.REJECTED];
/**
* Функция перевода заявки в статус "Ошибка реквизитов".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049
*/
export const changeToDetailsErrorStatus: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.DETAILS_ERROR),
guardians: [singleAction, inStatuses(DETAILS_ERROR_STATUSES)],
};
@@ -0,0 +1,31 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { changeStatusBankAdminAction } from './change-status-bank-admin-action';
/** Статусы, при которых доступна функция перевода заявки в статус "Загрузка документов". */
const DOCS_LOAD_STATUSES = [STATUS.COMPLETED, STATUS.FORMED, STATUS.REFUSED];
/** Статусы, доступные для перехода со статуса "Загрузка документов". */
export const DOCS_LOAD_AVAILABLE_STATUSES = [
STATUS.DELETED,
STATUS.DRAFT,
STATUS.FORMED,
STATUS.REFUSED,
STATUS.DELIVERED,
STATUS.DATA_ERROR,
STATUS.EDITING_DOCS_LOAD,
];
/**
* Функция перевода заявки в статус "Загрузка документов".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049
* */
export const changeToDocsLoadStatus: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.DOCS_LOAD),
guardians: [singleAction, inStatuses(DOCS_LOAD_STATUSES)],
};
@@ -0,0 +1,39 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { changeStatusBankAdminAction } from './change-status-bank-admin-action';
/** Статусы, при которых доступна функция перевода заявки в статус "Черновик". */
const DRAFT_STATUSES = [STATUS.DOCS_LOAD, STATUS.FORMED, STATUS.DATA_ERROR, STATUS.REFUSED];
/** Статусы, доступные для перехода со статуса "Черновик". */
export const DRAFT_AVAILABLE_STATUSES = [STATUS.COMPLETED, STATUS.DELETED, STATUS.EDITING_DRAFT, STATUS.REFUSED];
/**
* Функция перевода заявки в статус "Черновик".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049.
*/
export const changeToDraftStatus: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.DRAFT),
guardians: [singleAction, inStatuses(DRAFT_STATUSES)],
};
/** Статусы, при которых доступна функция перевода заявки в статус "Черновик" при типе пользователя BANK. */
const DRAFT_STATUSES_BANK_USER_TYPE = [STATUS.FORMED, STATUS.REFUSED];
/** Статусы, доступные для перехода со статуса "Черновик" при типе пользователя BANK. */
export const DRAFT_AVAILABLE_STATUSES_BANK_USER_TYPE = [STATUS.COMPLETED, STATUS.DELETED, STATUS.REFUSED];
/**
* Функция перевода заявки в статус "Черновик" при типе пользователя заявки BANK.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049.
*/
export const changeToDraftStatusBankUserType: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.DRAFT),
guardians: [singleAction, inStatuses(DRAFT_STATUSES_BANK_USER_TYPE)],
};
@@ -0,0 +1,23 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { changeStatusBankAdminAction } from './change-status-bank-admin-action';
/** Статусы, при которых доступна функция перевода заявки в статус "Заполнен сотрудником Банка". */
const EDITING_COMPLETED_STATUSES = [STATUS.EDITING_DRAFT];
/** Статусы, доступные для перехода со статуса "Заполнен сотрудником Банка". */
export const EDITING_COMPLETED_AVAILABLE_STATUSES = [STATUS.EDITING_DOCS_LOAD, STATUS.DATA_ERROR];
/**
* Функция перевода заявки в статус "Заполнен сотрудником Банка".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049
* */
export const changeToEditingCompletedStatus: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.EDITING_COMPLETED),
guardians: [singleAction, inStatuses(EDITING_COMPLETED_STATUSES)],
};
@@ -0,0 +1,23 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { changeStatusBankAdminAction } from './change-status-bank-admin-action';
/** Статусы, при которых доступна функция перевода заявки в статус "Загрузка документов сотрудником". */
const EDITING_DOCS_LOAD_STATUSES = [STATUS.COMPLETED, STATUS.DOCS_LOAD, STATUS.EDITING_COMPLETED];
/** Статусы, доступные для перехода со статуса "Загрузка документов сотрудником". */
export const EDITING_DOCS_LOAD_AVAILABLE_STATUSES = [STATUS.EDITING_DRAFT, STATUS.DATA_ERROR, STATUS.DELIVERED];
/**
* Функция перевода заявки в статус "Загрузка документов сотрудником".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049
* */
export const changeToEditingDocsLoadStatus: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.EDITING_DOCS_LOAD),
guardians: [singleAction, inStatuses(EDITING_DOCS_LOAD_STATUSES)],
};
@@ -0,0 +1,23 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { changeStatusBankAdminAction } from './change-status-bank-admin-action';
/** Статусы, при которых доступна функция перевода заявки в статус "Черновик сотрудника Банка". */
const EDITING_DRAFT_STATUSES = [STATUS.DRAFT, STATUS.DATA_ERROR, STATUS.EDITING_DOCS_LOAD];
/** Статусы, доступные для перехода со статуса "Черновик сотрудника Банка". */
export const EDITING_DRAFT_AVAILABLE_STATUSES = [STATUS.EDITING_COMPLETED, STATUS.DATA_ERROR];
/**
* Функция перевода заявки в статус "Черновик сотрудника Банка".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049
* */
export const changeToEditingDraftStatus: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.EDITING_DRAFT),
guardians: [singleAction, inStatuses(EDITING_DRAFT_STATUSES)],
};
@@ -0,0 +1,23 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { changeStatusBankAdminAction } from './change-status-bank-admin-action';
/** Статусы, при которых доступна функция перевода заявки в статус "Замена документов сотрудником Банка". */
const EDITING_REPLACING_DOCS_STATUSES = [STATUS.REPLACING_DOCS];
/** Статусы, доступные для перехода со статуса "Замена документов сотрудником Банка". */
export const EDITING_REPLACING_DOCS_AVAILABLE_STATUSES = [STATUS.REPLACING_DOCS, STATUS.DELIVERED];
/**
* Функция перевода заявки в статус "Замена документов сотрудником Банка".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049
* */
export const changeToEditingReplacingDocsStatus: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.EDITING_REPLACING_DOCS),
guardians: [singleAction, inStatuses(EDITING_REPLACING_DOCS_STATUSES)],
};
@@ -0,0 +1,23 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { changeStatusBankAdminAction } from './change-status-bank-admin-action';
/** Статусы, при которых доступна функция перевода заявки в статус "Заявка создана в ЕСК". */
const EXECUTED_BY_ESK_STATUSES = [STATUS.EXPORTED_TO_ESK];
/** Статусы, доступные для перехода со статуса "Заяка создана в ЕСК". */
export const EXECUTED_BY_ESK_AVAILABLE_STATUSES = [STATUS.EXPORT_TO_TESSA, STATUS.EXPORT_TO_ESK_ERROR];
/**
* Функция перевода заявки в статус "Заявка создана в ЕСК".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049
*/
export const changeToExecutedByEskStatus: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.EXECUTED_BY_ESK),
guardians: [singleAction, inStatuses(EXECUTED_BY_ESK_STATUSES)],
};
@@ -0,0 +1,23 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { changeStatusBankAdminAction } from './change-status-bank-admin-action';
/** Статусы, при которых доступна функция перевода заявки в статус "Документы выгружены в ТЕССА". */
const EXECUTED_BY_TESSA_STATUSES = [STATUS.EXPORT_TO_TESSA, STATUS.EXPORT_TO_TESSA_ERROR];
/** Статусы, доступные для перехода со статуса "Документы выгружены в ТЕССА". */
export const EXECUTED_BY_TESSA_AVAILABLE_STATUSES = [STATUS.WAITING_FOR_ESK_DECISION, STATUS.PROCESSING_TESSA_COMMENTS];
/**
* Функция перевода заявки в статус "Документы выгружены в ТЕССА".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049
*/
export const changeToExecutedByTessaStatus: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.EXECUTED_BY_TESSA),
guardians: [singleAction, inStatuses(EXECUTED_BY_TESSA_STATUSES)],
};
@@ -0,0 +1,23 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { changeStatusBankAdminAction } from './change-status-bank-admin-action';
/** Статусы, при которых доступна функция перевода заявки в статус "Исполнен". */
const EXECUTED_STATUSES = [STATUS.DELIVERED, STATUS.WAITING_FOR_ESK_ACCOUNTS];
/** Статусы, доступные для перехода со статуса "Исполнен". */
export const EXECUTED_AVAILABLE_STATUSES = [];
/**
* Функция перевода заявки в статус "Исполнен".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049
*/
export const changeToExecutedStatus: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.EXECUTED),
guardians: [singleAction, inStatuses(EXECUTED_STATUSES)],
};
@@ -0,0 +1,23 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { changeStatusBankAdminAction } from './change-status-bank-admin-action';
/** Статусы, при которых доступна функция перевода заявки в статус "Ошибка создания заявки в ЕСК". */
const EXPORT_TO_ESK_ERROR_STATUSES = [STATUS.EXPORT_TO_ESK, STATUS.EXPORTED_TO_ESK, STATUS.EXECUTED_BY_ESK];
/** Статусы, доступные для перехода со статуса "Ошибка создания заявки в ЕСК". */
export const EXPORT_TO_ESK_ERROR_AVAILABLE_STATUSES = [STATUS.DATA_ERROR, STATUS.APPROVED, STATUS.REJECTED];
/**
* Функция перевода заявки в статус "Ошибка создания заявки в ЕСК".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049
*/
export const changeToExportToEskErrorStatus: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.EXPORT_TO_ESK_ERROR),
guardians: [singleAction, inStatuses(EXPORT_TO_ESK_ERROR_STATUSES)],
};
@@ -0,0 +1,23 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { changeStatusBankAdminAction } from './change-status-bank-admin-action';
/** Статусы, при которых доступна функция перевода заявки в статус "Отправка запроса на создание заявки в ЕСК". */
const EXPORT_TO_ESK_STATUSES = [STATUS.RECEIVED];
/** Статусы, доступные для перехода со статуса "Отправка запроса на создание заявки в ЕСК". */
export const EXPORT_TO_ESK_AVAILABLE_STATUSES = [STATUS.EXPORTED_TO_ESK, STATUS.EXPORT_TO_ESK_ERROR];
/**
* Функция перевода заявки в статус "Отправка запроса на создание заявки в ЕСК".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049
*/
export const changeToExportToEskStatus: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.EXPORT_TO_ESK),
guardians: [singleAction, inStatuses(EXPORT_TO_ESK_STATUSES)],
};
@@ -0,0 +1,23 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { changeStatusBankAdminAction } from './change-status-bank-admin-action';
/** Статусы, при которых доступна функция перевода заявки в статус "Ошибка выгрузки документов в ТЕССА". */
const EXPORT_TO_TESSA_ERROR_STATUSES = [STATUS.EXPORT_TO_TESSA];
/** Статусы, доступные для перехода со статуса "Ошибка выгрузки документов в ТЕССА". */
export const EXPORT_TO_TESSA_ERROR_AVAILABLE_STATUSES = [STATUS.EXPORT_TO_TESSA, STATUS.EXECUTED_BY_TESSA];
/**
* Функция перевода заявки в статус "Ошибка выгрузки документов в ТЕССА".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049
*/
export const changeToExportToTessaErrorStatus: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.EXPORT_TO_TESSA_ERROR),
guardians: [singleAction, inStatuses(EXPORT_TO_TESSA_ERROR_STATUSES)],
};
@@ -0,0 +1,23 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { changeStatusBankAdminAction } from './change-status-bank-admin-action';
/** Статусы, при которых доступна функция перевода заявки в статус "Выгрузка документов в ТЕССА". */
const EXPORT_TO_TESSA_STATUSES = [STATUS.RECEIVED, STATUS.EXECUTED_BY_ESK, STATUS.EXPORT_TO_TESSA_ERROR, STATUS.PROCESSING_TESSA_COMMENTS];
/** Статусы, доступные для перехода со статуса "Выгрузка документов в ТЕССА". */
export const EXPORT_TO_TESSA_AVAILABLE_STATUSES = [STATUS.EXPORT_TO_TESSA_ERROR, STATUS.EXECUTED_BY_TESSA];
/**
* Функция перевода заявки в статус "Выгрузка документов в ТЕССА".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049
*/
export const changeToExportToTessaStatus: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.EXPORT_TO_TESSA),
guardians: [singleAction, inStatuses(EXPORT_TO_TESSA_STATUSES)],
};
@@ -0,0 +1,23 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { changeStatusBankAdminAction } from './change-status-bank-admin-action';
/** Статусы, при которых доступна функция перевода заявки в статус "Отправлен запрос на создание заявки в ЕСК". */
const EXPORTED_TO_ESK_STATUSES = [STATUS.EXPORT_TO_ESK];
/** Статусы, доступные для перехода со статуса "Отправлен запрос на создание заявки в ЕСК". */
export const EXPORTED_TO_ESK_AVAILABLE_STATUSES = [STATUS.EXPORT_TO_ESK_ERROR, STATUS.EXECUTED_BY_ESK];
/**
* Функция перевода заявки в статус "Отправлен запрос на создание заявки в ЕСК".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049
*/
export const changeToExportedToEskStatus: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.EXPORTED_TO_ESK),
guardians: [singleAction, inStatuses(EXPORTED_TO_ESK_STATUSES)],
};
@@ -0,0 +1,39 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { changeStatusBankAdminAction } from './change-status-bank-admin-action';
/** Статусы, при которых доступна функция перевода заявки в статус "Документы сформированы". */
const FORMED_STATUSES = [STATUS.COMPLETED, STATUS.DOCS_LOAD];
/** Статусы, доступные для перехода со статуса "Документы сформированы". */
export const FORMED_AVAILABLE_STATUSES = [STATUS.DOCS_LOAD, STATUS.DRAFT];
/**
* Функция перевода заявки в статус "Документы сформированы".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049.
*/
export const changeToFormedStatus: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.FORMED),
guardians: [singleAction, inStatuses(FORMED_STATUSES)],
};
/** Статусы, при которых доступна функция перевода заявки в статус "Документы сформированы" при типе пользователя BANK. */
const FORMED_STATUSES_BANK_USER_TYPE = [STATUS.COMPLETED];
/** Статусы, доступные для перехода со статуса "Документы сформированы" при типе пользователя BANK. */
export const FORMED_AVAILABLE_STATUSES_BANK_USER_TYPE = [STATUS.DRAFT];
/**
* Функция перевода заявки в статус "Документы сформированы" при типе пользователя заявки BANK.
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049.
*/
export const changeToFormedStatusBankUserType: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.FORMED),
guardians: [singleAction, inStatuses(FORMED_STATUSES_BANK_USER_TYPE)],
};
@@ -0,0 +1,28 @@
export * from './delivered';
export * from './completed';
export * from './deleted';
export * from './editing-draft';
export * from './formed';
export * from './docs-load';
export * from './editing-docs-load';
export * from './editing-completed';
export * from './editing-replacing-docs';
export * from './details-error';
export * from './export-to-esk';
export * from './export-to-tessa';
export * from './exported-to-esk';
export * from './export-to-esk-error';
export * from './executed-by-esk';
export * from './export-to-tessa-error';
export * from './waiting-for-esk-accounts';
export * from './waiting-for-esk-decision';
export * from './waiting-restriction';
export * from './draft';
export * from './approved';
export * from './executed';
export * from './data-error';
export * from './executed-by-tessa';
export * from './rejected';
export * from './refused';
export * from './processing-tessa-comments';
export * from './replacing-docs';
@@ -0,0 +1,29 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { changeToProcessingTessaCommentsAction } from '../change-to-processing-tessa-comments';
/** Статусы, при которых доступна функция перевода заявки в статус "Ручной разбор замечаний от ТЕССА". */
const PROCESSING_TESSA_COMMENTS_STATUSES = [STATUS.REPLACING_DOCS, STATUS.EXECUTED_BY_TESSA, STATUS.WAITING_FOR_ESK_DECISION];
/** Статусы, доступные для перехода со статуса "Ручной разбор замечаний от ТЕССА". */
export const PROCESSING_TESSA_COMMENTS_AVAILABLE_STATUSES = [
STATUS.REPLACING_DOCS,
STATUS.DATA_ERROR,
STATUS.REJECTED,
STATUS.APPROVED,
STATUS.EXPORT_TO_TESSA,
];
/**
* Функция перевода заявки в статус "Ручной разбор замечаний от ТЕССА".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049
*/
export const changeToProcessingTessaCommentsStatus: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeToProcessingTessaCommentsAction,
guardians: [singleAction, inStatuses(PROCESSING_TESSA_COMMENTS_STATUSES)],
};
@@ -0,0 +1,23 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { changeStatusBankAdminAction } from './change-status-bank-admin-action';
/** Статусы, при которых доступна функция перевода заявки в статус "Отклонен". */
const REFUSED_STATUSES = [STATUS.DRAFT, STATUS.DOCS_LOAD, STATUS.DATA_ERROR, STATUS.REPLACING_DOCS, STATUS.WAITING_FOR_ESK_ACCOUNTS];
/** Статусы, доступные для перехода со статуса "Отклонен". */
export const REFUSED_AVAILABLE_STATUSES = [];
/**
* Функция перевода заявки в статус "Отклонен".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049
*/
export const changeToRefusedStatus: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.REFUSED),
guardians: [singleAction, inStatuses(REFUSED_STATUSES)],
};
@@ -0,0 +1,30 @@
import type { IOnboardingAdminContext } from 'action-executers/admin';
import { inStatuses } from 'actions/guardians';
import type { OnboardingRequestDto } from 'interfaces';
import { STATUS } from 'stream-constants';
import { singleAction } from '@platform/core';
import type { IActionConfig } from '@platform/core';
import { changeStatusBankAdminAction } from './change-status-bank-admin-action';
/** Статусы, при которых доступна функция перевода заявки в статус "Отклонен". */
const REJECTED_STATUSES = [
STATUS.EXPORT_TO_ESK_ERROR,
STATUS.WAITING_FOR_ESK_DECISION,
STATUS.PROCESSING_TESSA_COMMENTS,
STATUS.WAITING_RESTRICTION,
STATUS.WAITING_FOR_ESK_ACCOUNTS,
STATUS.DETAILS_ERROR,
];
/** Статусы, доступные для перехода со статуса "Отклонен". */
export const REJECTED_AVAILABLE_STATUSES = [];
/**
* Функция перевода заявки в статус "Отклонен".
*
* @see https://confluence.gboteam.ru/pages/viewpage.action?pageId=138990049
*/
export const changeToRejectedStatus: IActionConfig<IOnboardingAdminContext, OnboardingRequestDto> = {
action: changeStatusBankAdminAction(STATUS.REJECTED),
guardians: [singleAction, inStatuses(REJECTED_STATUSES)],
};

Some files were not shown because too many files have changed in this diff Show More