feat(msb-treasury-deals): миграция от 18.11
This commit is contained in:
@@ -6,3 +6,4 @@ lerna-debug.log
|
||||
.idea
|
||||
.vscode
|
||||
/msb-*
|
||||
.eslintcache
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# Миграция ECO
|
||||
eco-treasury-deals/
|
||||
migration
|
||||
.eslintcache
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
"build:dev": "build-app build:dev",
|
||||
"build": "build-app build",
|
||||
"clone": "git clone ssh://git@bitbucket.gboteam.ru:7999/eco_fe/eco-treasury-deals.git && cd ./eco-treasury-deals && git checkout client_area_for_msb && cd ..",
|
||||
"lint-fix": "eslint --fix --ext .js,.jsx,.ts,.tsx ./src",
|
||||
"lint-fix": "eslint --cache --fix --ext .js,.jsx,.ts,.tsx ./src",
|
||||
"check-types": "tsc",
|
||||
"lint": "eslint --ext .js,.jsx,.ts,.tsx ./src --max-warnings=0",
|
||||
"lint": "eslint --cache --ext .js,.jsx,.ts,.tsx ./src --max-warnings=0",
|
||||
"stylelint": "stylelint --fix --ext .js,.jsx,.ts,.tsx ./src --max-warnings=0",
|
||||
"lint:ci": "eslint --quiet --ext .js,.jsx,.ts,.tsx ./src",
|
||||
"format": "prettier --write ./src",
|
||||
|
||||
+8
-12
@@ -103,13 +103,8 @@ export const SelectButtons: React.FC<ISelectButtons> = ({ userInfo, size = 'M' }
|
||||
locale.deposit.modal.mnoHeader,
|
||||
locale.conversion.modal.conversionHeader
|
||||
);
|
||||
const buttonText = returnDocTypeBinder(
|
||||
dealType,
|
||||
locale.common.dealType.deposit,
|
||||
locale.common.dealType.mno,
|
||||
locale.common.dealType.gsno,
|
||||
locale.common.dealType.conversion
|
||||
);
|
||||
const buttonText = locale.common.dealType.text({ dealType });
|
||||
const buttonDescription = locale.common.dealType.description({ dealType });
|
||||
|
||||
const handleClick = () => {
|
||||
if (viewOrNone(info)) {
|
||||
@@ -132,6 +127,7 @@ export const SelectButtons: React.FC<ISelectButtons> = ({ userInfo, size = 'M' }
|
||||
|
||||
return {
|
||||
text: isAllowed ? buttonText : <Tooltip text={locale.deposit.button.hover}>{buttonText}</Tooltip>,
|
||||
description: buttonDescription,
|
||||
onClick: handleClick,
|
||||
disabled: !isAllowed,
|
||||
};
|
||||
@@ -166,7 +162,7 @@ export const SelectButtons: React.FC<ISelectButtons> = ({ userInfo, size = 'M' }
|
||||
<ContextMenuBase<HTMLButtonElement>
|
||||
items={items as unknown as MenuItemProps[]}
|
||||
size={'L'}
|
||||
title={locale.common.dealType.createDeal}
|
||||
title={locale.common.createDeal}
|
||||
width={'100%'}
|
||||
>
|
||||
{({ ref, toggleOpen }) => (
|
||||
@@ -235,14 +231,14 @@ export const SelectButtons: React.FC<ISelectButtons> = ({ userInfo, size = 'M' }
|
||||
size="M"
|
||||
onClick={() => ModalService.showStatus(noPrivilegesModal)}
|
||||
>
|
||||
{locale.common.dealType.createDeal}
|
||||
{locale.common.createDeal}
|
||||
</Button>
|
||||
)}
|
||||
{items?.length > 0 && (
|
||||
<ContextMenuBase<HTMLButtonElement>
|
||||
items={items as unknown as MenuItemProps[]}
|
||||
size={'L'}
|
||||
title={locale.common.dealType.createDeal}
|
||||
title={locale.common.createDeal}
|
||||
width={'100%'}
|
||||
>
|
||||
{({ ref, toggleOpen }) => (
|
||||
@@ -254,7 +250,7 @@ export const SelectButtons: React.FC<ISelectButtons> = ({ userInfo, size = 'M' }
|
||||
size={'M'}
|
||||
onClick={e => (items?.length ? toggleOpen(e) : ModalService.showStatus(noPrivilegesModal))}
|
||||
>
|
||||
{locale.common.dealType.createDeal}
|
||||
{locale.common.createDeal}
|
||||
</Button>
|
||||
)}
|
||||
</ContextMenuBase>
|
||||
@@ -277,7 +273,7 @@ export const SelectButtons: React.FC<ISelectButtons> = ({ userInfo, size = 'M' }
|
||||
<ContextMenuBase<HTMLButtonElement>
|
||||
items={items as unknown as MenuItemProps[]}
|
||||
size="L"
|
||||
title={locale.common.dealType.createDeal}
|
||||
title={locale.common.createDeal}
|
||||
width={'100%'}
|
||||
>
|
||||
{({ ref, toggleOpen }) => (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Label, WithInfoTooltip } from '@msb/platform-compat/ui';
|
||||
import type { AUTO_COMPLETE } from '@msb/platform-compat/ui';
|
||||
import { Label, WithInfoTooltip } from '@msb/platform-compat/ui';
|
||||
import { isEqual, isFunction } from '@treasury-deals/common/utils/check-types';
|
||||
import type { FieldValidator } from 'final-form';
|
||||
import type { FieldInputProps, FieldMetaState } from 'react-final-form';
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import React from 'react';
|
||||
import type { IDstForSign } from '@msb/platform-compat/services/client';
|
||||
import { appendToPortal, asModal, deleteFromPortal } from '@msb/platform-compat/ui';
|
||||
import { appendToPortal, deleteFromPortal } from '@treasury-deals/common/components/portal-container';
|
||||
import { STATISTIC_TYPE } from '@treasury-deals/common/enums/statistics';
|
||||
import type { IDigestHolderDto } from '@treasury-deals/common/interfaces/common';
|
||||
import { StatisticService } from '@treasury-deals/common/services';
|
||||
import { getTextErrorMessage } from '@treasury-deals/common/utils/form';
|
||||
import { locale } from '@treasury-deals/localization';
|
||||
import { asModal } from '@platform/ui';
|
||||
import { CloudSignDialog } from './cloud-sign-dialog';
|
||||
|
||||
// type ICloudSignItem = Omit<ICloudSignData, 'documentId'>; // Todo типов там больше нет
|
||||
|
||||
@@ -21,4 +21,8 @@ export enum STATISTIC_TYPE {
|
||||
CRYPTO_ERROR = 'CRYPTO_ERROR',
|
||||
/** Лог профиля автокотирование. */
|
||||
AUTO_QUOTE_PROFILE = 'AUTO_QUOTE_PROFILE',
|
||||
/** Логирование перехода по банеру лучшей ставки. */
|
||||
DEAL_BEST_RATE_INIT = 'DEAL_BEST_RATE_INIT',
|
||||
/** Подписание сделки с лучшей ставкой. */
|
||||
DEAL_BEST_RATE_SIGN = 'DEAL_BEST_RATE_SIGN',
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/* eslint-disable @eco/no-missing-localization */
|
||||
/* eslint-disable jest/prefer-strict-equal */
|
||||
import { ACCOUNT_TYPES, ACCOUNT_USAGE_TYPES } from '@treasury-deals/common/constants/accounts';
|
||||
import { formatOther, formatAccountNumber, formatAccountType, formatAccountUsage, formatUserInfoOperations } from '../accounts';
|
||||
|
||||
describe('accounts', () => {
|
||||
test('formatOther', () => {
|
||||
expect(formatOther('test')).toBe('test');
|
||||
expect(formatOther('')).toBe('-');
|
||||
expect(formatOther({})).toBe('-');
|
||||
expect(formatOther(undefined)).toBe('-');
|
||||
expect(formatOther(null)).toBe('-');
|
||||
});
|
||||
test('formatAccountNumber', () => {
|
||||
expect(formatAccountNumber('40701840200007670001')).toBe('40701.840.2.00007670001');
|
||||
expect(formatAccountNumber('40201840201107672222')).toBe('40201.840.2.01107672222');
|
||||
expect(formatAccountNumber('hello')).not.toBe('40201.840.2.01107672222');
|
||||
expect(formatAccountNumber('')).toBe('-');
|
||||
});
|
||||
|
||||
test('formatAccountType', () => {
|
||||
expect(formatAccountType('INTERNAL')).toEqual(ACCOUNT_TYPES[0].title);
|
||||
expect(formatAccountType('EXTERNAL')).toEqual(ACCOUNT_TYPES[1].title);
|
||||
expect(formatAccountType('')).toBeUndefined();
|
||||
});
|
||||
|
||||
test('formatAccountUsage', () => {
|
||||
expect(formatAccountUsage([])).toBeUndefined();
|
||||
expect(formatAccountUsage(['MNO'])).toEqual(ACCOUNT_USAGE_TYPES[0].title);
|
||||
expect(formatAccountUsage(['DEPOSIT_VALUE'])).toEqual(ACCOUNT_USAGE_TYPES[1].title);
|
||||
expect(formatAccountUsage(['GSNO'])).toEqual(ACCOUNT_USAGE_TYPES[4].title);
|
||||
expect(formatAccountUsage(['DEPOSIT_VALUE', 'MNO'])).toBe(`${ACCOUNT_USAGE_TYPES[0].title}, ${ACCOUNT_USAGE_TYPES[1].title}`);
|
||||
expect(formatAccountUsage(['DEPOSIT_VALUE', 'DEPOSIT_MATURITY'])).toBe(
|
||||
`${ACCOUNT_USAGE_TYPES[2].title}, ${ACCOUNT_USAGE_TYPES[1].title}`
|
||||
);
|
||||
expect(formatAccountUsage(['DEPOSIT_VALUE', 'MNO', 'INTEREST'])).toBe(
|
||||
`${ACCOUNT_USAGE_TYPES[3].title}, ${ACCOUNT_USAGE_TYPES[0].title}, ${ACCOUNT_USAGE_TYPES[1].title}`
|
||||
);
|
||||
expect(formatAccountUsage(['DEPOSIT_VALUE', 'MNO', 'INTEREST', 'DEPOSIT_MATURITY'])).toBe(
|
||||
`${ACCOUNT_USAGE_TYPES[2].title}, ${ACCOUNT_USAGE_TYPES[3].title}, ${ACCOUNT_USAGE_TYPES[0].title}, ${ACCOUNT_USAGE_TYPES[1].title}`
|
||||
);
|
||||
expect(formatAccountUsage(['DEPOSIT_VALUE', 'GSNO', 'MNO'])).toBe(
|
||||
`${ACCOUNT_USAGE_TYPES[4].title}, ${ACCOUNT_USAGE_TYPES[0].title}, ${ACCOUNT_USAGE_TYPES[1].title}`
|
||||
);
|
||||
});
|
||||
|
||||
test('formatUserInfoOperations', () => {
|
||||
expect(formatUserInfoOperations(['DEPOSIT', 'MNO'])).toBe('');
|
||||
expect(formatUserInfoOperations(['MNO'])).toBe('депозитные сделки');
|
||||
expect(formatUserInfoOperations(['DEPOSIT'])).toBe('сделки МНО');
|
||||
expect(formatUserInfoOperations([])).toBe('сделки МНО, депозитные сделки');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,13 @@
|
||||
/* eslint-disable jest/prefer-strict-equal */
|
||||
import { AGREEMENTS_STATUS_TYPES } from '@treasury-deals/common/constants';
|
||||
import { AGREEMENT_STATUSES } from '@treasury-deals/common/enums';
|
||||
import { formatAgreementStatus } from '../agreements';
|
||||
|
||||
describe('agreements', () => {
|
||||
test('formatAgreementStatus', () => {
|
||||
expect(formatAgreementStatus(AGREEMENT_STATUSES.ACTIVE)).toEqual(AGREEMENTS_STATUS_TYPES[0].title);
|
||||
expect(formatAgreementStatus(AGREEMENT_STATUSES.BLOCKED)).toEqual(AGREEMENTS_STATUS_TYPES[1].title);
|
||||
expect(formatAgreementStatus(AGREEMENT_STATUSES.DELETED)).toEqual(AGREEMENTS_STATUS_TYPES[2].title);
|
||||
expect(formatAgreementStatus('')).toBeUndefined();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,46 @@
|
||||
import { ERROR_MESSAGE_DEVIATION } from '@treasury-deals/common/constants/autoquotation';
|
||||
import { checkRate } from '@treasury-deals/common/utils/autoquotation';
|
||||
|
||||
describe('checkRate', () => {
|
||||
it('returns ERROR_MESSAGE_DEVIATION when currentRate is greater than the maxRateDeviation', () => {
|
||||
const result = checkRate(100, 0.1, 121);
|
||||
|
||||
expect(result).toStrictEqual(ERROR_MESSAGE_DEVIATION);
|
||||
});
|
||||
|
||||
it('returns ERROR_MESSAGE_DEVIATION when currentRate is less than the minRateDeviation', () => {
|
||||
const result = checkRate(100, 0.1, 79);
|
||||
|
||||
expect(result).toStrictEqual(ERROR_MESSAGE_DEVIATION);
|
||||
});
|
||||
|
||||
it('returns nothing when currentRate is between the minRateDeviation and maxRateDeviation', () => {
|
||||
const result = checkRate(100, 0.1, 110);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it('correctly calculates the maxRateDeviation when given a positive rateDeviation', () => {
|
||||
const result = checkRate(100, 0.1, 115);
|
||||
|
||||
expect(result).toStrictEqual(ERROR_MESSAGE_DEVIATION);
|
||||
});
|
||||
|
||||
it('correctly calculates the minRateDeviation when given a positive rateDeviation', () => {
|
||||
const result = checkRate(100, 0.1, 105);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it('returns nothing when given a zero rateDeviation', () => {
|
||||
const result = checkRate(100, 0, 100);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it('correctly handles a zero originalRate', () => {
|
||||
const result = checkRate(undefined, 0.1, 5);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
/* eslint-disable jest/prefer-strict-equal */
|
||||
import { formatDate, formatTime, differenceInDays, addDaysToDate } from '../date';
|
||||
|
||||
describe('date', () => {
|
||||
test('formatDate', () => {
|
||||
expect(formatDate('2020-10-10')).toBe('10.10.2020');
|
||||
expect(formatDate('12.20.2020')).toBe('20.12.2020');
|
||||
expect(formatDate('2020/10/10')).toBe('10.10.2020');
|
||||
});
|
||||
|
||||
test('formatTime', () => {
|
||||
expect(formatTime(1)).toBe('00:00');
|
||||
expect(formatTime(20_000_000_000)).toBe('33:20');
|
||||
expect(formatTime(100_000)).toBe('01:40');
|
||||
});
|
||||
|
||||
test('differenceInDays', () => {
|
||||
expect(differenceInDays('2019-01-25', '2018-06-05')).toBe(234);
|
||||
expect(differenceInDays('2019-02-25', '2019-01-05')).toBe(51);
|
||||
expect(differenceInDays('2020-01-01', '2019-01-01')).toBe(365);
|
||||
});
|
||||
|
||||
test('addDaysToDate', () => {
|
||||
expect(addDaysToDate('2019-01-25', 1)).toBe('2019-01-26');
|
||||
expect(addDaysToDate('2019-02-25', 5)).toBe('2019-03-02');
|
||||
expect(addDaysToDate('2020-01-01', 10)).toBe('2020-01-11');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
/* eslint-disable jest/prefer-strict-equal */
|
||||
import { formatServerValidation, formatServerError } from '../form';
|
||||
import { ERROR, ERROR_OBJECT, DEFAULT_ERROR_MESSAGE } from '../test-constants';
|
||||
|
||||
describe('form utils', () => {
|
||||
test('formatServerValidation', () => {
|
||||
expect(formatServerValidation({})).toEqual({});
|
||||
expect(formatServerValidation(ERROR)).toEqual({ Error: 'Error message example' });
|
||||
});
|
||||
test('formatServerError', () => {
|
||||
expect(formatServerError({})).toEqual(DEFAULT_ERROR_MESSAGE);
|
||||
expect(formatServerError(ERROR_OBJECT)).toEqual(ERROR_OBJECT.message);
|
||||
});
|
||||
});
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
import { formattedRate } from '@treasury-deals/common/utils/autoquotation';
|
||||
|
||||
describe('formattedRate', () => {
|
||||
it('simple tests', () => {
|
||||
// prettier-ignore
|
||||
expect(formattedRate(75.55, 4)).toBe('75.5500');
|
||||
// prettier-ignore
|
||||
expect(formattedRate(75.134, 4)).toBe('75.1340');
|
||||
expect(formattedRate(75.556_666, 4)).toBe('75.5567');
|
||||
// prettier-ignore
|
||||
expect(formattedRate(75.4, 6)).toBe('75.400000');
|
||||
expect(formattedRate(75, 4)).toBe('75.0000');
|
||||
});
|
||||
|
||||
it('returns a string with the correct number of characters when the number of chars is zero', () => {
|
||||
const result = formattedRate(3.14, 0);
|
||||
|
||||
expect(result).toBe('3.14');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,121 @@
|
||||
/* eslint-disable jest/prefer-strict-equal */
|
||||
import { ACCOUNT_USAGE_TYPES } from '@treasury-deals/common/constants/accounts';
|
||||
import * as user from '@treasury-deals/common/constants/user';
|
||||
import {
|
||||
formatDeclination,
|
||||
formatDeclinationDays,
|
||||
formatUsageItem,
|
||||
formatAdminFilter,
|
||||
formatParamsToServer,
|
||||
formatTableSettingsColumns,
|
||||
formatTableExportColumns,
|
||||
getFilter,
|
||||
formatNumberWithSpace,
|
||||
formatNumberWithSpaceAndComma,
|
||||
DECL_DAYS,
|
||||
formatWithSpace,
|
||||
} from '../formatters';
|
||||
import {
|
||||
DECL_ITEMS,
|
||||
ADMIN_FILTERS,
|
||||
ADMIN_FILTERS_RESULT,
|
||||
TABLE_SETTINGS_COLUMNS,
|
||||
TABLE_COLUMNS,
|
||||
DATA_FOR_FORMATTING,
|
||||
DATA_WITHOUT_LABEL_VALUE,
|
||||
DATA_WITHOUT_LABEL,
|
||||
} from '../test-constants';
|
||||
|
||||
jest.mock('common/constants/user', () => ({
|
||||
__esModule: true,
|
||||
isAdmin: true,
|
||||
}));
|
||||
|
||||
const mockConfig = user as { isAdmin: boolean };
|
||||
|
||||
describe('formatters', () => {
|
||||
test('formatDeclination', () => {
|
||||
expect(formatDeclination(21, DECL_ITEMS)).toEqual(DECL_ITEMS[0]);
|
||||
expect(formatDeclination(34, DECL_ITEMS)).toEqual(DECL_ITEMS[1]);
|
||||
expect(formatDeclination(55, DECL_ITEMS)).toEqual(DECL_ITEMS[2]);
|
||||
expect(formatDeclination(24, [])).toBeUndefined();
|
||||
});
|
||||
|
||||
test('formatDeclinationDays', () => {
|
||||
expect(formatDeclinationDays(31)).toBe(`31 ${DECL_DAYS[0]}`);
|
||||
expect(formatDeclinationDays(24)).toBe(`24 ${DECL_DAYS[1]}`);
|
||||
expect(formatDeclinationDays(45)).toBe(`45 ${DECL_DAYS[2]}`);
|
||||
});
|
||||
|
||||
test('formatUsageItem', () => {
|
||||
expect(formatUsageItem(ACCOUNT_USAGE_TYPES, 'DEPOSIT_VALUE')).toEqual(ACCOUNT_USAGE_TYPES[1].title);
|
||||
expect(formatUsageItem(ACCOUNT_USAGE_TYPES, 'MNO')).toEqual(ACCOUNT_USAGE_TYPES[0].title);
|
||||
});
|
||||
|
||||
test('formatAdminFilter', () => {
|
||||
expect(formatAdminFilter(ADMIN_FILTERS.correct)).toMatchObject(ADMIN_FILTERS_RESULT.correct);
|
||||
expect(formatAdminFilter(ADMIN_FILTERS.incorrect)).toMatchObject(ADMIN_FILTERS_RESULT.incorrect);
|
||||
});
|
||||
|
||||
test('formatParamsToServer', () => {
|
||||
expect(formatParamsToServer({ filter: ADMIN_FILTERS.correct })).toMatchObject({
|
||||
filter: { ...ADMIN_FILTERS_RESULT.correct },
|
||||
});
|
||||
mockConfig.isAdmin = false;
|
||||
expect(formatParamsToServer({ filter: ADMIN_FILTERS.correct })).toMatchObject({
|
||||
filter: {},
|
||||
});
|
||||
});
|
||||
|
||||
test('formatTableSettingsColumns', () => {
|
||||
mockConfig.isAdmin = true;
|
||||
expect(formatTableSettingsColumns(TABLE_SETTINGS_COLUMNS.basic, TABLE_SETTINGS_COLUMNS.admin)).toEqual([
|
||||
TABLE_SETTINGS_COLUMNS.admin[0],
|
||||
TABLE_SETTINGS_COLUMNS.basic[0],
|
||||
]);
|
||||
mockConfig.isAdmin = false;
|
||||
expect(formatTableSettingsColumns(TABLE_SETTINGS_COLUMNS.basic, TABLE_SETTINGS_COLUMNS.admin)).toEqual(TABLE_SETTINGS_COLUMNS.basic);
|
||||
});
|
||||
|
||||
test('formatTableExportColumns', () => {
|
||||
const { showedColumns, exportColumnsArr } = TABLE_COLUMNS;
|
||||
|
||||
expect(formatTableExportColumns(showedColumns.slice(0, 2), exportColumnsArr)).toEqual([exportColumnsArr[0], exportColumnsArr[2]]);
|
||||
expect(formatTableExportColumns(showedColumns, exportColumnsArr)).toEqual([
|
||||
exportColumnsArr[0],
|
||||
exportColumnsArr[2],
|
||||
exportColumnsArr[1],
|
||||
exportColumnsArr[3],
|
||||
]);
|
||||
});
|
||||
|
||||
test('getFilter', () => {
|
||||
expect(getFilter('label')(DATA_FOR_FORMATTING)).toEqual(DATA_WITHOUT_LABEL);
|
||||
expect(getFilter('label', 'value')(DATA_FOR_FORMATTING)).toEqual(DATA_WITHOUT_LABEL_VALUE);
|
||||
expect(getFilter('name', 'code')(DATA_FOR_FORMATTING)).toEqual(DATA_FOR_FORMATTING);
|
||||
expect(getFilter('label', 'value')({})).toEqual({});
|
||||
expect(getFilter('')(DATA_FOR_FORMATTING)).toEqual(DATA_FOR_FORMATTING);
|
||||
});
|
||||
|
||||
test('formatNumberWithSpace', () => {
|
||||
expect(formatNumberWithSpace(222_222_222_222.0)).toBe('222 222 222 222.00');
|
||||
expect(formatNumberWithSpace('222222222222.00')).toBe('222 222 222 222.00');
|
||||
expect(formatNumberWithSpace('')).toBe('-');
|
||||
expect(formatNumberWithSpace(0)).toBe('-');
|
||||
expect(formatNumberWithSpace('')).toBe('-');
|
||||
});
|
||||
test('formatNumberWithSpaceAndComma', () => {
|
||||
expect(formatNumberWithSpaceAndComma(222_222_222_222.0)).toBe('222 222 222 222,00');
|
||||
expect(formatNumberWithSpaceAndComma('222222222222.00')).toBe('222 222 222 222,00');
|
||||
expect(formatNumberWithSpaceAndComma('')).toBe('-');
|
||||
expect(formatNumberWithSpaceAndComma(0)).toBe('-');
|
||||
expect(formatNumberWithSpaceAndComma('')).toBe('-');
|
||||
expect(formatNumberWithSpaceAndComma(50_000, true, true)).toBe('50 000');
|
||||
expect(formatNumberWithSpaceAndComma(50_000, true, false)).toBe('50 000,00');
|
||||
});
|
||||
test('formatWithSpace', () => {
|
||||
expect(formatWithSpace('322222222222.00')).toBe('322 222 222 222.00');
|
||||
expect(formatWithSpace('422222222222.00')).toBe('422 222 222 222.00');
|
||||
expect(formatWithSpace('522222222222.00')).toBe('522 222 222 222.00');
|
||||
});
|
||||
});
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/* eslint-disable @eco/no-missing-localization */
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import { renderErrorMessage } from '@treasury-deals/common/utils/autoquotation';
|
||||
|
||||
describe('renderErrorMessage', () => {
|
||||
it('should render an empty string when there are no errors', () => {
|
||||
const errors = {};
|
||||
const result = renderErrorMessage(errors);
|
||||
|
||||
expect(result).toBe('');
|
||||
|
||||
const { asFragment } = render(<div>{result}</div>);
|
||||
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render an error message for each error field', () => {
|
||||
const errors = {
|
||||
amountBuy: 'Error in amountBuy field',
|
||||
accountSell: 'Error in accountSell field',
|
||||
rate: 'Error in rate field',
|
||||
};
|
||||
|
||||
const result = renderErrorMessage(errors);
|
||||
|
||||
expect(result).toContain('Ошибка в поле покупка');
|
||||
expect(result).toContain('Ошибка в поле счет списания');
|
||||
expect(result).toContain('Ошибка в поле курс');
|
||||
expect(result).not.toContain('Ошибка в поле продажа');
|
||||
expect(result).not.toContain('Ошибка в поле счет зачисления');
|
||||
expect(result).not.toContain('Ошибка в поле генеральное соглашение');
|
||||
|
||||
const { asFragment } = render(<div>{result}</div>);
|
||||
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render an error message for each error field even if some fields have no errors', () => {
|
||||
const errors = {
|
||||
amountBuy: 'Error in amountBuy field',
|
||||
accountBuy: 'Error in accountBuy field',
|
||||
};
|
||||
|
||||
const result = renderErrorMessage(errors);
|
||||
|
||||
expect(result).toContain('Ошибка в поле покупка');
|
||||
expect(result).not.toContain('Ошибка в поле продажа');
|
||||
expect(result).toContain('Ошибка в поле счет зачисления');
|
||||
expect(result).not.toContain('Ошибка в поле счет списания');
|
||||
expect(result).not.toContain('Ошибка в поле курса');
|
||||
expect(result).not.toContain('Ошибка в поле генерального соглашения');
|
||||
|
||||
const { asFragment } = render(<div>{result}</div>);
|
||||
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,162 @@
|
||||
/* eslint-disable @eco/no-missing-localization */
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import type { ITradingInterval } from '@treasury-deals/common/interfaces/autoquotations/autoquote-v2';
|
||||
import { renderHoverText } from '@treasury-deals/common/utils/autoquotation';
|
||||
import { filterElementsById } from '@treasury-deals/common/utils/shared';
|
||||
import '@testing-library/jest-dom';
|
||||
|
||||
describe('filterElementsById', () => {
|
||||
it('должен правильно фильтровать элементы', () => {
|
||||
const idArray = ['id1', 'id2'];
|
||||
const elementsArray = [
|
||||
{
|
||||
id: 'id1',
|
||||
userActions: [{ type: 'DELETE', allowed: true, allowedForUser: true }],
|
||||
},
|
||||
{
|
||||
id: 'id2',
|
||||
userActions: [{ type: 'DELETE', allowed: true, allowedForUser: false }],
|
||||
},
|
||||
{
|
||||
id: 'id3',
|
||||
userActions: [],
|
||||
},
|
||||
];
|
||||
|
||||
const filteredElements = filterElementsById(idArray, elementsArray);
|
||||
|
||||
expect(filteredElements).toStrictEqual([
|
||||
{
|
||||
id: 'id1',
|
||||
userActions: [{ type: 'DELETE', allowed: true, allowedForUser: true }],
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('должен возвращать пустой массив при отсутствии совпадений', () => {
|
||||
const idArray = ['id4', 'id5'];
|
||||
const elementsArray = [
|
||||
{
|
||||
id: 'id1',
|
||||
userActions: [],
|
||||
},
|
||||
{
|
||||
id: 'id2',
|
||||
userActions: [],
|
||||
},
|
||||
];
|
||||
|
||||
const filteredElements = filterElementsById(idArray, elementsArray);
|
||||
|
||||
expect(filteredElements).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it('должен возвращать пустой массив при отсутствии элементов с type "DELETE"', () => {
|
||||
const idArray = ['id1', 'id2'];
|
||||
const elementsArray = [
|
||||
{
|
||||
id: 'id1',
|
||||
userActions: [],
|
||||
},
|
||||
{
|
||||
id: 'id2',
|
||||
userActions: [{ type: 'UPDATE', allowed: true, allowedForUser: true }],
|
||||
},
|
||||
];
|
||||
|
||||
const filteredElements = filterElementsById(idArray, elementsArray);
|
||||
|
||||
expect(filteredElements).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it('должен возвращать пустой массив при deleteAction.allowed: false', () => {
|
||||
const idArray = ['id1', 'id2'];
|
||||
const elementsArray = [
|
||||
{
|
||||
id: 'id1',
|
||||
userActions: [{ type: 'DELETE', allowed: false, allowedForUser: true }],
|
||||
},
|
||||
{
|
||||
id: 'id2',
|
||||
userActions: [{ type: 'DELETE', allowed: true, allowedForUser: true }],
|
||||
},
|
||||
];
|
||||
|
||||
const filteredElements = filterElementsById(idArray, elementsArray);
|
||||
|
||||
expect(filteredElements).toStrictEqual([
|
||||
{
|
||||
id: 'id2',
|
||||
userActions: [{ type: 'DELETE', allowed: true, allowedForUser: true }],
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('должен возвращать пустой массив при deleteAction.allowedForUser: false', () => {
|
||||
const idArray = ['id1', 'id2'];
|
||||
const elementsArray = [
|
||||
{
|
||||
id: 'id1',
|
||||
userActions: [{ type: 'DELETE', allowed: true, allowedForUser: false }],
|
||||
},
|
||||
{
|
||||
id: 'id2',
|
||||
userActions: [{ type: 'DELETE', allowed: true, allowedForUser: true }],
|
||||
},
|
||||
];
|
||||
|
||||
const filteredElements = filterElementsById(idArray, elementsArray);
|
||||
|
||||
expect(filteredElements).toStrictEqual([
|
||||
{
|
||||
id: 'id2',
|
||||
userActions: [{ type: 'DELETE', allowed: true, allowedForUser: true }],
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Функция renderHoverText', () => {
|
||||
const tradingIntervals: Record<string, ITradingInterval[]> = {
|
||||
buy: [
|
||||
{ timeFrom: '18:00:00', timeTo: '20:00:00' },
|
||||
{ timeFrom: '09:00:00', timeTo: '12:00:00' },
|
||||
{ timeFrom: '14:00:00', timeTo: '18:00:00' },
|
||||
],
|
||||
sell: [{ timeFrom: '10:00:00', timeTo: '13:00:00' }],
|
||||
};
|
||||
|
||||
const tradingIntervalsThree: Record<string, ITradingInterval[]> = {
|
||||
buy: [
|
||||
{ timeFrom: '15:00:00', timeTo: '16:00:00' },
|
||||
{ timeFrom: '02:00:00', timeTo: '13:50:00' },
|
||||
{ timeFrom: '18:00:00', timeTo: '23:00:00' },
|
||||
],
|
||||
sell: [{ timeFrom: '02:00:00', timeTo: '23:50:00' }],
|
||||
};
|
||||
|
||||
const tradingIntervalsFour: Record<string, ITradingInterval[]> = {
|
||||
buy: [{ timeFrom: '02:00:00', timeTo: '13:50:00' }],
|
||||
sell: [{ timeFrom: '02:00:00', timeTo: '13:50:00' }],
|
||||
};
|
||||
|
||||
it('должен отображать правильный текст, когда доступны оба направления', () => {
|
||||
render(renderHoverText(tradingIntervals, false));
|
||||
expect(screen.getByText('Доступно')).toBeInTheDocument();
|
||||
expect(screen.getByText('Покупка с 09:00 до 12:00')).toBeInTheDocument();
|
||||
expect(screen.getByText('Покупка с 14:00 до 18:00')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('вывод нескольких доступных интервалов', () => {
|
||||
render(renderHoverText(tradingIntervalsThree, false));
|
||||
expect(screen.getByText('Покупка с 02:00 до 13:50')).toBeInTheDocument();
|
||||
expect(screen.getByText('Покупка с 15:00 до 16:00')).toBeInTheDocument();
|
||||
expect(screen.getByText('Покупка с 18:00 до 23:00')).toBeInTheDocument();
|
||||
expect(screen.getByText('Продажа с 02:00 до 23:50')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('вывод одинаковых интервалов', () => {
|
||||
render(renderHoverText(tradingIntervalsFour, false));
|
||||
expect(screen.getByText('Покупка и Продажа с 02:00 до 13:50')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,72 @@
|
||||
/* eslint-disable jest/prefer-strict-equal */
|
||||
import * as user from '@treasury-deals/common/constants/user';
|
||||
import { selectRow, getTableColumns, getShowedColumnsIds, getTableSettingsColumns } from '../table';
|
||||
import { ROW_1, ROW_2, TABLE_COLUMNS } from '../test-constants';
|
||||
|
||||
// https://mikeborozdin.com/post/changing-jest-mocks-between-tests/
|
||||
jest.mock('common/constants/user', () => ({
|
||||
__esModule: true,
|
||||
isAdmin: true,
|
||||
}));
|
||||
|
||||
const mockConfig = user as { isAdmin: boolean };
|
||||
|
||||
describe('table utils', () => {
|
||||
test('selectRow', () => {
|
||||
expect(selectRow([], ROW_1)).toContain(ROW_1);
|
||||
expect(selectRow([ROW_1, ROW_2], ROW_1)).toEqual([ROW_2]);
|
||||
expect(selectRow([], [ROW_1, ROW_2])).toEqual([ROW_1, ROW_2]);
|
||||
expect(selectRow([ROW_1, ROW_2], [])).toEqual([]);
|
||||
expect(selectRow([], [])).toEqual([]);
|
||||
});
|
||||
|
||||
test('getTableColumns', () => {
|
||||
const { showedColumns, tableColumnsArr, columnSizes } = TABLE_COLUMNS;
|
||||
|
||||
expect(getTableColumns(showedColumns.slice(0, 2), columnSizes, tableColumnsArr)).toEqual([
|
||||
{
|
||||
...tableColumnsArr[0],
|
||||
width: columnSizes.accountNameExtended,
|
||||
},
|
||||
{
|
||||
...tableColumnsArr[2],
|
||||
width: columnSizes.currency,
|
||||
},
|
||||
]);
|
||||
expect(getTableColumns(showedColumns.slice(0, 1), columnSizes, tableColumnsArr)).toEqual([
|
||||
{
|
||||
...tableColumnsArr[0],
|
||||
width: columnSizes.accountNameExtended,
|
||||
},
|
||||
]);
|
||||
expect(getTableColumns(showedColumns, columnSizes, tableColumnsArr)).toEqual([
|
||||
{
|
||||
...tableColumnsArr[0],
|
||||
width: columnSizes.accountNameExtended,
|
||||
},
|
||||
{
|
||||
...tableColumnsArr[2],
|
||||
width: columnSizes.currency,
|
||||
},
|
||||
{
|
||||
...tableColumnsArr[1],
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test('getShowedColumnsIds', () => {
|
||||
const { tableSettings, showedColumns } = TABLE_COLUMNS;
|
||||
|
||||
expect(getShowedColumnsIds(tableSettings)).toEqual(showedColumns);
|
||||
});
|
||||
|
||||
test('getTableSettingsColumns', () => {
|
||||
const { tableSettings, adminTableSettings } = TABLE_COLUMNS;
|
||||
|
||||
expect(getTableSettingsColumns(tableSettings, adminTableSettings)).toEqual([...adminTableSettings, ...tableSettings]);
|
||||
|
||||
mockConfig.isAdmin = false;
|
||||
|
||||
expect(getTableSettingsColumns(tableSettings, adminTableSettings)).toEqual(tableSettings);
|
||||
});
|
||||
});
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
import type { ModalProps } from '@fractal-ui/overlays';
|
||||
import { CryptoInstallerModal, ERROR } from '@msb/platform-compat/services/client';
|
||||
import { appendToPortal, deleteFromPortal } from '@msb/platform-compat/ui';
|
||||
import { appendToPortal, deleteFromPortal } from '@treasury-deals/common/components/portal-container';
|
||||
import { serverErrorMessage, signErrorMessage } from '@treasury-deals/common/constants/error-messages';
|
||||
import type { Func } from '@treasury-deals/common/interfaces/common';
|
||||
import { formatServerError, getSignError } from '@treasury-deals/common/utils/form';
|
||||
|
||||
@@ -2910,20 +2910,28 @@
|
||||
"common.successPage.layout.header": {
|
||||
"ru": "Подтверждение отправлено"
|
||||
},
|
||||
"common.dealType.createDeal": {
|
||||
"common.createDeal": {
|
||||
"ru": "Заключить сделку"
|
||||
},
|
||||
"common.dealType.deposit": {
|
||||
"ru": "Заявка на депозит"
|
||||
"common.dealType.text": {
|
||||
"@dealType": "string",
|
||||
"ru": {
|
||||
"dealType === 'DEPOSIT'": "Заявка на депозит",
|
||||
"dealType === 'MNO'": "Заявка на МНО",
|
||||
"dealType === 'GSNO'": "Заявка на ГСНО",
|
||||
"dealType === 'FX'": "Заявка на конверсию",
|
||||
"true": ""
|
||||
}
|
||||
},
|
||||
"common.dealType.mno": {
|
||||
"ru": "Заявка на МНО"
|
||||
},
|
||||
"common.dealType.gsno": {
|
||||
"ru": "Заявка на ГСНО"
|
||||
},
|
||||
"common.dealType.conversion": {
|
||||
"ru": "Заявка на конверсию"
|
||||
"common.dealType.description": {
|
||||
"@dealType": "string",
|
||||
"ru": {
|
||||
"dealType === 'DEPOSIT'": "",
|
||||
"dealType === 'MNO'": "Неснижаемый остаток по счёту",
|
||||
"dealType === 'GSNO'": "Неснижаемый остаток группы счетов",
|
||||
"dealType === 'FX'": "",
|
||||
"true": ""
|
||||
}
|
||||
},
|
||||
"common.rateTimer.caption.end": {
|
||||
"ru": "Срок действия предложенной ставки истек. Пожалуйста, нажмите на кнопку «Запросить ставку», либо поменяйте параметры сделки, чтобы получить новое предложение."
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
-1
@@ -238,7 +238,6 @@ export const StyledRequestBody = styled.div`
|
||||
`;
|
||||
|
||||
export const StyledCounterText = styled.div`
|
||||
|
||||
@media (width <= 744px) {
|
||||
margin-top: 16px;
|
||||
margin-bottom: 16px;
|
||||
|
||||
+37
-21
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
import { Spinner } from '@fractal-ui/core';
|
||||
import { Fields } from '@fractal-ui/form';
|
||||
import { Wrapper, Text } from '@fractal-ui/styling';
|
||||
@@ -6,20 +6,35 @@ import { getInternalAccountsAppend } from '@treasury-deals/common/sources/accoun
|
||||
import { formatAccountNumber } from '@treasury-deals/common/utils/accounts';
|
||||
import { isEmpty } from '@treasury-deals/common/utils/check-types';
|
||||
import { locale } from '@treasury-deals/localization';
|
||||
import { useAccountsContext } from '@treasury-deals/pages/accounts/create-account/context';
|
||||
import { COMMON_FIELDS } from '@treasury-deals/pages/accounts/create-account/enums';
|
||||
import { useAllInternal } from '@treasury-deals/pages/accounts/create-account/hooks/use-all-internal-form';
|
||||
import { useSelectOrganization } from '@treasury-deals/pages/accounts/create-account/hooks/use-select-organization';
|
||||
import { formatAccountInitialValues } from '@treasury-deals/pages/accounts/create-account/utils/form';
|
||||
import { gap } from '@treasury-deals/pages/dashboard/constants/styles';
|
||||
import { Access } from '@treasury-deals/pages/reports-and-subscription/reports/components/access';
|
||||
import { useForm, useFormState } from 'react-final-form';
|
||||
import { SelectOrganization } from '../inputs/select-organization';
|
||||
import { DrawerContainer } from '../styled';
|
||||
|
||||
export const ChooseAccount: React.FC = () => {
|
||||
const { accounts, isLoading, onSelectAll, checkScroll, containerRef, unselectAllSelected, isFetchingNextPage } =
|
||||
useAllInternal(getInternalAccountsAppend);
|
||||
const { reset } = useForm();
|
||||
const {
|
||||
values: { organization },
|
||||
} = useFormState({ subscription: { values: true } });
|
||||
const { userInfo, formType } = useAccountsContext();
|
||||
const { handleChange, options, organizations } = useSelectOrganization(null, false);
|
||||
const handleReset = useCallback(() => {
|
||||
const init = formatAccountInitialValues(formType);
|
||||
|
||||
reset(init);
|
||||
}, [formType, reset]);
|
||||
|
||||
return (
|
||||
<DrawerContainer ref={containerRef} rowGap={gap.m} onScroll={checkScroll}>
|
||||
<Access action={handleReset} id={organization} privilege="accountsPrivilegeLevel" searchField="clientId" userInfo={userInfo} />
|
||||
<SelectOrganization
|
||||
handleChange={handleChange}
|
||||
isEdit={false}
|
||||
@@ -29,26 +44,27 @@ export const ChooseAccount: React.FC = () => {
|
||||
organizations={organizations}
|
||||
/>
|
||||
{isLoading && <Spinner dataName="accountsLoading" size="L" />}
|
||||
{Array.isArray(accounts) && isEmpty(accounts) ? (
|
||||
<Text.P2>{locale.account.form.create.text.noAccounts}</Text.P2>
|
||||
) : (
|
||||
<Wrapper display="grid" gridRowGap={gap.m}>
|
||||
{accounts && accounts.length > 0 && (
|
||||
<Wrapper borderBottomColor="bg.tertiary" borderBottomStyle="solid" borderBottomWidth="1px" pb={gap.s}>
|
||||
<Fields.Checkbox label={locale.account.fields.checkbox.add} name="allSelected" onChange={onSelectAll} />
|
||||
</Wrapper>
|
||||
)}
|
||||
{accounts?.map(account => (
|
||||
<Fields.Checkbox
|
||||
key={`accounts.account-${account.accountNumber}`}
|
||||
label={formatAccountNumber(account.accountNumber)}
|
||||
name={`accounts.account-${account.accountNumber}`}
|
||||
onChange={unselectAllSelected}
|
||||
/>
|
||||
))}
|
||||
{isFetchingNextPage && <Spinner dataName="nexPageLoading" />}
|
||||
</Wrapper>
|
||||
)}
|
||||
{organization &&
|
||||
(Array.isArray(accounts) && isEmpty(accounts) ? (
|
||||
<Text.P2>{locale.account.form.create.text.noAccounts}</Text.P2>
|
||||
) : (
|
||||
<Wrapper display="grid" gridRowGap={gap.m}>
|
||||
{accounts && accounts.length > 0 && (
|
||||
<Wrapper borderBottomColor="bg.tertiary" borderBottomStyle="solid" borderBottomWidth="1px" pb={gap.s}>
|
||||
<Fields.Checkbox label={locale.account.fields.checkbox.add} name="allSelected" onChange={onSelectAll} />
|
||||
</Wrapper>
|
||||
)}
|
||||
{accounts?.map(account => (
|
||||
<Fields.Checkbox
|
||||
key={`accounts.account-${account.accountNumber}`}
|
||||
label={formatAccountNumber(account.accountNumber)}
|
||||
name={`accounts.account-${account.accountNumber}`}
|
||||
onChange={unselectAllSelected}
|
||||
/>
|
||||
))}
|
||||
{isFetchingNextPage && <Spinner dataName="nexPageLoading" />}
|
||||
</Wrapper>
|
||||
))}
|
||||
</DrawerContainer>
|
||||
);
|
||||
};
|
||||
|
||||
+10
-9
@@ -113,14 +113,15 @@ export const Scroller: React.FC<IScroller> = ({
|
||||
const filtersWithoutClientId = Object.fromEntries(Object.entries(filters).filter(([key]) => key !== 'clientId'));
|
||||
|
||||
return (
|
||||
<MultiArmAccessMatrix
|
||||
generalAgreement={access.hasGeneralAgreement}
|
||||
hasDeals={tableData.length > 0}
|
||||
systemAgreement={access.hasSystemAgreement}
|
||||
>
|
||||
{isEmpty(filterObjectByNonEmptyArrays(filtersWithoutClientId)) && tableData.length === 0 && !table.isLoading ? (
|
||||
<>
|
||||
{isEmpty(filterObjectByNonEmptyArrays(filtersWithoutClientId)) && tableData.length === 0 && !table.isLoading && (
|
||||
<EmptyAccountsPlaceholder isMobile={breakpoints.XS} onOpenForm={onOpenForm} />
|
||||
) : (
|
||||
)}
|
||||
<MultiArmAccessMatrix
|
||||
generalAgreement={access.hasGeneralAgreement}
|
||||
hasDeals={tableData.length > 0}
|
||||
systemAgreement={access.hasSystemAgreement}
|
||||
>
|
||||
<TableWrapper flexGrow="1">
|
||||
{breakpoints.XS ? (
|
||||
<CardScroller
|
||||
@@ -175,7 +176,7 @@ export const Scroller: React.FC<IScroller> = ({
|
||||
onSubmit={handlerOnSubmit}
|
||||
/>
|
||||
</TableWrapper>
|
||||
)}
|
||||
</MultiArmAccessMatrix>
|
||||
</MultiArmAccessMatrix>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -53,3 +53,5 @@ export const STATUS_BADGE_TYPE: Record<string, BadgeType> = {
|
||||
ENDED: 'system',
|
||||
BLOCKED: 'system',
|
||||
};
|
||||
|
||||
export const PAGE_CONTENT_ID = '#page-content';
|
||||
|
||||
@@ -5,16 +5,17 @@ import { SERVICE_NAME } from '@treasury-deals/common/constants';
|
||||
import type { Step } from '@treasury-deals/common/interfaces/wizard';
|
||||
import { POSITION } from '@treasury-deals/common/interfaces/wizard';
|
||||
import { locale } from '@treasury-deals/localization';
|
||||
import { PAGE_CONTENT_ID } from './table';
|
||||
|
||||
export const WIZARD_RULE_DEFAULT: Step[] = [
|
||||
{
|
||||
selector: '#page-content',
|
||||
selector: PAGE_CONTENT_ID,
|
||||
position: POSITION.CENTER,
|
||||
description: locale.wizard.agreement.page({ service: SERVICE_NAME }),
|
||||
icon: <WdIcons.Agreements scale={'X2L'} />,
|
||||
},
|
||||
{
|
||||
selector: '[data-role="header"]',
|
||||
selector: PAGE_CONTENT_ID,
|
||||
position: POSITION.BOTTOM_CENTER,
|
||||
description: locale.wizard.agreement.default,
|
||||
icon: <img height="160" src={Images.AgreementDefault} width="400" />,
|
||||
@@ -34,7 +35,7 @@ export const WIZARD_RULE_DEFAULT: Step[] = [
|
||||
export const WIZARD_RULE_EXTENDED: Step[] = [
|
||||
...WIZARD_RULE_DEFAULT.slice(0, 2),
|
||||
{
|
||||
selector: '#page-content',
|
||||
selector: PAGE_CONTENT_ID,
|
||||
position: POSITION.CENTER,
|
||||
description: locale.wizard.agreement.gsno,
|
||||
width: 1010,
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ const Header: React.FC = () => {
|
||||
|
||||
return (
|
||||
<HeaderContainer px={{ XS: 'calendar.mobileHeaderPx', S: '0' }} onClick={handleContainerClick}>
|
||||
<Wrapper display="flex" height="32px" pb="12px" pt="16px">
|
||||
<Wrapper display="flex" pb="12px" pt="16px">
|
||||
<StyledHeaderButton
|
||||
data-action="monthselect"
|
||||
data-name="calendar-header-month-button"
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ export const ReportsBannerTab: React.FC = () => {
|
||||
<BannerTab onClick={toReports}>
|
||||
<Wrapper display="flex" flexDirection="column" justifyContent="space-evenly" pb={2} pt={2}>
|
||||
<Title.H5>Выписки по депозитным счетам</Title.H5>
|
||||
<Button dataAction="to-reports" height="24px" shape="default" size="XS" width="125px" onClick={toReports}>
|
||||
<Button dataAction="to-reports" height="24px" shape="default" size="XS" width="130px" onClick={toReports}>
|
||||
Получить выписку
|
||||
</Button>
|
||||
</Wrapper>
|
||||
|
||||
+2
-1
@@ -8,6 +8,7 @@ import { Overlay } from '@msb/shared/ui/loader';
|
||||
import { MultiArmAccessMatrix, Wizard } from '@treasury-deals/common/components/controls';
|
||||
import { TableFilter } from '@treasury-deals/common/components/table/table-filter-fractal';
|
||||
import { isAdmin } from '@treasury-deals/common/constants';
|
||||
import { isMsb } from '@treasury-deals/common/utils/is-msb';
|
||||
import { locale } from '@treasury-deals/localization';
|
||||
import { AutoQuotationV2 } from '@treasury-deals/modules/autoquotation-v2';
|
||||
import { RequestsBlock } from '@treasury-deals/modules/autoquotation-v2/components/requests-block';
|
||||
@@ -93,7 +94,7 @@ export const TableView = ({
|
||||
}) => (
|
||||
<GroupedRefetchProvider isEnabled={filteredOrganizations.length > 1} isGrouped={isGrouped}>
|
||||
<Wrapper data-id="tables-data" display="flex" flexDirection="column" height="100%">
|
||||
{!isAdmin && hasAutoQuotationAccess && (
|
||||
{!isMsb() && !isAdmin && hasAutoQuotationAccess && (
|
||||
<>
|
||||
{fakeAutoquoteWizard && <AutoQuotationWizard newbieSettings={newbieSettings} refreshNewbie={refreshNewbie} />}
|
||||
{!fakeAutoquoteWizard && (
|
||||
|
||||
+7
@@ -1,15 +1,19 @@
|
||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
import React, { useMemo } from 'react';
|
||||
import { ProgressDots } from '@fractal-ui/core';
|
||||
import { Informer } from '@fractal-ui/extended';
|
||||
import { Wrapper, useBreakpoints } from '@fractal-ui/styling';
|
||||
import { SpinnerWrapped } from '@treasury-deals/common/components/controls';
|
||||
import { STATISTIC_TYPE } from '@treasury-deals/common/enums/statistics';
|
||||
import { useFeatureToggles } from '@treasury-deals/common/hooks';
|
||||
import { StatisticService } from '@treasury-deals/common/services';
|
||||
import { returnDocTypeBinder } from '@treasury-deals/common/utils/table';
|
||||
import { locale } from '@treasury-deals/localization';
|
||||
import { gap } from '@treasury-deals/pages/dashboard/constants/styles';
|
||||
import { DEAL_EDIT_FIELDS } from '@treasury-deals/pages/deals/drawer-forms-old/constants/constants';
|
||||
import { checkIsGeneralAgreementDU, checkIsSingleOption } from '@treasury-deals/pages/deals/drawer-forms-old/helpers';
|
||||
import type { BestRate, CustomOption } from '@treasury-deals/pages/deals/drawer-forms-old/interfaces';
|
||||
import { useForm } from 'react-final-form';
|
||||
import { useDealForm } from '../../hooks/use-form';
|
||||
import { ActionBar } from '../action-bars/deals-action-bar';
|
||||
import { CustomSelect, SelectField } from '../common-inputs';
|
||||
@@ -24,6 +28,7 @@ import { dealProgressBarWidth, dealProgressBarWidthXSRequest, FormContainer, Ani
|
||||
|
||||
export const Fields = ({ type, values, submitError, modified }) => {
|
||||
const toggles = useFeatureToggles();
|
||||
const { getState } = useForm();
|
||||
const {
|
||||
generalAgreements,
|
||||
isGeneralAgreementDU,
|
||||
@@ -53,6 +58,8 @@ export const Fields = ({ type, values, submitError, modified }) => {
|
||||
|
||||
const handleApplyRate = async (rate: BestRate) => {
|
||||
await actions.applyBestRate(rate);
|
||||
|
||||
StatisticService.logRequest(STATISTIC_TYPE.DEAL_BEST_RATE_INIT, location.href, getState().values, {});
|
||||
};
|
||||
|
||||
const { clientWebDealingId, generalAgreement, dealRate, managementFund } = values;
|
||||
|
||||
+5
-1
@@ -46,7 +46,7 @@ export const cryptoSignController =
|
||||
const { signKind, certificateId } = certificate;
|
||||
|
||||
const { checkTimer, cloudExec, cloudResult, cloudResultError, timeout, cryptoServiceSignExec, signAndSendExec } = signParams;
|
||||
const { dealsNotification, isConfirmation, onClose, dispatch, setSaved, goBack, url, source } = sendParams;
|
||||
const { dealsNotification, isConfirmation, onClose, dispatch, setSaved, goBack, url, source, deal, isApplyBestRate } = sendParams;
|
||||
|
||||
const signature =
|
||||
signKind === SIGN_KIND.CLOUD_SIGN
|
||||
@@ -94,6 +94,10 @@ export const cryptoSignController =
|
||||
signResult
|
||||
);
|
||||
|
||||
if (isApplyBestRate) {
|
||||
StatisticService.logRequest(STATISTIC_TYPE.DEAL_BEST_RATE_SIGN, location.href, { ...deal }, {});
|
||||
}
|
||||
|
||||
if (!isConfirmation) onClose(false);
|
||||
} catch (err) {
|
||||
const { message, code } = formatError(err);
|
||||
|
||||
+46
-27
@@ -30,8 +30,20 @@ import { useDealStore } from '../store';
|
||||
import { updateBestRatesSelector } from '../store/selectors';
|
||||
|
||||
export const useFormActions = (requestType: string, clientId: string, isConfirmed: boolean, isTimeEnd: boolean): IUseFormActionsReturn => {
|
||||
const { dispatch, setOnSubmit, onClose, type, checkMatrixClientById, mode, dealsNotification, dirtyForm, deal, setSaved, goBack } =
|
||||
useDealContext();
|
||||
const {
|
||||
dispatch,
|
||||
setOnSubmit,
|
||||
onClose,
|
||||
type,
|
||||
checkMatrixClientById,
|
||||
mode,
|
||||
dealsNotification,
|
||||
dirtyForm,
|
||||
deal,
|
||||
setSaved,
|
||||
goBack,
|
||||
setBestRateApply,
|
||||
} = useDealContext();
|
||||
const { url, source, tab } = useGetPath();
|
||||
const { getState, change, submit } = useForm();
|
||||
const { values, submitError } = getState();
|
||||
@@ -55,30 +67,35 @@ export const useFormActions = (requestType: string, clientId: string, isConfirme
|
||||
setTimeout(submit, time);
|
||||
}, 200);
|
||||
|
||||
const handleRateRequest = useCallback(() => {
|
||||
updateBestRates(undefined);
|
||||
setOnSubmit({
|
||||
type: 'initialize',
|
||||
submitFunc: async formData => {
|
||||
const res = await rateExec(formData);
|
||||
const handleRateRequest = useCallback(
|
||||
() =>
|
||||
new Promise<void>(resolve => {
|
||||
updateBestRates(undefined);
|
||||
setOnSubmit({
|
||||
type: 'initialize',
|
||||
submitFunc: async formData => {
|
||||
const res = await rateExec(formData);
|
||||
|
||||
if (res?.dealRate) {
|
||||
change(DEAL_EDIT_FIELDS.DEAL_RATE, res.dealRate);
|
||||
}
|
||||
if (res?.dealRate) {
|
||||
change(DEAL_EDIT_FIELDS.DEAL_RATE, res.dealRate);
|
||||
}
|
||||
|
||||
return res;
|
||||
},
|
||||
submitType: 'rateRequest',
|
||||
});
|
||||
return res;
|
||||
},
|
||||
submitType: 'rateRequest',
|
||||
});
|
||||
|
||||
setTimeout(
|
||||
() =>
|
||||
submit()?.then(() => {
|
||||
afterRateRequest(dispatch);
|
||||
}),
|
||||
0
|
||||
);
|
||||
}, [dispatch, rateExec, setOnSubmit, submit, getBestRatesExec, type]);
|
||||
setTimeout(
|
||||
() =>
|
||||
submit()?.then(() => {
|
||||
afterRateRequest(dispatch);
|
||||
resolve();
|
||||
}),
|
||||
0
|
||||
);
|
||||
}),
|
||||
[dispatch, rateExec, setOnSubmit, submit, getBestRatesExec, type]
|
||||
);
|
||||
|
||||
const rateRequest = useDebouncedCallback(() => {
|
||||
const { values: formValues } = getState();
|
||||
@@ -91,7 +108,7 @@ export const useFormActions = (requestType: string, clientId: string, isConfirme
|
||||
return;
|
||||
}
|
||||
|
||||
handleRateRequest();
|
||||
void handleRateRequest();
|
||||
}, 700);
|
||||
|
||||
const sign = useCallback(async () => {
|
||||
@@ -164,7 +181,7 @@ export const useFormActions = (requestType: string, clientId: string, isConfirme
|
||||
okButtonText: locale.agreement.modal.check.error.decline,
|
||||
preventSimpleClose: true,
|
||||
cancelCallback: () => {
|
||||
if (isAllowedRequest && !hasDealRate) handleRateRequest();
|
||||
if (isAllowedRequest && !hasDealRate) void handleRateRequest();
|
||||
},
|
||||
okCallback: () => {
|
||||
onClose();
|
||||
@@ -238,7 +255,7 @@ export const useFormActions = (requestType: string, clientId: string, isConfirme
|
||||
handleValidateForm();
|
||||
};
|
||||
|
||||
const applyBestRate = (best: BestRate) => {
|
||||
const applyBestRate = async (best: BestRate) => {
|
||||
if (!best) return;
|
||||
|
||||
const amount = best.amount?.replace(/\s/g, '') ?? '';
|
||||
@@ -257,7 +274,9 @@ export const useFormActions = (requestType: string, clientId: string, isConfirme
|
||||
|
||||
change(DEAL_EDIT_FIELDS.DEAL_RATE, undefined);
|
||||
|
||||
handleRateRequest();
|
||||
setBestRateApply(best.rate);
|
||||
|
||||
await handleRateRequest();
|
||||
};
|
||||
|
||||
const redirectToAccounts = useCallback(() => {
|
||||
|
||||
+3
-2
@@ -22,10 +22,11 @@ interface DstForSign extends IDstForSign {
|
||||
}
|
||||
|
||||
export const useSign = () => {
|
||||
const { dealsNotification, onClose, deal, type, clientId, dispatch, isConfirmation, setSaved, goBack } = useDealContext();
|
||||
const { dealsNotification, onClose, deal, type, clientId, dispatch, isConfirmation, setSaved, goBack, bestRateApply } = useDealContext();
|
||||
const { url, source } = useGetPath();
|
||||
const isFx = type === DEPOSITS_OPERATION_TYPES_ENUM.CONVERSION;
|
||||
const hasVisa = 'visaType' in deal;
|
||||
const isApplyBestRate = 'dealRate' in deal && deal?.dealRate?.value === bestRateApply;
|
||||
const requestType = type.toLowerCase();
|
||||
const crypto = getCloudCrypto();
|
||||
const [, cloudResult, cloudResultError] = useExecute(crypto.getSignResult);
|
||||
@@ -91,7 +92,7 @@ export const useSign = () => {
|
||||
|
||||
const cryptoSign = cryptoSignController(
|
||||
{ checkTimer, cloudExec, cloudResult, cloudResultError, timeout, cryptoServiceSignExec, signAndSendExec },
|
||||
{ dealsNotification, isConfirmation, onClose, dispatch, setSaved, goBack, url, source }
|
||||
{ dealsNotification, isConfirmation, onClose, dispatch, setSaved, goBack, url, source, deal, isApplyBestRate }
|
||||
);
|
||||
|
||||
const handleCertAndSign = certAndSignController({
|
||||
|
||||
@@ -79,6 +79,7 @@ export const DrawerFormsOld: React.FC<IDrawerForm> = ({ clientIds, refresh }) =>
|
||||
} = useDeal(dealType, dealId, dealMode, source, clientIds as string[]);
|
||||
const [onSubmit, setOnSubmit] = useState<SubmitFuncStorage>({ submitFunc: noop, type: 'initialize' });
|
||||
const resetStore = useDealStore(state => state.reset);
|
||||
const [bestRateApply, setBestRateApply] = useState<string>();
|
||||
|
||||
const { userInfo } = useUserInfo({});
|
||||
|
||||
@@ -157,6 +158,8 @@ export const DrawerFormsOld: React.FC<IDrawerForm> = ({ clientIds, refresh }) =>
|
||||
canCloseWithoutWarning,
|
||||
goBack,
|
||||
searchParams,
|
||||
bestRateApply,
|
||||
setBestRateApply,
|
||||
}),
|
||||
[
|
||||
deal,
|
||||
@@ -188,6 +191,8 @@ export const DrawerFormsOld: React.FC<IDrawerForm> = ({ clientIds, refresh }) =>
|
||||
canCloseWithoutWarning,
|
||||
goBack,
|
||||
searchParams,
|
||||
bestRateApply,
|
||||
setBestRateApply,
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
+4
@@ -126,6 +126,10 @@ export interface DealPageContext {
|
||||
* Параметры url, подмешиваются в сделку.
|
||||
*/
|
||||
searchParams: Record<string, string> | null | undefined;
|
||||
/** Лучшая ставка. */
|
||||
bestRateApply?: string;
|
||||
/** Изменить лучшую ставку. */
|
||||
setBestRateApply: Dispatch<SetStateAction<string | undefined>>;
|
||||
}
|
||||
|
||||
export interface SubmitFuncStorage {
|
||||
|
||||
+2
@@ -32,6 +32,8 @@ export interface SendParams {
|
||||
goBack(): void;
|
||||
dispatch: Dispatch<DispatchAction>;
|
||||
setSaved: Dispatch<SetStateAction<boolean>>;
|
||||
deal: DealDto | IFxDealsDto;
|
||||
isApplyBestRate: boolean;
|
||||
}
|
||||
|
||||
export interface CertAndSign {
|
||||
|
||||
+7
@@ -1,8 +1,11 @@
|
||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
import React from 'react';
|
||||
import { Informer } from '@fractal-ui/extended';
|
||||
import { SearchIcon } from '@fractal-ui/library';
|
||||
import { Wrapper, useBreakpoints } from '@fractal-ui/styling';
|
||||
import { STATISTIC_TYPE } from '@treasury-deals/common/enums/statistics';
|
||||
import { useFeatureToggles } from '@treasury-deals/common/hooks';
|
||||
import { StatisticService } from '@treasury-deals/common/services';
|
||||
import { LABEL_POSITION } from '@treasury-deals/fractal/interfaces';
|
||||
import ModalService from '@treasury-deals/fractal/services/modal-service';
|
||||
import { locale } from '@treasury-deals/localization';
|
||||
@@ -11,6 +14,7 @@ import { DEAL_EDIT_FIELDS, formSubmitErrors } from '@treasury-deals/pages/deals/
|
||||
import { checkIsSingleOption } from '@treasury-deals/pages/deals/drawer-forms/helpers';
|
||||
import type { BestRate } from '@treasury-deals/pages/deals/drawer-forms/interfaces';
|
||||
import { useTimerStore } from '@treasury-deals/pages/deals/drawer-forms/store/timer';
|
||||
import { useForm } from 'react-final-form';
|
||||
import { pickHighestRate } from '../../helpers/drawer';
|
||||
import { useDealForm } from '../../hooks/use-form';
|
||||
import { useDealStore } from '../../store';
|
||||
@@ -32,6 +36,7 @@ import { dealProgressBarWidth, AnimatedContainer, FormGridContainer } from './st
|
||||
|
||||
export const FormFields = ({ type, values, submitError, modified, userInfoLoading }) => {
|
||||
const toggles = useFeatureToggles();
|
||||
const { getState } = useForm();
|
||||
const {
|
||||
generalAgreements,
|
||||
isGeneralAgreementDU,
|
||||
@@ -80,6 +85,8 @@ export const FormFields = ({ type, values, submitError, modified, userInfoLoadin
|
||||
const handleApplyRate = async (rate: BestRate) => {
|
||||
await actions.applyBestRate(rate);
|
||||
|
||||
StatisticService.logRequest(STATISTIC_TYPE.DEAL_BEST_RATE_INIT, location.href, getState().values, {});
|
||||
|
||||
updateBestRates(undefined);
|
||||
};
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ export const cryptoSignController =
|
||||
const { signKind, certificateId } = certificate;
|
||||
|
||||
const { checkTimer, cloudExec, cloudResult, cloudResultError, timeout, cryptoServiceSignExec, signAndSendExec } = signParams;
|
||||
const { dealsNotification, isConfirmation, onClose, dispatch, setSaved, goBack, url, source } = sendParams;
|
||||
const { dealsNotification, isConfirmation, onClose, dispatch, setSaved, goBack, url, source, deal, isApplyBestRate } = sendParams;
|
||||
|
||||
const signature =
|
||||
signKind === SIGN_KIND.CLOUD_SIGN
|
||||
@@ -94,6 +94,10 @@ export const cryptoSignController =
|
||||
signResult
|
||||
);
|
||||
|
||||
if (isApplyBestRate) {
|
||||
StatisticService.logRequest(STATISTIC_TYPE.DEAL_BEST_RATE_SIGN, location.href, { ...deal }, {});
|
||||
}
|
||||
|
||||
if (!isConfirmation) onClose(false);
|
||||
} catch (err) {
|
||||
const { message, code } = formatError(err);
|
||||
|
||||
+40
-22
@@ -30,8 +30,19 @@ import { useDealStore } from '../store';
|
||||
import { useTimerStore } from '../store/timer';
|
||||
|
||||
export const useFormActions = (requestType: string, clientId: string, isConfirmed: boolean): IUseFormActionsReturn => {
|
||||
const { dispatch, setOnSubmit, onClose, type, checkMatrixClientById, mode, dealsNotification, dirtyForm, setSaved, goBack } =
|
||||
useDealContext();
|
||||
const {
|
||||
dispatch,
|
||||
setOnSubmit,
|
||||
onClose,
|
||||
type,
|
||||
checkMatrixClientById,
|
||||
mode,
|
||||
dealsNotification,
|
||||
dirtyForm,
|
||||
setSaved,
|
||||
goBack,
|
||||
setBestRateApply,
|
||||
} = useDealContext();
|
||||
const { url, source, tab } = useGetPath();
|
||||
const { getState, change, submit } = useForm();
|
||||
const { values, submitError } = getState();
|
||||
@@ -56,23 +67,28 @@ export const useFormActions = (requestType: string, clientId: string, isConfirme
|
||||
setTimeout(submit, time);
|
||||
}, 200);
|
||||
|
||||
const handleRateRequest = useCallback(() => {
|
||||
updateBestRates(undefined);
|
||||
change(DEAL_EDIT_FIELDS.DEAL_RATE);
|
||||
setOnSubmit({
|
||||
type: 'initialize',
|
||||
submitFunc: rateExec,
|
||||
submitType: 'rateRequest',
|
||||
});
|
||||
const handleRateRequest = useCallback(
|
||||
() =>
|
||||
new Promise<void>(resolve => {
|
||||
updateBestRates(undefined);
|
||||
change(DEAL_EDIT_FIELDS.DEAL_RATE);
|
||||
setOnSubmit({
|
||||
type: 'initialize',
|
||||
submitFunc: rateExec,
|
||||
submitType: 'rateRequest',
|
||||
});
|
||||
|
||||
setTimeout(
|
||||
() =>
|
||||
submit()?.then(() => {
|
||||
afterRateRequest(dispatch);
|
||||
}),
|
||||
0
|
||||
);
|
||||
}, [updateBestRates, change, setOnSubmit, rateExec, submit, dispatch]);
|
||||
setTimeout(
|
||||
() =>
|
||||
submit()?.then(() => {
|
||||
afterRateRequest(dispatch);
|
||||
resolve();
|
||||
}),
|
||||
0
|
||||
);
|
||||
}),
|
||||
[updateBestRates, change, setOnSubmit, rateExec, submit, dispatch]
|
||||
);
|
||||
|
||||
const rateRequest = useDebouncedCallback(() => {
|
||||
const { values: formValues } = getState();
|
||||
@@ -87,7 +103,7 @@ export const useFormActions = (requestType: string, clientId: string, isConfirme
|
||||
return;
|
||||
}
|
||||
|
||||
handleRateRequest();
|
||||
void handleRateRequest();
|
||||
}, 700);
|
||||
|
||||
const sign = useCallback(async () => {
|
||||
@@ -160,7 +176,7 @@ export const useFormActions = (requestType: string, clientId: string, isConfirme
|
||||
okButtonText: locale.agreement.modal.check.error.decline,
|
||||
preventSimpleClose: true,
|
||||
cancelCallback: () => {
|
||||
if (isAllowedRequest && !hasDealRate) handleRateRequest();
|
||||
if (isAllowedRequest && !hasDealRate) void handleRateRequest();
|
||||
},
|
||||
okCallback: () => {
|
||||
onClose();
|
||||
@@ -232,7 +248,7 @@ export const useFormActions = (requestType: string, clientId: string, isConfirme
|
||||
handleValidateForm();
|
||||
};
|
||||
|
||||
const applyBestRate = (best: BestRate) => {
|
||||
const applyBestRate = async (best: BestRate) => {
|
||||
if (!best) return;
|
||||
|
||||
const amount = best.amount?.replace(/\s/g, '') ?? '';
|
||||
@@ -251,7 +267,9 @@ export const useFormActions = (requestType: string, clientId: string, isConfirme
|
||||
|
||||
change(DEAL_EDIT_FIELDS.DEAL_RATE, undefined);
|
||||
|
||||
handleRateRequest();
|
||||
setBestRateApply(best.rate);
|
||||
|
||||
await handleRateRequest();
|
||||
};
|
||||
|
||||
const redirectToAccounts = useCallback(() => {
|
||||
|
||||
@@ -22,10 +22,11 @@ interface DstForSign extends IDstForSign {
|
||||
}
|
||||
|
||||
export const useSign = () => {
|
||||
const { dealsNotification, onClose, deal, type, clientId, dispatch, isConfirmation, setSaved, goBack } = useDealContext();
|
||||
const { dealsNotification, onClose, deal, type, clientId, dispatch, isConfirmation, setSaved, goBack, bestRateApply } = useDealContext();
|
||||
const { url, source } = useGetPath();
|
||||
const isFx = type === DEPOSITS_OPERATION_TYPES_ENUM.CONVERSION;
|
||||
const hasVisa = 'visaType' in deal;
|
||||
const isApplyBestRate = 'dealRate' in deal && deal?.dealRate?.value === bestRateApply;
|
||||
const requestType = type.toLowerCase();
|
||||
const crypto = getCloudCrypto();
|
||||
const [, cloudResult, cloudResultError] = useExecute(crypto.getSignResult);
|
||||
@@ -90,7 +91,7 @@ export const useSign = () => {
|
||||
|
||||
const cryptoSign = cryptoSignController(
|
||||
{ checkTimer, cloudExec, cloudResult, cloudResultError, timeout, cryptoServiceSignExec, signAndSendExec },
|
||||
{ dealsNotification, isConfirmation, onClose, dispatch, setSaved, goBack, url, source }
|
||||
{ dealsNotification, isConfirmation, onClose, dispatch, setSaved, goBack, url, source, deal, isApplyBestRate }
|
||||
);
|
||||
|
||||
const handleCertAndSign = certAndSignController({
|
||||
|
||||
@@ -82,6 +82,7 @@ export const DrawerForms: React.FC<IDrawerForm> = ({ clientIds, refresh }) => {
|
||||
const [onSubmit, setOnSubmit] = useState<SubmitFuncStorage>({ submitFunc: noop, type: 'initialize' });
|
||||
const resetStore = useDealStore(state => state.reset);
|
||||
const clearAll = useTimerStore(state => state.clearAll);
|
||||
const [bestRateApply, setBestRateApply] = useState<string>();
|
||||
const { setupUserInfoState, reset } = useUserInfoStore(state => ({ setupUserInfoState: state.setupUserInfoState, reset: state.reset }));
|
||||
const { userInfoLoading, userInfo } = useUserInfo({
|
||||
onSuccess: setupUserInfoState,
|
||||
@@ -162,6 +163,8 @@ export const DrawerForms: React.FC<IDrawerForm> = ({ clientIds, refresh }) => {
|
||||
canCloseWithoutWarning,
|
||||
goBack,
|
||||
searchParams,
|
||||
bestRateApply,
|
||||
setBestRateApply,
|
||||
}),
|
||||
[
|
||||
deal,
|
||||
@@ -193,6 +196,8 @@ export const DrawerForms: React.FC<IDrawerForm> = ({ clientIds, refresh }) => {
|
||||
canCloseWithoutWarning,
|
||||
goBack,
|
||||
searchParams,
|
||||
bestRateApply,
|
||||
setBestRateApply,
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ export interface DealParameters {
|
||||
setMNO: boolean | string;
|
||||
signTimeEnded: boolean;
|
||||
expired: boolean;
|
||||
bestRateDeal: BestRate;
|
||||
}
|
||||
|
||||
export interface FractalSelectOnChange extends IFractalOnChangeFieldArgs {
|
||||
@@ -125,6 +126,10 @@ export interface DealPageContext {
|
||||
* Параметры url, подмешиваются в сделку.
|
||||
*/
|
||||
searchParams: Record<string, string> | null | undefined;
|
||||
/** Лучшая ставка. */
|
||||
bestRateApply?: string;
|
||||
/** Изменить лучшую ставку. */
|
||||
setBestRateApply: Dispatch<SetStateAction<string | undefined>>;
|
||||
}
|
||||
|
||||
export interface SubmitFuncStorage {
|
||||
|
||||
@@ -32,6 +32,8 @@ export interface SendParams {
|
||||
goBack(): void;
|
||||
dispatch: Dispatch<DispatchAction>;
|
||||
setSaved: Dispatch<SetStateAction<boolean>>;
|
||||
deal: DealDto | IFxDealsDto;
|
||||
isApplyBestRate: boolean;
|
||||
}
|
||||
|
||||
export interface CertAndSign {
|
||||
|
||||
@@ -233,7 +233,7 @@ export const DEPOSIT_TABLE_SETTINGS_COLUMNS = [
|
||||
{
|
||||
id: 'period',
|
||||
title: locale.table.column.period,
|
||||
show: !isMsb(),
|
||||
show: true,
|
||||
},
|
||||
{
|
||||
id: 'amount',
|
||||
@@ -351,7 +351,7 @@ export const DEPOSIT_DEFAULT_COLUMN_SETTINGS = [
|
||||
...((!isMsb() && [['dealDate']]) || []),
|
||||
['dateBegin'],
|
||||
...((!isMsb() && [['dateEnd']]) || []),
|
||||
...((!isMsb() && [['period']]) || []),
|
||||
['period'],
|
||||
['amount'],
|
||||
/* ['currency'], */
|
||||
['dealRateValue'],
|
||||
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/* eslint-disable sonarjs/no-duplicate-string */
|
||||
import { getUUID } from '../helper';
|
||||
|
||||
describe('getUUID function', () => {
|
||||
it('should return "" when path is an empty string', () => {
|
||||
const result = getUUID('');
|
||||
|
||||
expect(result).toBe('');
|
||||
});
|
||||
|
||||
it('should return "" when path is undefined', () => {
|
||||
const result = getUUID(undefined as unknown as string);
|
||||
|
||||
expect(result).toBe('');
|
||||
});
|
||||
|
||||
it('should return "" when path does not contain a valid UUID', () => {
|
||||
const result = getUUID('/some/random/path/withoutuuid');
|
||||
|
||||
expect(result).toBe('');
|
||||
});
|
||||
|
||||
it('should return "" when UUID is not properly formatted', () => {
|
||||
const result = getUUID('/some/path/with/invalid-uuid-format');
|
||||
|
||||
expect(result).toBe('');
|
||||
});
|
||||
|
||||
it('should return the UUID when the path contains a valid UUID at the end', () => {
|
||||
const result = getUUID('/users/123e4567-e89b-12d3-a456-426614174000');
|
||||
|
||||
expect(result).toBe('123e4567-e89b-12d3-a456-426614174000');
|
||||
});
|
||||
|
||||
it('should return "" if the UUID is malformed (e.g., missing hyphens)', () => {
|
||||
const result = getUUID('/path/without-hyphens/123e4567e89b12d3a456426614174000');
|
||||
|
||||
expect(result).toBe('');
|
||||
});
|
||||
|
||||
it('should return "" if the UUID is in uppercase format but still valid', () => {
|
||||
const result = getUUID('/path/with/uppercase/UUID/123E4567-E89B-12D3-A456-426614174000');
|
||||
|
||||
expect(result).toBe('123E4567-E89B-12D3-A456-426614174000');
|
||||
});
|
||||
|
||||
it('should return "" for a path with an invalid UUID and extra parts', () => {
|
||||
const result = getUUID('/some/path/with/invalid-uuid-format/extra/parts');
|
||||
|
||||
expect(result).toBe('');
|
||||
});
|
||||
|
||||
it('should return "" for a path that includes slashes but no UUID', () => {
|
||||
const result = getUUID('/some/random/path/');
|
||||
|
||||
expect(result).toBe('');
|
||||
});
|
||||
|
||||
it('should return the UUID if the path is just a single UUID', () => {
|
||||
const result = getUUID('123e4567-e89b-12d3-a456-426614174000');
|
||||
|
||||
expect(result).toBe('123e4567-e89b-12d3-a456-426614174000');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user