Compare commits

...

34 Commits

Author SHA1 Message Date
Chika
e4f00bdb22 add leaseback reactions 2022-11-02 21:34:25 +03:00
Chika
3d93f02a1e selectDealerPerson: show inn/kpp 2022-11-02 20:28:47 +03:00
Chika
60af0f86e7 fix reward fields blocking 2022-11-02 20:07:31 +03:00
Chika
fb2b452854 disable fillAgentRewardSummReaction when Process.LoadKP 2022-11-02 19:54:27 +03:00
Chika
6b3c01cd84 get sums from kp 2022-11-02 18:11:23 +03:00
Chika
8960773d43 trpc: remove lead & opportunity from query 2022-11-02 15:54:52 +03:00
Chika
98915374af trpc/quote: reduce request size 2022-11-02 14:43:08 +03:00
Chika
aa3adef0da trpc: fix http 431 2022-11-02 14:24:09 +03:00
Chika
2d496f8f6a trpc: fix query with basePath 2022-11-02 13:42:01 +03:00
Chika
f85373689a add trpc server
get calculation values types from zod schema
add loadKP reaction
get base agents data from kp
2022-11-02 13:18:33 +03:00
Chika
f7cf5134b2 agents: remove unused query 2022-10-29 12:11:43 +03:00
Chika
8d00622b03 create-reactions/validation: fix titles dublication 2022-10-28 12:18:13 +03:00
Chika
7034e599b4 add for a76c5f2 2022-10-27 11:05:41 +03:00
Chika
a76c5f234d fix display validation 2022-10-27 10:58:38 +03:00
Chika
a163e278c5 stores/validation: add helper 2022-10-27 09:41:53 +03:00
Chika
fef39e4a46 process/supplier-agent: add agents validation 2022-10-27 09:32:36 +03:00
Chika
1827b9ba54 process/supplier-agent: move queries closer to create-reactions 2022-10-27 08:30:24 +03:00
Chika
2ecd64b2fb validation: fixes 2022-10-26 20:23:03 +03:00
Chika
021363baa7 stores/tables: add validate method 2022-10-26 20:08:44 +03:00
Chika
4d5fff51b1 stores/validation: export types 2022-10-26 19:07:46 +03:00
Chika
e6bb6a4d6f store/calculation: use boolean validation flag 2022-10-26 17:50:44 +03:00
Chika
f02f785fb6 process/supplier-agent: add validation
store/calculation: add validation
2022-10-26 17:46:35 +03:00
Chika
f54dd44810 stores: refactor $calculation validation 2022-10-26 16:56:56 +03:00
Chika
99f82ec2f9 stores/calculation: support chain methods 2022-10-26 15:26:32 +03:00
Chika
31c70615af process/supplier-agents: common reactions for agents 2022-10-26 13:02:49 +03:00
Chika
a766546dfe process/supplier-agent: auto generate similar reactions 2022-10-25 20:53:12 +03:00
Chika
d9d49be4fe process/supplier-agents: add base supplier reactions 2022-10-25 19:18:31 +03:00
Chika
45e540fbfb process/supplier-agent: move reaction from supplier to agents 2022-10-25 18:56:13 +03:00
Chika
1d886bb43e process: rename agents -> supplier-agents
separate reactions
2022-10-25 18:27:57 +03:00
Chika
a2b2cc6a74 process/payments: make some reactions disposable 2022-10-25 17:29:06 +03:00
Chika
d0db6048aa process/lead-opportunity: make some reactions disposable 2022-10-25 17:28:22 +03:00
Chika
5b923f9de7 process/agents: make reactions disposable 2022-10-25 17:20:28 +03:00
Chika
202eb6e304 tools: add makeDisposable function for mobx reactions 2022-10-25 16:53:52 +03:00
Chika
815a6336ec stores: add process store 2022-10-25 15:57:08 +03:00
58 changed files with 2460 additions and 1098 deletions

View File

@ -74,7 +74,10 @@
"ignore": ["^.*.(jsx|tsx)$"] "ignore": ["^.*.(jsx|tsx)$"]
} }
], ],
"import/no-unresolved": "warn" "import/no-unresolved": "warn",
"implicit-arrow-linebreak": "warn",
"operator-linebreak": "warn",
"function-paren-newline": "warn"
}, },
"overrides": [ "overrides": [
// Only uses Testing Library lint rules in test files // Only uses Testing Library lint rules in test files

View File

@ -14,7 +14,7 @@ function PaymentsParams() {
const [selectSeasonType, tbxParmentsDecreasePercent, selectHighSeasonStart] = renderedElements; const [selectSeasonType, tbxParmentsDecreasePercent, selectHighSeasonStart] = renderedElements;
const { $calculation } = useStore(); const { $calculation } = useStore();
const graphType = $calculation.getElementValue('radioGraphType'); const graphType = $calculation.element('radioGraphType').getValue();
switch (graphType) { switch (graphType) {
case 100_000_000: case 100_000_000:

View File

@ -14,7 +14,7 @@ const QUERY_GET_CURRENCY_SYMBOL = gql`
const CurrencyAddon = observer(() => { const CurrencyAddon = observer(() => {
const { $calculation } = useStore(); const { $calculation } = useStore();
const currencyid = $calculation.$values.getValue('supplierCurrency'); const currencyid = $calculation.element('selectSupplierCurrency').getValue();
const { data } = useQuery< const { data } = useQuery<
CRMTypes.GetCurrencySymbolQuery, CRMTypes.GetCurrencySymbolQuery,

View File

@ -180,7 +180,7 @@ const overrideRender: Partial<Record<keyof typeof map, RenderProps>> = {
const Title = observer(() => { const Title = observer(() => {
const { $calculation } = useStore(); const { $calculation } = useStore();
const graphType = $calculation.getElementValue('radioGraphType'); const graphType = $calculation.element('radioGraphType').getValue();
switch (graphType) { switch (graphType) {
case 100_000_001: case 100_000_001:

View File

@ -3,7 +3,6 @@ import { observer } from 'mobx-react-lite';
import { useStore } from 'stores/hooks'; import { useStore } from 'stores/hooks';
import styled from 'styled-components'; import styled from 'styled-components';
import { Box, Flex } from 'UIKit/grid'; import { Box, Flex } from 'UIKit/grid';
import titles from '../Calculation/config/elements-titles';
const Bold = styled.span` const Bold = styled.span`
font-weight: bold; font-weight: bold;
@ -19,14 +18,19 @@ function Message(title, text) {
); );
} }
const AlertWrapper = styled(Box)`
margin: 0 0 5px 0;
`;
function getElementsErrors($calculation) { function getElementsErrors($calculation) {
const { elementsErrors } = $calculation.$validation; const errors = Object.values($calculation.$validation).map((validation) => {
const errors = Object.keys(elementsErrors).map((elementName) => { const elementErrors = validation.getMessages();
const elementErrors = elementsErrors[elementName]; const elementTitle = validation.params.err_title;
const elementTitle = titles[elementName];
return elementErrors.map((error) => ( return elementErrors.map((error) => (
<Alert key={error.name} type="error" showIcon message={Message(elementTitle, error.text)} /> <AlertWrapper>
<Alert key={error.name} type="error" showIcon message={Message(elementTitle, error)} />
</AlertWrapper>
)); ));
}); });
@ -51,14 +55,22 @@ function getInsuranceTableErrors($tables) {
const Errors = observer(() => { const Errors = observer(() => {
const { $calculation, $tables } = useStore(); const { $calculation, $tables } = useStore();
const hasElementsErrors = Object.values($calculation.$validation).some(
(validation) => validation.hasErrors
);
const hasPaymentsErrors = $tables.payments.validation.hasErrors;
const hasInsuranceErrors = $tables.insurance.validation.hasErrors;
if (!hasElementsErrors && !hasPaymentsErrors && !hasInsuranceErrors) {
return <Alert type="success" showIcon message="Ошибок нет 🙂" />;
}
const elementsErrors = getElementsErrors($calculation); const elementsErrors = getElementsErrors($calculation);
const paymentsErrors = getPaymentsTableErrors($tables); const paymentsErrors = getPaymentsTableErrors($tables);
const insuranceErrors = getInsuranceTableErrors($tables); const insuranceErrors = getInsuranceTableErrors($tables);
const errors = [...elementsErrors, ...paymentsErrors, ...insuranceErrors]; const errors = [...elementsErrors, ...paymentsErrors, ...insuranceErrors];
if (errors.length === 0) return <Alert type="success" showIcon message="Ошибок нет 🙂" />;
return <Flex flexDirection="column">{errors}</Flex>; return <Flex flexDirection="column">{errors}</Flex>;
}); });

2
Elements/message.js Normal file
View File

@ -0,0 +1,2 @@
/* eslint-disable no-restricted-exports */
export { message as default } from 'antd';

View File

@ -1,10 +1,10 @@
import type { CalculationStatuses } from 'stores/calculation/statuses/types'; import type { CalculationStatuses } from 'stores/calculation/statuses/types';
const defaultStatuses: CalculationStatuses = { const defaultStatuses: CalculationStatuses = {
selectIndAgent: 'Disabled', selectIndAgent: 'Default',
selectCalcBroker: 'Disabled', selectCalcBroker: 'Default',
selectCalcFinDepartment: 'Disabled', selectCalcFinDepartment: 'Default',
selectCalcDoubleAgent: 'Disabled', selectCalcDoubleAgent: 'Default',
selectClientType: 'Disabled', selectClientType: 'Disabled',
tbxImporterRewardRub: 'Disabled', tbxImporterRewardRub: 'Disabled',
tbxImporterRewardPerc: 'Disabled', tbxImporterRewardPerc: 'Disabled',
@ -71,13 +71,13 @@ const defaultStatuses: CalculationStatuses = {
selectDealerBrokerRewardCondition: 'Default', selectDealerBrokerRewardCondition: 'Default',
tbxDealerBrokerRewardSumm: 'Disabled', tbxDealerBrokerRewardSumm: 'Disabled',
selectIndAgentRewardCondition: 'Default', selectIndAgentRewardCondition: 'Default',
tbxIndAgentRewardSumm: 'Default', tbxIndAgentRewardSumm: 'Disabled',
selectCalcDoubleAgentRewardCondition: 'Default', selectCalcDoubleAgentRewardCondition: 'Default',
tbxCalcDoubleAgentRewardSumm: 'Default', tbxCalcDoubleAgentRewardSumm: 'Disabled',
selectCalcBrokerRewardCondition: 'Default', selectCalcBrokerRewardCondition: 'Default',
tbxCalcBrokerRewardSum: 'Default', tbxCalcBrokerRewardSum: 'Disabled',
selectFinDepartmentRewardCondtion: 'Default', selectFinDepartmentRewardCondtion: 'Default',
tbxFinDepartmentRewardSumm: 'Default', tbxFinDepartmentRewardSumm: 'Disabled',
selectGPSBrand: 'Default', selectGPSBrand: 'Default',
selectGPSModel: 'Default', selectGPSModel: 'Default',
selectRegionRegistration: 'Default', selectRegionRegistration: 'Default',

144
config/schema/values.ts Normal file
View File

@ -0,0 +1,144 @@
import { z } from 'zod';
const ValuesSchema = z.object({
lead: z.string().nullable(),
opportunity: z.string().nullable(),
quote: z.string().nullable(),
recalcWithRevision: z.boolean(),
product: z.string().nullable(),
clientRisk: z.string().nullable(),
clientType: z.string().nullable(),
leaseObjectPrice: z.number(),
supplierCurrency: z.string().nullable(),
supplierDiscountRub: z.number(),
supplierDiscountPerc: z.number(),
leasingPeriod: z.number(),
firstPaymentPerc: z.number(),
firstPaymentRub: z.number(),
lastPaymentPerc: z.number(),
lastPaymentRub: z.number(),
lastPaymentRule: z.number().nullable(),
importProgram: z.string().nullable(),
importProgramSum: z.number(),
addEquipmentPrice: z.number(),
redemptionPaymentSum: z.number(),
balanceHolder: z.number().nullable(),
graphType: z.number().nullable(),
parmentsDecreasePercent: z.number(),
seasonType: z.number().nullable(),
highSeasonStart: z.number().nullable(),
comissionPerc: z.number(),
comissionRub: z.number(),
saleBonus: z.number(),
IRR_Perc: z.number(),
leaseObjectType: z.string().nullable(),
deliveryTime: z.number().nullable(),
leaseObjectCount: z.number(),
withTrailer: z.boolean(),
leaseObjectUsed: z.boolean(),
maxMass: z.number(),
countSeats: z.number(),
maxSpeed: z.number(),
brand: z.string().nullable(),
model: z.string().nullable(),
configuration: z.string().nullable(),
leaseObjectYear: z.number(),
engineType: z.number().nullable(),
leaseObjectCategory: z.number().nullable(),
leaseObjectMotorPower: z.number(),
engineVolume: z.number(),
leaseObjectUseFor: z.number().nullable(),
dealer: z.string().nullable(),
dealerPerson: z.string().nullable(),
dealerRewardCondition: z.string().nullable(),
dealerRewardSumm: z.number(),
dealerBroker: z.string().nullable(),
dealerBrokerRewardCondition: z.string().nullable(),
dealerBrokerRewardSumm: z.number(),
indAgent: z.string().nullable(),
indAgentRewardCondition: z.string().nullable(),
indAgentRewardSumm: z.number(),
calcDoubleAgent: z.string().nullable(),
calcDoubleAgentRewardCondition: z.string().nullable(),
calcDoubleAgentRewardSumm: z.number(),
calcBroker: z.string().nullable(),
calcBrokerRewardCondition: z.string().nullable(),
calcBrokerRewardSum: z.number(),
calcFinDepartment: z.string().nullable(),
finDepartmentRewardCondtion: z.string().nullable(),
finDepartmentRewardSumm: z.number(),
GPSBrand: z.string().nullable(),
GPSModel: z.string().nullable(),
regionRegistration: z.string().nullable(),
townRegistration: z.string().nullable(),
infuranceOPF: z.number().nullable(),
insKaskoType: z.number().nullable(),
insDecentral: z.boolean(),
insFranchise: z.number(),
insUnlimitDrivers: z.boolean(),
insAgeDrivers: z.number(),
insExpDrivers: z.number(),
INNForCalc: z.number(),
lastPaymentRedemption: z.boolean(),
priceWithDiscount: z.boolean(),
fullPriceWithDiscount: z.boolean(),
costIncrease: z.boolean(),
insurance: z.boolean(),
registrationQuote: z.boolean(),
technicalCardQuote: z.boolean(),
NSIB: z.boolean(),
quoteName: z.string().nullable(),
quoteContactGender: z.number().nullable(),
quoteRedemptionGraph: z.boolean(),
showFinGAP: z.boolean(),
tarif: z.string().nullable(),
creditRate: z.number(),
rate: z.string().nullable(),
requirementTelematic: z.number().nullable(),
minPriceChange: z.number(),
maxPriceChange: z.number(),
importerRewardPerc: z.number(),
importerRewardRub: z.number(),
disableChecks: z.boolean(),
registration: z.string().nullable(),
insNSIB: z.string().nullable(),
technicalCard: z.string().nullable(),
telematic: z.string().nullable(),
tracker: z.string().nullable(),
mileage: z.number(),
calcType: z.number().nullable(),
totalPayments: z.number(),
objectRegistration: z.number().nullable(),
objectRegionRegistration: z.string().nullable(),
vehicleTaxInYear: z.number(),
vehicleTaxInLeasingPeriod: z.number(),
objectCategoryTax: z.number().nullable(),
objectTypeTax: z.number().nullable(),
typePTS: z.number().nullable(),
legalClientRegion: z.string().nullable(),
legalClientTown: z.string().nullable(),
subsidy: z.string().nullable(),
fuelCard: z.string().nullable(),
leaseObjectPriceWthtVAT: z.number(),
VATInLeaseObjectPrice: z.number(),
engineHours: z.number(),
bonusCoefficient: z.number(),
/** Link Values */
kpUrl: z.string().nullable(),
leadUrl: z.string().nullable(),
opportunityUrl: z.string().nullable(),
quoteUrl: z.string().nullable(),
/** Readonly Values */
leaseObjectRiskName: z.string().nullable(),
insKaskoPriceLeasePeriod: z.number(),
irrInfo: z.string().nullable(),
registrationDescription: z.string().nullable(),
depreciationGroup: z.string().nullable(),
subsidySum: z.number(),
plPriceRub: z.number(),
discountRub: z.number(),
});
export default ValuesSchema;

View File

@ -122,70 +122,6 @@ export type GetCurrencySymbolQueryVariables = Exact<{
export type GetCurrencySymbolQuery = { __typename?: 'Query', transactioncurrency?: { __typename?: 'transactioncurrency', currencysymbol?: string | null } | null }; export type GetCurrencySymbolQuery = { __typename?: 'Query', transactioncurrency?: { __typename?: 'transactioncurrency', currencysymbol?: string | null } | null };
export type GetAgentQueryVariables = Exact<{
agentid: Scalars['Uuid'];
}>;
export type GetAgentQuery = { __typename?: 'Query', agent?: { __typename?: 'account', label?: string | null, value?: any | null } | null };
export type GetAgentAccountIdFromLeadQueryVariables = Exact<{
leadid: Scalars['Uuid'];
}>;
export type GetAgentAccountIdFromLeadQuery = { __typename?: 'Query', lead?: { __typename?: 'lead', agentid?: any | null } | null };
export type GetDoubleAgentAccountIdQueryVariables = Exact<{
leadid: Scalars['Uuid'];
}>;
export type GetDoubleAgentAccountIdQuery = { __typename?: 'Query', lead?: { __typename?: 'lead', agentid?: any | null } | null };
export type GetBrokerAccountIdQueryVariables = Exact<{
leadid: Scalars['Uuid'];
}>;
export type GetBrokerAccountIdQuery = { __typename?: 'Query', lead?: { __typename?: 'lead', agentid?: any | null } | null };
export type GetFinDepartmentAccountIdQueryVariables = Exact<{
leadid: Scalars['Uuid'];
}>;
export type GetFinDepartmentAccountIdQuery = { __typename?: 'Query', lead?: { __typename?: 'lead', agentid?: any | null } | null };
export type GetDealerPersonQueryVariables = Exact<{
dealerId: Scalars['Uuid'];
}>;
export type GetDealerPersonQuery = { __typename?: 'Query', salon_providers?: Array<{ __typename?: 'account', label?: string | null, value?: any | null } | null> | null };
export type GetBrokerAccountIdFromDealerQueryVariables = Exact<{
dealerId: Scalars['Uuid'];
}>;
export type GetBrokerAccountIdFromDealerQuery = { __typename?: 'Query', dealer?: { __typename?: 'account', evo_broker_accountid?: any | null } | null };
export type GetRewardConditionsQueryVariables = Exact<{
agentid: Scalars['Uuid'];
currentDate?: InputMaybe<Scalars['DateTime']>;
}>;
export type GetRewardConditionsQuery = { __typename?: 'Query', evo_reward_conditions?: Array<{ __typename?: 'evo_reward_condition', evo_reward_summ?: any | null, label?: string | null, value?: any | null } | null> | null };
export type GetRewardSummQueryVariables = Exact<{
conditionId: Scalars['Uuid'];
}>;
export type GetRewardSummQuery = { __typename?: 'Query', evo_reward_condition?: { __typename?: 'evo_reward_condition', evo_reward_summ?: any | null } | null };
export type GetFinGapAddProductTypesQueryVariables = Exact<{ export type GetFinGapAddProductTypesQueryVariables = Exact<{
currentDate?: InputMaybe<Scalars['DateTime']>; currentDate?: InputMaybe<Scalars['DateTime']>;
}>; }>;
@ -301,3 +237,102 @@ export type GetCurrencyIsoCodeQueryVariables = Exact<{
export type GetCurrencyIsoCodeQuery = { __typename?: 'Query', transactioncurrency?: { __typename?: 'transactioncurrency', isocurrencycode?: string | null } | null }; export type GetCurrencyIsoCodeQuery = { __typename?: 'Query', transactioncurrency?: { __typename?: 'transactioncurrency', isocurrencycode?: string | null } | null };
export type GetRewardRulesQueryVariables = Exact<{
conditionId: Scalars['Uuid'];
}>;
export type GetRewardRulesQuery = { __typename?: 'Query', evo_reward_condition?: { __typename?: 'evo_reward_condition', evo_calc_reward_rules?: number | null } | null };
export type GetAgentsDataFromQuoteQueryVariables = Exact<{
quoteId: Scalars['Uuid'];
}>;
export type GetAgentsDataFromQuoteQuery = { __typename?: 'Query', quote?: { __typename?: 'quote', evo_supplier_accountid?: any | null, evo_dealer_person_accountid?: any | null, evo_dealer_reward_conditionid?: any | null, evo_dealer_reward_total?: any | null, evo_dealer_reward_summ?: any | null, evo_dealer_broker_accountid?: any | null, evo_dealer_broker_reward_conditionid?: any | null, evo_dealer_broker_reward_total?: any | null, evo_dealer_broker_reward_summ?: any | null, evo_agent_accountid?: any | null, evo_agent_reward_conditionid?: any | null, evo_agent_reward_total?: any | null, evo_agent_reward_summ?: any | null, evo_double_agent_accountid?: any | null, evo_double_agent_reward_conditionid?: any | null, evo_double_agent_reward_total?: any | null, evo_double_agent_reward_summ?: any | null, evo_broker_accountid?: any | null, evo_broker_reward_conditionid?: any | null, evo_broker_reward_total?: any | null, evo_broker_reward_summ?: any | null, evo_fin_department_accountid?: any | null, evo_fin_department_reward_conditionid?: any | null, evo_fin_department_reward_total?: any | null, evo_fin_department_reward_summ?: any | null } | null };
export type GetRewardConditionsQueryVariables = Exact<{
agentid: Scalars['Uuid'];
currentDate?: InputMaybe<Scalars['DateTime']>;
}>;
export type GetRewardConditionsQuery = { __typename?: 'Query', evo_reward_conditions?: Array<{ __typename?: 'evo_reward_condition', evo_reward_summ?: any | null, label?: string | null, value?: any | null } | null> | null };
export type GetRewardSummQueryVariables = Exact<{
conditionId: Scalars['Uuid'];
}>;
export type GetRewardSummQuery = { __typename?: 'Query', evo_reward_condition?: { __typename?: 'evo_reward_condition', evo_reward_summ?: any | null } | null };
export type GetRewardConditionQueryVariables = Exact<{
conditionId: Scalars['Uuid'];
}>;
export type GetRewardConditionQuery = { __typename?: 'Query', evo_reward_condition?: { __typename?: 'evo_reward_condition', evo_reward_summ?: any | null, evo_reduce_reward?: boolean | null, evo_min_reward_summ?: any | null } | null };
export type GetAgentAccountIdFromLeadQueryVariables = Exact<{
leadid: Scalars['Uuid'];
}>;
export type GetAgentAccountIdFromLeadQuery = { __typename?: 'Query', lead?: { __typename?: 'lead', agentid?: any | null } | null };
export type GetDoubleAgentAccountIdQueryVariables = Exact<{
leadid: Scalars['Uuid'];
}>;
export type GetDoubleAgentAccountIdQuery = { __typename?: 'Query', lead?: { __typename?: 'lead', agentid?: any | null } | null };
export type GetBrokerAccountIdQueryVariables = Exact<{
leadid: Scalars['Uuid'];
}>;
export type GetBrokerAccountIdQuery = { __typename?: 'Query', lead?: { __typename?: 'lead', agentid?: any | null } | null };
export type GetFinDepartmentAccountIdQueryVariables = Exact<{
leadid: Scalars['Uuid'];
}>;
export type GetFinDepartmentAccountIdQuery = { __typename?: 'Query', lead?: { __typename?: 'lead', agentid?: any | null } | null };
export type GetAgentQueryVariables = Exact<{
agentid: Scalars['Uuid'];
}>;
export type GetAgentQuery = { __typename?: 'Query', agent?: { __typename?: 'account', label?: string | null, value?: any | null } | null };
export type GetRewardWithoutOtherAgentQueryVariables = Exact<{
conditionId: Scalars['Uuid'];
}>;
export type GetRewardWithoutOtherAgentQuery = { __typename?: 'Query', evo_reward_condition?: { __typename?: 'evo_reward_condition', evo_agency_agreementidData?: { __typename?: 'evo_agency_agreement', evo_reward_without_other_agent?: boolean | null } | null } | null };
export type GetDealerReturnLeasingQueryVariables = Exact<{
dealerId: Scalars['Uuid'];
}>;
export type GetDealerReturnLeasingQuery = { __typename?: 'Query', dealer?: { __typename?: 'account', evo_return_leasing_dealer?: boolean | null } | null };
export type GetDealerPersonQueryVariables = Exact<{
dealerId: Scalars['Uuid'];
}>;
export type GetDealerPersonQuery = { __typename?: 'Query', salon_providers?: Array<{ __typename?: 'account', evo_inn?: string | null, evo_kpp?: string | null, label?: string | null, value?: any | null } | null> | null };
export type GetBrokerAccountIdFromDealerQueryVariables = Exact<{
dealerId: Scalars['Uuid'];
}>;
export type GetBrokerAccountIdFromDealerQuery = { __typename?: 'Query', dealer?: { __typename?: 'account', evo_broker_accountid?: any | null } | null };

View File

@ -16,7 +16,6 @@ const nextConfig = {
compiler: { compiler: {
styledComponents: true, styledComponents: true,
}, },
pageExtensions: ['tsx', 'jsx'],
rewrites: rewrites:
process.env.NODE_ENV === 'development' && process.env.NODE_ENV === 'development' &&
async function rewrites() { async function rewrites() {

View File

@ -21,7 +21,11 @@
"@ant-design/icons": "^4.7.0", "@ant-design/icons": "^4.7.0",
"@apollo/client": "^3.7.0", "@apollo/client": "^3.7.0",
"@fontsource/montserrat": "^4.5.12", "@fontsource/montserrat": "^4.5.12",
"@tanstack/react-query": "^4.13.0", "@tanstack/react-query": "^4.14.1",
"@trpc/client": "^10.0.0-rc.3",
"@trpc/next": "^10.0.0-rc.3",
"@trpc/react-query": "^10.0.0-rc.3",
"@trpc/server": "^10.0.0-rc.3",
"antd": "^4.21.3", "antd": "^4.21.3",
"axios": "^1.1.3", "axios": "^1.1.3",
"dayjs": "^1.11.2", "dayjs": "^1.11.2",
@ -40,7 +44,9 @@
"rebass": "^4.0.7", "rebass": "^4.0.7",
"sharp": "^0.30.4", "sharp": "^0.30.4",
"styled-components": "^5.3.5", "styled-components": "^5.3.5",
"use-debounce": "^8.0.1" "superjson": "^1.11.0",
"use-debounce": "^8.0.1",
"zod": "^3.19.1"
}, },
"devDependencies": { "devDependencies": {
"@graphql-codegen/cli": "2.12.0", "@graphql-codegen/cli": "2.12.0",

View File

@ -9,6 +9,7 @@ import 'normalize.css';
import { useMemo } from 'react'; import { useMemo } from 'react';
import StoreProvider from 'stores/Provider'; import StoreProvider from 'stores/Provider';
import { ThemeProvider } from 'styled-components'; import { ThemeProvider } from 'styled-components';
import { trpcClient } from 'trpc/client';
import { GlobalStyle } from 'UIKit/colors'; import { GlobalStyle } from 'UIKit/colors';
import theme from 'UIKit/theme'; import theme from 'UIKit/theme';
import '../styles/fonts.css'; import '../styles/fonts.css';
@ -51,4 +52,4 @@ function App({ Component, pageProps }) {
); );
} }
export default App; export default trpcClient.withTRPC(App);

8
pages/api/trpc/[trpc].ts Normal file
View File

@ -0,0 +1,8 @@
import * as trpcNext from '@trpc/server/adapters/next';
import appRouter from 'trpc/routers';
export default trpcNext.createNextApiHandler({
router: appRouter,
// eslint-disable-next-line object-curly-newline
createContext: () => ({}),
});

View File

@ -11,6 +11,7 @@ import injectDefaultReactions from 'process/init/inject-reactions/default';
import { useEffect } from 'react'; import { useEffect } from 'react';
import { useStore } from 'stores/hooks'; import { useStore } from 'stores/hooks';
import styled from 'styled-components'; import styled from 'styled-components';
import { trpcPureClient } from 'trpc/client';
import { Box } from 'UIKit/grid'; import { Box } from 'UIKit/grid';
import { min } from 'UIKit/mq'; import { min } from 'UIKit/mq';
@ -45,7 +46,7 @@ function Home() {
useEffect(() => { useEffect(() => {
getData(apolloClient, store); getData(apolloClient, store);
injectDefaultReactions(store, apolloClient, queryClient); injectDefaultReactions(store, apolloClient, queryClient, trpcPureClient);
}, []); }, []);
return ( return (

View File

@ -1,292 +0,0 @@
/* eslint-disable @typescript-eslint/naming-convention */
import type { ApolloClient } from '@apollo/client';
import { gql } from '@apollo/client';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import type * as CRMTypes from 'graphql/crm.types';
import { reaction } from 'mobx';
import type RootStore from 'stores/root';
import { normalizeOptions } from 'tools/entity';
import * as fillAgentsFromLead from '../lib/fill-agents-from-lead';
import { QUERY_GET_AGENT } from '../lib/query';
dayjs.extend(utc);
export default function commonReactions(store: RootStore, apolloClient: ApolloClient<object>) {
const { $calculation } = store;
/**
* Заполняем агентов из Интереса
*/
reaction(
() => $calculation.getElementValue('selectLead'),
(leadid) => {
fillAgentsFromLead.fillIndAgent(store, apolloClient, leadid);
fillAgentsFromLead.fillCalcDoubleAgent(store, apolloClient, leadid);
fillAgentsFromLead.fillCalcBroker(store, apolloClient, leadid);
fillAgentsFromLead.fillFinDepartment(store, apolloClient, leadid);
}
);
/**
* Заполняем selectDealerPerson
* На изменение Салон приобретения формируем список в поле ЮЛ поставщика - записи Контрагент,
* у которых статус = активный И Поставщик = Да И Тип поставщика = Юридическое лицо
* И связаны с карточкой Контрагент из поля "Салон приобретения" по связи Салон-ЮЛ
*/
const QUERY_GET_DEALER_PERSON = gql`
query GetDealerPerson($dealerId: Uuid!) {
salon_providers(statecode: 0, salonaccountid: $dealerId) {
label: name
value: accountid
}
}
`;
reaction(
() => $calculation.getElementValue('selectDealer'),
async (dealerId) => {
if (!dealerId) {
$calculation.resetElement('selectDealerPerson');
$calculation.resetElement('selectDealerBroker');
return;
}
const {
data: { salon_providers },
} = await apolloClient.query<
CRMTypes.GetDealerPersonQuery,
CRMTypes.GetDealerPersonQueryVariables
>({
query: QUERY_GET_DEALER_PERSON,
variables: {
dealerId,
},
});
if (salon_providers?.length) {
$calculation.setElementOptions('selectDealerPerson', normalizeOptions(salon_providers));
$calculation.setElementValue('selectDealerPerson', salon_providers[0]?.value);
}
}
);
/**
* Заполняем selectDealerBroker
*/
const QUERY_GET_BROKER_ACCOUNTID_FROM_DEALER = gql`
query GetBrokerAccountIdFromDealer($dealerId: Uuid!) {
dealer: account(accountid: $dealerId) {
evo_broker_accountid
}
}
`;
reaction(
() => $calculation.getElementValue('selectDealerPerson'),
async (dealerPersonId) => {
if (!dealerPersonId) {
return;
}
const {
data: { dealer },
} = await apolloClient.query<
CRMTypes.GetBrokerAccountIdFromDealerQuery,
CRMTypes.GetBrokerAccountIdFromDealerQueryVariables
>({
query: QUERY_GET_BROKER_ACCOUNTID_FROM_DEALER,
variables: {
dealerId: dealerPersonId,
},
});
if (dealer?.evo_broker_accountid) {
const {
data: { agent: dealerBroker },
} = await apolloClient.query<CRMTypes.GetAgentQuery, CRMTypes.GetAgentQueryVariables>({
query: QUERY_GET_AGENT,
variables: {
agentid: dealer?.evo_broker_accountid,
},
});
if (dealerBroker) {
$calculation.setElementOptions('selectDealerBroker', normalizeOptions([dealerBroker]));
$calculation.setElementValue('selectDealerBroker', dealerBroker.value);
}
} else {
$calculation.resetElement('selectDealerBroker');
}
}
);
/**
* Заполняем selectDealerRewardCondition
*/
const QUERY_GET_REWARD_CONDITIONS = gql`
query GetRewardConditions($agentid: Uuid!, $currentDate: DateTime) {
evo_reward_conditions(
evo_agent_accountid: $agentid
evo_datefrom_param: { lte: $currentDate }
evo_dateto_param: { gte: $currentDate }
statecode: 0
evo_agency_agreementid_param: { has: true }
) {
label: evo_name
value: evo_reward_conditionid
evo_reward_summ
}
}
`;
reaction(
() => $calculation.getElementValue('selectDealerPerson'),
async (dealerPersonId) => {
if (!dealerPersonId) {
$calculation.resetElement('selectDealerRewardCondition');
return;
}
const {
data: { evo_reward_conditions },
} = await apolloClient.query<
CRMTypes.GetRewardConditionsQuery,
CRMTypes.GetRewardConditionsQueryVariables
>({
query: QUERY_GET_REWARD_CONDITIONS,
variables: {
agentid: dealerPersonId,
currentDate: dayjs().toISOString(),
},
});
if (evo_reward_conditions?.length) {
$calculation.setElementOptions(
'selectDealerRewardCondition',
normalizeOptions(evo_reward_conditions)
);
}
}
);
const QUERY_GET_REWARD_SUMM = gql`
query GetRewardSumm($conditionId: Uuid!) {
evo_reward_condition(evo_reward_conditionid: $conditionId) {
evo_reward_summ
}
}
`;
reaction(
() => $calculation.getElementValue('selectDealerRewardCondition'),
async (rewardConditionId) => {
if (!rewardConditionId) {
$calculation.resetElement('tbxDealerRewardSumm');
return;
}
const {
data: { evo_reward_condition },
} = await apolloClient.query<
CRMTypes.GetRewardSummQuery,
CRMTypes.GetRewardSummQueryVariables
>({
query: QUERY_GET_REWARD_SUMM,
variables: {
conditionId: rewardConditionId,
},
});
$calculation.setElementValue('tbxDealerRewardSumm', evo_reward_condition?.evo_reward_summ);
$calculation.unblockElement('tbxDealerRewardSumm');
}
);
/**
* Заполняем selectDealerBrokerRewardCondition
*/
reaction(
() => $calculation.getElementValue('selectDealerBroker'),
async (dealerBrokerId) => {
if (!dealerBrokerId) {
$calculation.resetElement('selectDealerBrokerRewardCondition');
return;
}
const {
data: { evo_reward_conditions },
} = await apolloClient.query<
CRMTypes.GetRewardConditionsQuery,
CRMTypes.GetRewardConditionsQueryVariables
>({
query: QUERY_GET_REWARD_CONDITIONS,
variables: {
agentid: dealerBrokerId,
currentDate: dayjs().toISOString(),
},
});
if (evo_reward_conditions?.length) {
$calculation.setElementOptions(
'selectDealerBrokerRewardCondition',
normalizeOptions(evo_reward_conditions)
);
}
}
);
reaction(
() => $calculation.getElementValue('selectDealerBrokerRewardCondition'),
async (rewardConditionId) => {
if (!rewardConditionId) {
$calculation.resetElement('tbxDealerBrokerRewardSumm');
return;
}
const {
data: { evo_reward_condition },
} = await apolloClient.query<
CRMTypes.GetRewardSummQuery,
CRMTypes.GetRewardSummQueryVariables
>({
query: QUERY_GET_REWARD_SUMM,
variables: {
conditionId: rewardConditionId,
},
});
$calculation.setElementValue(
'tbxDealerBrokerRewardSumm',
evo_reward_condition?.evo_reward_summ
);
$calculation.unblockElement('tbxDealerBrokerRewardSumm');
}
);
reaction(
() => $calculation.getElementValue('selectDealerRewardCondition'),
(dealerRewardConditionId) => {
if (dealerRewardConditionId) {
$calculation.resetElementValue('selectDealerBroker');
}
}
);
reaction(
() => $calculation.getElementValue('selectDealerBrokerRewardCondition'),
(dealerBrokerRewardConditionId) => {
if (dealerBrokerRewardConditionId) {
$calculation.resetElementValue('selectDealerPerson');
}
}
);
}

View File

@ -1,2 +0,0 @@
/* eslint-disable import/prefer-default-export */
export { default as common } from './common';

View File

@ -6,7 +6,9 @@ export default function validationReactions(store: RootStore, apolloClient: Apol
const { $calculation, $tables } = store; const { $calculation, $tables } = store;
reaction( reaction(
() => { () => {
const hasElementsErrors = $calculation.$validation.hasErrors; const hasElementsErrors = Object.values($calculation.$validation).some(
(validation) => validation.hasErrors
);
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; const hasFingapErrors = $tables.fingap.validation.hasErrors;
@ -15,11 +17,11 @@ export default function validationReactions(store: RootStore, apolloClient: Apol
}, },
(hasErrors) => { (hasErrors) => {
if (hasErrors) { if (hasErrors) {
$calculation.blockElement('btnCalculate'); $calculation.$status.setStatus('btnCalculate', 'Disabled');
$calculation.blockElement('btnCreateKP'); $calculation.$status.setStatus('btnCreateKP', 'Disabled');
} else { } else {
$calculation.unblockElement('btnCalculate'); $calculation.$status.setStatus('btnCalculate', 'Default');
$calculation.unblockElement('btnCreateKP'); $calculation.$status.setStatus('btnCreateKP', 'Default');
} }
}, },
{ {

View File

@ -53,7 +53,7 @@ export default function commonReactions(
reaction( reaction(
() => { () => {
const finGAPInsuranceCompany = $tables.insurance.getRowValue('fingap', 'insuranceCompany'); const finGAPInsuranceCompany = $tables.insurance.getRowValue('fingap', 'insuranceCompany');
const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue();
return { return {
finGAPInsuranceCompany, finGAPInsuranceCompany,
@ -127,8 +127,8 @@ export default function commonReactions(
const paymentsValues = toJS($tables.payments.values); const paymentsValues = toJS($tables.payments.values);
const plPriceRub = $calculation.$values.getValue('plPriceRub'); const plPriceRub = $calculation.$values.getValue('plPriceRub');
const discountRub = $calculation.$values.getValue('discountRub'); const discountRub = $calculation.$values.getValue('discountRub');
const firstPaymentRub = $calculation.getElementValue('tbxFirstPaymentRub'); const firstPaymentRub = $calculation.element('tbxFirstPaymentRub').getValue();
const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue();
return { return {
finGAPInsuranceCompany, finGAPInsuranceCompany,
@ -147,8 +147,7 @@ export default function commonReactions(
firstPaymentRub, firstPaymentRub,
leasingPeriod, leasingPeriod,
}) => { }) => {
if ($tables.fingap.validation.hasErrors) return; if (!finGAPInsuranceCompany || $tables.payments.validation.hasErrors) return;
if (!finGAPInsuranceCompany) return;
const { const {
data: { evo_addproduct_types }, data: { evo_addproduct_types },

View File

@ -10,9 +10,6 @@ export default function validationReactions(
) { ) {
const { $tables } = store; const { $tables } = store;
const errorText = 'Неверно заполнены платежи';
let removeError: () => void;
reaction( reaction(
() => { () => {
const hasPaymentsErrors = $tables.payments.validation.hasErrors; const hasPaymentsErrors = $tables.payments.validation.hasErrors;
@ -24,9 +21,10 @@ export default function validationReactions(
}; };
}, },
({ hasPaymentsErrors, finGAPInsuranceCompany }) => { ({ hasPaymentsErrors, finGAPInsuranceCompany }) => {
if (finGAPInsuranceCompany && hasPaymentsErrors) { $tables.fingap.validate({
removeError = $tables.fingap.validation.addError(errorText); invalid: finGAPInsuranceCompany !== null && hasPaymentsErrors,
} else if (removeError) removeError(); message: 'Неверно заполнены платежи',
});
}, },
{ {
fireImmediately: true, fireImmediately: true,

View File

@ -10,7 +10,7 @@ export default function getData(apolloClient, store) {
function setManyOptions(options) { function setManyOptions(options) {
Object.keys(options).forEach((elementName) => { Object.keys(options).forEach((elementName) => {
const elementOptions = options[elementName]; const elementOptions = options[elementName];
$calculation.$options.setOptions(elementName, elementOptions); $calculation.element(elementName).setOptions(elementOptions);
}); });
} }

View File

@ -1,19 +1,28 @@
import * as agentsReactions from '../../agents/reactions'; import loadKpReactions from 'process/load-kp/reactions';
import * as calculateReactions from '../../calculate/reactions'; import * as calculateReactions from '../../calculate/reactions';
import * as fingapReactions from '../../fingap/reactions'; import * as fingapReactions from '../../fingap/reactions';
import * as leadOpportunityReactions from '../../lead-opportunity/reactions'; import * as leadOpportunityReactions from '../../lead-opportunity/reactions';
import paymentsReactions from '../../payments/reactions'; import paymentsReactions from '../../payments/reactions';
import * as priceReactions from '../../price/reactions'; import * as priceReactions from '../../price/reactions';
import * as agentsReactions from '../../supplier-agent/reactions/agents';
import leasebackReactions from '../../supplier-agent/reactions/leaseback';
import * as supplierReactions from '../../supplier-agent/reactions/supplier';
import setInitialValuesReactions from '../set-values/reactions'; import setInitialValuesReactions from '../set-values/reactions';
export default function injectDefaultReactions(store, apolloClient, queryClient) { export default function injectDefaultReactions(store, apolloClient, queryClient, trpcClient) {
leadOpportunityReactions.common(store, apolloClient, queryClient); leadOpportunityReactions.common(store, apolloClient, queryClient);
leadOpportunityReactions.urls(store, apolloClient, queryClient); leadOpportunityReactions.urls(store, apolloClient, queryClient);
paymentsReactions(store, apolloClient, queryClient); paymentsReactions(store, apolloClient, queryClient);
calculateReactions.validation(store, apolloClient, queryClient); calculateReactions.validation(store, apolloClient, queryClient);
agentsReactions.common(store, apolloClient, queryClient); supplierReactions.commonReactions(store, apolloClient, queryClient);
supplierReactions.validationReactions(store, apolloClient, queryClient);
agentsReactions.fillReactions(store, apolloClient, queryClient);
agentsReactions.commonReactions(store, apolloClient, queryClient);
agentsReactions.validationReactions(store, apolloClient, queryClient);
leasebackReactions(store, apolloClient, queryClient);
priceReactions.computed(store, apolloClient, queryClient); priceReactions.computed(store, apolloClient, queryClient);
fingapReactions.common(store, apolloClient, queryClient); fingapReactions.common(store, apolloClient, queryClient);
fingapReactions.validation(store, apolloClient, queryClient); fingapReactions.validation(store, apolloClient, queryClient);
setInitialValuesReactions(store, apolloClient, queryClient); setInitialValuesReactions(store, apolloClient, queryClient);
loadKpReactions(store, apolloClient, queryClient, trpcClient);
} }

View File

@ -35,10 +35,9 @@ export default function setInitialValuesReactions(
(x) => x?.isocurrencycode === 'RUB' (x) => x?.isocurrencycode === 'RUB'
); );
$calculation.setElementValue( $calculation
'selectSupplierCurrency', .element('selectSupplierCurrency')
transactioncurrency_rub?.transactioncurrencyid .setValue(transactioncurrency_rub?.transactioncurrencyid);
);
} }
); );
} }

View File

@ -1,12 +1,14 @@
/* eslint-disable implicit-arrow-linebreak */
import type { ApolloClient } from '@apollo/client'; import type { ApolloClient } from '@apollo/client';
import { gql } from '@apollo/client'; import { gql } from '@apollo/client';
import type * as CRMTypes from 'graphql/crm.types'; import type * as CRMTypes from 'graphql/crm.types';
import { reaction } from 'mobx'; import { reaction } from 'mobx';
import type RootStore from 'stores/root'; import type RootStore from 'stores/root';
import { normalizeOptions } from 'tools/entity'; import { normalizeOptions } from 'tools/entity';
import { makeDisposable } from 'tools/mobx';
export default function commonReactions(store: RootStore, apolloClient: ApolloClient<object>) { export default function commonReactions(store: RootStore, apolloClient: ApolloClient<object>) {
const { $calculation } = store; const { $calculation, $process } = store;
/** /**
* Если lead содержит данные, то в opportunity подгружается значение из поля Интереса * Если lead содержит данные, то в opportunity подгружается значение из поля Интереса
@ -26,33 +28,37 @@ export default function commonReactions(store: RootStore, apolloClient: ApolloCl
} }
`; `;
reaction( makeDisposable(
() => $calculation.getElementValue('selectLead'), () =>
async (leadid) => { reaction(
if (!leadid) { () => $calculation.element('selectLead').getValue(),
$calculation.resetElementValue('selectOpportunity'); async (leadid) => {
if (!leadid) {
$calculation.element('selectOpportunity').resetValue();
return; return;
} }
const { const {
data: { lead }, data: { lead },
} = await apolloClient.query< } = await apolloClient.query<
CRMTypes.GetOpportunityByLeadQuery, CRMTypes.GetOpportunityByLeadQuery,
CRMTypes.GetOpportunityByLeadQueryVariables CRMTypes.GetOpportunityByLeadQueryVariables
>({ >({
query: QUERY_GET_OPPORTUNITY_BY_LEAD, query: QUERY_GET_OPPORTUNITY_BY_LEAD,
variables: { variables: {
leadid, leadid,
}, },
}); });
if (lead?.evo_opportunityidData?.value) { if (lead?.evo_opportunityidData?.value) {
$calculation.setElementValue('selectOpportunity', lead?.evo_opportunityidData?.value); $calculation.element('selectOpportunity').setValue(lead?.evo_opportunityidData?.value);
} else { } else {
$calculation.resetElementValue('selectOpportunity'); $calculation.element('selectOpportunity').resetValue();
} }
} }
),
() => $process.has('LoadKP')
); );
/** /**
@ -70,9 +76,9 @@ export default function commonReactions(store: RootStore, apolloClient: ApolloCl
`; `;
reaction( reaction(
() => $calculation.getElementValue('selectOpportunity'), () => $calculation.element('selectOpportunity').getValue(),
async (opportunityid) => { async (opportunityid) => {
const leadid = $calculation.getElementValue('selectLead'); const leadid = $calculation.element('selectLead').getValue();
if (leadid) { if (leadid) {
const { const {
@ -88,7 +94,7 @@ export default function commonReactions(store: RootStore, apolloClient: ApolloCl
}); });
if (!opportunityid && lead?.evo_opportunityidData?.value) { if (!opportunityid && lead?.evo_opportunityidData?.value) {
$calculation.resetElementValue('selectLead'); $calculation.element('selectLead').resetValue();
} }
} }
@ -103,7 +109,7 @@ export default function commonReactions(store: RootStore, apolloClient: ApolloCl
}, },
}); });
$calculation.setElementValue('selectLead', data.opportunity?.evo_leadid); $calculation.element('selectLead').setValue(data.opportunity?.evo_leadid);
} }
} }
); );
@ -125,7 +131,7 @@ export default function commonReactions(store: RootStore, apolloClient: ApolloCl
`; `;
reaction( reaction(
() => $calculation.getElementValue('selectLead'), () => $calculation.element('selectLead').getValue(),
async (leadid) => { async (leadid) => {
if (leadid) { if (leadid) {
const { const {
@ -140,9 +146,9 @@ export default function commonReactions(store: RootStore, apolloClient: ApolloCl
}, },
}); });
$calculation.setElementOptions('selectQuote', normalizeOptions(quotes)); $calculation.element('selectQuote').setOptions(normalizeOptions(quotes));
} else { } else {
$calculation.resetElement('selectQuote'); $calculation.element('selectQuote').reset();
} }
} }
); );

View File

@ -12,10 +12,10 @@ export default function urlsReactions(store: RootStore, apolloClient: ApolloClie
*/ */
function makeLinkReaction(elementName: Elements, linkElementName: Elements, query: DocumentNode) { function makeLinkReaction(elementName: Elements, linkElementName: Elements, query: DocumentNode) {
reaction( reaction(
() => $calculation.getElementValue(elementName), () => $calculation.element(elementName).getValue(),
(id) => { (id) => {
if (!id) { if (!id) {
$calculation.resetElementValue(linkElementName); $calculation.element(linkElementName).resetValue();
return; return;
} }
@ -34,22 +34,22 @@ export default function urlsReactions(store: RootStore, apolloClient: ApolloClie
.then(({ data }) => { .then(({ data }) => {
clearTimeout(timeoutId); clearTimeout(timeoutId);
if (data.entity?.link) { if (data.entity?.link) {
$calculation.setElementValue(linkElementName, data.entity?.link); $calculation.element(linkElementName).setValue(data.entity?.link);
} }
}) })
.catch(() => { .catch(() => {
clearTimeout(timeoutId); clearTimeout(timeoutId);
$calculation.resetElementValue(linkElementName); $calculation.element(linkElementName).resetValue();
}); });
} }
); );
reaction( reaction(
() => $calculation.getElementValue(linkElementName), () => $calculation.element(linkElementName).getValue(),
(url) => { (url) => {
if (!url) { if (!url) {
$calculation.blockElement(linkElementName); $calculation.element(linkElementName).block();
} else { } else {
$calculation.unblockElement(linkElementName); $calculation.element(linkElementName).unblock();
} }
} }
); );

View File

@ -0,0 +1,51 @@
import type { ApolloClient } from '@apollo/client';
import type { QueryClient } from '@tanstack/react-query';
import message from 'Elements/message';
import { reaction, toJS } from 'mobx';
import type RootStore from 'stores/root';
import type { TRPCPureClient } from 'trpc/types';
export default function loadKpReactions(
store: RootStore,
apolloClient: ApolloClient<object>,
queryClient: QueryClient,
trpcClient: TRPCPureClient
) {
const { $calculation, $process } = store;
reaction(
() => $calculation.element('selectQuote').getValue(),
(quoteId) => {
if (!quoteId) return;
$process.add('LoadKP');
const quoteName = $calculation.element('selectQuote').getOption()?.label;
const { quote } = toJS($calculation.$values.values);
trpcClient.quote.getValues
.query({
values: {
quote,
},
})
.then(({ values }) => {
$calculation.$values.setValues({
values,
exclude: ['lead', 'opportunity', 'quote', 'leadUrl', 'opportunityUrl', 'quoteUrl'],
});
message.success({
content: `КП ${quoteName} загружено`,
});
})
.catch(() => {
message.error({
content: `Ошибка во время загрузки КП ${quoteName}`,
});
})
.finally(() => {
$process.delete('LoadKP');
});
}
);
}

View File

@ -8,7 +8,9 @@ import { shift } from 'radash';
import type { CalculationOptions } from 'stores/calculation/options/types'; import type { CalculationOptions } from 'stores/calculation/options/types';
import type RootStore from 'stores/root'; import type RootStore from 'stores/root';
import type { Row } from 'stores/tables/payments/types'; import type { Row } from 'stores/tables/payments/types';
import ValidationHelper from 'stores/validation/helper';
import { difference } from 'tools/array'; import { difference } from 'tools/array';
import { makeDisposable } from 'tools/mobx';
import * as seasonsConstants from './lib/seasons-constants'; import * as seasonsConstants from './lib/seasons-constants';
import * as seasonsTools from './lib/seasons-tools'; import * as seasonsTools from './lib/seasons-tools';
import validatePaymentsTable from './validation'; import validatePaymentsTable from './validation';
@ -18,17 +20,17 @@ export default function paymentsReactions(
apolloClient: ApolloClient<object>, apolloClient: ApolloClient<object>,
queryClient: QueryClient queryClient: QueryClient
) { ) {
const { $calculation, $tables } = store; const { $calculation, $tables, $process } = store;
reaction( reaction(
() => $calculation.getElementValue('tbxFirstPaymentPerc'), () => $calculation.element('tbxFirstPaymentPerc').getValue(),
(firstPaymentPerc) => { (firstPaymentPerc) => {
$tables.payments.setValue(0, firstPaymentPerc); $tables.payments.setValue(0, firstPaymentPerc);
} }
); );
reaction( reaction(
() => $calculation.getElementValue('tbxLastPaymentPerc'), () => $calculation.element('tbxLastPaymentPerc').getValue(),
(lastPaymentPerc) => { (lastPaymentPerc) => {
const paymentsLength = $tables.payments.values.length; const paymentsLength = $tables.payments.values.length;
$tables.payments.setValue(paymentsLength - 1, lastPaymentPerc); $tables.payments.setValue(paymentsLength - 1, lastPaymentPerc);
@ -38,155 +40,169 @@ export default function paymentsReactions(
/** /**
* Аннуитет * Аннуитет
*/ */
reaction( makeDisposable(
() => { () =>
const graphType = $calculation.getElementValue('radioGraphType'); reaction(
const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); () => {
const graphType = $calculation.element('radioGraphType').getValue();
const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue();
return { return {
graphType, graphType,
leasingPeriod, leasingPeriod,
}; };
}, },
({ graphType, leasingPeriod }) => { ({ graphType, leasingPeriod }) => {
if (graphType === 100_000_000) { if (graphType === 100_000_000) {
const middlePayments: Row[] = Array.from( const middlePayments: Row[] = Array.from(
{ {
length: leasingPeriod - 2, length: leasingPeriod - 2,
}, },
() => ({ () => ({
value: 100, value: 100,
status: 'Disabled', status: 'Disabled',
}) })
); );
const firstPaymentPerc = $calculation.getElementValue('tbxFirstPaymentPerc'); const firstPaymentPerc = $calculation.element('tbxFirstPaymentPerc').getValue();
const lastPaymentPerc = $calculation.getElementValue('tbxLastPaymentPerc'); const lastPaymentPerc = $calculation.element('tbxLastPaymentPerc').getValue();
$tables.payments.setRows([ $tables.payments.setRows([
{ {
value: firstPaymentPerc, value: firstPaymentPerc,
status: 'Disabled', status: 'Disabled',
}, },
...middlePayments, ...middlePayments,
{ {
value: lastPaymentPerc, value: lastPaymentPerc,
status: 'Disabled', status: 'Disabled',
}, },
]); ]);
} }
}, },
{ {
fireImmediately: true, fireImmediately: true,
} }
),
() => $process.has('LoadKP')
); );
/** /**
* Равноубывающий * Равноубывающий
*/ */
reaction( makeDisposable(
() => { () =>
const graphType = $calculation.getElementValue('radioGraphType'); reaction(
const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); () => {
const parmentsDecreasePercent = $calculation.getElementValue('tbxParmentsDecreasePercent'); const graphType = $calculation.element('radioGraphType').getValue();
const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue();
const parmentsDecreasePercent = $calculation
.element('tbxParmentsDecreasePercent')
.getValue();
return { return {
graphType, graphType,
leasingPeriod, leasingPeriod,
parmentsDecreasePercent, parmentsDecreasePercent,
}; };
}, },
({ graphType, leasingPeriod, parmentsDecreasePercent }) => { ({ graphType, leasingPeriod, parmentsDecreasePercent }) => {
if (graphType === 100_000_002) { if (graphType === 100_000_002) {
const middlePayments: Row[] = Array.from( const middlePayments: Row[] = Array.from(
{ {
length: leasingPeriod - 2, length: leasingPeriod - 2,
}, },
(_, k) => { (_, k) => {
const payment = 100 * (parmentsDecreasePercent / 100) ** k; const payment = 100 * (parmentsDecreasePercent / 100) ** k;
return { return {
value: Number(payment.toFixed(2)), value: Number(payment.toFixed(2)),
status: 'Disabled', status: 'Disabled',
}; };
}
);
const firstPaymentPerc = $calculation.element('tbxFirstPaymentPerc').getValue();
const lastPaymentPerc = $calculation.element('tbxLastPaymentPerc').getValue();
$tables.payments.setRows([
{
value: firstPaymentPerc,
status: 'Disabled',
},
...middlePayments,
{
value: lastPaymentPerc,
status: 'Disabled',
},
]);
} }
); }
),
const firstPaymentPerc = $calculation.getElementValue('tbxFirstPaymentPerc'); () => $process.has('LoadKP')
const lastPaymentPerc = $calculation.getElementValue('tbxLastPaymentPerc');
$tables.payments.setRows([
{
value: firstPaymentPerc,
status: 'Disabled',
},
...middlePayments,
{
value: lastPaymentPerc,
status: 'Disabled',
},
]);
}
}
); );
/** /**
* Легкий старт * Легкий старт
*/ */
reaction( makeDisposable(
() => { () =>
const graphType = $calculation.getElementValue('radioGraphType'); reaction(
const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); () => {
const graphType = $calculation.element('radioGraphType').getValue();
const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue();
return { return {
graphType, graphType,
leasingPeriod, leasingPeriod,
}; };
}, },
({ graphType, leasingPeriod }) => { ({ graphType, leasingPeriod }) => {
if (graphType === 100_000_004) { if (graphType === 100_000_004) {
const editablePayments: Row[] = [ const editablePayments: Row[] = [
{ {
value: 25, value: 25,
status: 'Default', status: 'Default',
}, },
{ {
value: 50, value: 50,
status: 'Default', status: 'Default',
}, },
{ {
value: 75, value: 75,
status: 'Default', status: 'Default',
}, },
]; ];
const payments: Row[] = Array.from( const payments: Row[] = Array.from(
{ {
length: leasingPeriod - 5, length: leasingPeriod - 5,
}, },
() => ({ () => ({
value: 100, value: 100,
status: 'Disabled', status: 'Disabled',
}) })
); );
const firstPaymentPerc = $calculation.getElementValue('tbxFirstPaymentPerc'); const firstPaymentPerc = $calculation.element('tbxFirstPaymentPerc').getValue();
const lastPaymentPerc = $calculation.getElementValue('tbxLastPaymentPerc'); const lastPaymentPerc = $calculation.element('tbxLastPaymentPerc').getValue();
$tables.payments.setRows([ $tables.payments.setRows([
{ {
value: firstPaymentPerc, value: firstPaymentPerc,
status: 'Disabled', status: 'Disabled',
}, },
...editablePayments, ...editablePayments,
...payments, ...payments,
{ {
value: lastPaymentPerc, value: lastPaymentPerc,
status: 'Disabled', status: 'Disabled',
}, },
]); ]);
} }
} }
),
() => $process.has('LoadKP')
); );
/** /**
@ -200,7 +216,7 @@ export default function paymentsReactions(
reaction( reaction(
() => { () => {
const graphType = $calculation.getElementValue('radioGraphType'); const graphType = $calculation.element('radioGraphType').getValue();
return graphType; return graphType;
}, },
@ -216,7 +232,7 @@ export default function paymentsReactions(
seasonSeasonTypes.has(option.value) seasonSeasonTypes.has(option.value)
); );
} }
$calculation.setElementOptions('selectSeasonType', selectSeasonTypeOptions); $calculation.element('selectSeasonType').setOptions(selectSeasonTypeOptions);
} }
); );
@ -227,133 +243,141 @@ export default function paymentsReactions(
100_000_006: [100, 7, 3], 100_000_006: [100, 7, 3],
}; };
reaction( makeDisposable(
() => { () =>
const degressionType = $calculation.getElementValue('selectSeasonType'); reaction(
const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); () => {
const graphType = $calculation.getElementValue('radioGraphType'); const degressionType = $calculation.element('selectSeasonType').getValue();
const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue();
const graphType = $calculation.element('radioGraphType').getValue();
return { return {
degressionType, degressionType,
leasingPeriod, leasingPeriod,
graphType, graphType,
}; };
}, },
({ degressionType, leasingPeriod, graphType }) => { ({ degressionType, leasingPeriod, graphType }) => {
if (graphType === 100_000_001) { if (graphType === 100_000_001) {
let payments: Row[] = []; let payments: Row[] = [];
switch (degressionType) { switch (degressionType) {
case 100_000_007: { case 100_000_007: {
const editablePayments: Row[] = Array.from( const editablePayments: Row[] = Array.from(
{
length: leasingPeriod - 3,
},
() => ({
value: 100,
status: 'Default',
})
);
payments = [
{
value: 100,
status: 'Disabled',
},
...editablePayments,
];
break;
}
case 100_000_003:
case 100_000_004:
case 100_000_005:
case 100_000_006: {
const [step1, step2, step3] = degressionSteps[degressionType];
const paymentsInStep = Math.ceil((leasingPeriod - 2) / 3);
payments = Array.from(
{
length: leasingPeriod - 2,
},
(_v, i) => {
let value = step3;
if (i <= paymentsInStep * 2 - 1) {
value = step2;
}
if (i <= paymentsInStep - 1) {
value = step1;
}
return {
value,
status: 'Disabled',
};
}
);
break;
}
default: {
break;
}
}
const firstPaymentPerc = $calculation.element('tbxFirstPaymentPerc').getValue();
const lastPaymentPerc = $calculation.element('tbxLastPaymentPerc').getValue();
$tables.payments.setRows([
{ {
length: leasingPeriod - 3, value: firstPaymentPerc,
},
() => ({
value: 100,
status: 'Default',
})
);
payments = [
{
value: 100,
status: 'Disabled', status: 'Disabled',
}, },
...editablePayments, ...payments,
];
break;
}
case 100_000_003:
case 100_000_004:
case 100_000_005:
case 100_000_006: {
const [step1, step2, step3] = degressionSteps[degressionType];
const paymentsInStep = Math.ceil((leasingPeriod - 2) / 3);
payments = Array.from(
{ {
length: leasingPeriod - 2, value: lastPaymentPerc,
status: 'Disabled',
}, },
(_v, i) => { ]);
let value = step3;
if (i <= paymentsInStep * 2 - 1) {
value = step2;
}
if (i <= paymentsInStep - 1) {
value = step1;
}
return {
value,
status: 'Disabled',
};
}
);
break;
}
default: {
break;
} }
} }
),
const firstPaymentPerc = $calculation.getElementValue('tbxFirstPaymentPerc'); () => $process.has('LoadKP')
const lastPaymentPerc = $calculation.getElementValue('tbxLastPaymentPerc');
$tables.payments.setRows([
{
value: firstPaymentPerc,
status: 'Disabled',
},
...payments,
{
value: lastPaymentPerc,
status: 'Disabled',
},
]);
}
}
); );
reaction( makeDisposable(
() => { () =>
const graphType = $calculation.getElementValue('radioGraphType'); reaction(
const payments = toJS($tables.payments.values); () => {
const degressionType = $calculation.getElementValue('selectSeasonType'); const graphType = $calculation.element('radioGraphType').getValue();
const payments = toJS($tables.payments.values);
const degressionType = $calculation.element('selectSeasonType').getValue();
return { return {
graphType, graphType,
payments, payments,
degressionType, degressionType,
}; };
}, },
(nextParams, prevParams) => { (nextParams, prevParams) => {
if (nextParams.graphType === 100_000_001 && nextParams.degressionType === 100_000_007) { if (nextParams.graphType === 100_000_001 && nextParams.degressionType === 100_000_007) {
const changes = difference(nextParams.payments, prevParams.payments); const changes = difference(nextParams.payments, prevParams.payments);
if (changes === null || changes.length > 1) return; if (changes === null || changes.length > 1) return;
const [changeIndex] = changes; const [changeIndex] = changes;
const value = nextParams.payments[changeIndex]; const value = nextParams.payments[changeIndex];
const payments = nextParams.payments.slice(1, -1).map((payment, i) => { const payments = nextParams.payments.slice(1, -1).map((payment, i) => {
if (i <= changeIndex - 2) return payment; if (i <= changeIndex - 2) return payment;
return value; return value;
}); });
const firstPaymentPerc = $calculation.getElementValue('tbxFirstPaymentPerc'); const firstPaymentPerc = $calculation.element('tbxFirstPaymentPerc').getValue();
const lastPaymentPerc = $calculation.getElementValue('tbxLastPaymentPerc'); const lastPaymentPerc = $calculation.element('tbxLastPaymentPerc').getValue();
$tables.payments.setValues([firstPaymentPerc, ...payments, lastPaymentPerc]); $tables.payments.setValues([firstPaymentPerc, ...payments, lastPaymentPerc]);
} }
}, },
{ {
delay: 50, delay: 50,
equals: comparer.structural, equals: comparer.structural,
} }
),
() => $process.has('LoadKP')
); );
/** /**
@ -362,7 +386,7 @@ export default function paymentsReactions(
reaction( reaction(
() => { () => {
const graphType = $calculation.getElementValue('radioGraphType'); const graphType = $calculation.element('radioGraphType').getValue();
return { return {
graphType, graphType,
@ -371,8 +395,8 @@ export default function paymentsReactions(
({ graphType }) => { ({ graphType }) => {
if (graphType !== 100_000_003) return; if (graphType !== 100_000_003) return;
const seasonType = $calculation.getElementValue('selectSeasonType'); const seasonType = $calculation.element('selectSeasonType').getValue();
const highSeasonStart = $calculation.getElementValue('selectHighSeasonStart'); const highSeasonStart = $calculation.element('selectHighSeasonStart').getValue();
if (!seasonType || !highSeasonStart) { if (!seasonType || !highSeasonStart) {
$tables.payments.setValues([]); $tables.payments.setValues([]);
@ -382,16 +406,16 @@ export default function paymentsReactions(
reaction( reaction(
() => { () => {
const seasonType = $calculation.getElementValue('selectSeasonType'); const seasonType = $calculation.element('selectSeasonType').getValue();
return seasonType; return seasonType;
}, },
(seasonType) => { (seasonType) => {
const graphType = $calculation.getElementValue('radioGraphType'); const graphType = $calculation.element('radioGraphType').getValue();
if (graphType !== 100_000_003) return; if (graphType !== 100_000_003) return;
if (!seasonType) { if (!seasonType) {
$calculation.resetElement('selectHighSeasonStart'); $calculation.element('selectHighSeasonStart').reset();
return; return;
} }
@ -400,7 +424,7 @@ export default function paymentsReactions(
(option) => !seasonsConstants.FORBIDDEN_HIGH_SEASON_START[seasonType].includes(option.label) (option) => !seasonsConstants.FORBIDDEN_HIGH_SEASON_START[seasonType].includes(option.label)
); );
$calculation.setElementOptions('selectHighSeasonStart', highSeasonStartOptions); $calculation.element('selectHighSeasonStart').setOptions(highSeasonStartOptions);
} }
); );
@ -418,123 +442,131 @@ export default function paymentsReactions(
return rows; return rows;
} }
reaction( makeDisposable(
() => { () =>
const seasonType = $calculation.getElementValue('selectSeasonType'); reaction(
const highSeasonStartOption = $calculation.getElementOption('selectHighSeasonStart'); () => {
const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); const seasonType = $calculation.element('selectSeasonType').getValue();
const highSeasonStartOption = $calculation.element('selectHighSeasonStart').getOption();
const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue();
return { return {
seasonType, seasonType,
highSeasonStartOption, highSeasonStartOption,
leasingPeriod, leasingPeriod,
}; };
},
({ seasonType, highSeasonStartOption, leasingPeriod }) => {
const graphType = $calculation.getElementValue('radioGraphType');
if (graphType !== 100_000_003) return;
if (!seasonType || !highSeasonStartOption) {
$tables.payments.setValues([]);
return;
}
const seasons = seasonsTools.generateSeasons(
seasonType,
seasonsConstants.DEFAULT_SEASONS_VALUES
);
const shiftNumber = Number.parseInt(highSeasonStartOption.label, 10) - 2;
const payments = seasonsTools.generateSeasonsPayments(
leasingPeriod,
shift(seasons, shiftNumber)
);
const rows: Row[] = generateSeasonPaymentsRows(seasonType, shiftNumber, payments);
const firstPaymentPerc = $calculation.getElementValue('tbxFirstPaymentPerc');
const lastPaymentPerc = $calculation.getElementValue('tbxLastPaymentPerc');
$tables.payments.setRows([
{
value: firstPaymentPerc,
status: 'Disabled',
}, },
...rows, ({ seasonType, highSeasonStartOption, leasingPeriod }) => {
{ const graphType = $calculation.element('radioGraphType').getValue();
value: lastPaymentPerc, if (graphType !== 100_000_003) return;
status: 'Disabled',
}, if (!seasonType || !highSeasonStartOption) {
]); $tables.payments.setValues([]);
}
return;
}
const seasons = seasonsTools.generateSeasons(
seasonType,
seasonsConstants.DEFAULT_SEASONS_VALUES
);
const shiftNumber = Number.parseInt(highSeasonStartOption.label, 10) - 2;
const payments = seasonsTools.generateSeasonsPayments(
leasingPeriod,
shift(seasons, shiftNumber)
);
const rows: Row[] = generateSeasonPaymentsRows(seasonType, shiftNumber, payments);
const firstPaymentPerc = $calculation.element('tbxFirstPaymentPerc').getValue();
const lastPaymentPerc = $calculation.element('tbxLastPaymentPerc').getValue();
$tables.payments.setRows([
{
value: firstPaymentPerc,
status: 'Disabled',
},
...rows,
{
value: lastPaymentPerc,
status: 'Disabled',
},
]);
}
),
() => $process.has('LoadKP')
); );
reaction( makeDisposable(
() => { () =>
const payments = toJS($tables.payments.values); reaction(
const seasons = payments.slice(1, seasonsConstants.SEASONS_PERIOD_NUMBER + 1); () => {
const payments = toJS($tables.payments.values);
const seasons = payments.slice(1, seasonsConstants.SEASONS_PERIOD_NUMBER + 1);
return seasons; return seasons;
},
(nextSeasons, prevSeasons) => {
const graphType = $calculation.getElementValue('radioGraphType');
if (graphType !== 100_000_003) return;
const seasonType = $calculation.getElementValue('selectSeasonType');
const highSeasonStartOption = $calculation.getElementOption('selectHighSeasonStart');
if (!seasonType || !highSeasonStartOption) return;
const shiftNumber = Number.parseInt(highSeasonStartOption.label, 10) - 2;
const unshiftedNextSeasons = shift(nextSeasons, -shiftNumber);
const unshiftedPrevSeasons = shift(prevSeasons, -shiftNumber);
const changes = difference(unshiftedNextSeasons, unshiftedPrevSeasons);
if (changes === null || changes.length > 1) return;
const [changeIndex] = changes;
const positionIndex = seasonsTools.getPositionIndex(seasonType, changeIndex);
const values = seasonsTools.getSeasonsValues(seasonType, unshiftedNextSeasons);
values[positionIndex] = unshiftedNextSeasons[changeIndex];
const seasons = seasonsTools.generateSeasons(seasonType, values);
const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod');
const payments = seasonsTools.generateSeasonsPayments(
leasingPeriod,
shift(seasons, shiftNumber)
);
const rows: Row[] = generateSeasonPaymentsRows(seasonType, shiftNumber, payments);
const firstPaymentPerc = $calculation.getElementValue('tbxFirstPaymentPerc');
const lastPaymentPerc = $calculation.getElementValue('tbxLastPaymentPerc');
$tables.payments.setRows([
{
value: firstPaymentPerc,
status: 'Disabled',
}, },
...rows, (nextSeasons, prevSeasons) => {
{ const graphType = $calculation.element('radioGraphType').getValue();
value: lastPaymentPerc, if (graphType !== 100_000_003) return;
status: 'Disabled',
const seasonType = $calculation.element('selectSeasonType').getValue();
const highSeasonStartOption = $calculation.element('selectHighSeasonStart').getOption();
if (!seasonType || !highSeasonStartOption) return;
const shiftNumber = Number.parseInt(highSeasonStartOption.label, 10) - 2;
const unshiftedNextSeasons = shift(nextSeasons, -shiftNumber);
const unshiftedPrevSeasons = shift(prevSeasons, -shiftNumber);
const changes = difference(unshiftedNextSeasons, unshiftedPrevSeasons);
if (changes === null || changes.length > 1) return;
const [changeIndex] = changes;
const positionIndex = seasonsTools.getPositionIndex(seasonType, changeIndex);
const values = seasonsTools.getSeasonsValues(seasonType, unshiftedNextSeasons);
values[positionIndex] = unshiftedNextSeasons[changeIndex];
const seasons = seasonsTools.generateSeasons(seasonType, values);
const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue();
const payments = seasonsTools.generateSeasonsPayments(
leasingPeriod,
shift(seasons, shiftNumber)
);
const rows: Row[] = generateSeasonPaymentsRows(seasonType, shiftNumber, payments);
const firstPaymentPerc = $calculation.element('tbxFirstPaymentPerc').getValue();
const lastPaymentPerc = $calculation.element('tbxLastPaymentPerc').getValue();
$tables.payments.setRows([
{
value: firstPaymentPerc,
status: 'Disabled',
},
...rows,
{
value: lastPaymentPerc,
status: 'Disabled',
},
]);
}, },
]); {
}, delay: 50,
{ equals: comparer.structural,
delay: 50, }
equals: comparer.structural, ),
} () => $process.has('LoadKP')
); );
/** /**
* Валидация * Валидация
*/ */
let removeError: () => void; const validationHelper = new ValidationHelper();
reaction( reaction(
() => { () => {
const payments = toJS($tables.payments.values); const payments = toJS($tables.payments.values);
const graphType = $calculation.getElementValue('radioGraphType'); const graphType = $calculation.element('radioGraphType').getValue();
const seasonType = $calculation.getElementValue('selectSeasonType'); const seasonType = $calculation.element('selectSeasonType').getValue();
const highSeasonStart = $calculation.getElementValue('selectHighSeasonStart'); const highSeasonStart = $calculation.element('selectHighSeasonStart').getValue();
const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue();
return { return {
payments, payments,
@ -545,11 +577,12 @@ export default function paymentsReactions(
}; };
}, },
() => { () => {
if (removeError) removeError(); validationHelper.removeErrors();
const errorText = validatePaymentsTable(store); const errorText = validatePaymentsTable(store);
if (errorText) { if (errorText) {
removeError = $tables.payments.validation.addError(errorText); const removeError = $tables.payments.validation.addError(errorText);
validationHelper.add(removeError);
} }
}, },
{ {

View File

@ -7,10 +7,10 @@ import { areEqual, isSorted } from 'tools/array';
import { SEASONS_PERIODS, SEASONS_PERIOD_NUMBER } from './lib/seasons-constants'; import { SEASONS_PERIODS, SEASONS_PERIOD_NUMBER } from './lib/seasons-constants';
export default function validatePaymentsTable({ $calculation, $tables }: RootStore) { export default function validatePaymentsTable({ $calculation, $tables }: RootStore) {
switch ($calculation.getElementValue('radioGraphType')) { switch ($calculation.element('radioGraphType').getValue()) {
// Дегрессия // Дегрессия
case 100_000_001: case 100_000_001:
if (!$calculation.getElementValue('selectSeasonType')) { if (!$calculation.element('selectSeasonType').getValue()) {
return 'Не выбран тип дегрессии'; return 'Не выбран тип дегрессии';
} }
/** /**
@ -18,7 +18,7 @@ export default function validatePaymentsTable({ $calculation, $tables }: RootSto
*/ */
{ {
const MIN_PAYMENT = 3; const MIN_PAYMENT = 3;
const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue();
const targetPayments = $tables.payments.values.slice(1, leasingPeriod - 1); const targetPayments = $tables.payments.values.slice(1, leasingPeriod - 1);
if (!targetPayments.every((payment) => payment >= MIN_PAYMENT)) { if (!targetPayments.every((payment) => payment >= MIN_PAYMENT)) {
@ -30,7 +30,7 @@ export default function validatePaymentsTable({ $calculation, $tables }: RootSto
* при Дегрессии все значения не должны быть равны друг другу + что при Легком старте 2,3 и 4 платежи не должны быть равны 100 * при Дегрессии все значения не должны быть равны друг другу + что при Легком старте 2,3 и 4 платежи не должны быть равны 100
*/ */
{ {
const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue();
const targetPayments = $tables.payments.values.slice(1, leasingPeriod - 1); const targetPayments = $tables.payments.values.slice(1, leasingPeriod - 1);
if (new Set(targetPayments).size === 1) { if (new Set(targetPayments).size === 1) {
@ -42,7 +42,7 @@ export default function validatePaymentsTable({ $calculation, $tables }: RootSto
* Проверка на возрастание * Проверка на возрастание
*/ */
{ {
const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue();
const targetPayments = $tables.payments.values.slice(1, leasingPeriod - 1); const targetPayments = $tables.payments.values.slice(1, leasingPeriod - 1);
for (let i = 2; i < targetPayments.length - 1; i += 1) { for (let i = 2; i < targetPayments.length - 1; i += 1) {
@ -73,7 +73,7 @@ export default function validatePaymentsTable({ $calculation, $tables }: RootSto
* иначе не осуществлять Расчет графика и выводить ошибку "Нельзя осуществить расчет - указана очень жетская дегрессия. Не менее чем у 4х платежей "Соотношение платежа" должно не отличаться между самой", * иначе не осуществлять Расчет графика и выводить ошибку "Нельзя осуществить расчет - указана очень жетская дегрессия. Не менее чем у 4х платежей "Соотношение платежа" должно не отличаться между самой",
*/ */
{ {
const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue();
const targetPayments = $tables.payments.values.slice(1, leasingPeriod - 1); const targetPayments = $tables.payments.values.slice(1, leasingPeriod - 1);
const counts = counting(targetPayments, (v) => v); const counts = counting(targetPayments, (v) => v);
if (Object.values(counts).filter((count) => count > 1).length < 2) { if (Object.values(counts).filter((count) => count > 1).length < 2) {
@ -84,17 +84,17 @@ export default function validatePaymentsTable({ $calculation, $tables }: RootSto
break; break;
case 100_000_003: { case 100_000_003: {
const leasingPeriod = $calculation.getElementValue('tbxLeasingPeriod'); const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue();
if (leasingPeriod < 14) { if (leasingPeriod < 14) {
return 'При сезонном виде графика срок лизинга должен быть больше 14 месяцев'; return 'При сезонном виде графика срок лизинга должен быть больше 14 месяцев';
} }
const seasonType = $calculation.getElementValue('selectSeasonType'); const seasonType = $calculation.element('selectSeasonType').getValue();
if (!seasonType) { if (!seasonType) {
return 'Не выбран тип сезонности'; return 'Не выбран тип сезонности';
} }
const highSeasonStartOption = $calculation.getElementOption('selectHighSeasonStart'); const highSeasonStartOption = $calculation.element('selectHighSeasonStart').getOption();
if (!highSeasonStartOption) { if (!highSeasonStartOption) {
return 'Не выбрано смещение сезонности'; return 'Не выбрано смещение сезонности';
} }

View File

@ -31,9 +31,9 @@ export default function computedReactions(store: RootStore, apolloClient: Apollo
autorun( autorun(
async () => { async () => {
const supplierCurrencyId = $calculation.getElementValue('selectSupplierCurrency'); const supplierCurrencyId = $calculation.element('selectSupplierCurrency').getValue();
const leaseObjectPrice = $calculation.getElementValue('tbxLeaseObjectPrice'); const leaseObjectPrice = $calculation.element('tbxLeaseObjectPrice').getValue();
const supplierDiscountRub = $calculation.getElementValue('tbxSupplierDiscountRub'); const supplierDiscountRub = $calculation.element('tbxSupplierDiscountRub').getValue();
if (!supplierCurrencyId) { if (!supplierCurrencyId) {
$calculation.$values.setValue('plPriceRub', leaseObjectPrice); $calculation.$values.setValue('plPriceRub', leaseObjectPrice);

View File

@ -0,0 +1,97 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { gql } from '@apollo/client';
import initializeApollo from 'apollo/client';
import type * as CRMTypes from 'graphql/crm.types';
import type { Quote } from './index';
const QUERY_GET_REWARD_RULES = gql`
query GetRewardRules($conditionId: Uuid!) {
evo_reward_condition(evo_reward_conditionid: $conditionId) {
evo_calc_reward_rules
}
}
`;
async function getRewardSum(
conditionId: string | null | undefined,
quote: Quote,
quoteRewardSummField: keyof Quote,
quoteRewardTotalField: keyof Quote
) {
if (!conditionId) return 0;
const apolloClient = initializeApollo();
const {
data: { evo_reward_condition },
} = await apolloClient.query<CRMTypes.GetRewardRulesQuery, CRMTypes.GetRewardRulesQueryVariables>(
{
query: QUERY_GET_REWARD_RULES,
variables: {
conditionId,
},
}
);
if (evo_reward_condition?.evo_calc_reward_rules === 100_000_001) {
return quote[quoteRewardSummField];
}
return quote[quoteRewardTotalField];
}
export default async function getSums(quote: Quote) {
const [
dealerRewardSumm,
dealerBrokerRewardSumm,
indAgentRewardSumm,
calcDoubleAgentRewardSumm,
calcBrokerRewardSum,
finDepartmentRewardSumm,
] = await Promise.all([
getRewardSum(
quote?.evo_dealer_reward_conditionid,
quote,
'evo_dealer_reward_summ',
'evo_dealer_reward_total'
),
getRewardSum(
quote?.evo_dealer_broker_reward_conditionid,
quote,
'evo_dealer_broker_reward_summ',
'evo_dealer_broker_reward_total'
),
getRewardSum(
quote?.evo_agent_reward_conditionid,
quote,
'evo_agent_reward_summ',
'evo_agent_reward_total'
),
getRewardSum(
quote.evo_double_agent_reward_conditionid,
quote,
'evo_double_agent_reward_summ',
'evo_double_agent_reward_total'
),
getRewardSum(
quote.evo_broker_reward_conditionid,
quote,
'evo_broker_reward_summ',
'evo_broker_reward_total'
),
getRewardSum(
quote.evo_fin_department_reward_conditionid,
quote,
'evo_fin_department_reward_summ',
'evo_fin_department_reward_total'
),
]);
return {
dealerRewardSumm,
dealerBrokerRewardSumm,
indAgentRewardSumm,
calcDoubleAgentRewardSumm,
calcBrokerRewardSum,
finDepartmentRewardSumm,
};
}

View File

@ -0,0 +1,103 @@
import { gql } from '@apollo/client';
import initializeApollo from 'apollo/client';
import type * as CRMTypes from 'graphql/crm.types';
import type { CalculationValues } from 'stores/calculation/values/types';
import getSums from './get-sums';
const QUERY_GET_AGENTS_DATA_FROM_QUOTE = gql`
query GetAgentsDataFromQuote($quoteId: Uuid!) {
quote(quoteId: $quoteId) {
evo_supplier_accountid
evo_dealer_person_accountid
evo_dealer_reward_conditionid
evo_dealer_reward_total
evo_dealer_reward_summ
evo_dealer_broker_accountid
evo_dealer_broker_reward_conditionid
evo_dealer_broker_reward_total
evo_dealer_broker_reward_summ
evo_agent_accountid
evo_agent_reward_conditionid
evo_agent_reward_total
evo_agent_reward_summ
evo_double_agent_accountid
evo_double_agent_reward_conditionid
evo_double_agent_reward_total
evo_double_agent_reward_summ
evo_broker_accountid
evo_broker_reward_conditionid
evo_broker_reward_total
evo_broker_reward_summ
evo_fin_department_accountid
evo_fin_department_reward_conditionid
evo_fin_department_reward_total
evo_fin_department_reward_summ
}
}
`;
export type Quote = NonNullable<CRMTypes.GetAgentsDataFromQuoteQuery['quote']>;
type InputData = {
quoteId: NonNullable<CalculationValues['quote']>;
};
type ResultData = {
values: Partial<CalculationValues>;
};
export default async function getSupplierAgentsDataFromKP({
quoteId,
}: InputData): Promise<ResultData> {
const apolloClient = initializeApollo();
const {
data: { quote },
} = await apolloClient.query<
CRMTypes.GetAgentsDataFromQuoteQuery,
CRMTypes.GetAgentsDataFromQuoteQueryVariables
>({
query: QUERY_GET_AGENTS_DATA_FROM_QUOTE,
variables: {
quoteId,
},
});
if (!quote) {
throw new Error('Quote is empty');
}
const {
dealerRewardSumm,
dealerBrokerRewardSumm,
indAgentRewardSumm,
calcDoubleAgentRewardSumm,
calcBrokerRewardSum,
finDepartmentRewardSumm,
} = await getSums(quote);
return {
values: {
dealer: quote?.evo_supplier_accountid,
dealerPerson: quote?.evo_dealer_person_accountid,
dealerRewardCondition: quote?.evo_dealer_reward_conditionid,
dealerRewardSumm,
dealerBroker: quote?.evo_dealer_broker_accountid,
dealerBrokerRewardCondition: quote?.evo_dealer_broker_reward_conditionid,
dealerBrokerRewardSumm,
indAgent: quote?.evo_agent_accountid,
indAgentRewardCondition: quote?.evo_agent_reward_conditionid,
indAgentRewardSumm,
calcDoubleAgent: quote?.evo_double_agent_accountid,
calcDoubleAgentRewardCondition: quote?.evo_double_agent_reward_conditionid,
calcDoubleAgentRewardSumm,
calcBroker: quote?.evo_broker_accountid,
calcBrokerRewardCondition: quote?.evo_broker_reward_conditionid,
calcBrokerRewardSum,
calcFinDepartment: quote?.evo_fin_department_accountid,
finDepartmentRewardCondtion: quote?.evo_fin_department_reward_conditionid,
finDepartmentRewardSumm,
},
};
}

View File

@ -0,0 +1,216 @@
/* eslint-disable @typescript-eslint/naming-convention */
import type { ApolloClient } from '@apollo/client';
import { gql } from '@apollo/client';
import type * as Values from 'Components/Calculation/config/map/values';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import type * as CRMTypes from 'graphql/crm.types';
import { reaction } from 'mobx';
import type RootStore from 'stores/root';
import ValidationHelper from 'stores/validation/helper';
import { normalizeOptions } from 'tools/entity';
import { makeDisposable } from 'tools/mobx';
dayjs.extend(utc);
const QUERY_GET_REWARD_CONDITIONS = gql`
query GetRewardConditions($agentid: Uuid!, $currentDate: DateTime) {
evo_reward_conditions(
evo_agent_accountid: $agentid
evo_datefrom_param: { lte: $currentDate }
evo_dateto_param: { gte: $currentDate }
statecode: 0
evo_agency_agreementid_param: { has: true }
) {
label: evo_name
value: evo_reward_conditionid
evo_reward_summ
}
}
`;
export function fillAgentRewardReaction(
store: RootStore,
apolloClient: ApolloClient<object>,
agentParams: {
agentField: Values.Elements;
rewardConditionField: Values.Elements;
}
) {
const { $calculation, $process } = store;
const { agentField, rewardConditionField } = agentParams;
reaction(
() => $calculation.element(agentField).getValue(),
async (agentId) => {
if (!agentId) {
$calculation.element(rewardConditionField).reset();
return;
}
const {
data: { evo_reward_conditions },
} = await apolloClient.query<
CRMTypes.GetRewardConditionsQuery,
CRMTypes.GetRewardConditionsQueryVariables
>({
query: QUERY_GET_REWARD_CONDITIONS,
variables: {
agentid: agentId,
currentDate: dayjs().toISOString(),
},
});
if (evo_reward_conditions?.length) {
$calculation
.element(rewardConditionField)
.setOptions(normalizeOptions(evo_reward_conditions));
}
}
);
}
const QUERY_GET_REWARD_SUMM = gql`
query GetRewardSumm($conditionId: Uuid!) {
evo_reward_condition(evo_reward_conditionid: $conditionId) {
evo_reward_summ
}
}
`;
export function fillAgentRewardSummReaction(
store: RootStore,
apolloClient: ApolloClient<object>,
agentParams: {
rewardConditionField: Values.Elements;
rewardSummField: Values.Elements;
}
) {
const { $calculation, $process } = store;
const { rewardConditionField, rewardSummField } = agentParams;
makeDisposable(
() =>
reaction(
() => $calculation.element(rewardConditionField).getValue(),
async (rewardConditionId) => {
if (!rewardConditionId) {
$calculation.element(rewardSummField).reset();
return;
}
const {
data: { evo_reward_condition },
} = await apolloClient.query<
CRMTypes.GetRewardSummQuery,
CRMTypes.GetRewardSummQueryVariables
>({
query: QUERY_GET_REWARD_SUMM,
variables: {
conditionId: rewardConditionId,
},
});
$calculation.element(rewardSummField).setValue(evo_reward_condition?.evo_reward_summ);
}
),
() => $process.has('LoadKP')
);
reaction(
() => $calculation.element(rewardConditionField).getValue(),
(rewardConditionId) => {
if (!rewardConditionId) {
$calculation.element(rewardSummField).block();
} else {
$calculation.element(rewardSummField).unblock();
}
}
);
}
const QUERY_GET_REWARD_CONDITION = gql`
query GetRewardCondition($conditionId: Uuid!) {
evo_reward_condition(evo_reward_conditionid: $conditionId) {
evo_reward_summ
evo_reduce_reward
evo_min_reward_summ
}
}
`;
export function validateAgentRewardSumm(
store: RootStore,
apolloClient: ApolloClient<object>,
agentParams: {
rewardConditionField: Values.Elements;
rewardSummField: Values.Elements;
}
) {
const { $calculation } = store;
const { rewardConditionField, rewardSummField } = agentParams;
const validationHelper = new ValidationHelper();
reaction(
() => $calculation.element(rewardSummField).getValue() as number,
async (rewardSumm) => {
const conditionId = $calculation.element(rewardConditionField).getValue();
if (!conditionId) {
validationHelper.removeErrors();
return;
}
const {
data: { evo_reward_condition },
} = await apolloClient.query<
CRMTypes.GetRewardConditionQuery,
CRMTypes.GetRewardConditionQueryVariables
>({
query: QUERY_GET_REWARD_CONDITION,
variables: {
conditionId,
},
});
$calculation
.element(rewardSummField)
.validate({
invalid:
evo_reward_condition?.evo_reward_summ &&
rewardSumm > evo_reward_condition.evo_reward_summ,
message: 'Вознаграждение указано больше условия по агентскому договору!',
})
.err((removeError) => {
validationHelper.add(removeError);
});
$calculation
.element(rewardSummField)
.validate({
invalid:
!evo_reward_condition?.evo_reduce_reward &&
evo_reward_condition?.evo_reward_summ &&
rewardSumm < evo_reward_condition.evo_reward_summ,
message: 'Вознаграждение указано меньше условия по агентскому договору!',
})
.err((removeError) => {
validationHelper.add(removeError);
});
$calculation
.element(rewardSummField)
.validate({
invalid:
evo_reward_condition?.evo_min_reward_summ &&
rewardSumm < evo_reward_condition?.evo_min_reward_summ,
message: 'Вознаграждение указано меньше условия по агентскому договору!',
})
.err((removeError) => {
validationHelper.add(removeError);
});
}
);
}

View File

@ -18,7 +18,7 @@ function makeFillAgentFromLead(
leadid: string | null leadid: string | null
) { ) {
if (!leadid) { if (!leadid) {
$calculation.resetElement(elementName); $calculation.element(elementName).reset();
return; return;
} }
@ -43,11 +43,13 @@ function makeFillAgentFromLead(
}); });
if (agent) { if (agent) {
$calculation.setElementOptions(elementName, normalizeOptions([agent])); $calculation
$calculation.setElementValue(elementName, agent.value); .element(elementName)
.setOptions(normalizeOptions([agent]))
.setValue(agent.value);
} }
} else { } else {
$calculation.resetElement(elementName); $calculation.element(elementName).reset();
} }
}; };
} }

View File

@ -1,6 +1,6 @@
/* eslint-disable import/prefer-default-export */
import { gql } from '@apollo/client'; import { gql } from '@apollo/client';
/* eslint-disable import/prefer-default-export */
export const QUERY_GET_AGENT = gql` export const QUERY_GET_AGENT = gql`
query GetAgent($agentid: Uuid!) { query GetAgent($agentid: Uuid!) {
agent: account(accountid: $agentid) { agent: account(accountid: $agentid) {

View File

@ -0,0 +1,513 @@
/* eslint-disable @typescript-eslint/naming-convention */
import type { ApolloClient } from '@apollo/client';
import { gql } from '@apollo/client';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import type * as CRMTypes from 'graphql/crm.types';
import { reaction } from 'mobx';
import type RootStore from 'stores/root';
import { makeDisposable } from 'tools/mobx';
import * as createReactions from '../lib/create-reactions';
import * as fillAgentsFromLead from '../lib/fill-agents-from-lead';
dayjs.extend(utc);
export function fillReactions(store: RootStore, apolloClient: ApolloClient<object>) {
const { $calculation, $process } = store;
/**
* Заполняем агентов из Интереса
*/
makeDisposable(
() =>
reaction(
() => $calculation.element('selectLead').getValue(),
(leadid) => {
fillAgentsFromLead.fillIndAgent(store, apolloClient, leadid);
fillAgentsFromLead.fillCalcDoubleAgent(store, apolloClient, leadid);
fillAgentsFromLead.fillCalcBroker(store, apolloClient, leadid);
fillAgentsFromLead.fillFinDepartment(store, apolloClient, leadid);
}
),
() => $process.has('LoadKP')
);
/**
* IndAgent
*/
// Заполняем selectIndAgentRewardCondition
createReactions.fillAgentRewardReaction(store, apolloClient, {
agentField: 'selectIndAgent',
rewardConditionField: 'selectIndAgentRewardCondition',
});
// Заполняем tbxIndAgentRewardSumm
createReactions.fillAgentRewardSummReaction(store, apolloClient, {
rewardConditionField: 'selectIndAgentRewardCondition',
rewardSummField: 'tbxIndAgentRewardSumm',
});
/**
* CalcDoubleAgent
*/
// Заполняем selectCalcDoubleAgentRewardCondition
createReactions.fillAgentRewardReaction(store, apolloClient, {
agentField: 'selectCalcDoubleAgent',
rewardConditionField: 'selectCalcDoubleAgentRewardCondition',
});
// Заполняем tbxCalcDoubleAgentRewardSumm
createReactions.fillAgentRewardSummReaction(store, apolloClient, {
rewardConditionField: 'selectCalcDoubleAgentRewardCondition',
rewardSummField: 'tbxCalcDoubleAgentRewardSumm',
});
/**
* CalcBroker
*/
// Заполняем selectCalcBrokerRewardCondition
createReactions.fillAgentRewardReaction(store, apolloClient, {
agentField: 'selectCalcBroker',
rewardConditionField: 'selectCalcBrokerRewardCondition',
});
// Заполняем tbxCalcBrokerRewardSum
createReactions.fillAgentRewardSummReaction(store, apolloClient, {
rewardConditionField: 'selectCalcBrokerRewardCondition',
rewardSummField: 'tbxCalcBrokerRewardSum',
});
/**
* CalcFinDepartment
*/
// Заполняем selectFinDepartmentRewardCondtion
createReactions.fillAgentRewardReaction(store, apolloClient, {
agentField: 'selectCalcFinDepartment',
rewardConditionField: 'selectFinDepartmentRewardCondtion',
});
// Заполняем tbxCalcBrokerRewardSum
createReactions.fillAgentRewardSummReaction(store, apolloClient, {
rewardConditionField: 'selectFinDepartmentRewardCondtion',
rewardSummField: 'tbxFinDepartmentRewardSumm',
});
}
export function commonReactions(store: RootStore, apolloClient: ApolloClient<object>) {
const { $calculation } = store;
const QUERY_GET_REWARD_WITHOUT_OTHER_AGENT = gql`
query GetRewardWithoutOtherAgent($conditionId: Uuid!) {
evo_reward_condition(evo_reward_conditionid: $conditionId) {
evo_agency_agreementidData {
evo_reward_without_other_agent
}
}
}
`;
/**
* Добавить реакцию на изменение списка в поле selectDealerRewardCondition :
Если в списке selectDealerRewardCondition есть запись,
у которой evo_reward_condition.evo_agency_agreementid.
Выплата без других агентов (evo_reward_without_other_agent) = True,
то сбрасывают значение и закрываются для выбора поля:
selectDealerBroker
selectIndAgent
selectCalcDoubleAgent
selectCalcBroker
selectFinDepartment
*/
reaction(
() => $calculation.element('selectDealerRewardCondition').getValue(),
async (rewardConditionId) => {
function fillAgents() {
const leadid = $calculation.element('selectLead').getValue();
fillAgentsFromLead.fillIndAgent(store, apolloClient, leadid);
fillAgentsFromLead.fillCalcDoubleAgent(store, apolloClient, leadid);
fillAgentsFromLead.fillCalcBroker(store, apolloClient, leadid);
fillAgentsFromLead.fillFinDepartment(store, apolloClient, leadid);
}
if (!rewardConditionId) {
fillAgents();
return;
}
const {
data: { evo_reward_condition },
} = await apolloClient.query<
CRMTypes.GetRewardWithoutOtherAgentQuery,
CRMTypes.GetRewardWithoutOtherAgentQueryVariables
>({
query: QUERY_GET_REWARD_WITHOUT_OTHER_AGENT,
variables: {
conditionId: rewardConditionId,
},
});
if (evo_reward_condition?.evo_agency_agreementidData?.evo_reward_without_other_agent) {
$calculation.element('selectDealerBroker').reset();
$calculation.element('selectIndAgent').reset();
$calculation.element('selectCalcDoubleAgent').reset();
$calculation.element('selectCalcBroker').reset();
$calculation.element('selectCalcFinDepartment').reset();
} else {
fillAgents();
}
}
);
/**
* Добавить реакцию на изменение списка в поле selectDealerBrokerRewardCondition :
Если в списке selectDealerBrokerRewardCondition есть запись,
у которой evo_reward_condition.evo_agency_agreementid.
Выплата без других агентов (evo_reward_without_other_agent) = True,
то сбрасывают значение и закрываются для выбора поля:
selectDealerPerson (не обнуляем)
selectIndAgent
selectCalcDoubleAgent
selectCalcBroker
selectFinDepartment
иначе
selectDealerPerson открываем для редактирования
selectIndAgent заполняется значением из Интереса
selectCalcDoubleAgent заполняется значением из Интереса
selectCalcBrokerRewardCondition заполняется значением из Интереса
selectFinDepartmentRewardCondtion заполняется значением из Интереса
*/
reaction(
() => $calculation.element('selectDealerBrokerRewardCondition').getValue(),
async (rewardConditionId) => {
function fillAgents() {
const leadid = $calculation.element('selectLead').getValue();
fillAgentsFromLead.fillIndAgent(store, apolloClient, leadid);
fillAgentsFromLead.fillCalcDoubleAgent(store, apolloClient, leadid);
fillAgentsFromLead.fillCalcBroker(store, apolloClient, leadid);
fillAgentsFromLead.fillFinDepartment(store, apolloClient, leadid);
}
if (!rewardConditionId) {
fillAgents();
return;
}
const {
data: { evo_reward_condition },
} = await apolloClient.query<
CRMTypes.GetRewardWithoutOtherAgentQuery,
CRMTypes.GetRewardWithoutOtherAgentQueryVariables
>({
query: QUERY_GET_REWARD_WITHOUT_OTHER_AGENT,
variables: {
conditionId: rewardConditionId,
},
});
if (evo_reward_condition?.evo_agency_agreementidData?.evo_reward_without_other_agent) {
$calculation.element('selectDealerPerson').block();
$calculation.element('selectIndAgent').reset();
$calculation.element('selectCalcDoubleAgent').reset();
$calculation.element('selectCalcBroker').reset();
$calculation.element('selectCalcFinDepartment').reset();
} else {
$calculation.element('selectDealerPerson').unblock();
fillAgents();
}
}
);
/**
* Добавить реакцию на изменение списка в поле selectIndAgentRewardCondition :
Если в списке selectIndAgentRewardCondition есть запись,
у которой evo_reward_condition.evo_agency_agreementid.
Выплата без других агентов (evo_reward_without_other_agent) = True,
то сбрасывают значение и закрываются для выбора поля:
selectDealerPerson (не обнуляем)
selectDealerBroker
selectCalcDoubleAgent
selectCalcBroker
selectFinDepartment
иначе
selectDealerPerson открываем для редактирования
selectDealerBroker открываем для редактирования
selectCalcDoubleAgent заполняется значением из Интереса
selectCalcBroker заполняется значением из Интереса
selectCalcFinDepartment заполняется значением из Интереса
*/
reaction(
() => $calculation.element('selectIndAgentRewardCondition').getValue(),
async (rewardConditionId) => {
function fillAgents() {
const leadid = $calculation.element('selectLead').getValue();
fillAgentsFromLead.fillCalcDoubleAgent(store, apolloClient, leadid);
fillAgentsFromLead.fillCalcBroker(store, apolloClient, leadid);
fillAgentsFromLead.fillFinDepartment(store, apolloClient, leadid);
}
if (!rewardConditionId) {
fillAgents();
return;
}
const {
data: { evo_reward_condition },
} = await apolloClient.query<
CRMTypes.GetRewardWithoutOtherAgentQuery,
CRMTypes.GetRewardWithoutOtherAgentQueryVariables
>({
query: QUERY_GET_REWARD_WITHOUT_OTHER_AGENT,
variables: {
conditionId: rewardConditionId,
},
});
if (evo_reward_condition?.evo_agency_agreementidData?.evo_reward_without_other_agent) {
$calculation.element('selectDealerPerson').block();
$calculation.element('selectDealerBroker').reset();
$calculation.element('selectCalcDoubleAgent').reset();
$calculation.element('selectCalcBroker').reset();
$calculation.element('selectCalcFinDepartment').reset();
} else {
$calculation.element('selectDealerPerson').unblock();
fillAgents();
}
}
);
/**
* Добавить реакцию на изменение списка в поле selectCalcDoubleAgentRewardCondition :
Если в списке selectCalcDoubleAgentRewardCondition есть запись,
у которой evo_reward_condition.evo_agency_agreementid.
Выплата без других агентов (evo_reward_without_other_agent) = True,
то сбрасывают значение и закрываются для выбора поля:
selectDealerPerson (не обнуляем)
selectDealerBroker
selectIndAgent
selectCalcBroker
selectCalcFinDepartment
иначе
selectDealerPerson открываем для редактирования
selectDealerBroker открываем для редактирования
selectIndAgent заполняется значением из Интереса
selectCalcBroker заполняется значением из Интереса
selectCalcFinDepartment заполняется значением из Интереса
*/
reaction(
() => $calculation.element('selectCalcDoubleAgentRewardCondition').getValue(),
async (rewardConditionId) => {
function fillAgents() {
const leadid = $calculation.element('selectLead').getValue();
fillAgentsFromLead.fillIndAgent(store, apolloClient, leadid);
fillAgentsFromLead.fillCalcBroker(store, apolloClient, leadid);
fillAgentsFromLead.fillFinDepartment(store, apolloClient, leadid);
}
if (!rewardConditionId) {
fillAgents();
return;
}
const {
data: { evo_reward_condition },
} = await apolloClient.query<
CRMTypes.GetRewardWithoutOtherAgentQuery,
CRMTypes.GetRewardWithoutOtherAgentQueryVariables
>({
query: QUERY_GET_REWARD_WITHOUT_OTHER_AGENT,
variables: {
conditionId: rewardConditionId,
},
});
if (evo_reward_condition?.evo_agency_agreementidData?.evo_reward_without_other_agent) {
$calculation.element('selectDealerPerson').block();
$calculation.element('selectDealerBroker').reset();
$calculation.element('selectIndAgent').reset();
$calculation.element('selectCalcBroker').reset();
$calculation.element('selectCalcFinDepartment').reset();
} else {
$calculation.element('selectDealerPerson').unblock();
$calculation.element('selectDealerBroker').unblock();
fillAgents();
}
}
);
/**
* @description
* Добавить реакцию на изменение списка в поле selectCalcBrokerRewardCondition:
Если в списке selectCalcBrokerRewardCondition есть запись,
у которой evo_reward_condition.evo_agency_agreementid.
Выплата без других агентов (evo_reward_without_other_agent) = True,
то сбрасывают значение и закрываются для выбора поля:
selectDealerPerson (не обнуляем)
selectDealerBroker
selectIndAgent
selectCalcDoubleAgent
selectCalcFinDepartment
иначе
selectDealerPerson открываем для редактирования
selectDealerBroker открываем для редактирования
selectIndAgent заполняется значением из Интереса
selectCalcDoubleAgent заполняется значением из Интереса
selectCalcFinDepartment заполняется значением из Интереса
*/
reaction(
() => $calculation.element('selectCalcBrokerRewardCondition').getValue(),
async (rewardConditionId) => {
function fillAgents() {
const leadid = $calculation.element('selectLead').getValue();
fillAgentsFromLead.fillIndAgent(store, apolloClient, leadid);
fillAgentsFromLead.fillCalcDoubleAgent(store, apolloClient, leadid);
fillAgentsFromLead.fillFinDepartment(store, apolloClient, leadid);
}
if (!rewardConditionId) {
fillAgents();
return;
}
const {
data: { evo_reward_condition },
} = await apolloClient.query<
CRMTypes.GetRewardWithoutOtherAgentQuery,
CRMTypes.GetRewardWithoutOtherAgentQueryVariables
>({
query: QUERY_GET_REWARD_WITHOUT_OTHER_AGENT,
variables: {
conditionId: rewardConditionId,
},
});
if (evo_reward_condition?.evo_agency_agreementidData?.evo_reward_without_other_agent) {
$calculation.element('selectDealerPerson').block();
$calculation.element('selectDealerBroker').reset();
$calculation.element('selectIndAgent').reset();
$calculation.element('selectCalcDoubleAgent').reset();
$calculation.element('selectCalcFinDepartment').reset();
} else {
$calculation.element('selectDealerPerson').unblock();
$calculation.element('selectDealerBroker').unblock();
fillAgents();
}
}
);
/**
* Добавить реакцию на изменение списка в поле selectFinDepartmentRewardCondtion:
Если в списке selectFinDepartmentRewardCondtion есть запись,
у которой evo_reward_condition.evo_agency_agreementid.
Выплата без других агентов (evo_reward_without_other_agent) = True,
то сбрасывают значение и закрываются для выбора поля:
selectDealerPerson (не обнуляем)
selectDealerBroker
selectIndAgent
selectCalcDoubleAgent
selectCalcBroker
иначе
selectDealerPerson открываем для редактирования
selectDealerBroker открываем для редактирования
selectIndAgent заполняется значением из Интереса
selectCalcDoubleAgent заполняется значением из Интереса
selectCalcBroker заполняется значением из Интереса
*/
reaction(
() => $calculation.element('selectFinDepartmentRewardCondtion').getValue(),
async (rewardConditionId) => {
function fillAgents() {
const leadid = $calculation.element('selectLead').getValue();
fillAgentsFromLead.fillIndAgent(store, apolloClient, leadid);
fillAgentsFromLead.fillCalcDoubleAgent(store, apolloClient, leadid);
fillAgentsFromLead.fillFinDepartment(store, apolloClient, leadid);
}
if (!rewardConditionId) {
fillAgents();
return;
}
const {
data: { evo_reward_condition },
} = await apolloClient.query<
CRMTypes.GetRewardWithoutOtherAgentQuery,
CRMTypes.GetRewardWithoutOtherAgentQueryVariables
>({
query: QUERY_GET_REWARD_WITHOUT_OTHER_AGENT,
variables: {
conditionId: rewardConditionId,
},
});
if (evo_reward_condition?.evo_agency_agreementidData?.evo_reward_without_other_agent) {
$calculation.element('selectDealerPerson').block();
$calculation.element('selectDealerBroker').reset();
$calculation.element('selectIndAgent').reset();
$calculation.element('selectCalcDoubleAgent').reset();
$calculation.element('selectCalcBroker').reset();
} else {
$calculation.element('selectDealerPerson').unblock();
$calculation.element('selectDealerBroker').unblock();
fillAgents();
}
}
);
}
export function validationReactions(store: RootStore, apolloClient: ApolloClient<object>) {
createReactions.validateAgentRewardSumm(store, apolloClient, {
rewardConditionField: 'selectDealerRewardCondition',
rewardSummField: 'tbxDealerRewardSumm',
});
createReactions.validateAgentRewardSumm(store, apolloClient, {
rewardConditionField: 'selectDealerBrokerRewardCondition',
rewardSummField: 'tbxDealerBrokerRewardSumm',
});
createReactions.validateAgentRewardSumm(store, apolloClient, {
rewardConditionField: 'selectIndAgentRewardCondition',
rewardSummField: 'tbxIndAgentRewardSumm',
});
createReactions.validateAgentRewardSumm(store, apolloClient, {
rewardConditionField: 'selectCalcDoubleAgentRewardCondition',
rewardSummField: 'tbxCalcDoubleAgentRewardSumm',
});
createReactions.validateAgentRewardSumm(store, apolloClient, {
rewardConditionField: 'selectCalcBrokerRewardCondition',
rewardSummField: 'tbxCalcBrokerRewardSum',
});
createReactions.validateAgentRewardSumm(store, apolloClient, {
rewardConditionField: 'selectFinDepartmentRewardCondtion',
rewardSummField: 'tbxFinDepartmentRewardSumm',
});
}

View File

@ -0,0 +1,90 @@
import type { ApolloClient } from '@apollo/client';
import { gql } from '@apollo/client';
import type * as CRMTypes from 'graphql/crm.types';
import { reaction } from 'mobx';
import type RootStore from 'stores/root';
export default function leasebackReactions(store: RootStore, apolloClient: ApolloClient<object>) {
const { $calculation, $tables } = store;
/**
* Дополнить реакцию на изменение поля Салон приобретения selectDealer:
если в поле selectDealer указан account, у которого evo_return_leasing_dealer = true, то
1) поле selectDealerPerson обнулять и закрывать для редактирования,
иначе формировать список связанных значений
2) в таблице страхования в столбце Плательщик
в строках ОСАГО и КАСКО указывать "Лизингополучатель" (100 000 000) и закрывать для редактирования ,
иначе открывать данные поля для редактирования
3) ПЛ БУ cbxLeaseObjectUsed = true
*/
const QUERY_GET_DEALER_RETURN_LEASING = gql`
query GetDealerReturnLeasing($dealerId: Uuid!) {
dealer: account(accountid: $dealerId) {
evo_return_leasing_dealer
}
}
`;
reaction(
() => $calculation.element('selectDealer').getValue(),
async (dealerId) => {
if (!dealerId) return;
const {
data: { dealer },
} = await apolloClient.query<
CRMTypes.GetDealerReturnLeasingQuery,
CRMTypes.GetDealerReturnLeasingQueryVariables
>({
query: QUERY_GET_DEALER_RETURN_LEASING,
variables: {
dealerId,
},
});
if (dealer?.evo_return_leasing_dealer === true) {
$tables.insurance.row('kasko').setValue('insured', 100_000_000).block('insured');
$calculation.element('cbxLeaseObjectUsed').setValue(true);
} else {
$tables.insurance.row('kasko').resetStatus('insured');
}
}
);
// объединили реакцию для прицепа и возвратного лизинга
reaction(
() => ({
dealerId: $calculation.element('selectDealer').getValue(),
leaseObjectCategory: $calculation.element('selectLeaseObjectCategory').getValue(),
}),
async ({ dealerId, leaseObjectCategory }) => {
const isTrailer = leaseObjectCategory === 100_000_004;
let returnLeasing = false;
if (dealerId) {
const {
data: { dealer },
} = await apolloClient.query<
CRMTypes.GetDealerReturnLeasingQuery,
CRMTypes.GetDealerReturnLeasingQueryVariables
>({
query: QUERY_GET_DEALER_RETURN_LEASING,
variables: {
dealerId,
},
});
returnLeasing = dealer?.evo_return_leasing_dealer === true;
}
if (isTrailer || returnLeasing) {
$tables.insurance.row('osago').setValue('insured', 100_000_000).block('insured');
} else {
$tables.insurance.row('osago').resetStatus('insured');
}
}
);
}

View File

@ -0,0 +1,173 @@
/* eslint-disable @typescript-eslint/naming-convention */
import type { ApolloClient } from '@apollo/client';
import { gql } from '@apollo/client';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import type * as CRMTypes from 'graphql/crm.types';
import { reaction } from 'mobx';
import { sift } from 'radash';
import type RootStore from 'stores/root';
import { normalizeOptions } from 'tools/entity';
import * as createReactions from '../lib/create-reactions';
import * as query from '../lib/query';
dayjs.extend(utc);
export function commonReactions(store: RootStore, apolloClient: ApolloClient<object>) {
const { $calculation, $process } = store;
/**
* Заполняем selectDealerPerson
* На изменение Салон приобретения формируем список в поле ЮЛ поставщика - записи Контрагент,
* у которых статус = активный И Поставщик = Да И Тип поставщика = Юридическое лицо
* И связаны с карточкой Контрагент из поля "Салон приобретения" по связи Салон-ЮЛ
*/
const QUERY_GET_DEALER_PERSON = gql`
query GetDealerPerson($dealerId: Uuid!) {
salon_providers(statecode: 0, salonaccountid: $dealerId) {
label: name
value: accountid
evo_inn
evo_kpp
}
}
`;
reaction(
() => $calculation.element('selectDealer').getValue(),
async (dealerId) => {
if (!dealerId) {
$calculation.element('selectDealerPerson').reset();
$calculation.element('selectDealerBroker').reset();
return;
}
const {
data: { salon_providers },
} = await apolloClient.query<
CRMTypes.GetDealerPersonQuery,
CRMTypes.GetDealerPersonQueryVariables
>({
query: QUERY_GET_DEALER_PERSON,
variables: {
dealerId,
},
});
if (salon_providers?.length) {
$calculation.element('selectDealerPerson').setOptions(
normalizeOptions(
salon_providers.map((dp) => ({
...dp,
label: `${dp?.label} ${sift([dp?.evo_inn, dp?.evo_kpp]).join(' | ')}`,
}))
)
);
if (!$process.has('LoadKP')) {
$calculation.element('selectDealerPerson').setValue(salon_providers[0]?.value);
}
}
}
);
/**
* Заполняем selectDealerBroker
*/
const QUERY_GET_BROKER_ACCOUNTID_FROM_DEALER = gql`
query GetBrokerAccountIdFromDealer($dealerId: Uuid!) {
dealer: account(accountid: $dealerId) {
evo_broker_accountid
}
}
`;
reaction(
() => $calculation.element('selectDealerPerson').getValue(),
async (dealerPersonId) => {
if (!dealerPersonId) {
return;
}
const {
data: { dealer },
} = await apolloClient.query<
CRMTypes.GetBrokerAccountIdFromDealerQuery,
CRMTypes.GetBrokerAccountIdFromDealerQueryVariables
>({
query: QUERY_GET_BROKER_ACCOUNTID_FROM_DEALER,
variables: {
dealerId: dealerPersonId,
},
});
if (dealer?.evo_broker_accountid) {
const {
data: { agent: dealerBroker },
} = await apolloClient.query<CRMTypes.GetAgentQuery, CRMTypes.GetAgentQueryVariables>({
query: query.QUERY_GET_AGENT,
variables: {
agentid: dealer?.evo_broker_accountid,
},
});
if (dealerBroker) {
$calculation.element('selectDealerBroker').setOptions(normalizeOptions([dealerBroker]));
if (!$process.has('LoadKP')) {
$calculation.element('selectDealerBroker').setValue(dealerBroker.value);
}
}
} else {
$calculation.element('selectDealerBroker').reset();
}
}
);
// Заполняем selectDealerRewardCondition
createReactions.fillAgentRewardReaction(store, apolloClient, {
agentField: 'selectDealerPerson',
rewardConditionField: 'selectDealerRewardCondition',
});
// Заполняем tbxDealerRewardSumm
createReactions.fillAgentRewardSummReaction(store, apolloClient, {
rewardConditionField: 'selectDealerRewardCondition',
rewardSummField: 'tbxDealerRewardSumm',
});
// Заполняем selectDealerBrokerRewardCondition
createReactions.fillAgentRewardReaction(store, apolloClient, {
agentField: 'selectDealerBroker',
rewardConditionField: 'selectDealerBrokerRewardCondition',
});
// Заполняем tbxDealerBrokerRewardSumm
createReactions.fillAgentRewardSummReaction(store, apolloClient, {
rewardConditionField: 'selectDealerBrokerRewardCondition',
rewardSummField: 'tbxDealerBrokerRewardSumm',
});
reaction(
() => $calculation.element('selectDealerRewardCondition').getValue(),
(dealerRewardConditionId) => {
if (dealerRewardConditionId) {
$calculation.element('selectDealerBroker').resetValue();
}
}
);
reaction(
() => $calculation.element('selectDealerBrokerRewardCondition').getValue(),
(dealerBrokerRewardConditionId) => {
if (dealerBrokerRewardConditionId) {
$calculation.element('selectDealerPerson').resetValue();
}
}
);
}
export function validationReactions(store: RootStore, apolloClient: ApolloClient<object>) {}

View File

@ -1,72 +1,118 @@
/* eslint-disable import/no-cycle */ /* eslint-disable import/no-cycle */
import type { Elements as ElementsActions } from 'Components/Calculation/config/map/actions'; import titles from 'Components/Calculation/config/elements-titles';
import type * as Values from 'Components/Calculation/config/map/values'; import type * as Values from 'Components/Calculation/config/map/values';
import { getValueName } from 'Components/Calculation/config/map/values'; import { getValueName } from 'Components/Calculation/config/map/values';
import type { BaseOption } from 'Elements/types'; import type { BaseOption } from 'Elements/types';
import { observable } from 'mobx';
import type RootStore from 'stores/root'; import type RootStore from 'stores/root';
import Validation from 'stores/validation';
import type { RemoveError, ValidationParams } from '../validation/types';
import OptionsStore from './options'; import OptionsStore from './options';
import StatusStore from './statuses'; import StatusStore from './statuses';
import ValidationStore from './validation';
import ValuesStore from './values'; import ValuesStore from './values';
export default class CalculationStore { export default class CalculationStore {
$values: ValuesStore; $values: ValuesStore;
$status: StatusStore; $status: StatusStore;
$options: OptionsStore; $options: OptionsStore;
$validation: ValidationStore; $validation: Partial<Record<Values.Elements, Validation>>;
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {
this.$values = new ValuesStore(rootStore); this.$values = new ValuesStore(rootStore);
this.$status = new StatusStore(rootStore); this.$status = new StatusStore(rootStore);
this.$options = new OptionsStore(rootStore); this.$options = new OptionsStore(rootStore);
this.$validation = new ValidationStore(rootStore); this.$validation = observable.object({});
} }
resetElement = (elementName: Values.Elements) => { private createElementValidation = <E extends Values.Elements>(elementName: E) => {
this.resetElementValue(elementName); this.$validation[elementName] = new Validation({
this.$options.resetOptions(elementName); err_key: elementName,
this.$status.resetStatus(elementName); err_title: titles[elementName],
this.$validation.clearErrors(elementName); });
}; };
blockElement = (elementName: Values.Elements | ElementsActions) => { element = <E extends Values.Elements>(elementName: E) => ({
this.$status.setStatus(elementName, 'Disabled'); reset: () => {
}; const valueName = getValueName(elementName);
this.$values.resetValue(valueName);
unblockElement = (elementName: Values.Elements | ElementsActions) => { this.$options.resetOptions(elementName);
this.$status.setStatus(elementName, 'Default'); this.$status.resetStatus(elementName);
}; this.$validation[elementName]?.clearErrors();
getElementValue<E extends Values.Elements>(elementName: E) { return this.element(elementName);
const valueName = getValueName(elementName); },
return this.$values.getValue(valueName) as Values.ElementsTypes[E]; block: () => {
} this.$status.setStatus(elementName, 'Disabled');
setElementValue = <E extends Values.Elements>(elementName: E, value: Values.ElementsTypes[E]) => { return this.element(elementName);
const valueName = getValueName(elementName); },
this.$values.setValue(valueName, value);
};
resetElementValue = (elementName: Values.Elements) => { unblock: () => {
const valueName = getValueName(elementName); this.$status.setStatus(elementName, 'Default');
this.$values.resetValue(valueName);
};
setElementOptions = <T extends Values.Elements>( return this.element(elementName);
elementName: T, },
options: BaseOption<Values.ElementsTypes[T]>[]
) => {
this.$options.setOptions(elementName, options);
};
resetElementOptions = <T extends Values.Elements>(elementName: T) => { getValue: () => {
this.$options.resetOptions(elementName); const valueName = getValueName(elementName);
};
getElementOption<T extends Values.Elements>(elementName: T) { return this.$values.getValue(valueName) as Values.ElementsTypes[E];
const value = this.getElementValue(elementName); },
return this.$options.getOptions(elementName)?.find((x) => x.value === value); setValue: (value: Values.ElementsTypes[E]) => {
} const valueName = getValueName(elementName);
this.$values.setValue(valueName, value);
return this.element(elementName);
},
resetValue: () => {
const valueName = getValueName(elementName);
this.$values.resetValue(valueName);
return this.element(elementName);
},
getOption: () => {
const valueName = getValueName(elementName);
const value = this.$values.getValue(valueName) as Values.ElementsTypes[E];
return this.$options.getOptions(elementName)?.find((x) => x.value === value);
},
setOptions: (options: BaseOption<Values.ElementsTypes[E]>[]) => {
this.$options.setOptions(elementName, options);
return this.element(elementName);
},
resetOptions: () => {
this.$options.resetOptions(elementName);
return this.element(elementName);
},
validate: ({ invalid, message }: ValidationParams) => {
if (!this.$validation[elementName]) this.createElementValidation(elementName);
let removeError: RemoveError | undefined;
if (invalid) {
removeError = this.$validation[elementName]?.addError(message);
} else {
this.$validation[elementName]?.removeError(message);
}
return {
err(callback: (removeError: RemoveError) => void) {
if (removeError) callback(removeError);
},
};
},
cleanErrors: () => {
this.$validation[elementName]?.clearErrors();
},
});
} }

View File

@ -30,13 +30,12 @@ export default class OptionsStore {
/** /**
* Проверяем, что значение есть в новом списке, иначе сбрасываем значение * Проверяем, что значение есть в новом списке, иначе сбрасываем значение
*/ */
const value = this.root.$calculation.getElementValue(elementName); const value = this.root.$calculation.element(elementName).getValue();
if ( if (
// eslint-disable-next-line operator-linebreak
!this.options[elementName]?.length || !this.options[elementName]?.length ||
!this.options[elementName].some((x) => x.value === value) !this.options[elementName].some((x) => x.value === value)
) { ) {
this.root.$calculation.resetElementValue(elementName); this.root.$calculation.element(elementName).resetValue();
} }
}; };

View File

@ -3,10 +3,16 @@ import { useStore } from 'stores/hooks';
export function useValidation(elementName) { export function useValidation(elementName) {
const { $calculation } = useStore(); const { $calculation } = useStore();
const validationResult = $calculation.$validation.getValidation(elementName); const messages = $calculation.$validation[elementName]?.getMessages();
if (messages?.length) {
return {
isValid: false,
help: 'Некорректные данные',
};
}
return { return {
...validationResult, isValid: true,
help: validationResult?.isValid === false ? 'Некорректные данные' : null,
}; };
} }

View File

@ -1,60 +0,0 @@
/* eslint-disable object-curly-newline */
import titles from 'Components/Calculation/config/elements-titles';
import type { Elements } from 'Components/Calculation/config/map/values';
import notification from 'Elements/notification';
import { makeAutoObservable, observable } from 'mobx';
import type RootStore from 'stores/root';
import type { ElementsErrors, Error } from './types';
export default class ValidationStore {
root: RootStore;
elementsErrors: Partial<ElementsErrors> = {};
constructor(rootStore: RootStore) {
makeAutoObservable(this);
this.root = rootStore;
}
get hasErrors() {
return (Object.keys(this.elementsErrors) as Elements[]).some(
(elementName) => this.elementsErrors[elementName]?.length
);
}
getValidation(elementName: Elements) {
return {
isValid: !this.elementsErrors[elementName]?.length,
errors: this.elementsErrors[elementName]?.map((x) => x.text),
};
}
addError = (elementName: Elements, error: Error) => {
if (!this.elementsErrors[elementName]) this.elementsErrors[elementName] = observable([]);
const errorIndex = this.elementsErrors[elementName]?.findIndex((x) => x.name === error.name);
const hasError = errorIndex !== undefined && errorIndex !== -1;
if (!hasError) {
this.elementsErrors[elementName]?.push(error);
} else {
this.elementsErrors[elementName]?.splice(errorIndex, 1, error);
}
notification.error({
key: error.name,
message: `${titles[elementName]}`,
description: error.text,
});
return () => this.#removeError(elementName, error.name);
};
#removeError = (elementName: Elements, errorName: Error['name']) => {
const errorIndex = this.elementsErrors[elementName]?.findIndex((x) => x.name === errorName);
if (errorIndex) this.elementsErrors[elementName]?.splice(errorIndex, 1);
};
clearErrors = (elementName: Elements) => {
this.elementsErrors[elementName]?.clear();
};
}

View File

@ -1,5 +0,0 @@
import type { Elements } from 'Components/Calculation/config/map/values';
import type { IObservableArray } from 'mobx';
export type Error = { name: string; text: string };
export type ElementsErrors = Record<Elements, IObservableArray<Error>>;

View File

@ -1,6 +1,7 @@
/* eslint-disable object-curly-newline */ /* eslint-disable object-curly-newline */
import defaultValues from 'config/default-values'; import defaultValues from 'config/default-values';
import { makeAutoObservable } from 'mobx'; import { makeAutoObservable } from 'mobx';
import { pick } from 'radash';
import type RootStore from '../../root'; import type RootStore from '../../root';
import type { CalculationValues, Values } from './types'; import type { CalculationValues, Values } from './types';
@ -17,6 +18,13 @@ export default class ValuesStore {
this.values = initialValues; this.values = initialValues;
}; };
setValues = (params: { values: CalculationValues; exclude: Values[] }) => {
const { values, exclude } = params;
const savedValues = pick(this.values, exclude);
this.values = { ...values, ...savedValues };
};
getValue<V extends Values>(valueName: V) { getValue<V extends Values>(valueName: V) {
return this.values[valueName]; return this.values[valueName];
} }

View File

@ -1,142 +1,5 @@
export type CalculationValues = { import type ValuesSchema from 'config/schema/values';
lead: string | null; import type { z } from 'zod';
opportunity: string | null;
quote: string | null;
recalcWithRevision: boolean;
product: string | null;
clientRisk: string | null;
clientType: string | null;
leaseObjectPrice: number;
supplierCurrency: string | null;
supplierDiscountRub: number;
supplierDiscountPerc: number;
leasingPeriod: number;
firstPaymentPerc: number;
firstPaymentRub: number;
lastPaymentPerc: number;
lastPaymentRub: number;
lastPaymentRule: number | null;
importProgram: string | null;
importProgramSum: number;
addEquipmentPrice: number;
redemptionPaymentSum: number;
balanceHolder: number | null;
graphType: number | null;
parmentsDecreasePercent: number;
seasonType: number | null;
highSeasonStart: number | null;
comissionPerc: number;
comissionRub: number;
saleBonus: number;
IRR_Perc: number;
leaseObjectType: string | null;
deliveryTime: number | null;
leaseObjectCount: number;
withTrailer: boolean;
leaseObjectUsed: boolean;
maxMass: number;
countSeats: number;
maxSpeed: number;
brand: string | null;
model: string | null;
configuration: string | null;
leaseObjectYear: number;
engineType: number | null;
leaseObjectCategory: number | null;
leaseObjectMotorPower: number;
engineVolume: number;
leaseObjectUseFor: number | null;
dealer: string | null;
dealerPerson: string | null;
dealerRewardCondition: string | null;
dealerRewardSumm: number;
dealerBroker: string | null;
dealerBrokerRewardCondition: string | null;
dealerBrokerRewardSumm: number;
indAgent: string | null;
indAgentRewardCondition: string | null;
indAgentRewardSumm: number;
calcDoubleAgent: string | null;
calcDoubleAgentRewardCondition: string | null;
calcDoubleAgentRewardSumm: number;
calcBroker: string | null;
calcBrokerRewardCondition: string | null;
calcBrokerRewardSum: number;
calcFinDepartment: string | null;
finDepartmentRewardCondtion: string | null;
finDepartmentRewardSumm: number;
GPSBrand: string | null;
GPSModel: string | null;
regionRegistration: string | null;
townRegistration: string | null;
infuranceOPF: number | null;
insKaskoType: number | null;
insDecentral: boolean;
insFranchise: number;
insUnlimitDrivers: boolean;
insAgeDrivers: number;
insExpDrivers: number;
INNForCalc: number;
lastPaymentRedemption: boolean;
priceWithDiscount: boolean;
fullPriceWithDiscount: boolean;
costIncrease: boolean;
insurance: boolean;
registrationQuote: boolean;
technicalCardQuote: boolean;
NSIB: boolean;
quoteName: string | null;
quoteContactGender: number | null;
quoteRedemptionGraph: boolean;
showFinGAP: boolean;
tarif: string | null;
creditRate: number;
rate: string | null;
requirementTelematic: number | null;
minPriceChange: number;
maxPriceChange: number;
importerRewardPerc: number;
importerRewardRub: number;
disableChecks: boolean;
registration: string | null;
insNSIB: string | null;
technicalCard: string | null;
telematic: string | null;
tracker: string | null;
mileage: number;
calcType: number | null;
totalPayments: number;
objectRegistration: number | null;
objectRegionRegistration: string | null;
vehicleTaxInYear: number;
vehicleTaxInLeasingPeriod: number;
objectCategoryTax: number | null;
objectTypeTax: number | null;
typePTS: number | null;
legalClientRegion: string | null;
legalClientTown: string | null;
subsidy: string | null;
fuelCard: string | null;
leaseObjectPriceWthtVAT: number;
VATInLeaseObjectPrice: number;
engineHours: number;
bonusCoefficient: number;
/** Link Values */
kpUrl: string | null;
leadUrl: string | null;
opportunityUrl: string | null;
quoteUrl: string | null;
/** Readonly Values */
leaseObjectRiskName: string | null;
insKaskoPriceLeasePeriod: number;
irrInfo: string | null;
registrationDescription: string | null;
depreciationGroup: string | null;
subsidySum: number;
plPriceRub: number;
discountRub: number;
};
export type CalculationValues = z.infer<typeof ValuesSchema>;
export type Values = keyof CalculationValues; export type Values = keyof CalculationValues;

9
stores/process/index.ts Normal file
View File

@ -0,0 +1,9 @@
import type { ObservableSet } from 'mobx';
import { observable } from 'mobx';
export type Process = 'LoadKP' | 'ELT';
export type ProcessStore = ObservableSet<Process>;
export default function createProcessStore() {
return observable.set<Process>();
}

View File

@ -1,6 +1,8 @@
/* eslint-disable import/no-cycle */ /* eslint-disable import/no-cycle */
import { enableStaticRendering } from 'mobx-react-lite'; import { enableStaticRendering } from 'mobx-react-lite';
import CalculationStore from './calculation'; import CalculationStore from './calculation';
import type { ProcessStore } from './process';
import createProcessStore from './process';
import ResultsStore from './results'; import ResultsStore from './results';
import TablesStore from './tables'; import TablesStore from './tables';
@ -10,10 +12,12 @@ export default class RootStore {
$calculation: CalculationStore; $calculation: CalculationStore;
$results: ResultsStore; $results: ResultsStore;
$tables: TablesStore; $tables: TablesStore;
$process: ProcessStore;
constructor() { constructor() {
this.$calculation = new CalculationStore(this); this.$calculation = new CalculationStore(this);
this.$results = new ResultsStore(this); this.$results = new ResultsStore(this);
this.$tables = new TablesStore(this); this.$tables = new TablesStore(this);
this.$process = createProcessStore();
} }
} }

View File

@ -2,7 +2,8 @@ import type * as FinGAP from 'Components/Calculation/Form/Insurance/FinGAPTable/
import type { IObservableArray } from 'mobx'; import type { IObservableArray } from 'mobx';
import { makeAutoObservable, observable } from 'mobx'; import { makeAutoObservable, observable } from 'mobx';
import type RootStore from 'stores/root'; import type RootStore from 'stores/root';
import Validation from '../validation'; import Validation from '../../validation';
import type { ValidationParams } from '../../validation/types';
export default class FinGAPTable { export default class FinGAPTable {
root: RootStore; root: RootStore;
@ -13,13 +14,13 @@ export default class FinGAPTable {
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {
this.selectedKeys = new Set(); this.selectedKeys = new Set();
this.risks = observable<FinGAP.Risk>([]); this.risks = observable<FinGAP.Risk>([]);
makeAutoObservable(this);
this.validation = new Validation({ this.validation = new Validation({
err_key: 'ERR_FINGAP_TABLE', err_key: 'ERR_FINGAP_TABLE',
err_title: 'Таблица рисков Safe Finance', err_title: 'Таблица рисков Safe Finance',
}); });
makeAutoObservable(this);
this.root = rootStore; this.root = rootStore;
} }
@ -37,6 +38,14 @@ export default class FinGAPTable {
.reduce((sum, risk) => sum + risk.premium, 0); .reduce((sum, risk) => sum + risk.premium, 0);
} }
validate = ({ invalid, message }: ValidationParams) => {
if (invalid) {
this.validation?.addError(message);
} else {
this.validation?.removeError(message);
}
};
clear = () => { clear = () => {
this.risks.clear(); this.risks.clear();
this.selectedKeys.clear(); this.selectedKeys.clear();

View File

@ -3,7 +3,8 @@ import type * as Insurance from 'Components/Calculation/Form/Insurance/Insurance
import * as insuranceTableConfig from 'config/tables/insurance-table'; import * as insuranceTableConfig from 'config/tables/insurance-table';
import { makeAutoObservable } from 'mobx'; import { makeAutoObservable } from 'mobx';
import type RootStore from 'stores/root'; import type RootStore from 'stores/root';
import Validation from '../validation'; import Validation from '../../validation';
import type { ValidationParams } from '../../validation/types';
export interface InsuranceTableData { export interface InsuranceTableData {
values?: Insurance.RowValues[]; values?: Insurance.RowValues[];
@ -19,12 +20,13 @@ export default class InsuranceTable {
statuses: Record<Insurance.Keys, Insurance.RowStatuses> = insuranceTableConfig.defaultStatuses; statuses: Record<Insurance.Keys, Insurance.RowStatuses> = insuranceTableConfig.defaultStatuses;
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {
this.root = rootStore;
this.validation = new Validation({ this.validation = new Validation({
err_key: 'ERR_INSURANCE_TABLE', err_key: 'ERR_INSURANCE_TABLE',
err_title: 'Таблица страхования', err_title: 'Таблица страхования',
}); });
makeAutoObservable(this); makeAutoObservable(this);
this.root = rootStore;
} }
hydrate = ({ hydrate = ({
@ -49,6 +51,8 @@ export default class InsuranceTable {
if (rowIndex >= 0) { if (rowIndex >= 0) {
this.values[rowIndex] = { ...this.values[rowIndex], ...rowValues }; this.values[rowIndex] = { ...this.values[rowIndex], ...rowValues };
} }
return this;
}; };
getRowOptions(key: Insurance.Keys) { getRowOptions(key: Insurance.Keys) {
@ -65,12 +69,81 @@ export default class InsuranceTable {
setRowStatuses = (key: Insurance.Keys, rowStatuses: Partial<Insurance.RowStatuses>) => { setRowStatuses = (key: Insurance.Keys, rowStatuses: Partial<Insurance.RowStatuses>) => {
this.statuses[key] = { ...this.statuses[key], ...rowStatuses }; this.statuses[key] = { ...this.statuses[key], ...rowStatuses };
return this;
}; };
reset = () => { validate = ({ invalid, message }: ValidationParams) => {
if (invalid) {
this.validation?.addError(message);
} else {
this.validation?.removeError(message);
}
};
resetTable = () => {
this.values = insuranceTableConfig.defaultValues; this.values = insuranceTableConfig.defaultValues;
this.options = insuranceTableConfig.defaultOptions; this.options = insuranceTableConfig.defaultOptions;
this.statuses = insuranceTableConfig.defaultStatuses; this.statuses = insuranceTableConfig.defaultStatuses;
this.validation.clearErrors(); this.validation.clearErrors();
}; };
row = <K extends Insurance.Keys>(key: K) => ({
setValue: <V extends Insurance.Values>(valueName: V, value: Insurance.RowValues[V]) => {
const rowIndex = this.values.findIndex((x) => x.key === key);
if (rowIndex >= 0) {
this.values[rowIndex] = { ...this.values[rowIndex], [valueName]: value };
}
return this.row(key);
},
block: (valueName: Insurance.Values) => {
this.statuses[key][valueName] = 'Disabled';
return this.row(key);
},
unblock: (valueName: Insurance.Values) => {
this.statuses[key][valueName] = 'Default';
return this.row(key);
},
setOptions: <V extends Insurance.Values>(valueName: V, options: Insurance.RowOptions[V]) => {
this.options[key][valueName] = options;
return this.row(key);
},
resetValue: (valueName: Insurance.Values) => {
const rowIndex = this.values.findIndex((x) => x.key === key);
if (rowIndex >= 0) {
const defaultValue = insuranceTableConfig.defaultValues[rowIndex][valueName];
this.values[rowIndex] = { ...this.values[rowIndex], [valueName]: defaultValue };
}
return this.row(key);
},
resetStatus: (valueName: Insurance.Values) => {
this.statuses[key][valueName] = insuranceTableConfig.defaultStatuses[key][valueName];
return this.row(key);
},
resetOptions: <V extends Insurance.Values>(valueName: V) => {
this.options[key][valueName] = insuranceTableConfig.defaultOptions[key][valueName];
return this.row(key);
},
reset: (valueName: Insurance.Values) => {
this.row(key).resetValue(valueName).resetStatus(valueName).resetOptions(valueName);
return this.row(key);
},
});
} }

View File

@ -3,7 +3,8 @@ import type { IObservableArray } from 'mobx';
import { makeAutoObservable, observable, reaction } from 'mobx'; import { makeAutoObservable, observable, reaction } from 'mobx';
import type RootStore from 'stores/root'; import type RootStore from 'stores/root';
import Validation from '../validation'; import Validation from '../../validation';
import type { ValidationParams } from '../../validation/types';
import type { Row } from './types'; import type { Row } from './types';
export default class PaymentsTable { export default class PaymentsTable {
@ -13,14 +14,16 @@ export default class PaymentsTable {
statuses: IObservableArray<Status>; statuses: IObservableArray<Status>;
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {
this.root = rootStore;
this.validation = new Validation({ this.validation = new Validation({
err_key: 'ERR_PAYMENTS_TABLE', err_key: 'ERR_PAYMENTS_TABLE',
err_title: 'Таблица платежей', err_title: 'Таблица платежей',
}); });
this.values = observable<number>([]); this.values = observable<number>([]);
this.statuses = observable<Status>([]); this.statuses = observable<Status>([]);
makeAutoObservable(this); makeAutoObservable(this);
this.root = rootStore;
/** /**
* Синхронизируем длину массива значений и статусов * Синхронизируем длину массива значений и статусов
@ -70,6 +73,14 @@ export default class PaymentsTable {
this.setStatuses(statuses); this.setStatuses(statuses);
}; };
validate = ({ invalid, message }: ValidationParams) => {
if (invalid) {
this.validation?.addError(message);
} else {
this.validation?.removeError(message);
}
};
reset = () => { reset = () => {
this.values.clear(); this.values.clear();
this.statuses.clear(); this.statuses.clear();

View File

@ -0,0 +1,20 @@
import type { ObservableSet } from 'mobx';
import { observable } from 'mobx';
import type { RemoveError } from './types';
export default class ValidationHelper {
errors: ObservableSet<RemoveError>;
constructor() {
this.errors = observable.set();
}
add = (removeError: RemoveError) => {
this.errors.add(removeError);
};
removeErrors = () => {
this.errors.forEach((removeError) => removeError());
this.errors.clear();
};
}

View File

@ -1,17 +1,13 @@
import notification from 'Elements/notification'; import notification from 'Elements/notification';
import { makeAutoObservable } from 'mobx'; import { makeAutoObservable } from 'mobx';
import type { ValidationConfig } from './types';
type Params = {
err_key: string;
err_title: string;
};
export default class Validation { export default class Validation {
params: Params; params: ValidationConfig;
messages: Set<string>; messages: Set<string>;
constructor(params: Params) { constructor(config: ValidationConfig) {
this.params = params; this.params = config;
this.messages = new Set(); this.messages = new Set();
makeAutoObservable(this); makeAutoObservable(this);
} }
@ -24,24 +20,25 @@ export default class Validation {
return [...this.messages]; return [...this.messages];
} }
removeError = (message: string) => {
this.messages.delete(message);
if (this.messages.size === 0) notification.close(this.params.err_key);
};
addError = (message: string) => { addError = (message: string) => {
this.messages.add(message); this.messages.add(message);
const removeError = () => {
this.messages.delete(message);
notification.close(this.params.err_key);
};
notification.error({ notification.error({
key: this.params.err_key, key: this.params.err_key,
message: this.params.err_title, message: this.params.err_title,
description: message, description: message,
}); });
return removeError; return () => this.removeError(message);
}; };
clearErrors = () => { clearErrors = () => {
this.messages.clear(); this.messages.clear();
notification.close(this.params.err_key);
}; };
} }

View File

@ -0,0 +1,11 @@
export type ValidationConfig = {
err_key: string;
err_title: string;
};
export type ValidationParams = {
invalid: boolean;
message: string;
};
export type RemoveError = () => void;

23
tools/mobx.ts Normal file
View File

@ -0,0 +1,23 @@
/* eslint-disable import/prefer-default-export */
import type { IReactionDisposer } from 'mobx';
import { autorun } from 'mobx';
export function makeDisposable(
createReaction: () => IReactionDisposer,
mustBeDisposed: () => boolean
) {
let disposer: IReactionDisposer | undefined;
function cleanDisposer() {
disposer = undefined;
}
autorun(() => {
if (mustBeDisposed()) {
if (disposer !== undefined) disposer();
cleanDisposer();
} else {
disposer = createReaction();
}
});
}

35
trpc/client.ts Normal file
View File

@ -0,0 +1,35 @@
import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
import { createTRPCNext } from '@trpc/next';
import SuperJSON from 'superjson';
import type { AppRouter } from './routers';
function getBaseUrl() {
if (typeof window !== 'undefined') {
return process.env.NEXT_PUBLIC_BASE_PATH ?? '';
}
return `http://localhost:${process.env.PORT ?? 3000}${process.env.NEXT_PUBLIC_BASE_PATH ?? ''}`;
}
export const trpcClient = createTRPCNext<AppRouter>({
config() {
return {
links: [
httpBatchLink({
url: `${getBaseUrl()}/api/trpc`,
}),
],
transformer: SuperJSON,
};
},
ssr: true,
});
export const trpcPureClient = createTRPCProxyClient<AppRouter>({
links: [
httpBatchLink({
url: `${getBaseUrl()}/api/trpc`,
}),
],
transformer: SuperJSON,
});

10
trpc/routers/index.ts Normal file
View File

@ -0,0 +1,10 @@
import { t } from '../server';
import quoteRouter from './quote';
const appRouter = t.router({
quote: quoteRouter,
});
export type AppRouter = typeof appRouter;
export default appRouter;

32
trpc/routers/quote.ts Normal file
View File

@ -0,0 +1,32 @@
import defaultValues from 'config/default-values';
import ValuesSchema from 'config/schema/values';
import getSupplierAgentsDataFromKP from 'process/supplier-agent/get-kp-values';
import { z } from 'zod';
import { t } from '../server';
const quoteRouter = t.router({
getValues: t.procedure
.input(
z.object({
values: ValuesSchema.pick({
quote: true,
}),
})
)
.output(
z.object({
values: ValuesSchema,
})
)
.query(async ({ input }) => {
const { values } = await getSupplierAgentsDataFromKP({
quoteId: input.values.quote!,
});
return {
values: Object.assign(defaultValues, values),
};
}),
});
export default quoteRouter;

7
trpc/server.ts Normal file
View File

@ -0,0 +1,7 @@
/* eslint-disable import/prefer-default-export */
import { initTRPC } from '@trpc/server';
import SuperJSON from 'superjson';
export const t = initTRPC.create({
transformer: SuperJSON,
});

5
trpc/types.ts Normal file
View File

@ -0,0 +1,5 @@
import type { trpcClient, trpcPureClient } from './client';
export type TRPCClient = typeof trpcClient;
export type TRPCPureClient = typeof trpcPureClient;

View File

@ -2078,17 +2078,17 @@
dependencies: dependencies:
tslib "^2.4.0" tslib "^2.4.0"
"@tanstack/query-core@4.13.0": "@tanstack/query-core@4.14.1":
version "4.13.0" version "4.14.1"
resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-4.13.0.tgz#89153096d1fce42c0294fa1d1ae4b3e72aa5353b" resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-4.14.1.tgz#a74c4da03e79a8be07fa5ab2ebc12865146915e2"
integrity sha512-PzmLQcEgC4rl2OzkiPHYPC9O79DFcMGaKsOzDEP+U4PJ+tbkcEP+Z+FQDlfvX8mCwYC7UNH7hXrQ5EdkGlJjVg== integrity sha512-mUejKoFDe4NZB8jQJR1uuAl6IwvkUpOD2m8NcuTVPOu0pcxeeFPdrnHaljwOEFPtlqXoiiIIQGYy6whjCMN+iQ==
"@tanstack/react-query@^4.13.0": "@tanstack/react-query@^4.14.1":
version "4.13.0" version "4.14.1"
resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-4.13.0.tgz#13797d590a6c0708545881e38aea5eb39b960c28" resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-4.14.1.tgz#336545119b191e2096c394a3f2df2744cdc5e041"
integrity sha512-dI/5hJ/pGQ74P5hxBLC9h6K0/Cap2T3k0ZjjjFLBCNnohDYgl7LNmMopzrRzBHk2mMjf2hgXHIzcKNG8GOZ5hg== integrity sha512-cRgNzigw4GSPwGlTEkXi8hi/xgUnSEt9jCkiC8oAT3PEIdsQ50onZcpXd+JNJcZk2RTh8KM1fGyWz6xYLiY8bg==
dependencies: dependencies:
"@tanstack/query-core" "4.13.0" "@tanstack/query-core" "4.14.1"
use-sync-external-store "^1.2.0" use-sync-external-store "^1.2.0"
"@testing-library/dom@^8.5.0": "@testing-library/dom@^8.5.0":
@ -2139,6 +2139,28 @@
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
"@trpc/client@^10.0.0-rc.3":
version "10.0.0-rc.3"
resolved "https://registry.yarnpkg.com/@trpc/client/-/client-10.0.0-rc.3.tgz#22cea038dd5e38ce0e39ff4a339793bb5808ab18"
integrity sha512-gZYVfZra1YB2DluDY+GcIrL7KqPXCI9y0mF4utXYAUAl+jrxfLyG63pCv30USRRYlwwSKaoLJNpjQB9k05aYaw==
"@trpc/next@^10.0.0-rc.3":
version "10.0.0-rc.3"
resolved "https://registry.yarnpkg.com/@trpc/next/-/next-10.0.0-rc.3.tgz#2585aa271c2916afb2f7291583c9299c324f799d"
integrity sha512-L9sHV93dPA4lZ/I8opfn3BJONnlnnJzJERggv7srt8H3aEhKVlNWIqxciNLHGXSq9q0C9i3Q6ND4F5kpRSQ5YA==
dependencies:
react-ssr-prepass "^1.5.0"
"@trpc/react-query@^10.0.0-rc.3":
version "10.0.0-rc.3"
resolved "https://registry.yarnpkg.com/@trpc/react-query/-/react-query-10.0.0-rc.3.tgz#34a0449c62544522d1fa0f07844d1f11cf38eb55"
integrity sha512-nEBqkTdKsd+vIE4RuDRX/b8U5ayxENp0G2vnh/fn4hiIszrLiPTGvnhGCZm/fT2GGW5nk7EEBcqf2o0z3r8Ftg==
"@trpc/server@^10.0.0-rc.3":
version "10.0.0-rc.3"
resolved "https://registry.yarnpkg.com/@trpc/server/-/server-10.0.0-rc.3.tgz#4ddc4410305b17a47248b3bfa881df3b52202e60"
integrity sha512-aSs3uDQ5wumwVjtxj855WLDjlDC+v50QoqHzvuptI33NhJZV7meu0pU2EJkrSZXFt27CSNfP9o2ZPfoReoPUuw==
"@tsconfig/node10@^1.0.7": "@tsconfig/node10@^1.0.7":
version "1.0.9" version "1.0.9"
resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2"
@ -3897,6 +3919,13 @@ copy-anything@^2.0.1:
dependencies: dependencies:
is-what "^3.14.1" is-what "^3.14.1"
copy-anything@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-3.0.2.tgz#7189171ff5e1893b2287e8bf574b8cd448ed50b1"
integrity sha512-CzATjGXzUQ0EvuvgOCI6A4BGOo2bcVx8B+eC2nF862iv9fopnPQwlrbACakNCHRIJbCSBj+J/9JeDf60k64MkA==
dependencies:
is-what "^4.1.6"
copy-to-clipboard@^3.2.0: copy-to-clipboard@^3.2.0:
version "3.3.1" version "3.3.1"
resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz#115aa1a9998ffab6196f93076ad6da3b913662ae" resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz#115aa1a9998ffab6196f93076ad6da3b913662ae"
@ -5928,6 +5957,11 @@ is-what@^3.14.1:
resolved "https://registry.yarnpkg.com/is-what/-/is-what-3.14.1.tgz#e1222f46ddda85dead0fd1c9df131760e77755c1" resolved "https://registry.yarnpkg.com/is-what/-/is-what-3.14.1.tgz#e1222f46ddda85dead0fd1c9df131760e77755c1"
integrity sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA== integrity sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==
is-what@^4.1.6:
version "4.1.7"
resolved "https://registry.yarnpkg.com/is-what/-/is-what-4.1.7.tgz#c41dc1d2d2d6a9285c624c2505f61849c8b1f9cc"
integrity sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==
is-windows@^1.0.1: is-windows@^1.0.1:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
@ -8315,6 +8349,11 @@ react-is@^18.0.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
react-ssr-prepass@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/react-ssr-prepass/-/react-ssr-prepass-1.5.0.tgz#bc4ca7fcb52365e6aea11cc254a3d1bdcbd030c5"
integrity sha512-yFNHrlVEReVYKsLI5lF05tZoHveA5pGzjFbFJY/3pOqqjGOmMmqx83N4hIjN2n6E1AOa+eQEUxs3CgRnPmT0RQ==
react@^18.2.0: react@^18.2.0:
version "18.2.0" version "18.2.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
@ -9178,6 +9217,13 @@ styled-system@^5.0.0, styled-system@^5.1.5:
"@styled-system/variant" "^5.1.5" "@styled-system/variant" "^5.1.5"
object-assign "^4.1.1" object-assign "^4.1.1"
superjson@^1.11.0:
version "1.11.0"
resolved "https://registry.yarnpkg.com/superjson/-/superjson-1.11.0.tgz#f6e2ae0d8fbac61c3fca09ab6739ac9678414d1b"
integrity sha512-6PfAg1FKhqkwWvPb2uXhH4MkMttdc17eJ91+Aoz4s1XUEDZFmLfFx/xVA3wgkPxAGy5dpozgGdK6V/n20Wj9yg==
dependencies:
copy-anything "^3.0.2"
supports-color@^2.0.0: supports-color@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
@ -10028,3 +10074,8 @@ zen-observable@0.8.15, zen-observable@^0.8.0:
version "0.8.15" version "0.8.15"
resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15" resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15"
integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ== integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==
zod@^3.19.1:
version "3.19.1"
resolved "https://registry.yarnpkg.com/zod/-/zod-3.19.1.tgz#112f074a97b50bfc4772d4ad1576814bd8ac4473"
integrity sha512-LYjZsEDhCdYET9ikFu6dVPGp2YH9DegXjdJToSzD9rO6fy4qiRYFoyEYwps88OseJlPyl2NOe2iJuhEhL7IpEA==