diff --git a/Components/Calculation/Form/Payments/PaymentsParams.jsx b/Components/Calculation/Form/Payments/PaymentsParams.jsx
new file mode 100644
index 0000000..4f3174f
--- /dev/null
+++ b/Components/Calculation/Form/Payments/PaymentsParams.jsx
@@ -0,0 +1,45 @@
+import { observer } from 'mobx-react-lite';
+import { useStore } from 'stores/hooks';
+import { Flex } from 'UIKit/grid';
+import elementsRender from '../../config/elements-render';
+import { elements } from './config';
+
+function PaymentsParams() {
+ const renderedElements = elements.map((elementName) => {
+ const render = elementsRender[elementName]?.render;
+
+ return render();
+ });
+
+ const [selectSeasonType, tbxParmentsDecreasePercent, selectHighSeasonStart] = renderedElements;
+
+ const { $calculation } = useStore();
+ const graphType = $calculation.getElementValue('radioGraphType');
+
+ switch (graphType) {
+ case 100_000_000:
+ return null;
+ case 100_000_001: {
+ return {selectSeasonType};
+ }
+ case 100_000_002: {
+ return {tbxParmentsDecreasePercent};
+ }
+ case 100_000_003: {
+ return (
+
+ {selectSeasonType}
+ {selectHighSeasonStart}
+
+ );
+ }
+ case 100_000_004: {
+ return null;
+ }
+
+ default:
+ break;
+ }
+}
+
+export default observer(PaymentsParams);
diff --git a/Components/Calculation/Form/Payments/config.ts b/Components/Calculation/Form/Payments/config.ts
index e95a193..796b0c7 100644
--- a/Components/Calculation/Form/Payments/config.ts
+++ b/Components/Calculation/Form/Payments/config.ts
@@ -4,7 +4,6 @@ export const id = 'payments';
export const title = 'Платежи';
export const elements: ElementsRow['0'] = [
- 'radioGraphType',
'selectSeasonType',
'tbxParmentsDecreasePercent',
'selectHighSeasonStart',
diff --git a/Components/Calculation/Form/Payments/index.jsx b/Components/Calculation/Form/Payments/index.jsx
index c32133c..11f0673 100644
--- a/Components/Calculation/Form/Payments/index.jsx
+++ b/Components/Calculation/Form/Payments/index.jsx
@@ -1,18 +1,11 @@
import { Box, Flex } from 'UIKit/grid';
import elementsRender from '../../config/elements-render';
-import { elements, id, title } from './config';
+import { id, title } from './config';
+import PaymentsParams from './PaymentsParams';
import PaymentsTable from './PaymentsTable';
function Payments() {
- const renderedElements = elements.map((elementName) => {
- const render = elementsRender[elementName]?.render;
-
- return render();
- });
-
- // eslint-disable-next-line operator-linebreak
- const [radioGraphType, selectSeasonType, tbxParmentsDecreasePercent, selectHighSeasonStart] =
- renderedElements;
+ const radioGraphType = elementsRender.radioGraphType.render();
return (
@@ -24,11 +17,7 @@ function Payments() {
}}
>
{radioGraphType}
-
- {selectSeasonType}
- {tbxParmentsDecreasePercent}
- {selectHighSeasonStart}
-
+
diff --git a/Components/Calculation/config/elements-render/override.tsx b/Components/Calculation/config/elements-render/override.tsx
index 506120e..2e08e79 100644
--- a/Components/Calculation/config/elements-render/override.tsx
+++ b/Components/Calculation/config/elements-render/override.tsx
@@ -2,7 +2,9 @@
import { Container, Head } from 'Components/Layout/Element';
import Link from 'Elements/Link';
import Tooltip from 'Elements/Tooltip';
+import { observer } from 'mobx-react-lite';
import type { ComponentProps } from 'react';
+import { useStore } from 'stores/hooks';
import buildReadonly from '../../builders/build-readonly';
import builders from '../elements-builders';
import components from '../elements-components';
@@ -162,6 +164,42 @@ const overrideRender: Partial> = {
);
},
},
+
+ selectSeasonType: {
+ render: () => {
+ const elementName = 'selectSeasonType';
+ const valueName = map.selectSeasonType;
+ const Component = components.selectSeasonType;
+ const props = elementsProps.selectSeasonType;
+ const builder = builders.selectSeasonType;
+
+ const Element = builder(Component, {
+ elementName,
+ valueName,
+ });
+
+ const Title = observer(() => {
+ const { $calculation } = useStore();
+ const graphType = $calculation.getElementValue('radioGraphType');
+
+ switch (graphType) {
+ case 100_000_001:
+ return Тип дегрессии;
+ case 100_000_003:
+ return Тип сезонности;
+ default:
+ return {titles.selectSeasonType};
+ }
+ });
+
+ return (
+
+ } />
+
+
+ );
+ },
+ },
};
export default overrideRender;
diff --git a/Components/Layout/Element.tsx b/Components/Layout/Element.tsx
index 0d7570a..5f968d5 100644
--- a/Components/Layout/Element.tsx
+++ b/Components/Layout/Element.tsx
@@ -23,7 +23,7 @@ export function Head({
addon,
htmlFor,
}: {
- title: string;
+ title: ReactNode;
addon?: ReactNode;
htmlFor: string;
}) {
diff --git a/config/default-options.ts b/config/default-options.ts
index 097cf84..7882924 100644
--- a/config/default-options.ts
+++ b/config/default-options.ts
@@ -1,6 +1,51 @@
import { alphabetical } from 'radash/dist/array';
import type { CalculationOptions } from 'stores/calculation/options/types';
+export const selectSeasonType = [
+ {
+ label: '6/6',
+ value: 100_000_000,
+ },
+ {
+ label: '8/4',
+ value: 100_000_001,
+ },
+ {
+ label: '4/4/4',
+ value: 100_000_002,
+ },
+ {
+ label: 'Гибкая дегрессия',
+ value: 100_000_007,
+ },
+ {
+ label: '100.50.25',
+ value: 100_000_003,
+ },
+ {
+ label: '100.30.10',
+ value: 100_000_004,
+ },
+ {
+ label: '100.70.40',
+ value: 100_000_005,
+ },
+ {
+ label: '100.7.3',
+ value: 100_000_006,
+ },
+];
+
+export const selectHighSeasonStart = Array.from(
+ {
+ length: 12,
+ },
+ (_, i) => ({
+ label: `${i + 2}`,
+ value: 100_000_000 + i,
+ })
+);
+
const defaultOptions: CalculationOptions = {
radioLastPaymentRule: [
{
@@ -51,50 +96,9 @@ const defaultOptions: CalculationOptions = {
},
],
- selectSeasonType: [
- {
- label: '6/6',
- value: 100_000_000,
- },
- {
- label: '8/4',
- value: 100_000_001,
- },
- {
- label: '4/4/4',
- value: 100_000_002,
- },
- {
- label: 'Гибкая дегрессия',
- value: 100_000_007,
- },
- {
- label: '100.50.25',
- value: 100_000_003,
- },
- {
- label: '100.30.10',
- value: 100_000_004,
- },
- {
- label: '100.70.40',
- value: 100_000_005,
- },
- {
- label: '100.7.3',
- value: 100_000_006,
- },
- ],
+ selectSeasonType,
- selectHighSeasonStart: Array.from(
- {
- length: 12,
- },
- (_, i) => ({
- label: `${i + 2}`,
- value: 100_000_000 + i,
- })
- ),
+ selectHighSeasonStart,
radioDeliveryTime: [
{
diff --git a/config/default-values.ts b/config/default-values.ts
index 16308b6..c6a66bb 100644
--- a/config/default-values.ts
+++ b/config/default-values.ts
@@ -23,8 +23,8 @@ const defaultValues: CalculationValues = {
balanceHolder: 100_000_001,
graphType: 100_000_000,
parmentsDecreasePercent: 94,
- seasonType: 100_000_000,
- highSeasonStart: 100_000_000,
+ seasonType: null,
+ highSeasonStart: null,
comissionPerc: 0,
comissionRub: 0,
saleBonus: 1.3,
diff --git a/process/fingap/reactions/validation.ts b/process/fingap/reactions/validation.ts
index aa76f91..1a2778d 100644
--- a/process/fingap/reactions/validation.ts
+++ b/process/fingap/reactions/validation.ts
@@ -26,9 +26,7 @@ export default function validationReactions(
({ hasPaymentsErrors, finGAPInsuranceCompany }) => {
if (finGAPInsuranceCompany && hasPaymentsErrors) {
removeError = $tables.fingap.validation.addError(errorText);
- } else {
- removeError();
- }
+ } else if (removeError) removeError();
},
{
fireImmediately: true,
diff --git a/process/payments/lib/__tests__/seasons.test.js b/process/payments/lib/__tests__/seasons.test.js
new file mode 100644
index 0000000..9bedb98
--- /dev/null
+++ b/process/payments/lib/__tests__/seasons.test.js
@@ -0,0 +1,25 @@
+import { getPositionIndex } from '../seasons-tools';
+
+describe('process/payments/lib/seasons-tools', () => {
+ describe('[function] getPositionIndex', () => {
+ test('should return 0', () => {
+ const result = getPositionIndex(100_000_001, 0);
+ expect(result).toEqual(0);
+ });
+
+ test('should return 0', () => {
+ const result = getPositionIndex(100_000_001, 7);
+ expect(result).toEqual(0);
+ });
+
+ test('should return 1', () => {
+ const result = getPositionIndex(100_000_001, 8);
+ expect(result).toEqual(1);
+ });
+
+ test('should return 1', () => {
+ const result = getPositionIndex(100_000_001, 11);
+ expect(result).toEqual(1);
+ });
+ });
+});
diff --git a/process/payments/lib/seasons-constants.ts b/process/payments/lib/seasons-constants.ts
new file mode 100644
index 0000000..889bc29
--- /dev/null
+++ b/process/payments/lib/seasons-constants.ts
@@ -0,0 +1,15 @@
+export const SEASONS_PERIODS: Record> = {
+ 100_000_000: [0, 6],
+ 100_000_001: [0, 8],
+ 100_000_002: [0, 4, 8],
+};
+
+export const FORBIDDEN_HIGH_SEASON_START: Record> = {
+ 100_000_000: ['9', '10'],
+ 100_000_001: ['7', '8', '9'],
+ 100_000_002: ['11'],
+};
+
+export const SEASONS_PERIOD_NUMBER = 12;
+
+export const DEFAULT_SEASONS_VALUES = [100, 75, 50];
diff --git a/process/payments/lib/seasons-tools.ts b/process/payments/lib/seasons-tools.ts
new file mode 100644
index 0000000..f930165
--- /dev/null
+++ b/process/payments/lib/seasons-tools.ts
@@ -0,0 +1,55 @@
+/* eslint-disable implicit-arrow-linebreak */
+import type { CalculationValues } from 'stores/calculation/values/types';
+import { SEASONS_PERIODS, SEASONS_PERIOD_NUMBER } from './seasons-constants';
+
+type SeasonType = NonNullable;
+type LeasingPeriod = CalculationValues['leasingPeriod'];
+
+export function getPositionIndex(seasonType: SeasonType, seasonsIndex: number) {
+ let positionIndex = 0;
+
+ SEASONS_PERIODS[seasonType].forEach((position, i) => {
+ if (seasonsIndex >= position) {
+ positionIndex = i;
+ }
+ });
+
+ return positionIndex;
+}
+
+export function getSeasonsValues(seasonType: SeasonType, seasons: Array) {
+ return SEASONS_PERIODS[seasonType].map((index) => seasons[index]);
+}
+
+export function generateSeasons(seasonType: SeasonType, values: Array) {
+ const positions = SEASONS_PERIODS[seasonType];
+
+ const seasons: Array = [];
+
+ [...positions, SEASONS_PERIOD_NUMBER].forEach((position, i, arr) => {
+ if (position < SEASONS_PERIOD_NUMBER) {
+ const start = arr[i];
+ const end = arr[i + 1];
+ const value = values[i];
+
+ // eslint-disable-next-line unicorn/new-for-builtins
+ seasons.push(...Array(end - start).fill(value));
+ }
+ });
+
+ return seasons;
+}
+
+export function generateSeasonsPayments(leasingPeriod: LeasingPeriod, seasons: Array) {
+ return (
+ Array.from(
+ {
+ length: Math.floor((leasingPeriod - 2) / SEASONS_PERIOD_NUMBER),
+ },
+ () => seasons
+ )
+ .flat()
+ // eslint-disable-next-line unicorn/prefer-spread
+ .concat(seasons.slice(0, (leasingPeriod - 2) % SEASONS_PERIOD_NUMBER))
+ );
+}
diff --git a/process/payments/reactions.ts b/process/payments/reactions.ts
index c950d1f..4b9d5ac 100644
--- a/process/payments/reactions.ts
+++ b/process/payments/reactions.ts
@@ -1,25 +1,78 @@
+/* eslint-disable function-paren-newline */
+/* eslint-disable implicit-arrow-linebreak */
import type { ApolloClient } from '@apollo/client';
-import { reaction, toJS } from 'mobx';
+import type { QueryClient } from '@tanstack/react-query';
+import { selectHighSeasonStart, selectSeasonType } from 'config/default-options';
+import { comparer, reaction, toJS } from 'mobx';
+import type { CalculationOptions } from 'stores/calculation/options/types';
import type RootStore from 'stores/root';
+import type { Row } from 'stores/tables/payments/types';
+import { difference, shift } from 'tools/array';
+import * as seasonsConstants from './lib/seasons-constants';
+import * as seasonsTools from './lib/seasons-tools';
+import validatePaymentsTable from './validation';
-export default function paymentsReactions(store: RootStore, apolloClient: ApolloClient