216 lines
9.2 KiB
TypeScript
216 lines
9.2 KiB
TypeScript
/* eslint-disable sonarjs/cognitive-complexity */
|
||
/* eslint-disable complexity */
|
||
import { SEASONS_PERIOD_NUMBER, SEASONS_PERIODS } from './lib/seasons-constants';
|
||
import { selectHighSeasonStart } from '@/config/default-options';
|
||
import PaymentsSchema from '@/config/schema/payments';
|
||
import ValuesSchema from '@/config/schema/values';
|
||
import { MIN_LASTPAYMENT_NSIB, MIN_PAYMENT } from '@/constants/values';
|
||
import { counting, max, min, shift, sort } from 'radash';
|
||
import { areEqual, isSorted } from 'tools/array';
|
||
import { z } from 'zod';
|
||
|
||
export function createValidationSchema() {
|
||
return ValuesSchema.pick({
|
||
graphType: true,
|
||
highSeasonStart: true,
|
||
insNSIB: true,
|
||
lastPaymentRub: true,
|
||
leasingPeriod: true,
|
||
seasonType: true,
|
||
})
|
||
.extend({
|
||
payments: PaymentsSchema,
|
||
})
|
||
.superRefine(
|
||
async (
|
||
{
|
||
graphType,
|
||
highSeasonStart,
|
||
leasingPeriod,
|
||
payments,
|
||
seasonType,
|
||
insNSIB,
|
||
lastPaymentRub,
|
||
},
|
||
ctx
|
||
) => {
|
||
if (Boolean(insNSIB) && lastPaymentRub < MIN_LASTPAYMENT_NSIB) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message: `Последний платеж не может быть меньше ${MIN_LASTPAYMENT_NSIB} руб. при наличии НСИБ, укажите большее значение`,
|
||
path: ['tbxLastPaymentRub'],
|
||
});
|
||
}
|
||
|
||
{
|
||
const targetPayments = payments.values.slice(1, leasingPeriod - 1);
|
||
|
||
if (!targetPayments.every((payment) => payment >= MIN_PAYMENT)) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message: `Минимальное значение платежа должно быть равно ${MIN_PAYMENT}`,
|
||
path: ['payments'],
|
||
});
|
||
}
|
||
}
|
||
|
||
switch (graphType) {
|
||
// Дегрессия
|
||
case 100_000_001: {
|
||
if (!seasonType) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message: 'Не выбран тип дегрессии',
|
||
path: ['payments', 'selectSeasonType'],
|
||
});
|
||
break;
|
||
}
|
||
|
||
/**
|
||
* при Дегрессии все значения не должны быть равны друг другу
|
||
* + что при Легком старте 2,3 и 4 платежи не должны быть равны 100
|
||
*/
|
||
{
|
||
const targetPayments = payments.values.slice(1, leasingPeriod - 1);
|
||
if (new Set(targetPayments).size === 1) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message: 'Платежи не должны быть равны друг другу',
|
||
path: ['payments'],
|
||
});
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Проверка на возрастание
|
||
*/
|
||
{
|
||
const targetPayments = payments.values.slice(1, leasingPeriod - 1);
|
||
for (let i = 2; i < targetPayments.length - 1; i += 1) {
|
||
if (targetPayments[i] > targetPayments[i - 1]) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message: 'Платежи должны убывать',
|
||
path: ['payments'],
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Если вид графика = Дегрессия И значения в "Соотношении платежей" у 2, 3 и 4 платежа отличаются друг от друга не более чем на 10
|
||
* (т.е. берем значения в этих полях, определяем максимальное и минимальное значение и смотрим на их разницу)
|
||
* то не осуществлять Расчет графика и выводить ошибку "Нельзя осуществить расчет - указана очень жетская дегрессия.
|
||
* На 2-4 платежах Соотношение платежа должен отличаться не более чем на 10%",
|
||
* иначе осуществлять расчет
|
||
*/
|
||
{
|
||
const targetPayments = payments.values.slice(1, 4);
|
||
|
||
if ((max(targetPayments) || 0) - (min(targetPayments) || 0) > 10) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message:
|
||
'Указана очень жесткая дегрессия. На 2-4 платежах Соотношение платежа должен отличаться не более чем на 10%',
|
||
path: ['payments'],
|
||
});
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Если вид графика = Дегрессия И значения в "Соотношении платежей" для строк с 2 До "Срок лизинга-1" как минимум 2 раза по 2 платежа должны между собой быть равны
|
||
* (т.е. берем значения "Соотношения платежей" для строк с 2 до "Срок лизинга-1" и делаем сводную таблицу - если кол-во одинаковых значение больше 2 встречаются 2 и более раза),
|
||
* то осуществлять расчет,
|
||
* иначе не осуществлять Расчет графика и выводить ошибку "Нельзя осуществить расчет - указана очень жетская дегрессия. Не менее чем у 4х платежей "Соотношение платежа" должно не отличаться между самой",
|
||
*/
|
||
{
|
||
const targetPayments = payments.values.slice(1, leasingPeriod - 1);
|
||
const counts = counting(targetPayments, (v) => v);
|
||
if (Object.values(counts).filter((count) => count > 1).length < 2) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message:
|
||
'Указана очень жесткая дегрессия. Не менее чем у 4х платежей соотношение должно не отличаться между собой',
|
||
path: ['payments'],
|
||
});
|
||
}
|
||
}
|
||
|
||
break;
|
||
}
|
||
|
||
case 100_000_003: {
|
||
if (leasingPeriod < 14) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message: 'При сезонном виде графика срок лизинга должен быть больше 14 месяцев',
|
||
path: ['payments', 'tbxLeasingPeriod'],
|
||
});
|
||
}
|
||
|
||
if (!seasonType) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message: 'Не выбран тип сезонности',
|
||
path: ['payments', 'selectSeasonType'],
|
||
});
|
||
break;
|
||
}
|
||
|
||
if (!highSeasonStart) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message: 'Не выбрано смещение сезонности',
|
||
path: ['payments', 'selectHighSeasonStart'],
|
||
});
|
||
break;
|
||
}
|
||
|
||
const seasons = payments.values.slice(1, SEASONS_PERIOD_NUMBER + 1);
|
||
const highSeasonStartOption = selectHighSeasonStart.find(
|
||
(x) => x.value === highSeasonStart
|
||
);
|
||
|
||
if (highSeasonStartOption) {
|
||
const shiftNumber = Number.parseInt(highSeasonStartOption.label, 10) - 2;
|
||
const unshiftedSeasons = shift(seasons, -shiftNumber);
|
||
|
||
const positions = SEASONS_PERIODS[seasonType];
|
||
const seasonsValues = positions.map((position) => unshiftedSeasons[position]);
|
||
|
||
if (isSorted(seasonsValues)) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message: 'Сезонные платежи должны убывать',
|
||
path: ['payments'],
|
||
});
|
||
}
|
||
}
|
||
|
||
break;
|
||
}
|
||
|
||
// Легкий старт
|
||
case 100_000_004: {
|
||
const targetPayments = payments.values.slice(1, 4);
|
||
const sortedPayments = sort(targetPayments, (x) => x);
|
||
const areEqualPayments = new Set(targetPayments).size === 1;
|
||
|
||
if (!areEqual(targetPayments, sortedPayments) || areEqualPayments) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message: '2, 3, 4 платежи должны возрастать',
|
||
path: ['payments'],
|
||
});
|
||
}
|
||
|
||
break;
|
||
}
|
||
default: {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
);
|
||
}
|