Compare commits

...

14 Commits

Author SHA1 Message Date
vchikalkin
29f9e79867 add prefix _ to column names 2023-04-21 11:11:23 +03:00
vchikalkin
6adb1be0cf process/leasing-object: add selectConfiguration validation 2023-04-21 11:05:47 +03:00
vchikalkin
4d9cdf79a4 calculate: fix output validation 2023-04-21 10:59:48 +03:00
vchikalkin
5432536b2e fix prepared-values 2023-04-21 10:19:33 +03:00
vchikalkin
2097b28870 bfabdba: setTimeout for restart reaction 2023-04-21 09:47:33 +03:00
vchikalkin
b7f0a3e6cf unlimited: add new results values 2023-04-20 18:20:11 +03:00
vchikalkin
9f0c126ffb вывод столбцов для unlimited 2023-04-20 18:01:10 +03:00
vchikalkin
94e053c38d fix nsibBase 2023-04-20 17:47:37 +03:00
vchikalkin
f040cec7d2 fix preparedValues 2023-04-20 17:45:14 +03:00
vchikalkin
956180c52b fix loanRate 2023-04-20 16:21:53 +03:00
vchikalkin
8e2e9167fc calculate: pass payment sums to preparedPayments 2023-04-20 14:13:16 +03:00
vchikalkin
b38f25a039 extend payments table for unlimited 2023-04-20 13:48:44 +03:00
vchikalkin
6c3b93c914 Отключить реакцию на фильтрацию списка Методов расчета CalcType и отображать всегда все 3 значения списка (Irr? Сумма, Маржа) 2023-04-19 23:46:58 +03:00
vchikalkin
cc1f07d9e4 options: add graphType индивидуальный график 2023-04-19 23:45:39 +03:00
28 changed files with 352 additions and 97 deletions

View File

@ -1,4 +1,4 @@
import { usePaymentValue } from './hooks';
import { usePaymentSum, usePaymentValue } from './hooks';
import { useRowStatus } from '@/stores/tables/payments/hooks';
import { observer } from 'mobx-react-lite';
import type { ComponentType } from 'react';
@ -11,3 +11,12 @@ export function buildValueComponent<T>(index: number, Component: ComponentType<T
return <Component setValue={setValue} status={status} value={value} {...props} />;
});
}
export function buildSumComponent<T>(index: number, Component: ComponentType<T>) {
return observer((props: T) => {
const [value, setValue] = usePaymentSum(index);
const status = useRowStatus(index);
return <Component setValue={setValue} status={status} value={value} {...props} />;
});
}

View File

@ -1,14 +1,22 @@
/* eslint-disable canonical/sort-keys */
import { buildValueComponent } from './builders';
import { buildSumComponent, buildValueComponent } from './builders';
import type { ColumnsType } from 'antd/lib/table';
import { parser } from 'tools/number';
import { InputNumber } from 'ui/elements';
import { createFormatter } from 'ui/elements/InputNumber';
type Payment = {
key: number;
num: number;
paymentRelation: number;
paymentSum: number;
};
const formatter = createFormatter({
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
export const columns: ColumnsType<Payment> = [
{
key: 'num',
@ -27,4 +35,14 @@ export const columns: ColumnsType<Payment> = [
return <Component max={100} min={0} precision={payment.num === 0 ? 4 : 2} step={1} />;
},
},
{
key: 'paymentSum',
dataIndex: 'paymentSum',
title: 'Сумма',
render: (_value, payment) => {
const Component = buildSumComponent(payment.num, InputNumber);
return <Component min={0} precision={2} step={1000} formatter={formatter} parser={parser} />;
},
},
];

View File

@ -1,4 +1,4 @@
import { useRowValue } from '@/stores/tables/payments/hooks';
import { useRowSum, useRowValue } from '@/stores/tables/payments/hooks';
import { useEffect, useState } from 'react';
import { useDebouncedCallback } from 'use-debounce';
@ -20,3 +20,22 @@ export function usePaymentValue(index) {
return [value, setValue];
}
export function usePaymentSum(index) {
const [storeValue, setStoreValue] = useRowSum(index);
const [value, setValue] = useState(storeValue);
const debouncedSetStoreValue = useDebouncedCallback(setStoreValue, 350, { maxWait: 1000 });
useEffect(() => {
if (storeValue !== value) {
debouncedSetStoreValue(value);
}
}, [value]);
useEffect(() => {
setValue(storeValue);
}, [storeValue]);
return [value, setValue];
}

View File

@ -3,9 +3,12 @@ import { useStore } from '@/stores/hooks';
import { min } from '@/styles/mq';
import { computed } from 'mobx';
import { observer } from 'mobx-react-lite';
import { createContext, useContext, useMemo, useState } from 'react';
import styled from 'styled-components';
import { Segmented } from 'ui/antd';
import { Alert, Table } from 'ui/elements';
import { Box, Flex } from 'ui/grid';
import { useDebouncedCallback } from 'use-debounce';
const Grid = styled(Flex)`
flex-direction: column;
@ -47,6 +50,8 @@ const Validation = observer(() => {
return null;
});
export const ModeContext = createContext('paymentRelation');
const SPLIT_NUMBER = 12;
function TablePart({ num }) {
@ -55,16 +60,25 @@ function TablePart({ num }) {
const values = payments.values.slice(num * SPLIT_NUMBER, num * SPLIT_NUMBER + SPLIT_NUMBER);
const dataSource = values.map((value, index) => ({
const dataSource = values.map((_, index) => ({
key: index + num * SPLIT_NUMBER,
num: index + num * SPLIT_NUMBER,
paymentRelation: value,
}));
return (
<TableWrapper>
<Table size="small" columns={columns} dataSource={dataSource} pagination={false} />
</TableWrapper>
const mode = useContext(ModeContext);
return useMemo(
() => (
<TableWrapper>
<Table
size="small"
columns={columns.filter((x) => ['num', mode].includes(x.key))}
dataSource={dataSource}
pagination={false}
/>
</TableWrapper>
),
[dataSource, mode]
);
}
@ -84,11 +98,36 @@ const TablesGroup = observer(() => {
return <TablesGroupGrid>{tables}</TablesGroupGrid>;
});
function Mode({ setMode }) {
const { $process } = useStore();
if (!$process.has('Unlimited')) {
return false;
}
return (
<Segmented
block
options={[
{ label: 'Процент', value: 'paymentRelation' },
{ label: 'Сумма', value: 'paymentSum' },
]}
onChange={(value) => setMode(value)}
/>
);
}
export default function TablePayments() {
const [mode, setMode] = useState('paymentRelation');
const debouncedSetMode = useDebouncedCallback(setMode, 300);
return (
<Grid>
<Validation />
<TablesGroup />
<ModeContext.Provider value={mode}>
<Validation />
<Mode setMode={debouncedSetMode} />
<TablesGroup />
</ModeContext.Provider>
</Grid>
);
}

View File

@ -36,4 +36,49 @@ export const columns: ColumnsType<ResultPayment> = [
currency: 'RUB',
}).format,
},
{
key: '_piColumn',
dataIndex: '_piColumn',
title: 'PI Column',
render: Intl.NumberFormat('ru', {
style: 'currency',
currency: 'RUB',
}).format,
},
{
key: '_cashflowMsfoWithCfColumn',
dataIndex: '_cashflowMsfoWithCfColumn',
title: 'CashflowMSFOWithCF Column',
render: Intl.NumberFormat('ru', {
style: 'currency',
currency: 'RUB',
}).format,
},
{
key: '_creditPaymentColumn',
dataIndex: '_creditPaymentColumn',
title: 'CreditPayment Column',
render: Intl.NumberFormat('ru', {
style: 'currency',
currency: 'RUB',
}).format,
},
{
key: '_cashflowMsfoColumn',
dataIndex: '_cashflowMsfoColumn',
title: 'CashflowMSFO Column',
render: Intl.NumberFormat('ru', {
style: 'currency',
currency: 'RUB',
}).format,
},
{
key: '_interestColumn',
dataIndex: '_interestColumn',
title: 'Interest Column',
render: Intl.NumberFormat('ru', {
style: 'currency',
currency: 'RUB',
}).format,
},
];

View File

@ -1,3 +1,4 @@
/* eslint-disable no-negated-condition */
import { columns } from './config';
import { MAX_LEASING_PERIOD } from '@/constants/values';
import { useStore } from '@/stores/hooks';
@ -6,11 +7,13 @@ import { observer } from 'mobx-react-lite';
import { Table } from 'ui/elements';
const PaymentsTable = observer(() => {
const { $results } = useStore();
const { $results, $process } = useStore();
const unlimited = $process.has('Unlimited');
return (
<Table
columns={columns}
columns={!unlimited ? columns.filter((x) => !x.key.includes('_')) : columns}
dataSource={toJS($results.payments)}
size="small"
pagination={{

View File

@ -4,6 +4,12 @@ export const id = 'output';
export const title = 'Результаты';
export const titles: Record<keyof ResultValues, string> = {
_resultContractEconomy: 'Экономика',
_resultContractEconomyWithVAT: 'Экономика, с НДС',
_resultPi: 'PI',
_resultSumCredit: 'Сумма кредита',
_resultSumCreditPayment: 'Сумма платежей по кредиту',
_resultVatRecoverable: 'НДС к возмещению',
resultAB_FL: 'АВ ФЛ, без НДФЛ.',
resultAB_UL: 'АВ ЮЛ, с НДС.',
resultBonusDopProd: 'Бонус МПЛ за доп.продукты, без НДФЛ',
@ -37,6 +43,12 @@ const percentFormatter = Intl.NumberFormat('ru', {
}).format;
export const formatters = {
_resultContractEconomy: moneyFormatter,
_resultContractEconomyWithVAT: moneyFormatter,
_resultPi: percentFormatter,
_resultSumCredit: moneyFormatter,
_resultSumCreditPayment: moneyFormatter,
_resultVatRecoverable: moneyFormatter,
resultAB_FL: moneyFormatter,
resultAB_UL: moneyFormatter,
resultBonusDopProd: moneyFormatter,

View File

@ -4,6 +4,7 @@ import { useStore } from '@/stores/hooks';
import { min } from '@/styles/mq';
import { toJS } from 'mobx';
import { observer } from 'mobx-react-lite';
import { omit } from 'radash';
import styled from 'styled-components';
import { Text } from 'ui/elements';
import { Box } from 'ui/grid';
@ -18,8 +19,16 @@ const Grid = styled(Box)`
`;
const Results = observer(() => {
const { $results } = useStore();
const values = toJS($results.values);
const { $results, $process } = useStore();
const resultsValues = toJS($results.values);
// eslint-disable-next-line no-negated-condition
const values = !$process.has('Unlimited')
? omit(
resultsValues,
Object.keys(resultsValues).filter((x) => x.includes('_'))
)
: resultsValues;
return (
<Grid>

View File

@ -217,6 +217,10 @@ const ColumnsSchema = z.object({
nominal: z.number(),
values: z.number().array(),
}),
cashflowMsfoWithCfColumn: z.object({
sum: z.number(),
values: z.number().array(),
}),
cashflowNpvColumn: z.object({
values: z.number().array(),
}),
@ -240,6 +244,10 @@ const ColumnsSchema = z.object({
sum: z.number(),
values: z.number().array(),
}),
creditPaymentColumn: z.object({
sum: z.number(),
values: z.number().array(),
}),
creditVATColumn: z.object({
sum: z.number(),
values: z.number().array(),
@ -351,6 +359,9 @@ const ColumnsSchema = z.object({
percentPaymentColumn: z.object({
values: z.number().array(),
}),
piColumn: z.object({
values: z.number().array(),
}),
ratExpensesColumn: z.object({
sum: z.number(),
values: z.number().array(),
@ -416,6 +427,10 @@ const ColumnsSchema = z.object({
sum: z.number(),
values: z.number().array(),
}),
vatRecoverableColumn: z.object({
sum: z.number(),
values: z.number().array(),
}),
});
export const ResponseCalculateSchema = z.object({

View File

@ -68,6 +68,10 @@ export const radioGraphType = [
label: 'легкий старт',
value: 100_000_004,
},
{
label: 'индивидуальный график',
value: 100_000_005,
},
];
export const selectObjectCategoryTax = [

View File

@ -1,6 +1,7 @@
import { z } from 'zod';
const PaymentsSchema = z.object({
sums: z.number().optional().array(),
values: z.number().array(),
});

View File

@ -1,6 +1,12 @@
import { z } from 'zod';
export const ResultValuesSchema = z.object({
_resultContractEconomy: z.number(),
_resultContractEconomyWithVAT: z.number(),
_resultPi: z.number(),
_resultSumCredit: z.number(),
_resultSumCreditPayment: z.number(),
_resultVatRecoverable: z.number(),
resultAB_FL: z.number(),
resultAB_UL: z.number(),
resultBonusDopProd: z.number(),
@ -23,6 +29,11 @@ export const ResultValuesSchema = z.object({
});
export const ResultPaymentSchema = z.object({
_cashflowMsfoColumn: z.number(),
_cashflowMsfoWithCfColumn: z.number(),
_creditPaymentColumn: z.number(),
_interestColumn: z.number(),
_piColumn: z.number(),
key: z.string(),
ndsCompensation: z.number(),
num: z.number(),

View File

@ -22,12 +22,13 @@ export async function action({ store, trpcClient }: ProcessContext) {
osago: toJS($tables.insurance.row('osago').getValues()),
};
const payments = toJS($tables.payments.values);
const paymentRelations = toJS($tables.payments.values);
const paymentSums = toJS($tables.payments.sums);
trpcClient.calculate
.mutate({
insurance: { values: insurance },
payments: { values: payments },
payments: { sums: paymentSums, values: paymentRelations },
values,
})
.then((res) => {

View File

@ -1,8 +1,10 @@
/* eslint-disable sonarjs/cognitive-complexity */
import { radioCalcType, radioGraphType, selectSeasonType } from '@/config/default-options';
import * as CRMTypes from '@/graphql/crm.types';
import { SEASON_TYPES } from '@/process/payments/lib/seasons-constants';
import type { ProcessContext } from '@/process/types';
import { normalizeOptions } from '@/utils/entity';
import { disposableReaction } from '@/utils/mobx';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import { reaction } from 'mobx';
@ -11,7 +13,7 @@ import { diff } from 'radash';
dayjs.extend(utc);
export default function reactions({ store, apolloClient, user }: ProcessContext) {
const { $calculation } = store;
const { $calculation, $process } = store;
reaction(
() => $calculation.$values.getValues(['dealer', 'importProgram', 'product', 'subsidy']),
@ -20,7 +22,6 @@ export default function reactions({ store, apolloClient, user }: ProcessContext)
subsidy: subsidyId,
importProgram: importProgramId,
dealer: dealerId,
// eslint-disable-next-line sonarjs/cognitive-complexity
}) => {
/**
* #1
@ -241,15 +242,21 @@ export default function reactions({ store, apolloClient, user }: ProcessContext)
({ evo_tarif } = data);
}
if (evo_tarif?.evo_graphtype_exception?.length) {
const filteredGraphTypes = radioGraphType.filter(
let options = radioGraphType;
if (!$process.has('Unlimited')) {
options = options.filter((x) => x.value !== 100_000_005);
}
if (!$process.has('Unlimited') && evo_tarif?.evo_graphtype_exception?.length) {
options = options.filter(
(type) => !evo_tarif?.evo_graphtype_exception?.includes(type.value)
);
$calculation.element('radioGraphType').setOptions(filteredGraphTypes);
} else {
$calculation.element('radioGraphType').resetOptions();
}
$calculation.element('radioGraphType').setOptions(options);
},
{
fireImmediately: true,
}
);
@ -299,7 +306,8 @@ export default function reactions({ store, apolloClient, user }: ProcessContext)
* radioCalcType фильтровать значения согласно списку
* в поле "Доступные Методы расчета в калькуляторе" evo_calculation_method в selectProduct
*/
reaction(
disposableReaction(
() => $process.has('Unlimited'),
() => $calculation.element('selectProduct').getValue(),
async (productId) => {
const IRRCalcTypeOptions = radioCalcType.filter((x) => x.value === 100_000_000);

View File

@ -25,13 +25,14 @@ export function action({ store, trpcClient, apolloClient }: ProcessContext) {
const fingap = $tables.fingap.getSelectedRisks();
const payments = toJS($tables.payments.values);
const paymentRelations = toJS($tables.payments.values);
const paymentSums = toJS($tables.payments.sums);
trpcClient.createQuote
.mutate({
fingap,
insurance: { values: insurance },
payments: { values: payments },
payments: { sums: paymentSums, values: paymentRelations },
values,
})
.then(async (res) => {

View File

@ -8,6 +8,7 @@ import { z } from 'zod';
export function createValidationSchema({ apolloClient }: ValidationContext) {
return ValuesSchema.pick({
brand: true,
configuration: true,
countSeats: true,
engineType: true,
engineVolume: true,
@ -30,6 +31,7 @@ export function createValidationSchema({ apolloClient }: ValidationContext) {
brand,
model,
leaseObjectUseFor,
configuration,
},
ctx
) => {
@ -57,6 +59,23 @@ export function createValidationSchema({ apolloClient }: ValidationContext) {
});
}
if (model && !configuration) {
const {
data: { evo_equipments },
} = await apolloClient.query({
query: CRMTypes.GetConfigurationsDocument,
variables: { modelId: model },
});
if (evo_equipments?.length) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: 'Не заполнено поле',
path: ['selectConfiguration'],
});
}
}
if (!leaseObjectUseFor) {
ctx.addIssue({
code: z.ZodIssueCode.custom,

View File

@ -72,9 +72,7 @@ export function common({ store, trpcClient }: ProcessContext) {
$calculation.element('selectQuote').resetValue();
})
.finally(() => {
setTimeout(() => {
$process.delete('LoadKP');
}, 100);
$process.delete('LoadKP');
});
}
);

View File

@ -79,6 +79,7 @@ export async function getKPData({
return {
payments: {
sums: [],
values: [
quote?.evo_first_payment_perc ?? 0,
...paymentsValues,

View File

@ -53,7 +53,7 @@ export default function reactions({ store }: ProcessContext) {
};
},
({ graphType, leasingPeriod }) => {
if (graphType === 100_000_000) {
if ([100_000_000, 100_000_005].includes(graphType)) {
const middlePayments: Row[] = Array.from(
{
length: leasingPeriod - 2,

View File

@ -19,7 +19,7 @@ export function createValidationSchema() {
seasonType: true,
})
.extend({
payments: PaymentsSchema,
payments: PaymentsSchema.omit({ sums: true }),
})
.superRefine(
async (

View File

@ -7,7 +7,7 @@ import helper from '@/process/calculate/lib/helper';
import { createCurrencyUtility } from '@/utils/currency';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import { max, sum } from 'radash';
import { min, sum } from 'radash';
dayjs.extend(utc);
@ -33,16 +33,44 @@ export async function createRequestData({
const { RUB } = createCurrencyUtility({ apolloClient });
let tracker: CRMTypes.GetAddProductTypeQuery['evo_addproduct_type'] = null;
if (input.values.tracker) {
const { data } = await apolloClient.query({
query: CRMTypes.GetAddProductTypeDocument,
variables: { addproductTypeId: input.values.tracker },
});
tracker = data.evo_addproduct_type;
}
let telematic: CRMTypes.GetAddProductTypeQuery['evo_addproduct_type'] = null;
if (input.values.telematic) {
const { data } = await apolloClient.query({
query: CRMTypes.GetAddProductTypeDocument,
variables: { addproductTypeId: input.values.telematic },
});
telematic = data.evo_addproduct_type;
}
const preparedPayments: CoreTypes.PreparedPayments = {
rows: payments.values.map((payment, index) => ({
gpsBasePayment: 0,
gpsCostPayment: 0,
numberPayment: index + 1,
percentPayment: index === 0 ? 0 : payment,
sumPayment: 0,
tlmBasePayment: 0,
tlmCostPayment: 0,
})),
rows: payments.values.map((value, index) => {
const tracker_evo_planpayments = tracker?.evo_planpayments?.[index];
const telematic_evo_planpayments = telematic?.evo_planpayments?.[index];
return {
gpsBasePayment:
(tracker_evo_planpayments?.evo_cost_price_telematics_withoutnds || 0) +
(tracker_evo_planpayments?.evo_cost_equipment_withoutnds || 0),
gpsCostPayment: tracker_evo_planpayments?.evo_cost_telematics_withoutnds || 0,
numberPayment: index + 1,
percentPayment: index === 0 ? 0 : value,
sumPayment: (payments.sums[index] ?? 0) / (1 + VAT),
tlmBasePayment:
(telematic_evo_planpayments?.evo_cost_price_telematics_withoutnds || 0) +
(telematic_evo_planpayments?.evo_cost_equipment_withoutnds || 0),
tlmCostPayment: telematic_evo_planpayments?.evo_cost_telematics_withoutnds || 0,
};
}),
};
const currentDate = dayjs().utc(false);
@ -389,7 +417,9 @@ export async function createRequestData({
(x) => x?.evo_sot_coefficient_typeidData?.evo_id === 'DIRECTOR_BONUS_NSIB'
);
return evo_coefficient?.evo_sot_coefficient || 0;
const nsibBrutto = await this.nsibBrutto();
return (evo_coefficient?.evo_sot_coefficient || 0) * nsibBrutto;
},
async directorExtraBonus() {
@ -754,7 +784,7 @@ export async function createRequestData({
},
async loanRate() {
return values.creditRate;
return values.creditRate / 100;
},
async loanRatePeriod() {
@ -809,9 +839,9 @@ export async function createRequestData({
},
async nmperInsurance() {
const { insured } = insurance.values.kasko;
const { insTerm } = insurance.values.kasko;
return insured === 100_000_001 ? values.leasingPeriod : 12;
return insTerm === 100_000_001 ? values.leasingPeriod : 12;
},
async npvniDelta() {
@ -832,47 +862,16 @@ export async function createRequestData({
},
async nsBonus() {
const evo_coefficient = evo_coefficients?.find(
(x) =>
x?.evo_job_titleid === systemuser?.evo_job_titleid &&
x?.evo_sot_coefficient_typeidData?.evo_id === 'BONUS_NS_PR'
);
return evo_coefficient?.evo_sot_coefficient || 0;
return 0;
},
async nsibBase() {
const discount = await this.discount();
const plPrice = await this.plPrice();
const importProgramSum = await this.importProgramSum();
const insuranceContract = await this.insuranceContract();
const rats = await this.rats();
const registration = await this.registration();
const trackerCost = await this.trackerCost();
const tLMCost = await this.tlmCost();
const transportTaxGr = await this.transportTaxGr();
const tlmCostPaymentSum = await this.tlmCostPaymentSum();
const gpsCostPaymentSum = await this.gpsCostPaymentSum();
const leasing0K = await this.leasing0K();
const firstPaymentSum = await this.firstPaymentSum();
const value =
(plPrice -
importProgramSum +
(insuranceContract +
rats +
registration +
trackerCost +
tLMCost +
transportTaxGr +
tlmCostPaymentSum +
gpsCostPaymentSum) *
leasing0K -
firstPaymentSum -
(values.product === 'LEASING0' ? 0 : discount)) *
(1 + VAT);
const value = (plPrice - firstPaymentSum) * (1 + VAT);
return max([NSIB_MAX, value], (v) => v) ?? NSIB_MAX;
return min([NSIB_MAX, value]) ?? NSIB_MAX;
},
async nsibBonus() {

View File

@ -21,11 +21,16 @@ export function transformCalculateResults({
length: preparedValues.nmper,
},
(_, i) => ({
_cashflowMsfoColumn: columns?.cashflowMsfoColumn.values[i + 1] || 0,
_cashflowMsfoWithCfColumn: columns?.cashflowMsfoWithCfColumn.values[i + 1] || 0,
_creditPaymentColumn: columns?.creditPaymentColumn.values[i + 1] || 0,
_interestColumn: columns?.interestColumn.values[i + 1] || 0,
_piColumn: columns?.piColumn.values[i + 1] || 0,
key: String(i + 1),
ndsCompensation: columns.vatColumn.values[i + 1],
ndsCompensation: columns?.vatColumn.values[i + 1] || 0,
num: i + 1,
paymentSum: columns.sumWithVatColumn.values[i + 1],
redemptionAmount: columns.sumRepaymentColumn.values[i + 1],
paymentSum: columns?.sumWithVatColumn.values[i + 1] || 0,
redemptionAmount: columns?.sumRepaymentColumn.values[i + 1] || 0,
})
);
@ -34,6 +39,12 @@ export function transformCalculateResults({
resultPayments[0].ndsCompensation -= subsidySum - subsidySum / (1 + VAT);
const resultValues: OutputData['resultValues'] = {
_resultContractEconomy: postValues.contractEconomy,
_resultContractEconomyWithVAT: postValues.contractEconomyWithVAT,
_resultPi: columns?.piColumn.values[0],
_resultSumCredit: columns?.sumCreditColumn.values[1],
_resultSumCreditPayment: columns?.creditPaymentColumn.values[0],
_resultVatRecoverable: columns?.vatRecoverableColumn.values[0],
resultAB_FL: ((preparedValues.agentsSum + preparedValues.doubleAgentsSum) / ESN) * (1 - NDFL),
resultAB_UL:
(preparedValues.deliverySum +
@ -45,11 +56,11 @@ export function transformCalculateResults({
(columns?.npvBonusExpensesColumn?.values[1] / (1 + preparedValues?.salaryRate)) * (1 - NDFL)
),
resultBonusMPL: Math.abs(
(columns.npvBonusExpensesColumn.values[2] / (1 + preparedValues.salaryRate)) * (1 - NDFL)
(columns?.npvBonusExpensesColumn.values[2] / (1 + preparedValues.salaryRate)) * (1 - NDFL)
),
resultBonusSafeFinance: preparedValues?.bonusFinGAP * (1 - NDFL),
resultDopMPLLeasing: Math.abs(
(columns.extraBonusSumColumn.values[2] / (1 + preparedValues.salaryRate)) * (1 - NDFL)
(columns?.extraBonusSumColumn.values[2] / (1 + preparedValues.salaryRate)) * (1 - NDFL)
),
resultDopProdSum:
preparedValues.rats +
@ -60,8 +71,8 @@ export function transformCalculateResults({
preparedValues.insuranceFinGAPNmper,
resultFirstPayment: preparedValues.firstPaymentSum * (1 + VAT) - inputValues.subsidySum,
resultFirstPaymentRiskPolicy: preparedValues?.firstPayment,
resultIRRGraphPerc: columns.sumColumn.irr,
resultIRRNominalPerc: columns.cashflowMsfoColumn.nominal,
resultIRRGraphPerc: columns?.sumColumn.irr,
resultIRRNominalPerc: columns?.cashflowMsfoColumn.nominal,
resultInsKasko: preparedValues.insuranceKasko,
resultInsOsago: preparedValues.insuranceOsago,
resultLastPayment: last(columns?.sumWithVatColumn?.values) || 0,
@ -70,9 +81,9 @@ export function transformCalculateResults({
(preparedValues.ratBonus + preparedValues.nsBonus + preparedValues.nsibBonus) *
preparedValues.marketRate *
preparedValues.districtRate +
Math.abs(columns.npvBonusExpensesColumn.values[0]) +
Math.abs(columns?.npvBonusExpensesColumn.values[0]) +
Math.abs(
columns.extraBonusSumColumn.values[0] +
columns?.extraBonusSumColumn.values[0] +
preparedValues.importerSum +
preparedValues.agentsSum +
preparedValues.deliverySum +
@ -86,7 +97,7 @@ export function transformCalculateResults({
inputValues.importProgramSum,
resultPriceUpPr: postValues.priceUP_Year_PR,
resultTerm: preparedValues.nmper,
resultTotalGraphwithNDS: columns.sumWithVatColumn.values[0] - inputValues.subsidySum,
resultTotalGraphwithNDS: columns?.sumWithVatColumn.values[0] - inputValues.subsidySum,
};
const values: OutputData['values'] = {

View File

@ -46,7 +46,7 @@ const defaultInsurance = {
};
const defaultFingap = { keys: [] };
const defaultPayments = { values: [] };
const defaultPayments = { values: [], sums: [] };
const { URL_CRM_DOWNLOADKP_BASE } = getUrls();

View File

@ -1,6 +1,12 @@
import type { ResultValues } from './types';
export const defaultResultsValues: ResultValues = {
_resultContractEconomy: 0,
_resultContractEconomyWithVAT: 0,
_resultPi: 0,
_resultSumCredit: 0,
_resultSumCreditPayment: 0,
_resultVatRecoverable: 0,
resultAB_FL: 0,
resultAB_UL: 0,
resultBonusDopProd: 0,

View File

@ -13,6 +13,18 @@ export function useRowValue(index) {
return [storeValue, setStoreValue];
}
export function useRowSum(index) {
const { $tables } = useStore();
const storeValue = computed(() => $tables.payments.getSum(index)).get();
function setStoreValue(value) {
$tables.payments.setSum(index, value);
}
return [storeValue, setStoreValue];
}
export function useRowStatus(index) {
const { $tables } = useStore();

View File

@ -10,6 +10,7 @@ export default class PaymentsTable {
private root: RootStore;
public validation: Validation;
public values: IObservableArray<number>;
public sums: IObservableArray<number>;
private statuses: IObservableArray<Status>;
private overridedStatus: IObservableValue<Status | undefined>;
@ -23,6 +24,7 @@ export default class PaymentsTable {
);
this.values = observable<number>([]);
this.sums = observable<number>([]);
this.statuses = observable<Status>([]);
this.overridedStatus = observable.box(undefined);
@ -36,6 +38,7 @@ export default class PaymentsTable {
() => this.values.length,
(length) => {
this.statuses.length = length;
this.sums.length = length;
}
);
}
@ -52,6 +55,14 @@ export default class PaymentsTable {
this.values[index] = value;
};
public getSum(index: number) {
return this.sums[index];
}
public setSum = (index: number, sum: number) => {
this.sums[index] = sum;
};
public setValues = (values: number[]) => {
this.values.replace(values);
};

View File

@ -27,11 +27,13 @@ export function disposableReaction<T, FireImmediately extends boolean = false>(
if (disposer !== undefined) disposer();
cleanDisposer();
} else {
disposer = reaction(
expression,
effect,
reactionOpts ? omit(reactionOpts, ['fireImmediately']) : undefined
);
setTimeout(() => {
disposer = reaction(
expression,
effect,
reactionOpts ? omit(reactionOpts, ['fireImmediately']) : undefined
);
}, 100);
}
});
}

View File

@ -0,0 +1 @@
export * from 'antd';