378 lines
15 KiB
TypeScript
378 lines
15 KiB
TypeScript
/* eslint-disable sonarjs/cognitive-complexity */
|
||
/* eslint-disable complexity */
|
||
import type { ValidationContext } from '../types';
|
||
import type { Elements } from '@/Components/Calculation/config/map/values';
|
||
import { FinGAPSchema } from '@/config/schema/fingap';
|
||
import { InsuranceSchema } from '@/config/schema/insurance';
|
||
import ValuesSchema from '@/config/schema/values';
|
||
import { MAX_MASS, VEHICLE_SEATS } from '@/constants/values';
|
||
import * as CRMTypes from '@/graphql/crm.types';
|
||
import { z } from 'zod';
|
||
|
||
export function createValidationSchema({ apolloClient }: ValidationContext) {
|
||
return ValuesSchema.pick({
|
||
IRR_Perc: true,
|
||
addEquipmentPrice: true,
|
||
countSeats: true,
|
||
dealerPerson: true,
|
||
discountRub: true,
|
||
engineVolume: true,
|
||
firstPaymentPerc: true,
|
||
importProgramSum: true,
|
||
insNSIB: true,
|
||
lastPaymentPerc: true,
|
||
leaseObjectCategory: true,
|
||
leaseObjectCount: true,
|
||
leaseObjectMotorPower: true,
|
||
leaseObjectPriceWthtVAT: true,
|
||
leaseObjectUsed: true,
|
||
leaseObjectYear: true,
|
||
maxMass: true,
|
||
objectRegistration: true,
|
||
partialVAT: true,
|
||
plPriceRub: true,
|
||
product: true,
|
||
quote: true,
|
||
recalcWithRevision: true,
|
||
technicalCard: true,
|
||
})
|
||
.extend({
|
||
fingap: FinGAPSchema,
|
||
insurance: InsuranceSchema,
|
||
})
|
||
.superRefine(
|
||
async (
|
||
{
|
||
addEquipmentPrice,
|
||
dealerPerson: dealerPersonId,
|
||
importProgramSum,
|
||
leaseObjectPriceWthtVAT,
|
||
leaseObjectUsed,
|
||
product: productId,
|
||
quote: quoteId,
|
||
recalcWithRevision,
|
||
discountRub,
|
||
plPriceRub,
|
||
firstPaymentPerc,
|
||
leaseObjectCount,
|
||
maxMass,
|
||
countSeats,
|
||
leaseObjectYear,
|
||
lastPaymentPerc,
|
||
leaseObjectCategory,
|
||
partialVAT,
|
||
IRR_Perc,
|
||
leaseObjectMotorPower,
|
||
engineVolume,
|
||
insNSIB,
|
||
technicalCard,
|
||
objectRegistration,
|
||
fingap: fingapRisks,
|
||
insurance,
|
||
},
|
||
ctx
|
||
) => {
|
||
if (!recalcWithRevision) {
|
||
return;
|
||
}
|
||
|
||
if (!quoteId) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message: 'Не указано предложение, по которому осуществляется Пересчет без пересмотра',
|
||
path: ['selectQuote'],
|
||
});
|
||
}
|
||
|
||
if (dealerPersonId && quoteId && productId) {
|
||
const {
|
||
data: { dealer_person },
|
||
} = await apolloClient.query({
|
||
query: CRMTypes.GetDealerPersonDocument,
|
||
variables: { dealerPersonId },
|
||
});
|
||
|
||
const {
|
||
data: { quote },
|
||
} = await apolloClient.query({
|
||
query: CRMTypes.GetQuoteDocument,
|
||
variables: { quoteId },
|
||
});
|
||
|
||
const maxCondition1 =
|
||
leaseObjectUsed === false &&
|
||
dealer_person?.evo_supplier_type !== 100_000_001 &&
|
||
quote?.evo_max_price_change &&
|
||
!partialVAT &&
|
||
plPriceRub - discountRub + addEquipmentPrice - importProgramSum >
|
||
quote.evo_max_price_change;
|
||
|
||
const maxCondition2 =
|
||
leaseObjectUsed === false &&
|
||
dealer_person?.evo_supplier_type !== 100_000_001 &&
|
||
quote?.evo_max_price_change &&
|
||
partialVAT &&
|
||
leaseObjectPriceWthtVAT >
|
||
quote.evo_max_price_change - (quote.evo_nds_in_price_supplier_currency || 0);
|
||
|
||
const maxCondition3 =
|
||
(leaseObjectUsed === true || dealer_person?.evo_supplier_type === 100_000_001) &&
|
||
quote?.evo_supplier_currency_price &&
|
||
plPriceRub - discountRub + addEquipmentPrice - importProgramSum >
|
||
quote.evo_supplier_currency_price -
|
||
(quote.evo_discount_supplier_currency || 0) +
|
||
(quote.evo_equip_price || 0) -
|
||
(quote.evo_program_import_subsidy_sum || 0);
|
||
|
||
const minCondition1 =
|
||
!partialVAT &&
|
||
quote?.evo_min_change_price &&
|
||
plPriceRub - discountRub + addEquipmentPrice - importProgramSum <
|
||
quote.evo_min_change_price;
|
||
|
||
const minCondition2 =
|
||
partialVAT &&
|
||
quote?.evo_min_change_price &&
|
||
leaseObjectPriceWthtVAT <
|
||
quote.evo_min_change_price - (quote.evo_nds_in_price_supplier_currency || 0);
|
||
|
||
if (maxCondition1 || maxCondition2) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message:
|
||
'Указанная стоимость предмета лизинга больше возможного изменения стоимости предмета лизинга при пересчете без пересмотра. ' +
|
||
'Уменьшите стоимость предмета лизинга',
|
||
path: ['tbxLeaseObjectPrice'],
|
||
});
|
||
} else if (maxCondition3) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message:
|
||
'При пересчете без пересмотра КП с ПЛ БУ или с непрофессиональным поставщиком недопустимо увеличение стоимости. Создайте новое КП и отправьте его на рассмотрение андеррайтингу для повторной проверки оценщиком.',
|
||
path: ['tbxLeaseObjectPrice'],
|
||
});
|
||
} else if (minCondition1 || minCondition2) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message:
|
||
'Указанная стоимость предмета лизинга меньше возможного изменения стоимости предмета лизинга при пересчете без пересмотра. ' +
|
||
'Увеличьте стоимость предмета лизинга',
|
||
path: ['tbxLeaseObjectPrice'],
|
||
});
|
||
}
|
||
}
|
||
|
||
if (quoteId) {
|
||
const {
|
||
data: { quote },
|
||
} = await apolloClient.query({
|
||
query: CRMTypes.GetQuoteDocument,
|
||
variables: { quoteId },
|
||
});
|
||
|
||
if (
|
||
firstPaymentPerc <
|
||
(quote?.evo_approved_first_payment || 0) + (quote?.evo_percent_subsidy || 0)
|
||
) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message: `Указанный первый платеж меньше одобренного ${quote?.evo_approved_first_payment}. При пересчете без пересмотра изменение первого платежа возможно только в большую сторону от одобренного значения`,
|
||
path: ['tbxFirstPaymentPerc'],
|
||
});
|
||
}
|
||
|
||
if (quote?.evo_recalc_limit && leaseObjectCount > quote.evo_recalc_limit) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message: 'Количество ПЛ превышает лимит пересчета без пересмотра',
|
||
path: ['tbxLeaseObjectCount'],
|
||
});
|
||
}
|
||
|
||
if (
|
||
quote?.evo_max_mass &&
|
||
((quote.evo_max_mass < MAX_MASS && maxMass >= MAX_MASS) ||
|
||
(quote?.evo_max_mass >= MAX_MASS && maxMass < MAX_MASS))
|
||
) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message:
|
||
'Указанная разрешенная макс. масса выходит из утвержденного диапазона. Для изменения параметра требуется пересмотр сделки',
|
||
path: ['tbxMaxMass'],
|
||
});
|
||
}
|
||
|
||
if (
|
||
leaseObjectCategory === 100_000_003 &&
|
||
quote?.evo_seats &&
|
||
((quote.evo_seats < VEHICLE_SEATS && countSeats >= VEHICLE_SEATS) ||
|
||
(quote.evo_seats >= VEHICLE_SEATS && countSeats < VEHICLE_SEATS))
|
||
) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message:
|
||
'Указанное кол-во мест выходит из утвержденного диапазона. Для изменения параметра требуется пересмотр сделки',
|
||
path: ['tbxCountSeats'],
|
||
});
|
||
}
|
||
|
||
if (quote?.evo_year && leaseObjectYear < quote.evo_year) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message: 'При пересчете без пересмотра год выпуска нельзя уменьшать',
|
||
path: ['tbxLeaseObjectYear'],
|
||
});
|
||
}
|
||
|
||
if (
|
||
quote?.evo_last_payment_perc &&
|
||
lastPaymentPerc > 1 &&
|
||
lastPaymentPerc > quote.evo_last_payment_perc
|
||
) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message:
|
||
'При пересчете без пересмотра последний платеж можно уменьшать или увеличивать до 1%',
|
||
path: ['tbxLastPaymentPerc'],
|
||
});
|
||
}
|
||
|
||
if (partialVAT !== quote?.evo_sale_without_nds) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message: 'Нельзя менять частичный НДС при пересчете без пересмотра',
|
||
path: ['selectProduct'],
|
||
});
|
||
}
|
||
|
||
if (quote?.evo_committee_quote === 100_000_000 && quote.evo_accept_quoteid) {
|
||
const {
|
||
data: { quote: accept_quote },
|
||
} = await apolloClient.query({
|
||
query: CRMTypes.GetQuoteDocument,
|
||
variables: { quoteId: quote.evo_accept_quoteid },
|
||
});
|
||
|
||
if (accept_quote?.evo_msfo_irr && IRR_Perc - accept_quote?.evo_msfo_irr > 0.1)
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message: 'Нельзя увеличивать IRR после рассмотрения предложения на КК',
|
||
path: ['tbxIRR_Perc'] as Elements[],
|
||
});
|
||
|
||
if (
|
||
accept_quote?.evo_power &&
|
||
Math.abs(leaseObjectMotorPower - accept_quote.evo_power) > 10
|
||
) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message:
|
||
'Нельзя корректировать мощность более чем на 10 л.с. после рассмотрения предложения на КК',
|
||
path: ['tbxLeaseObjectMotorPower'] as Elements[],
|
||
});
|
||
}
|
||
|
||
if (
|
||
accept_quote?.evo_engine_volume &&
|
||
Math.abs(engineVolume - accept_quote.evo_engine_volume) > 0.1
|
||
) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message:
|
||
'Нельзя корректировать объем двигателя более чем на 0.1 л после рассмотрения предложения на КК',
|
||
path: ['tbxEngineVolume'] as Elements[],
|
||
});
|
||
}
|
||
|
||
if (insNSIB && !accept_quote?.evo_nsib) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message: 'Нельзя включать в график НСИБ после рассмотрения предложения на КК',
|
||
path: ['selectInsNSIB'] as Elements[],
|
||
});
|
||
}
|
||
|
||
if (
|
||
technicalCard &&
|
||
!accept_quote?.evo_addproduct_types?.some((x) => x?.evo_product_type === 100_000_000)
|
||
) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message:
|
||
'Нельзя включать в график карту тех.помощи после рассмотрения предложения на КК',
|
||
path: ['selectTechnicalCard'] as Elements[],
|
||
});
|
||
}
|
||
|
||
if (
|
||
objectRegistration &&
|
||
objectRegistration !== accept_quote?.evo_db_accept_registration
|
||
) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message: 'Нельзя менять регистрацию после рассмотрения предложения на КК',
|
||
path: ['radioObjectRegistration'] as Elements[],
|
||
});
|
||
}
|
||
|
||
if (
|
||
insurance.values.fingap.insured === 100_000_001 &&
|
||
fingapRisks?.length > 0 &&
|
||
fingapRisks.some(
|
||
(fingapRisk) =>
|
||
!accept_quote?.evo_product_risks?.some(
|
||
(evo_product_risk) =>
|
||
fingapRisk.riskId === evo_product_risk?.evo_addproduct_typeid
|
||
)
|
||
)
|
||
) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message:
|
||
'Нельзя включать новые риски Safe Finance после рассмотрения предложения на КК',
|
||
path: ['fingap'],
|
||
});
|
||
}
|
||
|
||
if (
|
||
insurance.values.fingap.insured === 100_000_001 &&
|
||
accept_quote?.evo_fingap_payer &&
|
||
insurance.values.fingap.insured !== accept_quote?.evo_fingap_payer
|
||
) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message:
|
||
'Нельзя включать в график SafeFinance после рассмотрения предложения на КК',
|
||
path: ['insurance'],
|
||
});
|
||
}
|
||
|
||
if (
|
||
insurance.values.osago.insured === 100_000_001 &&
|
||
accept_quote?.evo_osago_payer &&
|
||
insurance.values.osago.insured !== accept_quote?.evo_osago_payer
|
||
) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message: 'Нельзя включать в график ОСАГО после рассмотрения предложения на КК',
|
||
path: ['insurance'],
|
||
});
|
||
}
|
||
|
||
if (
|
||
insurance.values.kasko.insured === 100_000_001 &&
|
||
accept_quote?.evo_kasko_payer &&
|
||
insurance.values.kasko.insured !== accept_quote?.evo_kasko_payer
|
||
) {
|
||
ctx.addIssue({
|
||
code: z.ZodIssueCode.custom,
|
||
message: 'Нельзя включать в график КАСКО после рассмотрения предложения на КК',
|
||
path: ['insurance'],
|
||
});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
);
|
||
}
|