468 lines
13 KiB
TypeScript
468 lines
13 KiB
TypeScript
import * as degressionTools from '../lib/degression-tools';
|
|
import * as seasonsConstants from '../lib/seasons-constants';
|
|
import * as seasonsTools from '../lib/seasons-tools';
|
|
import { selectHighSeasonStart } from '@/config/default-options';
|
|
import { MIN_PAYMENT } from '@/constants/values';
|
|
import type { ProcessContext } from '@/process/types';
|
|
import type { Row } from '@/stores/tables/payments/types';
|
|
import { disposableReaction } from '@/utils/mobx';
|
|
import { comparer, reaction, toJS } from 'mobx';
|
|
import { shift } from 'radash';
|
|
import { difference } from 'tools/array';
|
|
|
|
const {
|
|
generateSeasonPaymentsRows,
|
|
generateSeasons,
|
|
generateSeasonsPayments,
|
|
getPositionIndex,
|
|
getSeasonsValues,
|
|
} = seasonsTools;
|
|
|
|
const { DEFAULT_SEASONS_VALUES, FORBIDDEN_HIGH_SEASON_START, SEASONS_PERIOD_NUMBER } =
|
|
seasonsConstants;
|
|
|
|
export default function reactions({ store }: ProcessContext) {
|
|
const { $calculation, $tables, $process } = store;
|
|
|
|
reaction(
|
|
() => $calculation.element('tbxFirstPaymentPerc').getValue(),
|
|
(firstPaymentPerc) => {
|
|
$tables.payments.setValue(0, firstPaymentPerc);
|
|
}
|
|
);
|
|
|
|
reaction(
|
|
() => $calculation.element('tbxLastPaymentPerc').getValue(),
|
|
(lastPaymentPerc) => {
|
|
const paymentsLength = $tables.payments.values.length;
|
|
$tables.payments.setValue(paymentsLength - 1, lastPaymentPerc);
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Аннуитет
|
|
*/
|
|
reaction(
|
|
() => {
|
|
const graphType = $calculation.element('radioGraphType').getValue();
|
|
const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue();
|
|
|
|
return {
|
|
graphType,
|
|
leasingPeriod,
|
|
};
|
|
},
|
|
({ graphType, leasingPeriod }) => {
|
|
if ([100_000_000, 100_000_005].includes(graphType)) {
|
|
const middlePayments: Row[] = Array.from(
|
|
{
|
|
length: leasingPeriod - 2,
|
|
},
|
|
() => ({
|
|
status: 'Disabled',
|
|
value: 100,
|
|
})
|
|
);
|
|
|
|
const firstPaymentPerc = $calculation.element('tbxFirstPaymentPerc').getValue();
|
|
const lastPaymentPerc = $calculation.element('tbxLastPaymentPerc').getValue();
|
|
|
|
const rows: Row[] = [
|
|
{
|
|
status: 'Disabled',
|
|
value: firstPaymentPerc,
|
|
},
|
|
...middlePayments,
|
|
{
|
|
status: 'Disabled',
|
|
value: lastPaymentPerc,
|
|
},
|
|
];
|
|
|
|
if (!$process.has('LoadKP')) {
|
|
$tables.payments.setValues(rows.map((row) => row.value));
|
|
}
|
|
|
|
$tables.payments.setStatuses(rows.map((row) => row.status));
|
|
}
|
|
},
|
|
{
|
|
fireImmediately: true,
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Равноубывающий
|
|
*/
|
|
|
|
reaction(
|
|
() => {
|
|
const graphType = $calculation.element('radioGraphType').getValue();
|
|
const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue();
|
|
const parmentsDecreasePercent = $calculation.element('tbxParmentsDecreasePercent').getValue();
|
|
|
|
return {
|
|
graphType,
|
|
leasingPeriod,
|
|
parmentsDecreasePercent,
|
|
};
|
|
},
|
|
({ graphType, leasingPeriod, parmentsDecreasePercent }) => {
|
|
if (graphType === 100_000_002) {
|
|
const middlePayments: Row[] = Array.from(
|
|
{
|
|
length: leasingPeriod - 2,
|
|
},
|
|
(_, k) => {
|
|
let payment = 100 * (parmentsDecreasePercent / 100) ** k;
|
|
if (payment < MIN_PAYMENT) payment = MIN_PAYMENT;
|
|
|
|
return {
|
|
status: 'Disabled',
|
|
value: Number(payment.toFixed(2)),
|
|
};
|
|
}
|
|
);
|
|
|
|
const firstPaymentPerc = $calculation.element('tbxFirstPaymentPerc').getValue();
|
|
const lastPaymentPerc = $calculation.element('tbxLastPaymentPerc').getValue();
|
|
|
|
const rows: Row[] = [
|
|
{
|
|
status: 'Disabled',
|
|
value: firstPaymentPerc,
|
|
},
|
|
...middlePayments,
|
|
{
|
|
status: 'Disabled',
|
|
value: lastPaymentPerc,
|
|
},
|
|
];
|
|
|
|
if (!$process.has('LoadKP')) {
|
|
$tables.payments.setValues(rows.map((row) => row.value));
|
|
}
|
|
|
|
$tables.payments.setStatuses(rows.map((row) => row.status));
|
|
}
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Легкий старт
|
|
*/
|
|
|
|
reaction(
|
|
() => {
|
|
const graphType = $calculation.element('radioGraphType').getValue();
|
|
const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue();
|
|
|
|
return {
|
|
graphType,
|
|
leasingPeriod,
|
|
};
|
|
},
|
|
({ graphType, leasingPeriod }) => {
|
|
if (graphType === 100_000_004) {
|
|
const editablePayments: Row[] = [
|
|
{
|
|
status: 'Default',
|
|
value: 25,
|
|
},
|
|
{
|
|
status: 'Default',
|
|
value: 50,
|
|
},
|
|
{
|
|
status: 'Default',
|
|
value: 75,
|
|
},
|
|
];
|
|
|
|
const payments: Row[] = Array.from(
|
|
{
|
|
length: leasingPeriod - 5,
|
|
},
|
|
() => ({
|
|
status: 'Disabled',
|
|
value: 100,
|
|
})
|
|
);
|
|
|
|
const firstPaymentPerc = $calculation.element('tbxFirstPaymentPerc').getValue();
|
|
const lastPaymentPerc = $calculation.element('tbxLastPaymentPerc').getValue();
|
|
|
|
const rows: Row[] = [
|
|
{
|
|
status: 'Disabled',
|
|
value: firstPaymentPerc,
|
|
},
|
|
...editablePayments,
|
|
...payments,
|
|
{
|
|
status: 'Disabled',
|
|
value: lastPaymentPerc,
|
|
},
|
|
];
|
|
|
|
if (!$process.has('LoadKP')) {
|
|
$tables.payments.setValues(rows.map((row) => row.value));
|
|
}
|
|
|
|
$tables.payments.setStatuses(rows.map((row) => row.status));
|
|
}
|
|
}
|
|
);
|
|
|
|
// /**
|
|
// * Дегрессия
|
|
// */
|
|
|
|
// reaction(
|
|
// () => {
|
|
// const graphType = $calculation.element('radioGraphType').getValue();
|
|
|
|
// return graphType;
|
|
// },
|
|
// (graphType) => {
|
|
// if (!graphType) {
|
|
// $calculation.element('selectSeasonType').resetOptions();
|
|
|
|
// return;
|
|
// }
|
|
|
|
// if (graphType === 100_000_001 || graphType === 100_000_003) {
|
|
// const allowedSeasonTypes = SEASON_TYPES[graphType];
|
|
|
|
// const selectSeasonTypeOptions = selectSeasonType.filter((option) =>
|
|
// allowedSeasonTypes.includes(option.value)
|
|
// );
|
|
|
|
// $calculation.element('selectSeasonType').setOptions(selectSeasonTypeOptions);
|
|
// } else {
|
|
// $calculation.element('selectSeasonType').resetOptions();
|
|
// }
|
|
// }
|
|
// );
|
|
|
|
disposableReaction(
|
|
() => $calculation.element('radioGraphType').getValue() !== 100_000_001,
|
|
() => $calculation.$values.getValues(['leasingPeriod', 'seasonType']),
|
|
({ seasonType, leasingPeriod }) => {
|
|
const middlePayments: Row[] = degressionTools.generateDegressionRows({
|
|
leasingPeriod,
|
|
seasonType,
|
|
});
|
|
|
|
const firstPaymentPerc = $calculation.element('tbxFirstPaymentPerc').getValue();
|
|
const lastPaymentPerc = $calculation.element('tbxLastPaymentPerc').getValue();
|
|
|
|
const rows: Row[] = [
|
|
{
|
|
status: 'Disabled',
|
|
value: firstPaymentPerc,
|
|
},
|
|
...middlePayments,
|
|
{
|
|
status: 'Disabled',
|
|
value: lastPaymentPerc,
|
|
},
|
|
];
|
|
|
|
if (!$process.has('LoadKP')) {
|
|
$tables.payments.setValues(rows.map((row) => row.value));
|
|
}
|
|
|
|
$tables.payments.setStatuses(rows.map((row) => row.status));
|
|
}
|
|
);
|
|
|
|
disposableReaction(
|
|
() => $process.has('LoadKP'),
|
|
() => toJS($tables.payments.values),
|
|
(nextPayments, prevPayments) => {
|
|
const graphType = $calculation.element('radioGraphType').getValue();
|
|
const degressionType = $calculation.element('selectSeasonType').getValue();
|
|
|
|
if (graphType === 100_000_001 && degressionType === 100_000_007) {
|
|
const changes = difference(nextPayments, prevPayments);
|
|
|
|
if (!changes?.length || changes.length > 1) return;
|
|
|
|
const [changeIndex] = changes;
|
|
const value = nextPayments[changeIndex];
|
|
const payments = nextPayments.slice(1, -1).map((payment, i) => {
|
|
if (i <= changeIndex - 2) return payment;
|
|
|
|
return value;
|
|
});
|
|
|
|
const firstPaymentPerc = $calculation.element('tbxFirstPaymentPerc').getValue();
|
|
const lastPaymentPerc = $calculation.element('tbxLastPaymentPerc').getValue();
|
|
|
|
$tables.payments.setValues([firstPaymentPerc, ...payments, lastPaymentPerc]);
|
|
}
|
|
},
|
|
{
|
|
delay: 50,
|
|
equals: comparer.structural,
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Сезонный
|
|
*/
|
|
|
|
reaction(
|
|
() => {
|
|
const graphType = $calculation.element('radioGraphType').getValue();
|
|
|
|
return {
|
|
graphType,
|
|
};
|
|
},
|
|
({ graphType }) => {
|
|
if (graphType !== 100_000_003) return;
|
|
|
|
const seasonType = $calculation.element('selectSeasonType').getValue();
|
|
const highSeasonStart = $calculation.element('selectHighSeasonStart').getValue();
|
|
|
|
if (!seasonType || !highSeasonStart) {
|
|
$tables.payments.setValues([]);
|
|
}
|
|
}
|
|
);
|
|
|
|
reaction(
|
|
() => $calculation.element('selectSeasonType').getValue(),
|
|
(seasonType) => {
|
|
const graphType = $calculation.element('radioGraphType').getValue();
|
|
if (graphType !== 100_000_003) return;
|
|
|
|
if (!seasonType) {
|
|
$calculation.element('selectHighSeasonStart').reset();
|
|
|
|
return;
|
|
}
|
|
|
|
const highSeasonStartOptions = selectHighSeasonStart.filter(
|
|
(option) => !FORBIDDEN_HIGH_SEASON_START[seasonType].includes(option.label)
|
|
);
|
|
|
|
$calculation.element('selectHighSeasonStart').setOptions(highSeasonStartOptions);
|
|
}
|
|
);
|
|
|
|
reaction(
|
|
() => {
|
|
const seasonType = $calculation.element('selectSeasonType').getValue();
|
|
const highSeasonStartOption = $calculation.element('selectHighSeasonStart').getOption();
|
|
const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue();
|
|
|
|
return {
|
|
highSeasonStartOption,
|
|
leasingPeriod,
|
|
seasonType,
|
|
};
|
|
},
|
|
({ seasonType, highSeasonStartOption, leasingPeriod }) => {
|
|
const graphType = $calculation.element('radioGraphType').getValue();
|
|
if (graphType !== 100_000_003) return;
|
|
|
|
if (!seasonType || !highSeasonStartOption) {
|
|
$tables.payments.setValues([]);
|
|
|
|
return;
|
|
}
|
|
|
|
const seasons = generateSeasons(seasonType, DEFAULT_SEASONS_VALUES);
|
|
const shiftNumber = Number.parseInt(highSeasonStartOption.label, 10) - 2;
|
|
const payments = generateSeasonsPayments(leasingPeriod, shift(seasons, shiftNumber));
|
|
const middlePayments: Row[] = generateSeasonPaymentsRows(seasonType, shiftNumber, payments);
|
|
const firstPaymentPerc = $calculation.element('tbxFirstPaymentPerc').getValue();
|
|
const lastPaymentPerc = $calculation.element('tbxLastPaymentPerc').getValue();
|
|
|
|
const rows: Row[] = [
|
|
{
|
|
status: 'Disabled',
|
|
value: firstPaymentPerc,
|
|
},
|
|
...middlePayments,
|
|
{
|
|
status: 'Disabled',
|
|
value: lastPaymentPerc,
|
|
},
|
|
];
|
|
|
|
if (!$process.has('LoadKP')) {
|
|
$tables.payments.setValues(rows.map((row) => row.value));
|
|
}
|
|
|
|
$tables.payments.setStatuses(rows.map((row) => row.status));
|
|
}
|
|
);
|
|
|
|
disposableReaction(
|
|
() => $process.has('LoadKP'),
|
|
() => {
|
|
const payments = toJS($tables.payments.values);
|
|
|
|
return payments.slice(1, SEASONS_PERIOD_NUMBER + 1);
|
|
},
|
|
(nextSeasons, prevSeasons) => {
|
|
const graphType = $calculation.element('radioGraphType').getValue();
|
|
if (graphType !== 100_000_003) return;
|
|
|
|
const seasonType = $calculation.element('selectSeasonType').getValue();
|
|
const highSeasonStartOption = $calculation.element('selectHighSeasonStart').getOption();
|
|
if (!seasonType || !highSeasonStartOption) return;
|
|
|
|
const shiftNumber = Number.parseInt(highSeasonStartOption.label, 10) - 2;
|
|
const unshiftedNextSeasons = shift(nextSeasons, -shiftNumber);
|
|
const unshiftedPrevSeasons = shift(prevSeasons, -shiftNumber);
|
|
|
|
const changes = difference(unshiftedNextSeasons, unshiftedPrevSeasons);
|
|
if (changes === null || changes.length > 1) return;
|
|
|
|
const [changeIndex] = changes;
|
|
const positionIndex = getPositionIndex(seasonType, changeIndex);
|
|
|
|
const values = getSeasonsValues(seasonType, unshiftedNextSeasons);
|
|
values[positionIndex] = unshiftedNextSeasons[changeIndex];
|
|
|
|
const seasons = generateSeasons(seasonType, values);
|
|
const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue();
|
|
const payments = generateSeasonsPayments(leasingPeriod, shift(seasons, shiftNumber));
|
|
const rows: Row[] = generateSeasonPaymentsRows(seasonType, shiftNumber, payments);
|
|
const firstPaymentPerc = $calculation.element('tbxFirstPaymentPerc').getValue();
|
|
const lastPaymentPerc = $calculation.element('tbxLastPaymentPerc').getValue();
|
|
|
|
$tables.payments.setRows([
|
|
{
|
|
status: 'Disabled',
|
|
value: firstPaymentPerc,
|
|
},
|
|
...rows,
|
|
{
|
|
status: 'Disabled',
|
|
value: lastPaymentPerc,
|
|
},
|
|
]);
|
|
},
|
|
{
|
|
delay: 50,
|
|
equals: comparer.structural,
|
|
}
|
|
);
|
|
|
|
disposableReaction(
|
|
() => $process.has('LoadKP'),
|
|
() => $calculation.element('radioGraphType').getValue(),
|
|
() => {
|
|
$calculation.element('selectSeasonType').resetValue();
|
|
$calculation.element('selectHighSeasonStart').resetValue();
|
|
$calculation.element('tbxParmentsDecreasePercent').resetValue();
|
|
}
|
|
);
|
|
}
|