Compare commits

...

15 Commits

Author SHA1 Message Date
vchikalkin
e9a4612262 fix: Нельзя включать новые риски Safe Finance после рассмотрения предложения на КК 2024-05-14 11:04:15 +03:00
vchikalkin
d4b0ae503f fix: Нельзя увеличивать бонус МПЛ после рассмотрения предложения на КК 2024-05-14 10:43:03 +03:00
vchikalkin
1dd23ea03d добавили проверку fingap.insured === 100_000_001 в проверку на новые риски 2024-05-14 10:34:33 +03:00
vchikalkin
746166a59d fix: Нельзя включать новые риски Safe Finance после рассмотрения предложения на КК 2024-05-14 10:15:01 +03:00
vchikalkin
c57fc73fdc Validation.jsx: simplify code 2024-05-13 18:09:52 +03:00
vchikalkin
c82144dc7e fix show fingap alerts 2024-05-13 18:08:00 +03:00
vchikalkin
870d7b373b fix quote?.evo_committee_quote check 2024-05-13 14:20:44 +03:00
vchikalkin
7797325f8c По итогам расчета графика платежей перед выводм результата расчета заложить валидацию
если Пересчете без пересмотра recalcWithRevision = True и если в Предложении selectQuote в поле "КП по итогам КК" = Да

и значение из итогов расчета npvBonusExpensesColumn (3я строка)/ (1 + PreparedValue.SalaryRate) больше значения суммы в полях Сумма бонуса МПЛ за лизинг, руб. quote.evo_leasing_bonus_summ + Сумма бонуса МПЛ за РАТ, руб quote.evo_card_bonus_summ + Сумма бонуса МПЛ за НСИБ, руб. quote.evo_nsib_bonus_summ из Предложения , которое указано в Предложении selectQuote в поле Одобренное КА quote.evo_accept_quoteid, больше 100,

то выводить сообщение "Нельзя увеличивать бонус МПЛ после рассмотрения предложения на КК"
2024-05-08 14:03:27 +03:00
vchikalkin
009c9fb5dd На изменение Плательщик insuredFinGAP в строке SafeFinance в таблице страхования добавить проверку:
если Пересчете без пересмотра recalcWithRevision = True и если в Предложении selectQuote в поле "КП по итогам КК" = Да

и значение insuredFinGAP = 100 000 001 Лизингодатель и в поле Плательщик ФинGAP  evo_fingap_payer значение не равно 100 000 001 Лизингодатель из Предложения , которое указано в Предложении selectQuote в поле Одобренное КА quote.evo_accept_quoteid,

то выводить сообщение "Нельзя включать в график SafeFinance после рассмотрения предложения на КК"

На изменение Плательщик insuredOSAGO  в строке ОСАГО в таблице страхования добавить проверку:

если Пересчете без пересмотра recalcWithRevision = True и если в Предложении selectQuote в поле "КП по итогам КК" = Да

и значение insuredOSAGO = 100 000 001 Лизингодатель и в поле Плательщик ОСАГО evo_osago_payer значение не равно 100 000 001 Лизингодатель из Предложения , которое указано в Предложении selectQuote в поле Одобренное КА quote.evo_accept_quoteid,

то выводить сообщение "Нельзя включать в график ОСАГО после рассмотрения предложения на КК"

На изменение Плательщик insuredKASKO  в строке КАСКО в таблице страхования добавить проверку:

если Пересчете без пересмотра recalcWithRevision = True и если в Предложении selectQuote в поле "КП по итогам КК" = Да

и значение insuredKASKO  = 100 000 001 Лизингодатель и в поле Плательщик КАСКО evo_kasko_payer значение не равно 100 000 001 Лизингодатель из Предложения , которое указано в Предложении selectQuote в поле Одобренное КА quote.evo_accept_quoteid,

то выводить сообщение "Нельзя включать в график КАСКО после рассмотрения предложения на КК"
2024-05-08 13:22:32 +03:00
vchikalkin
464e3cba8d На изменение Суммы за 1-й период inscostFinGAP в строке SafeFinance в таблице страхования добавить проверку:
если Пересчете без пересмотра recalcWithRevision = True и если в Предложении selectQuote в поле "КП по итогам КК" = Да

и выбранные риски SafeFinance по Типу доп.продукта evo_addproduct_typeid содержатся в связанных Рисках по продукту evo_product_risk с Предложением , которое указано в Предложении selectQuote в поле Одобренное КА quote.evo_accept_quoteid,

то выводить сообщение "Нельзя включать новые риски SafeFinance после рассмотрения предложения на КК"
2024-05-08 13:01:56 +03:00
vchikalkin
d9c3c7e2a5 На изменение параметра На кого регистрация ТС objectRegistration добавить проверку:
если Пересчете без пересмотра recalcWithRevision = True и если в Предложении selectQuote в поле "КП по итогам КК" = Да

и На кого регистрация ТС objectRegistration  не равно значение в поле Регистрируется на (по итогам проверки УЭБ) quote.evo_db_accept_registration из Предложения , которое указано в Предложении selectQuote в поле Одобренное КА quote.evo_accept_quoteid,

то выводить сообщение "Нельзя менять регистрацию после рассмотрения предложения на КК"
2024-05-08 12:29:36 +03:00
vchikalkin
63462becc5 На изменение параметра НСИБ insNSIB добавить проверку:
если Пересчете без пересмотра recalcWithRevision = True и если в Предложении selectQuote в поле "КП по итогам КК" = Да

и НСИБ insNSIB содержит значение, а  в Предложении selectQuote, в поле Одобренное КА quote.evo_accept_quoteid указана запись Предложение, у которой в поле НСИБ quote.evo_nsib значение = Нет,

то выводить сообщение "Нельзя включать в график НСИБ после рассмотрения предложения на КК"

На изменение параметра Карта техпомощи technicalCard добавить проверку:

если Пересчете без пересмотра recalcWithRevision = True и если в Предложении selectQuote в поле "КП по итогам КК" = Да

и Карта техпомощи technicalCard содержит значение, а  в Предложении selectQuote, в поле Одобренное КА quote.evo_accept_quoteid указана запись Предложение, у которой в связанных Типах доп.продуктов evo_addproduct_type отсутствует запись, у которой Тип продукта evo_product_type = Карта тех.помощи 100 000 000,

то выводить сообщение "Нельзя включать в график карту тех.помощи после рассмотрения предложения на КК"
2024-05-08 12:27:44 +03:00
vchikalkin
ba22659578 На изменение параметра Мощность л.с. leaseObjectMotorPower добавить проверку:
если Пересчете без пересмотра recalcWithRevision = True и если в Предложении selectQuote в поле "КП по итогам КК" = Да

и текущее значение Мощность л.с. leaseObjectMotorPower минус Мощность л.с. quote.evo_power из Предложения , которое указано в Предложении selectQuote в поле Одобренное КА quote.evo_accept_quoteid, больше 10 по модулю,

то выводить сообщение "Нельзя корректировать мощность более чем на 10 л.с. после рассмотрения предложения на КК"

На изменение параметра Объем двигателя engineVolume добавить проверку:

если Пересчете без пересмотра recalcWithRevision = True и если в Предложении selectQuote в поле "КП по итогам КК" = Да

и текущее значение Объем двигателя engineVolume  минус Объем двигателя, л quote.evo_engine_volume из Предложения , которое указано в Предложении selectQuote в поле Одобренное КА quote.evo_accept_quoteid, больше 0.1 по модулю,

то выводить сообщение "Нельзя корректировать объем двигателя более чем на 0.1 л после рассмотрения предложения на КК"
2024-05-08 12:18:01 +03:00
vchikalkin
af5c9cb061 На изменение параметра IRR tbxIRR_Perc добавить проверку:
если Пересчете без пересмотра recalcWithRevision = True и если в Предложении selectQuote в поле "КП по итогам КК" = Да

и текущее значение IRR tbxIRR_Perc минус "IRR МСФО (номинал), %" quote.evo_msfo_irr для из Предложения , которое указано в Предложении selectQuote в поле Одобренное КА quote.evo_accept_quoteid, больше 0.1,

то выводить сообщение "Нельзя увеличивать IRR после рассмотрения предложения на КК"
2024-05-08 12:03:55 +03:00
vchikalkin
47807b7bda Закрыть на редактирование поля при Пересчете без пересмотра recalcWithRevision = True и если в Предложении selectQuote в поле "КП по итогам КК" = Да
Срок поставки* radioDeliveryTime
Цель использования*  selectLeaseObjectUseFor
Тип двигателя selectEngineType
Децентрализованное страхование cbxInsDecentral
2024-05-08 11:55:34 +03:00
9 changed files with 520 additions and 256 deletions

View File

@ -23,73 +23,34 @@ const AlertWrapper = styled(Box)`
margin: 0 0 5px 0;
`;
function getAlerts(errors, title, $process) {
return errors.map(({ key, message }) => (
<AlertWrapper>
<Alert
key={key}
type={$process.has('Unlimited') ? 'warning' : 'error'}
showIcon
message={Message(title, message)}
/>
</AlertWrapper>
));
}
function getElementsErrors({ $calculation, $process }) {
return Object.values($calculation.$validation).map((validation) => {
const elementErrors = validation.getErrors();
const elementTitle = validation.params.err_title;
return elementErrors.map(({ key, message }) => (
<AlertWrapper>
<Alert
key={key}
type={$process.has('Unlimited') ? 'warning' : 'error'}
showIcon
message={Message(elementTitle, message)}
/>
</AlertWrapper>
));
return getAlerts(elementErrors, elementTitle, $process);
});
}
function getPaymentsTableErrors({ $process, $tables }) {
const { payments } = $tables;
const errors = payments.validation.getErrors();
const title = payments.validation.params.err_title;
function getTableErrors(tableName, { $process, $tables }) {
const table = $tables[tableName];
const errors = table.validation.getErrors();
const title = table.validation.params.err_title;
return errors.map(({ key, message }) => (
<AlertWrapper>
<Alert
key={key}
type={$process.has('Unlimited') ? 'warning' : 'error'}
showIcon
message={Message(title, message)}
/>
</AlertWrapper>
));
}
function getInsuranceTableErrors({ $process, $tables }) {
const { insurance } = $tables;
const errors = insurance.validation.getErrors();
const title = insurance.validation.params.err_title;
return errors.map(({ key, message }) => (
<AlertWrapper>
<Alert
key={key}
type={$process.has('Unlimited') ? 'warning' : 'error'}
showIcon
message={Message(title, message)}
/>
</AlertWrapper>
));
}
function getFingapTableErrors({ $process, $tables }) {
const { fingap } = $tables;
const errors = fingap.validation.getErrors();
const title = fingap.validation.params.err_title;
return errors.map(({ key, message }) => (
<AlertWrapper>
<Alert
key={key}
type={$process.has('Unlimited') ? 'warning' : 'error'}
showIcon
message={Message(title, message)}
/>
</AlertWrapper>
));
return getAlerts(errors, title, $process);
}
const Errors = observer(() => {
@ -101,15 +62,16 @@ const Errors = observer(() => {
);
const hasPaymentsErrors = $tables.payments.validation.hasErrors;
const hasInsuranceErrors = $tables.insurance.validation.hasErrors;
const hasFingapErrors = $tables.fingap.validation.hasErrors;
if (!hasElementsErrors && !hasPaymentsErrors && !hasInsuranceErrors) {
if (!hasElementsErrors && !hasPaymentsErrors && !hasInsuranceErrors && !hasFingapErrors) {
return <Alert type="success" showIcon message="Ошибок нет 🙂" />;
}
const elementsErrors = getElementsErrors(store);
const paymentsErrors = getPaymentsTableErrors(store);
const insuranceErrors = getInsuranceTableErrors(store);
const fingapErrors = getFingapTableErrors(store);
const paymentsErrors = getTableErrors('payments', store);
const insuranceErrors = getTableErrors('insurance', store);
const fingapErrors = getTableErrors('fingap', store);
const errors = [...elementsErrors, ...paymentsErrors, ...insuranceErrors, ...fingapErrors];

View File

@ -110,6 +110,25 @@ query GetQuote($quoteId: Uuid!) {
evo_promotion
evo_sale_without_nds
link
evo_committee_quote
evo_msfo_irr
evo_accept_quoteid
evo_power
evo_engine_volume
evo_nsib
evo_addproduct_types {
evo_product_type
}
evo_db_accept_registration
evo_product_risks {
evo_addproduct_typeid
}
evo_fingap_payer
evo_osago_payer
evo_kasko_payer
evo_leasing_bonus_summ
evo_card_bonus_summ
evo_nsib_bonus_summ
}
}

View File

@ -2523,6 +2523,7 @@ type quote {
evo_coefficien_bonus_reducttion: Decimal
evo_comission_perc: Decimal
evo_comission_rub: Decimal
evo_committee_quote: Int
evo_contact_name: String
evo_cost_increace: Boolean
evo_cost_increase_perc: Decimal

File diff suppressed because one or more lines are too long

View File

@ -1,10 +1,11 @@
import type { ProcessContext } from '../types';
import { createValidationSchema } from './validation';
import type { Elements } from '@/Components/Calculation/config/map/values';
import * as CRMTypes from '@/graphql/crm.types';
import { createValidationReaction } from '@/process/tools';
import { reaction } from 'mobx';
export function common({ store }: ProcessContext) {
export function common({ store, apolloClient }: ProcessContext) {
const { $calculation, $tables } = store;
reaction(
@ -65,6 +66,7 @@ export function common({ store }: ProcessContext) {
// 'tbxLastPaymentRub',
'cbxPartialVAT',
];
reaction(
() => $calculation.element('cbxRecalcWithRevision').getValue(),
(recalcWithRevision) => {
@ -79,7 +81,53 @@ export function common({ store }: ProcessContext) {
}
}
);
}
{
/**
* Закрыть на редактирование поля при Пересчете без пересмотра recalcWithRevision = True и если в Предложении selectQuote в поле "КП по итогам КК" = Да
* Срок поставки* radioDeliveryTime
* Цель использования* selectLeaseObjectUseFor
* Тип двигателя selectEngineType
* Децентрализованное страхование cbxInsDecentral
*/
const elements: Elements[] = [
'radioDeliveryTime',
'selectLeaseObjectUseFor',
'selectEngineType',
'cbxInsDecentral',
];
reaction(
() => $calculation.$values.getValues(['recalcWithRevision', 'quote']),
async ({ recalcWithRevision, quote: quoteId }) => {
if (!recalcWithRevision || !quoteId) {
elements.forEach((elementName) => $calculation.$status.clearOverridedStatus(elementName));
return;
}
const {
data: { quote },
} = await apolloClient.query({
query: CRMTypes.GetQuoteDocument,
variables: {
quoteId,
},
});
if (quote?.evo_committee_quote === 100_000_000) {
elements.forEach((elementName) =>
$calculation.$status.overrideStatus(elementName, 'Disabled')
);
} else {
elements.forEach((elementName) => $calculation.$status.clearOverridedStatus(elementName));
}
}
);
}
{
const agents: Elements[] = [
'selectCalcBrokerRewardCondition',
'selectCalcDoubleAgentRewardCondition',

View File

@ -1,6 +1,9 @@
/* 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';
@ -8,25 +11,36 @@ 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,
}).superRefine(
technicalCard: true,
})
.extend({
fingap: FinGAPSchema,
insurance: InsuranceSchema,
})
.superRefine(
async (
{
addEquipmentPrice,
@ -47,6 +61,14 @@ export function createValidationSchema({ apolloClient }: ValidationContext) {
lastPaymentPerc,
leaseObjectCategory,
partialVAT,
IRR_Perc,
leaseObjectMotorPower,
engineVolume,
insNSIB,
technicalCard,
objectRegistration,
fingap: fingapRisks,
insurance,
},
ctx
) => {
@ -222,6 +244,133 @@ export function createValidationSchema({ apolloClient }: ValidationContext) {
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'],
});
}
}
}
}
);

View File

@ -1,4 +1,5 @@
import { router } from '../../trpc';
import { validateResults } from './lib/post-validation';
import { createRequestData } from './lib/request';
import { transformCalculateResults } from './lib/transform';
import { validate } from './lib/validation';
@ -52,6 +53,20 @@ export const calculateRouter = router({
const calculateResult = await calculate(requestData);
const postValidationResult = await validateResults({
calculateResult,
context: {
apolloClient,
queryClient,
user: ctx.user,
},
input,
});
if (postValidationResult.success === false) {
throw new HttpError(postValidationResult.message, 400);
}
const result = transformCalculateResults({
calculateInput: input,
requestCalculate: requestData,

View File

@ -0,0 +1,55 @@
import type { CalculateInput, Context } from '../types';
import type { ResponseCalculate } from '@/api/core/types';
import * as CRMTypes from '@/graphql/crm.types';
export async function validateResults({
input,
context,
calculateResult,
}: {
calculateResult: ResponseCalculate;
context: Context;
input: CalculateInput;
}) {
const { recalcWithRevision, quote: quoteId } = input.values;
if (recalcWithRevision && quoteId) {
const { apolloClient } = context;
const {
data: { quote },
} = await apolloClient.query({
query: CRMTypes.GetQuoteDocument,
variables: {
quoteId,
},
});
if (quote?.evo_committee_quote === 100_000_000 && quote.evo_accept_quoteid) {
const { preparedValues } = calculateResult;
const { npvBonusExpensesColumn } = calculateResult.columns;
const {
data: { quote: accept_quote },
} = await apolloClient.query({
query: CRMTypes.GetQuoteDocument,
variables: { quoteId: quote.evo_accept_quoteid },
});
if (
Math.abs(npvBonusExpensesColumn.values.at(2) || 0) / (1 + preparedValues.salaryRate) -
(accept_quote?.evo_leasing_bonus_summ || 0) >
100
) {
return {
message: 'Нельзя увеличивать бонус МПЛ после рассмотрения предложения на КК',
success: false,
};
}
}
}
return {
message: '',
success: true,
};
}

View File

@ -1,6 +1,7 @@
/* eslint-disable canonical/sort-keys */
import { protectedProcedure } from '../../procedure';
import { router } from '../../trpc';
import { validateResults } from '../calculate/lib/post-validation';
import { createRequestData } from '../calculate/lib/request';
import { transformCalculateResults } from '../calculate/lib/transform';
import { validate } from '../calculate/lib/validation';
@ -147,6 +148,20 @@ export const quoteRouter = router({
const calculateResult = await calculate(requestData);
const postValidationResult = await validateResults({
calculateResult,
context: {
apolloClient,
queryClient,
user: ctx.user,
},
input,
});
if (postValidationResult.success === false) {
throw new HttpError(postValidationResult.message, 400);
}
const requestCreateKP = compatRequestCreateKP({
domainName: user.domainName,
finGAP: input.fingap,