2023-03-10 09:37:37 +03:00

216 lines
9.2 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* 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;
}
}
}
);
}