339 lines
8.7 KiB
TypeScript

/* eslint-disable function-paren-newline */
/* eslint-disable implicit-arrow-linebreak */
import type { ApolloClient } from '@apollo/client';
import type { QueryClient } from '@tanstack/react-query';
import { selectSeasonType } from 'config/default-options';
import { reaction, toJS } from 'mobx';
import { sort } from 'radash/dist/array';
import type RootStore from 'stores/root';
import type { Row } from 'stores/tables/payments/types';
import { areEqual } from 'tools/array';
export default function paymentsReactions(
store: RootStore,
apolloClient: ApolloClient<object>,
queryClient: QueryClient
) {
const { $calculation, $tables } = store;
reaction(
() => $calculation.getElementValue('tbxFirstPaymentPerc'),
(firstPaymentPerc) => {
$tables.payments.setValue(0, firstPaymentPerc);
}
);
reaction(
() => $calculation.getElementValue('tbxLastPaymentPerc'),
(lastPaymentPerc) => {
const paymentsLength = $tables.payments.values.length;
$tables.payments.setValue(paymentsLength - 1, lastPaymentPerc);
}
);
/**
* Аннуитет
*/
reaction(
() => {
const graphType = $calculation.getElementValue('radioGraphType');
const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod');
return {
graphType,
leasingPeriod,
};
},
({ graphType, leasingPeriod }) => {
if (graphType === 100_000_000) {
const middlePayments: Row[] = Array.from(
{
length: leasingPeriod - 2,
},
() => ({
value: 100,
status: 'Disabled',
})
);
const firstPaymentPerc = $calculation.getElementValue('tbxFirstPaymentPerc');
const lastPaymentPerc = $calculation.getElementValue('tbxLastPaymentPerc');
$tables.payments.setRows([
{
value: firstPaymentPerc,
status: 'Disabled',
},
...middlePayments,
{
value: lastPaymentPerc,
status: 'Disabled',
},
]);
}
},
{
fireImmediately: true,
}
);
/**
* Равноубывающий
*/
reaction(
() => {
const graphType = $calculation.getElementValue('radioGraphType');
const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod');
const parmentsDecreasePercent = $calculation.getElementValue('tbxParmentsDecreasePercent');
return {
graphType,
leasingPeriod,
parmentsDecreasePercent,
};
},
({ graphType, leasingPeriod, parmentsDecreasePercent }) => {
if (graphType === 100_000_002) {
const middlePayments: Row[] = Array.from(
{
length: leasingPeriod - 2,
},
(_, k) => {
const payment = 100 * (parmentsDecreasePercent / 100) ** k;
return {
value: Number(payment.toFixed(2)),
status: 'Disabled',
};
}
);
const firstPaymentPerc = $calculation.getElementValue('tbxFirstPaymentPerc');
const lastPaymentPerc = $calculation.getElementValue('tbxLastPaymentPerc');
$tables.payments.setRows([
{
value: firstPaymentPerc,
status: 'Disabled',
},
...middlePayments,
{
value: lastPaymentPerc,
status: 'Disabled',
},
]);
}
}
);
/**
* Легкий старт
*/
reaction(
() => {
const graphType = $calculation.getElementValue('radioGraphType');
const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod');
return {
graphType,
leasingPeriod,
};
},
({ graphType, leasingPeriod }) => {
if (graphType === 100_000_004) {
const editablePayments: Row[] = [
{
value: 25,
status: 'Default',
},
{
value: 50,
status: 'Default',
},
{
value: 75,
status: 'Default',
},
];
const payments: Row[] = Array.from(
{
length: leasingPeriod - 5,
},
() => ({
value: 100,
status: 'Disabled',
})
);
const firstPaymentPerc = $calculation.getElementValue('tbxFirstPaymentPerc');
const lastPaymentPerc = $calculation.getElementValue('tbxLastPaymentPerc');
$tables.payments.setRows([
{
value: firstPaymentPerc,
status: 'Disabled',
},
...editablePayments,
...payments,
{
value: lastPaymentPerc,
status: 'Disabled',
},
]);
}
}
);
const errorText = 'При виде графика "Легкий старт" 2, 3, 4 платежи должны возрастать';
let removeError: () => void;
reaction(
() => {
const graphType = $calculation.getElementValue('radioGraphType');
const payments = $tables.payments.values;
return {
payments: toJS(payments),
graphType,
};
},
({ payments, graphType }) => {
if (graphType === 100_000_004) {
const targetPayments = payments.slice(1, 4);
const sortedPayments = sort(targetPayments, (x) => x);
const areEqualPayments = new Set(targetPayments).size === 1;
if (!areEqual(targetPayments, sortedPayments) || areEqualPayments) {
removeError = $tables.payments.validation.addError(errorText);
} else if (removeError) removeError();
} else if (removeError) removeError();
}
);
/**
* Дегрессия
*/
const degressionSeasonTypes = new Set([
100_000_003, 100_000_004, 100_000_005, 100_000_006, 100_000_007,
]);
reaction(
() => {
const graphType = $calculation.getElementValue('radioGraphType');
return graphType;
},
(graphType) => {
if (!graphType || graphType !== 100_000_001) {
$calculation.setElementOptions('selectSeasonType', []);
return;
}
const selectSeasonTypeOptions = selectSeasonType.filter((option) =>
degressionSeasonTypes.has(option.value)
);
$calculation.setElementOptions('selectSeasonType', selectSeasonTypeOptions);
}
);
const degressionSteps: { [key: number]: Array<number> } = {
100_000_003: [100, 50, 25],
100_000_004: [100, 30, 10],
100_000_005: [100, 70, 40],
100_000_006: [100, 7, 3],
};
reaction(
() => {
const degressionType = $calculation.getElementValue('selectSeasonType');
const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod');
const graphType = $calculation.getElementValue('radioGraphType');
return {
degressionType,
leasingPeriod,
graphType,
};
},
({ degressionType, leasingPeriod, graphType }) => {
if (graphType === 100_000_001) {
let payments: Row[] = [];
switch (degressionType) {
case 100_000_007: {
const editablePayments: Row[] = Array.from(
{
length: leasingPeriod - 3,
},
() => ({
value: 100,
status: 'Default',
})
);
payments = [
{
value: 100,
status: 'Disabled',
},
...editablePayments,
];
break;
}
case 100_000_003:
case 100_000_004:
case 100_000_005:
case 100_000_006: {
const [step1, step2, step3] = degressionSteps[degressionType];
const paymentsInStep = Math.ceil((leasingPeriod - 2) / 3);
payments = Array.from(
{
length: leasingPeriod - 2,
},
(_v, i) => {
let value = step3;
if (i <= paymentsInStep * 2 - 1) {
value = step2;
}
if (i <= paymentsInStep - 1) {
value = step1;
}
return {
value,
status: 'Disabled',
};
}
);
break;
}
default: {
break;
}
}
const firstPaymentPerc = $calculation.getElementValue('tbxFirstPaymentPerc');
const lastPaymentPerc = $calculation.getElementValue('tbxLastPaymentPerc');
$tables.payments.setRows([
{
value: firstPaymentPerc,
status: 'Disabled',
},
...payments,
{
value: lastPaymentPerc,
status: 'Disabled',
},
]);
}
}
);
}