import { calculateFinGAP } from '@/api/core/query'; import type { RequestFinGAP } from '@/api/core/types'; import type { Risk } from '@/Components/Calculation/Form/Insurance/FinGAPTable/types'; import { STALE_TIME } from '@/constants/request'; import type * as CRMTypes from '@/graphql/crm.types'; import type { ProcessContext } from '@/process/types'; import { disposableReaction } from '@/utils/mobx'; import { gql } from '@apollo/client'; import type { QueryFunctionContext } from '@tanstack/react-query'; import dayjs from 'dayjs'; import utc from 'dayjs/plugin/utc'; import { comparer, reaction, toJS } from 'mobx'; import { flatten } from 'tools/object'; dayjs.extend(utc); export default function reactions({ store, apolloClient, queryClient }: ProcessContext) { const { $calculation, $tables, $process } = store; // Расчет итоговой суммы ФинГАП и запись в таблицу страхования reaction( () => $tables.fingap.totalSum, (totalSum) => { $tables.insurance.row('fingap').setValue('insCost', totalSum); } ); /** * Реакция на изменение Страховой компании у ФинГАП и Срока лизинга: * * Если Страхованя компания = Не выбрано, то * * Плательщик insuredFinGAP = ЛП (100 000 000) и закрыто для редактирования, * Стоимость за первый период inscostFinGAP = 0 * Срок страхования insTermFinGAP = 12 мес (100 000 000) и закрыто для редактирования * * иначе * * Плательщик insuredFinGAP = открыто для редактирования, * Стоимость за первый период inscostFinGAP = 0 * Срок страхования insTermFinGAP = Если срок лизинга tbxLeasingPeriod < 13, * то указываем Срок страхования insTermFinGAP = 12 мес * и закрываем для редактирования, иначе открыто для редактирования */ reaction( () => { const finGAPInsuranceCompany = $tables.insurance.row('fingap').getValue('insuranceCompany'); const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue(); return { finGAPInsuranceCompany, leasingPeriod, }; }, ({ finGAPInsuranceCompany, leasingPeriod }) => { // eslint-disable-next-line no-negated-condition if (!finGAPInsuranceCompany) { $tables.insurance.row('fingap').column('insured').setValue(100_000_000).block(); $tables.insurance.row('fingap').column('insCost').setValue(0); $tables.insurance.row('fingap').column('insTerm').setValue(100_000_000).block(); } else { $tables.insurance.row('fingap').column('insured').unblock(); if (leasingPeriod < 13) { $tables.insurance.row('fingap').column('insTerm').setValue(100_000_000).block(); } else { $tables.insurance.row('fingap').column('insTerm').unblock(); } } }, { equals: comparer.shallow, fireImmediately: true, } ); // Очищаем таблицу ФинГАП, если не выбрана страховая компания reaction( () => $tables.insurance.row('fingap').getValue('insuranceCompany'), (finGAPInsuranceCompany) => { if (!finGAPInsuranceCompany) { $tables.fingap.clear(); } } ); const QUERY_GET_FINGAP_ADDPRODUCT_TYPES = gql` query GetFinGAPAddProductTypes($currentDate: DateTime) { evo_addproduct_types( statecode: 0 evo_datefrom_param: { lte: $currentDate } evo_dateto_param: { gte: $currentDate } evo_product_type: 100000006 ) { evo_addproduct_typeid evo_name evo_type_calc_cerebellum evo_cost_service_provider_withoutnds evo_addproduct_types { evo_addproduct_typeid } } } `; // Заполнение таблицы рисков ФинГАП + Запрос расчета финГАП в мозжечок disposableReaction( () => $process.has('Calculate'), () => { const finGAPInsuranceCompany = $tables.insurance.row('fingap').getValue('insuranceCompany'); const paymentsValues = toJS($tables.payments.values); const plPriceRub = $calculation.$values.getValue('plPriceRub'); const discountRub = $calculation.$values.getValue('discountRub'); const firstPaymentRub = $calculation.element('tbxFirstPaymentRub').getValue(); const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue(); const hasPaymentsErrors = $tables.payments.validation.hasErrors; return { discountRub, finGAPInsuranceCompany, firstPaymentRub, hasPaymentsErrors, leasingPeriod, paymentsValues, plPriceRub, }; }, async ({ finGAPInsuranceCompany, paymentsValues, plPriceRub, discountRub, firstPaymentRub, leasingPeriod, hasPaymentsErrors, }) => { if (!finGAPInsuranceCompany || hasPaymentsErrors) { $tables.fingap.clear(); return; } const { data: { evo_addproduct_types }, } = await apolloClient.query< CRMTypes.GetFinGapAddProductTypesQuery, CRMTypes.GetFinGapAddProductTypesQueryVariables >({ query: QUERY_GET_FINGAP_ADDPRODUCT_TYPES, variables: { currentDate: dayjs().utc(false).toISOString(), }, }); const risks = evo_addproduct_types?.map( (evo_addproduct_type) => ({ calcType: evo_addproduct_type?.evo_type_calc_cerebellum, key: evo_addproduct_type?.evo_addproduct_typeid, keys: evo_addproduct_type?.evo_addproduct_types?.map( (addproduct_type) => addproduct_type?.evo_addproduct_typeid ), premium: 0, premiumPerc: evo_addproduct_type?.evo_cost_service_provider_withoutnds, riskId: evo_addproduct_type?.evo_addproduct_typeid, riskName: evo_addproduct_type?.evo_name, sum: 0, } as Risk) ); if (!risks) return; // $tables.fingap.setRisks(risks); function getFingapRequestDataFromRisk(risk: Risk): RequestFinGAP { return { calcType: risk.calcType, payments: paymentsValues.map((payment) => ({ percentPayment: payment, })), values: { discount: discountRub, firstPayment: firstPaymentRub, leasingPeriod, plPrice: plPriceRub, premiumPerc: risk.premiumPerc || 0, }, }; } // eslint-disable-next-line unicorn/consistent-function-scoping function makeRequestGetFinGAP(request: RequestFinGAP) { const queryCalculateFinGAP = (context: QueryFunctionContext) => calculateFinGAP(request, context); return queryClient.fetchQuery( ['core', 'fingap', ...flatten(request)], queryCalculateFinGAP, { staleTime: STALE_TIME, } ); } Promise.all( risks .map((risk) => getFingapRequestDataFromRisk(risk)) .map((data) => makeRequestGetFinGAP(data)) ).then((results) => { const newRisks = risks.map((risk, i) => ({ ...risk, premium: results.at(i)?.premium || 0, sum: results.at(i)?.sum || 0, })); $tables.fingap.setRisks(newRisks); }); }, { // Important: delay prohibits multiple reaction invocation delay: 100, equals: comparer.structural, } ); }