calculate pt.1: add server validation
This commit is contained in:
parent
9d45a7bff0
commit
8994cd8ec8
@ -1,4 +1,5 @@
|
||||
import type { Elements } from '../config/map/actions';
|
||||
import { useProcessContext } from '@/process/hooks';
|
||||
import { useStatus } from '@/stores/calculation/statuses/hooks';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import type { ComponentType } from 'react';
|
||||
@ -15,9 +16,12 @@ export default function buildAction<T>(
|
||||
return observer((props: T) => {
|
||||
const status = useStatus(elementName);
|
||||
|
||||
const context = useProcessContext();
|
||||
|
||||
return (
|
||||
<Component
|
||||
action={() => import(`process/${processName}/action`).then((module) => module.action())}
|
||||
action={() =>
|
||||
import(`process/${processName}/action`).then((module) => module.action(context))}
|
||||
status={status}
|
||||
{...props}
|
||||
/>
|
||||
|
||||
@ -1,14 +1,12 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export const RiskSchema = z
|
||||
.object({
|
||||
calcType: z.number(),
|
||||
key: z.string(),
|
||||
keys: z.array(z.string()).optional(),
|
||||
premium: z.number(),
|
||||
premiumPerc: z.number(),
|
||||
riskId: z.string(),
|
||||
riskName: z.string(),
|
||||
sum: z.number(),
|
||||
})
|
||||
.strict();
|
||||
export const RiskSchema = z.object({
|
||||
calcType: z.number(),
|
||||
key: z.string(),
|
||||
keys: z.array(z.string()).optional(),
|
||||
premium: z.number(),
|
||||
premiumPerc: z.number(),
|
||||
riskId: z.string(),
|
||||
riskName: z.string(),
|
||||
sum: z.number(),
|
||||
});
|
||||
|
||||
@ -2,13 +2,19 @@ import { z } from 'zod';
|
||||
|
||||
export const KeysSchema = z.enum(['osago', 'kasko', 'fingap']);
|
||||
|
||||
export const RowSchema = z
|
||||
.object({
|
||||
insCost: z.number(),
|
||||
insTerm: z.number().nullable(),
|
||||
insuranceCompany: z.string().nullable(),
|
||||
insured: z.number().nullable(),
|
||||
key: KeysSchema,
|
||||
policyType: z.string(),
|
||||
})
|
||||
.strict();
|
||||
export const RowSchema = z.object({
|
||||
insCost: z.number(),
|
||||
insTerm: z.number().nullable(),
|
||||
insuranceCompany: z.string().nullable(),
|
||||
insured: z.number().nullable(),
|
||||
key: KeysSchema,
|
||||
policyType: z.string(),
|
||||
});
|
||||
|
||||
export const InsuranceSchema = z.object({
|
||||
values: z.object({
|
||||
fingap: RowSchema,
|
||||
kasko: RowSchema,
|
||||
osago: RowSchema,
|
||||
}),
|
||||
});
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const PaymentsSchema = z
|
||||
.object({
|
||||
values: z.number().array(),
|
||||
})
|
||||
.strict();
|
||||
const PaymentsSchema = z.object({
|
||||
values: z.number().array(),
|
||||
});
|
||||
|
||||
export default PaymentsSchema;
|
||||
|
||||
@ -1,150 +1,148 @@
|
||||
/* eslint-disable canonical/sort-keys */
|
||||
import { z } from 'zod';
|
||||
|
||||
const ValuesSchema = z
|
||||
.object({
|
||||
addEquipmentPrice: z.number(),
|
||||
balanceHolder: z.number().nullable(),
|
||||
bonusCoefficient: z.number(),
|
||||
brand: z.string().nullable(),
|
||||
calcBroker: z.string().nullable(),
|
||||
calcBrokerRewardCondition: z.string().nullable(),
|
||||
calcBrokerRewardSum: z.number(),
|
||||
calcDoubleAgent: z.string().nullable(),
|
||||
calcDoubleAgentRewardCondition: z.string().nullable(),
|
||||
calcDoubleAgentRewardSumm: z.number(),
|
||||
calcFinDepartment: z.string().nullable(),
|
||||
calcType: z.number().nullable(),
|
||||
clientRisk: z.string().nullable(),
|
||||
clientType: z.string().nullable(),
|
||||
comissionPerc: z.number(),
|
||||
comissionRub: z.number(),
|
||||
configuration: z.string().nullable(),
|
||||
costIncrease: z.boolean(),
|
||||
countSeats: z.number(),
|
||||
creditRate: z.number(),
|
||||
dealer: z.string().nullable(),
|
||||
dealerBroker: z.string().nullable(),
|
||||
dealerBrokerRewardCondition: z.string().nullable(),
|
||||
dealerBrokerRewardSumm: z.number(),
|
||||
dealerPerson: z.string().nullable(),
|
||||
dealerRewardCondition: z.string().nullable(),
|
||||
dealerRewardSumm: z.number(),
|
||||
deliveryTime: z.number().nullable(),
|
||||
disableChecks: z.boolean(),
|
||||
engineHours: z.number(),
|
||||
engineType: z.number().nullable(),
|
||||
engineVolume: z.number(),
|
||||
finDepartmentRewardCondtion: z.string().nullable(),
|
||||
finDepartmentRewardSumm: z.number(),
|
||||
firstPaymentPerc: z.number(),
|
||||
firstPaymentRub: z.number(),
|
||||
fuelCard: z.string().nullable(),
|
||||
fullPriceWithDiscount: z.boolean(),
|
||||
GPSBrand: z.string().nullable(),
|
||||
GPSModel: z.string().nullable(),
|
||||
graphType: z.number().nullable(),
|
||||
highSeasonStart: z.number().nullable(),
|
||||
importerRewardPerc: z.number(),
|
||||
importerRewardRub: z.number(),
|
||||
importProgram: z.string().nullable(),
|
||||
importProgramSum: z.number(),
|
||||
indAgent: z.string().nullable(),
|
||||
indAgentRewardCondition: z.string().nullable(),
|
||||
indAgentRewardSumm: z.number(),
|
||||
insAgeDrivers: z.number(),
|
||||
insDecentral: z.boolean(),
|
||||
insExpDrivers: z.number(),
|
||||
insFranchise: z.number(),
|
||||
insNSIB: z.string().nullable(),
|
||||
insUnlimitDrivers: z.boolean(),
|
||||
insurance: z.boolean(),
|
||||
IRR_Perc: z.number(),
|
||||
lastPaymentPerc: z.number(),
|
||||
lastPaymentRedemption: z.boolean(),
|
||||
lastPaymentRub: z.number(),
|
||||
lastPaymentRule: z.number().nullable(),
|
||||
lead: z.string().nullable(),
|
||||
leaseObjectCategory: z.number().nullable(),
|
||||
leaseObjectCount: z.number(),
|
||||
leaseObjectMotorPower: z.number(),
|
||||
leaseObjectPrice: z.number(),
|
||||
leaseObjectPriceWthtVAT: z.number(),
|
||||
leaseObjectType: z.string().nullable(),
|
||||
leaseObjectUsed: z.boolean(),
|
||||
leaseObjectUseFor: z.number().nullable(),
|
||||
leaseObjectYear: z.number(),
|
||||
leasingPeriod: z.number(),
|
||||
leasingWithoutKasko: z.string().nullable(),
|
||||
legalClientRegion: z.string().nullable(),
|
||||
legalClientTown: z.string().nullable(),
|
||||
maxMass: z.number(),
|
||||
maxPriceChange: z.number(),
|
||||
maxSpeed: z.number(),
|
||||
mileage: z.number(),
|
||||
minPriceChange: z.number(),
|
||||
model: z.string().nullable(),
|
||||
NSIB: z.boolean(),
|
||||
objectCategoryTax: z.number().nullable(),
|
||||
objectRegionRegistration: z.string().nullable(),
|
||||
objectRegistration: z.number().nullable(),
|
||||
objectTypeTax: z.number().nullable(),
|
||||
opportunity: z.string().nullable(),
|
||||
parmentsDecreasePercent: z.number(),
|
||||
priceWithDiscount: z.boolean(),
|
||||
product: z.string().nullable(),
|
||||
quote: z.string().nullable(),
|
||||
quoteContactGender: z.number().nullable(),
|
||||
quoteName: z.string().nullable(),
|
||||
quoteRedemptionGraph: z.boolean(),
|
||||
rate: z.string().nullable(),
|
||||
recalcWithRevision: z.boolean(),
|
||||
redemptionPaymentSum: z.number(),
|
||||
regionRegistration: z.string().nullable(),
|
||||
registration: z.string().nullable(),
|
||||
registrationQuote: z.boolean(),
|
||||
requirementTelematic: z.number().nullable(),
|
||||
saleBonus: z.number(),
|
||||
seasonType: z.number().nullable(),
|
||||
showFinGAP: z.boolean(),
|
||||
subsidy: z.string().nullable(),
|
||||
supplierCurrency: z.string().nullable(),
|
||||
supplierDiscountPerc: z.number(),
|
||||
supplierDiscountRub: z.number(),
|
||||
tarif: z.string().nullable(),
|
||||
technicalCard: z.string().nullable(),
|
||||
technicalCardQuote: z.boolean(),
|
||||
telematic: z.string().nullable(),
|
||||
totalPayments: z.number(),
|
||||
townRegistration: z.string().nullable(),
|
||||
tracker: z.string().nullable(),
|
||||
typePTS: z.number().nullable(),
|
||||
VATInLeaseObjectPrice: z.number(),
|
||||
vehicleTaxInLeasingPeriod: z.number(),
|
||||
vehicleTaxInYear: z.number(),
|
||||
withTrailer: z.boolean(),
|
||||
vin: z.string().nullable(),
|
||||
const ValuesSchema = z.object({
|
||||
addEquipmentPrice: z.number(),
|
||||
balanceHolder: z.number().nullable(),
|
||||
bonusCoefficient: z.number(),
|
||||
brand: z.string().nullable(),
|
||||
calcBroker: z.string().nullable(),
|
||||
calcBrokerRewardCondition: z.string().nullable(),
|
||||
calcBrokerRewardSum: z.number(),
|
||||
calcDoubleAgent: z.string().nullable(),
|
||||
calcDoubleAgentRewardCondition: z.string().nullable(),
|
||||
calcDoubleAgentRewardSumm: z.number(),
|
||||
calcFinDepartment: z.string().nullable(),
|
||||
calcType: z.number().nullable(),
|
||||
clientRisk: z.string().nullable(),
|
||||
clientType: z.string().nullable(),
|
||||
comissionPerc: z.number(),
|
||||
comissionRub: z.number(),
|
||||
configuration: z.string().nullable(),
|
||||
costIncrease: z.boolean(),
|
||||
countSeats: z.number(),
|
||||
creditRate: z.number(),
|
||||
dealer: z.string().nullable(),
|
||||
dealerBroker: z.string().nullable(),
|
||||
dealerBrokerRewardCondition: z.string().nullable(),
|
||||
dealerBrokerRewardSumm: z.number(),
|
||||
dealerPerson: z.string().nullable(),
|
||||
dealerRewardCondition: z.string().nullable(),
|
||||
dealerRewardSumm: z.number(),
|
||||
deliveryTime: z.number().nullable(),
|
||||
disableChecks: z.boolean(),
|
||||
engineHours: z.number(),
|
||||
engineType: z.number().nullable(),
|
||||
engineVolume: z.number(),
|
||||
finDepartmentRewardCondtion: z.string().nullable(),
|
||||
finDepartmentRewardSumm: z.number(),
|
||||
firstPaymentPerc: z.number(),
|
||||
firstPaymentRub: z.number(),
|
||||
fuelCard: z.string().nullable(),
|
||||
fullPriceWithDiscount: z.boolean(),
|
||||
GPSBrand: z.string().nullable(),
|
||||
GPSModel: z.string().nullable(),
|
||||
graphType: z.number().nullable(),
|
||||
highSeasonStart: z.number().nullable(),
|
||||
importerRewardPerc: z.number(),
|
||||
importerRewardRub: z.number(),
|
||||
importProgram: z.string().nullable(),
|
||||
importProgramSum: z.number(),
|
||||
indAgent: z.string().nullable(),
|
||||
indAgentRewardCondition: z.string().nullable(),
|
||||
indAgentRewardSumm: z.number(),
|
||||
insAgeDrivers: z.number(),
|
||||
insDecentral: z.boolean(),
|
||||
insExpDrivers: z.number(),
|
||||
insFranchise: z.number(),
|
||||
insNSIB: z.string().nullable(),
|
||||
insUnlimitDrivers: z.boolean(),
|
||||
insurance: z.boolean(),
|
||||
IRR_Perc: z.number(),
|
||||
lastPaymentPerc: z.number(),
|
||||
lastPaymentRedemption: z.boolean(),
|
||||
lastPaymentRub: z.number(),
|
||||
lastPaymentRule: z.number().nullable(),
|
||||
lead: z.string().nullable(),
|
||||
leaseObjectCategory: z.number().nullable(),
|
||||
leaseObjectCount: z.number(),
|
||||
leaseObjectMotorPower: z.number(),
|
||||
leaseObjectPrice: z.number(),
|
||||
leaseObjectPriceWthtVAT: z.number(),
|
||||
leaseObjectType: z.string().nullable(),
|
||||
leaseObjectUsed: z.boolean(),
|
||||
leaseObjectUseFor: z.number().nullable(),
|
||||
leaseObjectYear: z.number(),
|
||||
leasingPeriod: z.number(),
|
||||
leasingWithoutKasko: z.string().nullable(),
|
||||
legalClientRegion: z.string().nullable(),
|
||||
legalClientTown: z.string().nullable(),
|
||||
maxMass: z.number(),
|
||||
maxPriceChange: z.number(),
|
||||
maxSpeed: z.number(),
|
||||
mileage: z.number(),
|
||||
minPriceChange: z.number(),
|
||||
model: z.string().nullable(),
|
||||
NSIB: z.boolean(),
|
||||
objectCategoryTax: z.number().nullable(),
|
||||
objectRegionRegistration: z.string().nullable(),
|
||||
objectRegistration: z.number().nullable(),
|
||||
objectTypeTax: z.number().nullable(),
|
||||
opportunity: z.string().nullable(),
|
||||
parmentsDecreasePercent: z.number(),
|
||||
priceWithDiscount: z.boolean(),
|
||||
product: z.string().nullable(),
|
||||
quote: z.string().nullable(),
|
||||
quoteContactGender: z.number().nullable(),
|
||||
quoteName: z.string().nullable(),
|
||||
quoteRedemptionGraph: z.boolean(),
|
||||
rate: z.string().nullable(),
|
||||
recalcWithRevision: z.boolean(),
|
||||
redemptionPaymentSum: z.number(),
|
||||
regionRegistration: z.string().nullable(),
|
||||
registration: z.string().nullable(),
|
||||
registrationQuote: z.boolean(),
|
||||
requirementTelematic: z.number().nullable(),
|
||||
saleBonus: z.number(),
|
||||
seasonType: z.number().nullable(),
|
||||
showFinGAP: z.boolean(),
|
||||
subsidy: z.string().nullable(),
|
||||
supplierCurrency: z.string().nullable(),
|
||||
supplierDiscountPerc: z.number(),
|
||||
supplierDiscountRub: z.number(),
|
||||
tarif: z.string().nullable(),
|
||||
technicalCard: z.string().nullable(),
|
||||
technicalCardQuote: z.boolean(),
|
||||
telematic: z.string().nullable(),
|
||||
totalPayments: z.number(),
|
||||
townRegistration: z.string().nullable(),
|
||||
tracker: z.string().nullable(),
|
||||
typePTS: z.number().nullable(),
|
||||
VATInLeaseObjectPrice: z.number(),
|
||||
vehicleTaxInLeasingPeriod: z.number(),
|
||||
vehicleTaxInYear: z.number(),
|
||||
withTrailer: z.boolean(),
|
||||
vin: z.string().nullable(),
|
||||
|
||||
/**
|
||||
* Link Values
|
||||
*/
|
||||
kpUrl: z.string().nullable(),
|
||||
leadUrl: z.string().nullable(),
|
||||
opportunityUrl: z.string().nullable(),
|
||||
quoteUrl: z.string().nullable(),
|
||||
/**
|
||||
* Link Values
|
||||
*/
|
||||
kpUrl: z.string().nullable(),
|
||||
leadUrl: z.string().nullable(),
|
||||
opportunityUrl: z.string().nullable(),
|
||||
quoteUrl: z.string().nullable(),
|
||||
|
||||
/**
|
||||
* Readonly Values
|
||||
*/
|
||||
depreciationGroup: z.string().nullable(),
|
||||
discountRub: z.number(),
|
||||
insKaskoPriceLeasePeriod: z.number(),
|
||||
irrInfo: z.string().nullable(),
|
||||
leaseObjectRiskName: z.string().nullable(),
|
||||
plPriceRub: z.number(),
|
||||
registrationDescription: z.string().nullable(),
|
||||
subsidySum: z.number(),
|
||||
})
|
||||
.strict();
|
||||
/**
|
||||
* Readonly Values
|
||||
*/
|
||||
depreciationGroup: z.string().nullable(),
|
||||
discountRub: z.number(),
|
||||
insKaskoPriceLeasePeriod: z.number(),
|
||||
irrInfo: z.string().nullable(),
|
||||
leaseObjectRiskName: z.string().nullable(),
|
||||
plPriceRub: z.number(),
|
||||
registrationDescription: z.string().nullable(),
|
||||
subsidySum: z.number(),
|
||||
});
|
||||
|
||||
export default ValuesSchema;
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
export * from './get-kp-data';
|
||||
export * as reactions from './reactions';
|
||||
export * from './validation';
|
||||
|
||||
@ -15,7 +15,7 @@ export function createValidationSchema(context: ValidationContext) {
|
||||
if (round(saleBonus, 2) > round(maxBonus, 2)) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: 'Размер бонуса МПЛ не может быть выше установленного по СОТ',
|
||||
message: 'Бонус не может быть выше установленного по СОТ',
|
||||
path: ['tbxSaleBonus'],
|
||||
});
|
||||
}
|
||||
|
||||
@ -1 +1,34 @@
|
||||
export function action() {}
|
||||
import type { ProcessContext } from '../types';
|
||||
import { toJS } from 'mobx';
|
||||
import notification from 'ui/elements/notification';
|
||||
|
||||
const key = 'ACTION_CALCULATE';
|
||||
const message = 'Ошибка во время расчета графика';
|
||||
|
||||
export async function action({ store, trpcClient }: ProcessContext) {
|
||||
const { $calculation, $tables } = store;
|
||||
|
||||
const values = $calculation.$values.getValues();
|
||||
|
||||
const insurance = {
|
||||
fingap: toJS($tables.insurance.row('fingap').getValues()),
|
||||
kasko: toJS($tables.insurance.row('kasko').getValues()),
|
||||
osago: toJS($tables.insurance.row('osago').getValues()),
|
||||
};
|
||||
|
||||
const payments = toJS($tables.payments.values);
|
||||
|
||||
const { error, success } = await trpcClient.calculate.calculate.query({
|
||||
insurance: { values: insurance },
|
||||
payments: { values: payments },
|
||||
values,
|
||||
});
|
||||
|
||||
if (!success) {
|
||||
notification.error({
|
||||
description: error,
|
||||
key,
|
||||
message,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
export * from './get-kp-data';
|
||||
export * as reactions from './reactions';
|
||||
export * from './validation';
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
export * from './get-kp-data';
|
||||
export * as reactions from './reactions';
|
||||
export * from './validation';
|
||||
|
||||
@ -1,21 +1,27 @@
|
||||
import type { Process } from '@/process/types';
|
||||
import type { Process, ProcessContext } from '@/process/types';
|
||||
import { useStore } from '@/stores/hooks';
|
||||
import { trpcPureClient } from '@/trpc/client';
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
export function useProcess({ reactions }: Process) {
|
||||
const context = useProcessContext();
|
||||
|
||||
Object.keys(reactions).forEach((name) => {
|
||||
const injector = reactions[name];
|
||||
injector(context);
|
||||
});
|
||||
}
|
||||
|
||||
export function useProcessContext(): ProcessContext {
|
||||
const store = useStore();
|
||||
const apolloClient = useApolloClient();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
Object.keys(reactions).forEach((name) => {
|
||||
const injector = reactions[name];
|
||||
injector({
|
||||
apolloClient,
|
||||
queryClient,
|
||||
store,
|
||||
trpcClient: trpcPureClient,
|
||||
});
|
||||
});
|
||||
return {
|
||||
apolloClient,
|
||||
queryClient,
|
||||
store,
|
||||
trpcClient: trpcPureClient,
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
export * from './get-kp-data';
|
||||
export * as reactions from './reactions';
|
||||
export * from './validation';
|
||||
|
||||
@ -285,9 +285,11 @@ export function validation(context: ProcessContext) {
|
||||
|
||||
return {
|
||||
insurance: {
|
||||
fingap: toJS($tables.insurance.row('fingap').getValues()),
|
||||
kasko: toJS($tables.insurance.row('kasko').getValues()),
|
||||
osago: toJS($tables.insurance.row('osago').getValues()),
|
||||
values: {
|
||||
fingap: toJS($tables.insurance.row('fingap').getValues()),
|
||||
kasko: toJS($tables.insurance.row('kasko').getValues()),
|
||||
osago: toJS($tables.insurance.row('osago').getValues()),
|
||||
},
|
||||
},
|
||||
...values,
|
||||
};
|
||||
|
||||
@ -1,19 +1,11 @@
|
||||
/* eslint-disable zod/require-strict */
|
||||
import type { ValidationContext } from '../types';
|
||||
import type * as Insurance from '@/Components/Calculation/Form/Insurance/InsuranceTable/types';
|
||||
import { RowSchema } from '@/config/schema/insurance';
|
||||
import { InsuranceSchema } from '@/config/schema/insurance';
|
||||
import ValuesSchema from '@/config/schema/values';
|
||||
import * as CRMTypes from '@/graphql/crm.types';
|
||||
import { z } from 'zod';
|
||||
|
||||
const InsuranceSchema = z.object({
|
||||
insurance: z.object({
|
||||
fingap: RowSchema,
|
||||
kasko: RowSchema,
|
||||
osago: RowSchema,
|
||||
}),
|
||||
});
|
||||
|
||||
export function createValidationSchema({ apolloClient }: ValidationContext) {
|
||||
return ValuesSchema.pick({
|
||||
insDecentral: true,
|
||||
@ -22,7 +14,10 @@ export function createValidationSchema({ apolloClient }: ValidationContext) {
|
||||
quote: true,
|
||||
recalcWithRevision: true,
|
||||
})
|
||||
.merge(InsuranceSchema)
|
||||
.extend({
|
||||
insurance: InsuranceSchema,
|
||||
})
|
||||
|
||||
.superRefine(
|
||||
async (
|
||||
{
|
||||
@ -46,7 +41,7 @@ export function createValidationSchema({ apolloClient }: ValidationContext) {
|
||||
recalcWithRevision &&
|
||||
quote?.evo_one_year_insurance === true &&
|
||||
leasingPeriod > 15 &&
|
||||
insurance.kasko.insTerm === 100_000_001
|
||||
insurance.values.kasko.insTerm === 100_000_001
|
||||
) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
@ -58,7 +53,7 @@ export function createValidationSchema({ apolloClient }: ValidationContext) {
|
||||
}
|
||||
|
||||
(['osago', 'kasko'] as Insurance.Keys[]).forEach((key) => {
|
||||
const { insCost, insured, policyType, insuranceCompany, insTerm } = insurance[key];
|
||||
const { insCost, insured, policyType, insuranceCompany, insTerm } = insurance.values[key];
|
||||
|
||||
if (insured === 100_000_001 && insCost < 1000) {
|
||||
ctx.addIssue({
|
||||
@ -96,14 +91,14 @@ export function createValidationSchema({ apolloClient }: ValidationContext) {
|
||||
if (
|
||||
!leasingWithoutKasko &&
|
||||
!insDecentral &&
|
||||
insurance.osago.insuranceCompany &&
|
||||
insurance.kasko.insuranceCompany !== insurance.osago.insuranceCompany
|
||||
insurance.values.osago.insuranceCompany &&
|
||||
insurance.values.kasko.insuranceCompany !== insurance.values.osago.insuranceCompany
|
||||
) {
|
||||
const {
|
||||
data: { account },
|
||||
} = await apolloClient.query({
|
||||
query: CRMTypes.GetInsuranceCompanyDocument,
|
||||
variables: { accountId: insurance.osago.insuranceCompany },
|
||||
variables: { accountId: insurance.values.osago.insuranceCompany },
|
||||
});
|
||||
|
||||
if (account?.evo_osago_with_kasko) {
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
export * from './get-kp-data';
|
||||
export * as reactions from './reactions';
|
||||
export * from './validation';
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
export * from './get-kp-data';
|
||||
export * as reactions from './reactions';
|
||||
export * from './validation';
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
export * from './get-kp-data';
|
||||
export * as reactions from './reactions';
|
||||
export * from './validation';
|
||||
|
||||
@ -117,7 +117,8 @@ export default function reactions({ store, apolloClient }: ProcessContext) {
|
||||
reaction(
|
||||
() => $calculation.element('tbxFirstPaymentRub').getValue(),
|
||||
(firstPaymentRub) => {
|
||||
const { plPriceRub, addEquipmentPrice, importProgramSum } = $calculation.$values.values;
|
||||
const { plPriceRub, addEquipmentPrice, importProgramSum } =
|
||||
$calculation.$values.getValues();
|
||||
const perc =
|
||||
(firstPaymentRub / (plPriceRub + addEquipmentPrice - importProgramSum)) * 100;
|
||||
$calculation.element('tbxFirstPaymentPerc').setValue(perc);
|
||||
@ -139,7 +140,7 @@ export default function reactions({ store, apolloClient }: ProcessContext) {
|
||||
reaction(
|
||||
() => $calculation.element('tbxComissionRub').getValue(),
|
||||
(comissionRub) => {
|
||||
const { plPriceRub } = $calculation.$values.values;
|
||||
const { plPriceRub } = $calculation.$values.getValues();
|
||||
const perc = (comissionRub / plPriceRub) * 100;
|
||||
$calculation.element('tbxComissionPerc').setValue(perc);
|
||||
}
|
||||
@ -170,7 +171,8 @@ export default function reactions({ store, apolloClient }: ProcessContext) {
|
||||
reaction(
|
||||
() => $calculation.element('tbxLastPaymentRub').getValue(),
|
||||
(lastPaymentRub) => {
|
||||
const { plPriceRub, addEquipmentPrice, importProgramSum } = $calculation.$values.values;
|
||||
const { plPriceRub, addEquipmentPrice, importProgramSum } =
|
||||
$calculation.$values.getValues();
|
||||
const perc = (lastPaymentRub / (plPriceRub + addEquipmentPrice - importProgramSum)) * 100;
|
||||
$calculation.element('tbxLastPaymentPerc').setValue(perc);
|
||||
}
|
||||
|
||||
@ -1 +1,2 @@
|
||||
export * as reactions from './reactions';
|
||||
export * from './validation';
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
export * from './get-kp-data';
|
||||
export * as reactions from './reactions';
|
||||
export * from './validation';
|
||||
|
||||
@ -14,4 +14,4 @@ export type Process = {
|
||||
reactions: Record<string, (context: ProcessContext) => void>;
|
||||
};
|
||||
|
||||
export type ValidationContext = Omit<ProcessContext, 'store'>;
|
||||
export type ValidationContext = Omit<ProcessContext, 'store' | 'trpcClient'>;
|
||||
|
||||
@ -1 +1,2 @@
|
||||
export * as reactions from './reactions';
|
||||
export * from './validation';
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import type RootStore from '../../root';
|
||||
import type { CalculationValues, Values } from './types';
|
||||
import defaultValues from '@/config/default-values';
|
||||
import { makeAutoObservable } from 'mobx';
|
||||
import { makeAutoObservable, toJS } from 'mobx';
|
||||
import { pick } from 'radash';
|
||||
|
||||
export default class ValuesStore {
|
||||
private root: RootStore;
|
||||
public values = defaultValues;
|
||||
private values = defaultValues;
|
||||
|
||||
constructor(rootStore: RootStore) {
|
||||
makeAutoObservable(this);
|
||||
@ -17,7 +17,11 @@ export default class ValuesStore {
|
||||
this.values = { ...defaultValues, ...initialValues };
|
||||
};
|
||||
|
||||
public getValues = <K extends keyof CalculationValues>(keys: K[]) => pick(this.values, keys);
|
||||
public getValues = <K extends keyof CalculationValues>(keys?: K[]) => {
|
||||
if (keys) return pick(this.values, keys);
|
||||
|
||||
return toJS(this.values);
|
||||
};
|
||||
|
||||
public setValues = (values: Partial<CalculationValues>) => {
|
||||
(Object.keys(values) as Array<keyof CalculationValues>).forEach((valueName) => {
|
||||
|
||||
37
apps/web/trpc/routers/calculate/index.ts
Normal file
37
apps/web/trpc/routers/calculate/index.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { t } from '../../server';
|
||||
import { CalculateInputSchema, CalculateOutputSchema } from './types';
|
||||
import { validate } from './validation';
|
||||
import initializeApollo from '@/apollo/client';
|
||||
import { QueryClient } from '@tanstack/react-query';
|
||||
|
||||
const calculateRouter = t.router({
|
||||
calculate: t.procedure
|
||||
.input(CalculateInputSchema)
|
||||
.output(CalculateOutputSchema)
|
||||
.query(async ({ input }) => {
|
||||
const apolloClient = initializeApollo();
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
const { success, error } = await validate({
|
||||
context: {
|
||||
apolloClient,
|
||||
queryClient,
|
||||
},
|
||||
input,
|
||||
});
|
||||
|
||||
if (!success) {
|
||||
return {
|
||||
error,
|
||||
success,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
error: undefined,
|
||||
success,
|
||||
};
|
||||
}),
|
||||
});
|
||||
|
||||
export default calculateRouter;
|
||||
17
apps/web/trpc/routers/calculate/types.ts
Normal file
17
apps/web/trpc/routers/calculate/types.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { InsuranceSchema } from '@/config/schema/insurance';
|
||||
import PaymentsSchema from '@/config/schema/payments';
|
||||
import ValuesSchema from '@/config/schema/values';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const CalculateInputSchema = z
|
||||
.object({
|
||||
insurance: InsuranceSchema,
|
||||
payments: PaymentsSchema,
|
||||
values: ValuesSchema,
|
||||
})
|
||||
.strict();
|
||||
|
||||
export const CalculateOutputSchema = z.object({
|
||||
error: z.string().optional(),
|
||||
success: z.boolean(),
|
||||
});
|
||||
73
apps/web/trpc/routers/calculate/validation.ts
Normal file
73
apps/web/trpc/routers/calculate/validation.ts
Normal file
@ -0,0 +1,73 @@
|
||||
import type { CalculateInputSchema } from './types';
|
||||
import { CalculateOutputSchema } from './types';
|
||||
import elementsTitles from '@/Components/Calculation/config/elements-titles';
|
||||
import type { Elements } from '@/Components/Calculation/config/map/values';
|
||||
import * as bonuses from '@/process/bonuses';
|
||||
import * as configurator from '@/process/configurator';
|
||||
import * as gibdd from '@/process/gibdd';
|
||||
import * as insuranceProcess from '@/process/insurance';
|
||||
import * as leasingObject from '@/process/leasing-object';
|
||||
import * as paymentsProcess from '@/process/payments';
|
||||
import * as price from '@/process/price';
|
||||
import * as supplierAgent from '@/process/supplier-agent';
|
||||
import type { ValidationContext } from '@/process/types';
|
||||
import type { z, ZodIssue } from 'zod';
|
||||
|
||||
const processes = [
|
||||
configurator,
|
||||
supplierAgent,
|
||||
paymentsProcess,
|
||||
price,
|
||||
bonuses,
|
||||
leasingObject,
|
||||
gibdd,
|
||||
insuranceProcess,
|
||||
];
|
||||
|
||||
const titles = Object.assign(elementsTitles, {
|
||||
insurance: 'Таблица страхования',
|
||||
payments: 'Таблица платежей',
|
||||
});
|
||||
|
||||
function getMessage(errors: ZodIssue[]) {
|
||||
const elementName = errors?.at(0)?.path.at(0) as Elements;
|
||||
const title = titles[elementName];
|
||||
const message = errors?.at(0)?.message;
|
||||
|
||||
return `${title}: ${message}`;
|
||||
}
|
||||
|
||||
const ValidationOutputSchema = CalculateOutputSchema.pick({
|
||||
error: true,
|
||||
success: true,
|
||||
});
|
||||
|
||||
type ValidationOutput = z.infer<typeof ValidationOutputSchema>;
|
||||
type ValidationInput = z.infer<typeof CalculateInputSchema>;
|
||||
|
||||
export async function validate({
|
||||
input,
|
||||
context,
|
||||
}: {
|
||||
context: ValidationContext;
|
||||
input: ValidationInput;
|
||||
}): Promise<ValidationOutput> {
|
||||
for (const { createValidationSchema } of processes) {
|
||||
const validationSchema = createValidationSchema(context);
|
||||
const validationResult = await validationSchema.safeParseAsync({
|
||||
...input.values,
|
||||
insurance: input.insurance,
|
||||
payments: input.payments,
|
||||
});
|
||||
|
||||
if (validationResult.success === false) {
|
||||
const error = getMessage(validationResult.error.errors);
|
||||
|
||||
return { error, success: false };
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
}
|
||||
@ -1,7 +1,9 @@
|
||||
import { t } from '../server';
|
||||
import calculateRouter from './calculate';
|
||||
import quoteRouter from './quote';
|
||||
|
||||
const appRouter = t.router({
|
||||
calculate: calculateRouter,
|
||||
quote: quoteRouter,
|
||||
});
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user