Compare commits
15 Commits
dev
...
release/dy
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9a4612262 | ||
|
|
d4b0ae503f | ||
|
|
1dd23ea03d | ||
|
|
746166a59d | ||
|
|
c57fc73fdc | ||
|
|
c82144dc7e | ||
|
|
870d7b373b | ||
|
|
7797325f8c | ||
|
|
009c9fb5dd | ||
|
|
464e3cba8d | ||
|
|
d9c3c7e2a5 | ||
|
|
63462becc5 | ||
|
|
ba22659578 | ||
|
|
af5c9cb061 | ||
|
|
47807b7bda |
@ -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];
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
@ -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',
|
||||
|
||||
@ -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'],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@ -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,
|
||||
|
||||
55
apps/web/server/routers/calculate/lib/post-validation.ts
Normal file
55
apps/web/server/routers/calculate/lib/post-validation.ts
Normal 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,
|
||||
};
|
||||
}
|
||||
@ -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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user