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;
|
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 }) {
|
function getElementsErrors({ $calculation, $process }) {
|
||||||
return Object.values($calculation.$validation).map((validation) => {
|
return Object.values($calculation.$validation).map((validation) => {
|
||||||
const elementErrors = validation.getErrors();
|
const elementErrors = validation.getErrors();
|
||||||
const elementTitle = validation.params.err_title;
|
const elementTitle = validation.params.err_title;
|
||||||
|
|
||||||
return elementErrors.map(({ key, message }) => (
|
return getAlerts(elementErrors, elementTitle, $process);
|
||||||
<AlertWrapper>
|
|
||||||
<Alert
|
|
||||||
key={key}
|
|
||||||
type={$process.has('Unlimited') ? 'warning' : 'error'}
|
|
||||||
showIcon
|
|
||||||
message={Message(elementTitle, message)}
|
|
||||||
/>
|
|
||||||
</AlertWrapper>
|
|
||||||
));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPaymentsTableErrors({ $process, $tables }) {
|
function getTableErrors(tableName, { $process, $tables }) {
|
||||||
const { payments } = $tables;
|
const table = $tables[tableName];
|
||||||
const errors = payments.validation.getErrors();
|
const errors = table.validation.getErrors();
|
||||||
const title = payments.validation.params.err_title;
|
const title = table.validation.params.err_title;
|
||||||
|
|
||||||
return errors.map(({ key, message }) => (
|
return getAlerts(errors, title, $process);
|
||||||
<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>
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Errors = observer(() => {
|
const Errors = observer(() => {
|
||||||
@ -101,15 +62,16 @@ const Errors = observer(() => {
|
|||||||
);
|
);
|
||||||
const hasPaymentsErrors = $tables.payments.validation.hasErrors;
|
const hasPaymentsErrors = $tables.payments.validation.hasErrors;
|
||||||
const hasInsuranceErrors = $tables.insurance.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="Ошибок нет 🙂" />;
|
return <Alert type="success" showIcon message="Ошибок нет 🙂" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const elementsErrors = getElementsErrors(store);
|
const elementsErrors = getElementsErrors(store);
|
||||||
const paymentsErrors = getPaymentsTableErrors(store);
|
const paymentsErrors = getTableErrors('payments', store);
|
||||||
const insuranceErrors = getInsuranceTableErrors(store);
|
const insuranceErrors = getTableErrors('insurance', store);
|
||||||
const fingapErrors = getFingapTableErrors(store);
|
const fingapErrors = getTableErrors('fingap', store);
|
||||||
|
|
||||||
const errors = [...elementsErrors, ...paymentsErrors, ...insuranceErrors, ...fingapErrors];
|
const errors = [...elementsErrors, ...paymentsErrors, ...insuranceErrors, ...fingapErrors];
|
||||||
|
|
||||||
|
|||||||
@ -110,6 +110,25 @@ query GetQuote($quoteId: Uuid!) {
|
|||||||
evo_promotion
|
evo_promotion
|
||||||
evo_sale_without_nds
|
evo_sale_without_nds
|
||||||
link
|
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_coefficien_bonus_reducttion: Decimal
|
||||||
evo_comission_perc: Decimal
|
evo_comission_perc: Decimal
|
||||||
evo_comission_rub: Decimal
|
evo_comission_rub: Decimal
|
||||||
|
evo_committee_quote: Int
|
||||||
evo_contact_name: String
|
evo_contact_name: String
|
||||||
evo_cost_increace: Boolean
|
evo_cost_increace: Boolean
|
||||||
evo_cost_increase_perc: Decimal
|
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 type { ProcessContext } from '../types';
|
||||||
import { createValidationSchema } from './validation';
|
import { createValidationSchema } from './validation';
|
||||||
import type { Elements } from '@/Components/Calculation/config/map/values';
|
import type { Elements } from '@/Components/Calculation/config/map/values';
|
||||||
|
import * as CRMTypes from '@/graphql/crm.types';
|
||||||
import { createValidationReaction } from '@/process/tools';
|
import { createValidationReaction } from '@/process/tools';
|
||||||
import { reaction } from 'mobx';
|
import { reaction } from 'mobx';
|
||||||
|
|
||||||
export function common({ store }: ProcessContext) {
|
export function common({ store, apolloClient }: ProcessContext) {
|
||||||
const { $calculation, $tables } = store;
|
const { $calculation, $tables } = store;
|
||||||
|
|
||||||
reaction(
|
reaction(
|
||||||
@ -65,6 +66,7 @@ export function common({ store }: ProcessContext) {
|
|||||||
// 'tbxLastPaymentRub',
|
// 'tbxLastPaymentRub',
|
||||||
'cbxPartialVAT',
|
'cbxPartialVAT',
|
||||||
];
|
];
|
||||||
|
|
||||||
reaction(
|
reaction(
|
||||||
() => $calculation.element('cbxRecalcWithRevision').getValue(),
|
() => $calculation.element('cbxRecalcWithRevision').getValue(),
|
||||||
(recalcWithRevision) => {
|
(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[] = [
|
const agents: Elements[] = [
|
||||||
'selectCalcBrokerRewardCondition',
|
'selectCalcBrokerRewardCondition',
|
||||||
'selectCalcDoubleAgentRewardCondition',
|
'selectCalcDoubleAgentRewardCondition',
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
/* eslint-disable sonarjs/cognitive-complexity */
|
/* eslint-disable sonarjs/cognitive-complexity */
|
||||||
/* eslint-disable complexity */
|
/* eslint-disable complexity */
|
||||||
import type { ValidationContext } from '../types';
|
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 ValuesSchema from '@/config/schema/values';
|
||||||
import { MAX_MASS, VEHICLE_SEATS } from '@/constants/values';
|
import { MAX_MASS, VEHICLE_SEATS } from '@/constants/values';
|
||||||
import * as CRMTypes from '@/graphql/crm.types';
|
import * as CRMTypes from '@/graphql/crm.types';
|
||||||
@ -8,221 +11,367 @@ import { z } from 'zod';
|
|||||||
|
|
||||||
export function createValidationSchema({ apolloClient }: ValidationContext) {
|
export function createValidationSchema({ apolloClient }: ValidationContext) {
|
||||||
return ValuesSchema.pick({
|
return ValuesSchema.pick({
|
||||||
|
IRR_Perc: true,
|
||||||
addEquipmentPrice: true,
|
addEquipmentPrice: true,
|
||||||
countSeats: true,
|
countSeats: true,
|
||||||
dealerPerson: true,
|
dealerPerson: true,
|
||||||
discountRub: true,
|
discountRub: true,
|
||||||
|
engineVolume: true,
|
||||||
firstPaymentPerc: true,
|
firstPaymentPerc: true,
|
||||||
importProgramSum: true,
|
importProgramSum: true,
|
||||||
|
insNSIB: true,
|
||||||
lastPaymentPerc: true,
|
lastPaymentPerc: true,
|
||||||
leaseObjectCategory: true,
|
leaseObjectCategory: true,
|
||||||
leaseObjectCount: true,
|
leaseObjectCount: true,
|
||||||
|
leaseObjectMotorPower: true,
|
||||||
leaseObjectPriceWthtVAT: true,
|
leaseObjectPriceWthtVAT: true,
|
||||||
leaseObjectUsed: true,
|
leaseObjectUsed: true,
|
||||||
leaseObjectYear: true,
|
leaseObjectYear: true,
|
||||||
maxMass: true,
|
maxMass: true,
|
||||||
|
objectRegistration: true,
|
||||||
partialVAT: true,
|
partialVAT: true,
|
||||||
plPriceRub: true,
|
plPriceRub: true,
|
||||||
product: true,
|
product: true,
|
||||||
quote: true,
|
quote: true,
|
||||||
recalcWithRevision: true,
|
recalcWithRevision: true,
|
||||||
}).superRefine(
|
technicalCard: true,
|
||||||
async (
|
})
|
||||||
{
|
.extend({
|
||||||
addEquipmentPrice,
|
fingap: FinGAPSchema,
|
||||||
dealerPerson: dealerPersonId,
|
insurance: InsuranceSchema,
|
||||||
importProgramSum,
|
})
|
||||||
leaseObjectPriceWthtVAT,
|
.superRefine(
|
||||||
leaseObjectUsed,
|
async (
|
||||||
product: productId,
|
{
|
||||||
quote: quoteId,
|
addEquipmentPrice,
|
||||||
recalcWithRevision,
|
dealerPerson: dealerPersonId,
|
||||||
discountRub,
|
importProgramSum,
|
||||||
plPriceRub,
|
leaseObjectPriceWthtVAT,
|
||||||
firstPaymentPerc,
|
leaseObjectUsed,
|
||||||
leaseObjectCount,
|
product: productId,
|
||||||
maxMass,
|
quote: quoteId,
|
||||||
countSeats,
|
recalcWithRevision,
|
||||||
leaseObjectYear,
|
discountRub,
|
||||||
lastPaymentPerc,
|
plPriceRub,
|
||||||
leaseObjectCategory,
|
firstPaymentPerc,
|
||||||
partialVAT,
|
leaseObjectCount,
|
||||||
},
|
maxMass,
|
||||||
ctx
|
countSeats,
|
||||||
) => {
|
leaseObjectYear,
|
||||||
if (!recalcWithRevision) {
|
lastPaymentPerc,
|
||||||
return;
|
leaseObjectCategory,
|
||||||
}
|
partialVAT,
|
||||||
|
IRR_Perc,
|
||||||
|
leaseObjectMotorPower,
|
||||||
|
engineVolume,
|
||||||
|
insNSIB,
|
||||||
|
technicalCard,
|
||||||
|
objectRegistration,
|
||||||
|
fingap: fingapRisks,
|
||||||
|
insurance,
|
||||||
|
},
|
||||||
|
ctx
|
||||||
|
) => {
|
||||||
|
if (!recalcWithRevision) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!quoteId) {
|
if (!quoteId) {
|
||||||
ctx.addIssue({
|
|
||||||
code: z.ZodIssueCode.custom,
|
|
||||||
message: 'Не указано предложение, по которому осуществляется Пересчет без пересмотра',
|
|
||||||
path: ['selectQuote'],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dealerPersonId && quoteId && productId) {
|
|
||||||
const {
|
|
||||||
data: { account: dealerPerson },
|
|
||||||
} = await apolloClient.query({
|
|
||||||
query: CRMTypes.GetDealerPersonDocument,
|
|
||||||
variables: { dealerPersonId },
|
|
||||||
});
|
|
||||||
|
|
||||||
const {
|
|
||||||
data: { quote },
|
|
||||||
} = await apolloClient.query({
|
|
||||||
query: CRMTypes.GetQuoteDocument,
|
|
||||||
variables: { quoteId },
|
|
||||||
});
|
|
||||||
|
|
||||||
const maxCondition1 =
|
|
||||||
leaseObjectUsed === false &&
|
|
||||||
dealerPerson?.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 &&
|
|
||||||
dealerPerson?.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 || dealerPerson?.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({
|
ctx.addIssue({
|
||||||
code: z.ZodIssueCode.custom,
|
code: z.ZodIssueCode.custom,
|
||||||
message:
|
message: 'Не указано предложение, по которому осуществляется Пересчет без пересмотра',
|
||||||
'Указанная стоимость предмета лизинга больше возможного изменения стоимости предмета лизинга при пересчете без пересмотра. ' +
|
path: ['selectQuote'],
|
||||||
'Уменьшите стоимость предмета лизинга',
|
|
||||||
path: ['tbxLeaseObjectPrice'],
|
|
||||||
});
|
});
|
||||||
} else if (maxCondition3) {
|
}
|
||||||
ctx.addIssue({
|
|
||||||
code: z.ZodIssueCode.custom,
|
if (dealerPersonId && quoteId && productId) {
|
||||||
message:
|
const {
|
||||||
'При пересчете без пересмотра КП с ПЛ БУ или с непрофессиональным поставщиком недопустимо увеличение стоимости. Создайте новое КП и отправьте его на рассмотрение андеррайтингу для повторной проверки оценщиком.',
|
data: { account: dealerPerson },
|
||||||
path: ['tbxLeaseObjectPrice'],
|
} = await apolloClient.query({
|
||||||
|
query: CRMTypes.GetDealerPersonDocument,
|
||||||
|
variables: { dealerPersonId },
|
||||||
});
|
});
|
||||||
} else if (minCondition1 || minCondition2) {
|
|
||||||
ctx.addIssue({
|
const {
|
||||||
code: z.ZodIssueCode.custom,
|
data: { quote },
|
||||||
message:
|
} = await apolloClient.query({
|
||||||
'Указанная стоимость предмета лизинга меньше возможного изменения стоимости предмета лизинга при пересчете без пересмотра. ' +
|
query: CRMTypes.GetQuoteDocument,
|
||||||
'Увеличьте стоимость предмета лизинга',
|
variables: { quoteId },
|
||||||
path: ['tbxLeaseObjectPrice'],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const maxCondition1 =
|
||||||
|
leaseObjectUsed === false &&
|
||||||
|
dealerPerson?.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 &&
|
||||||
|
dealerPerson?.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 || dealerPerson?.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'],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
);
|
||||||
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'],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { router } from '../../trpc';
|
import { router } from '../../trpc';
|
||||||
|
import { validateResults } from './lib/post-validation';
|
||||||
import { createRequestData } from './lib/request';
|
import { createRequestData } from './lib/request';
|
||||||
import { transformCalculateResults } from './lib/transform';
|
import { transformCalculateResults } from './lib/transform';
|
||||||
import { validate } from './lib/validation';
|
import { validate } from './lib/validation';
|
||||||
@ -52,6 +53,20 @@ export const calculateRouter = router({
|
|||||||
|
|
||||||
const calculateResult = await calculate(requestData);
|
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({
|
const result = transformCalculateResults({
|
||||||
calculateInput: input,
|
calculateInput: input,
|
||||||
requestCalculate: requestData,
|
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 */
|
/* eslint-disable canonical/sort-keys */
|
||||||
import { protectedProcedure } from '../../procedure';
|
import { protectedProcedure } from '../../procedure';
|
||||||
import { router } from '../../trpc';
|
import { router } from '../../trpc';
|
||||||
|
import { validateResults } from '../calculate/lib/post-validation';
|
||||||
import { createRequestData } from '../calculate/lib/request';
|
import { createRequestData } from '../calculate/lib/request';
|
||||||
import { transformCalculateResults } from '../calculate/lib/transform';
|
import { transformCalculateResults } from '../calculate/lib/transform';
|
||||||
import { validate } from '../calculate/lib/validation';
|
import { validate } from '../calculate/lib/validation';
|
||||||
@ -147,6 +148,20 @@ export const quoteRouter = router({
|
|||||||
|
|
||||||
const calculateResult = await calculate(requestData);
|
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({
|
const requestCreateKP = compatRequestCreateKP({
|
||||||
domainName: user.domainName,
|
domainName: user.domainName,
|
||||||
finGAP: input.fingap,
|
finGAP: input.fingap,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user