merge release/calc-18_season-graphs

This commit is contained in:
vchikalkin 2021-03-22 12:35:28 +03:00 committed by Chika
parent bfd6f1d1f9
commit ed80a94791
10 changed files with 234 additions and 121 deletions

View File

@ -96,7 +96,7 @@ const sections: ISection[] = [
'radioGraphType',
'selectSeasonType',
'tbxParmentsDecreasePercent',
// 'selectHighSeasonStart',
'selectHighSeasonStart',
],
layout: {
newLine: true,

View File

@ -1,6 +1,10 @@
import elementsTitles, { tablesTitles } from 'client/Containers/Calculation/lib/elements/titles';
import { TableNames } from 'core/types/Calculation/Store/tables';
import elementsTitles, {
tablesTitles,
} from 'client/Containers/Calculation/lib/elements/titles';
import CalculationStore from 'client/stores/CalculationStore';
import { toJS } from 'mobx';
import { omit } from 'lodash';
export default () => {
let invalidElements: string[] = [];
@ -14,9 +18,11 @@ export default () => {
let invalidTables: string[] = [];
const { tables: storeTables } = CalculationStore;
const tables = toJS(storeTables);
const tables = omit(toJS(storeTables), tablesExclusion);
Object.keys(tables).forEach(tableName => {
if (
!tables[tableName].rows ||
tables[tableName].rows.length === 0 ||
tables[tableName].rows.some(row =>
Object.keys(row).some(propName => row[propName].validation === false),
)
@ -27,3 +33,5 @@ export default () => {
return { invalidElements, invalidTables };
};
const tablesExclusion: TableNames[] = ['tableResults'];

View File

@ -1,6 +1,10 @@
import { elementsValues } from 'client/Containers/Calculation/lib/elements/values';
import { shiftRight } from 'core/tools/array';
import { TElements } from 'core/types/Calculation/Store/elements';
import { isEqual } from 'lodash';
import CalculationStore from '../../..';
import valuesConstants from 'core/constants/values';
const { PERIODS_NUMBER } = valuesConstants;
const VALIDATIONS = {
IS_NULL: valueName =>
@ -27,6 +31,12 @@ const elementsValidations: TElements<any> = {
selectRegistration: VALIDATIONS.IS_NULL,
selectLeaseObjectCategory: VALIDATIONS.IS_NULL,
tbxLeasingPeriod: valueName => CalculationStore.getValue(valueName) < 7,
selectSeasonType: valueName =>
CalculationStore.getValue('graphType') === 100000003 &&
VALIDATIONS.IS_NULL(valueName),
selectHighSeasonStart: valueName =>
CalculationStore.getValue('graphType') === 100000003 &&
VALIDATIONS.IS_NULL(valueName),
tbxLeaseObjectPrice: VALIDATIONS.LESS_OR_EQUALS_ZERO,
tbxLastPaymentPerc: VALIDATIONS.IS_NULL,
tbxLastPaymentRub: VALIDATIONS.IS_NULL,
@ -35,7 +45,7 @@ const elementsValidations: TElements<any> = {
tbxLeaseObjectCount: VALIDATIONS.LESS_OR_EQUALS_ZERO,
selectQuote: valueName =>
CalculationStore.getValue('recalcWithRevision') === true &&
!CalculationStore.getValue(valueName),
VALIDATIONS.IS_NULL(valueName),
};
const validateElement = (elementName, condition) => {
@ -91,16 +101,15 @@ const validateInsuranceTable = () => {
const validatePaymentsTable = () => {
const { graphType } = CalculationStore.values;
const payments = CalculationStore.tables.tablePayments.rows;
const payments = CalculationStore.tables.tablePayments.rows.map(
x => x.paymentRelation?.value,
);
switch (graphType) {
case 100000001: {
{
const areMiddleRowsEqual =
new Set(
payments
.slice(1, payments.length - 1)
.map(x => x.paymentRelation?.value),
).size === 1;
new Set(payments.slice(1, payments.length - 1)).size === 1;
CalculationStore.setTableRows(
'tablePayments',
@ -119,9 +128,7 @@ const validatePaymentsTable = () => {
x => x.paymentRelation?.validation === false,
)
) {
const target_payments = payments
.slice(1, 4)
.map(x => x.paymentRelation?.value);
const target_payments = payments.slice(1, 4);
const min = Math.min.apply(Math, target_payments);
const max = Math.max.apply(Math, target_payments);
const areInvalidRows = max - min > 10;
@ -143,9 +150,7 @@ const validatePaymentsTable = () => {
x => x.paymentRelation?.validation === false,
)
) {
const target_payments = payments
.slice(1, payments.length - 1)
.map(x => x.paymentRelation?.value);
const target_payments = payments.slice(1, payments.length - 1);
let pairs_number = 0;
new Set(target_payments).forEach(set_v => {
let setValueCount = 0;
@ -173,10 +178,57 @@ const validatePaymentsTable = () => {
break;
}
case 100000003: {
const { highSeasonStart: highSeasonStartId } = CalculationStore.values;
if (!highSeasonStartId) {
return;
}
const highSeasonStart = parseInt(
CalculationStore.options.selectHighSeasonStart?.find(
x => x.value === highSeasonStartId,
)?.name || '2',
);
const shiftNumber = highSeasonStart - 2;
const middleRows = payments.slice(1, PERIODS_NUMBER + 1);
const unshiftedMiddleRows = shiftRight(middleRows, shiftNumber);
const { seasonType } = CalculationStore.values;
if (!seasonType) {
return;
}
const seasonTypeOptions = CalculationStore.options.selectSeasonType?.find(
x => x.value === seasonType,
);
const startPositions =
seasonTypeOptions && seasonTypeOptions.startPositions;
let stepsValues = [];
for (let i = 0; i < startPositions.length; i++) {
const targetIndex = startPositions[i];
//@ts-ignore
stepsValues.push(unshiftedMiddleRows[targetIndex]);
}
const areCorrectSeasonPayments = isEqual(
stepsValues,
[...stepsValues].sort((a, b) => b - a),
);
CalculationStore.setTableRows(
'tablePayments',
1,
)(
Array.from({ length: PERIODS_NUMBER }, () => ({
paymentRelation: {
validation: areCorrectSeasonPayments,
},
})),
);
break;
}
case 100000004: {
const areMiddleRowsEqual =
new Set(payments.slice(1, 4).map(x => x.paymentRelation?.value))
.size === 1;
const areMiddleRowsEqual = new Set(payments.slice(1, 4)).size === 1;
CalculationStore.setTableRows(
'tablePayments',

View File

@ -735,6 +735,8 @@ const reactionEffects: IReactionEffect[] = [
effect: graphType => {
if (graphType) {
calculationStore.setValue('seasonType', null);
calculationStore.setValue('highSeasonStart', null);
calculationStore.setValue('parmentsDecreasePercent', 50);
switch (graphType) {
case 100000001: {
calculationStore.setStatus(

View File

@ -5,6 +5,8 @@ import { Process } from 'core/types/Calculation/Store/process';
import { ITableCell, TableProps } from 'core/types/Calculation/Store/tables';
import { ElementStatus } from 'core/types/statuses';
import { toJS } from 'mobx';
import valuesConstants from 'core/constants/values';
const { PERIODS_NUMBER } = valuesConstants;
export default [
(calculationStore, calculationProcess) => ({
@ -516,19 +518,20 @@ export default [
const targetSeasonType = calculationStore.options?.selectSeasonType?.find(
x => x?.value === seasonType,
);
const steps: number[] = targetSeasonType && targetSeasonType.steps;
const stepsValues: number[] =
targetSeasonType && targetSeasonType.stepsValues;
const middleRows = Array.from(
{ length: leasingPeriod - 2 },
(_v, i) => {
let value = steps[2];
let value = stepsValues[2];
if (i <= paymentsInStep * 2 - 1) {
value = steps[1];
value = stepsValues[1];
}
if (i <= paymentsInStep - 1) {
value = steps[0];
value = stepsValues[0];
}
return {
@ -540,7 +543,6 @@ export default [
},
);
payments = [...payments, ...middleRows];
} else {
const middleRows = Array.from(
{ length: leasingPeriod - 3 },
@ -602,59 +604,56 @@ export default [
}
case 100000003: {
let HIGH = 100,
MIDDLE = 75,
LOW = 50;
if (!seasonType) {
return;
}
const next_seasonType_option = calculationStore.options.selectSeasonType?.find(
x => x.value === seasonType,
);
const {
//@ts-ignore
startPositions: nextStartPositions,
//@ts-ignore
paymentsInStep: nextPaymentsInStep,
//@ts-ignore
stepsValues: nextStepsValues,
} = next_seasonType_option;
let stepsValues: number[] = nextStepsValues;
const {
seasonType: prevSeasonType,
highSeasonStart: prevHighSeasonStart,
} = prevParams;
if (
prevParams.graphType === nextParams.graphType
// && nextParams.graphType === 100000003
prevParams.graphType === nextParams.graphType &&
prevSeasonType === seasonType &&
prevHighSeasonStart !== highSeasonStart
) {
/**
* FIND PREV HIGH, MIDDLE, LOW
*/
const {
leasingPeriod: prevLeasingPeriod,
seasonType: prevSeasonType,
highSeasonStart: prevHighSeasonStart,
} = prevParams;
const prevPeriodsNumber =
prevLeasingPeriod <= 14 ? prevLeasingPeriod - 2 : 12;
//TODO: change 2 to variable from options selectHighSeasonStart
const prevShiftNumber = prevHighSeasonStart - 2;
let middleRows = prevValues.slice(1, prevPeriodsNumber + 1);
if (middleRows.length < 12) {
middleRows = [
...middleRows,
...Array.from({ length: 12 - middleRows.length }, v => 0),
];
}
let middleRows = prevValues.slice(1, PERIODS_NUMBER + 1);
// prevent unnecessary running shiftRight
if (prevShiftNumber > 0)
middleRows = shiftRight(middleRows, prevShiftNumber);
switch (prevSeasonType) {
// 6/6
case 100000000: {
HIGH = middleRows[0];
LOW = middleRows[6];
break;
}
// 8/4
case 100000001: {
HIGH = middleRows[0];
LOW = middleRows[8];
const prev_seasonType_option = calculationStore.options.selectSeasonType?.find(
x => x.value === prevSeasonType,
);
const prevStartPositions =
prev_seasonType_option && prev_seasonType_option.startPositions;
break;
}
// 4/4/4
case 100000002: {
HIGH = middleRows[0];
MIDDLE = middleRows[4];
LOW = middleRows[8];
break;
}
}
stepsValues = prevStartPositions.map(
startPosition => middleRows[startPosition],
);
/** */
}
@ -662,58 +661,36 @@ export default [
* GENERATE PERIODS
*/
const {
leasingPeriod: nextLeasingPeriod,
seasonType: nextSeasonType,
highSeasonStart: nextHighSeasonStart,
} = nextParams;
const nextPeriodsNumber =
nextLeasingPeriod <= 14 ? nextLeasingPeriod - 2 : 12;
const nextShiftNumber = nextHighSeasonStart - 2;
const nextShiftNumber = highSeasonStart - 2;
let nextPeriods: number[] = [];
switch (nextSeasonType) {
// 6/6
case 100000000: {
nextPeriods = Array.from({ length: 12 }, (v, i) =>
i < 6 ? HIGH : LOW,
);
break;
nextStartPositions.forEach((startPosition, i) => {
for (
let j = startPosition;
j < startPosition + nextPaymentsInStep[i];
j++
) {
nextPeriods[j] = stepsValues[i];
}
// 8/4
case 100000001: {
nextPeriods = Array.from({ length: 12 }, (v, i) =>
i < 8 ? HIGH : LOW,
);
break;
}
// 4/4/4
case 100000002: {
nextPeriods = Array.from(
{ length: 12 },
(v, i) => (i < 4 && HIGH) || (i < 8 && MIDDLE) || LOW,
);
break;
}
}
});
if (nextShiftNumber > 0) {
nextPeriods = shift(nextPeriods, nextShiftNumber);
}
nextPeriods.length = nextPeriodsNumber;
nextPeriods.length = PERIODS_NUMBER;
const middleRows = Array.from(
{ length: nextLeasingPeriod - 2 },
{ length: leasingPeriod - 2 },
(v, i) => {
return {
paymentRelation: {
value:
nextPeriods[
i - nextPeriodsNumber * Math.floor(i / nextPeriodsNumber)
],
i < PERIODS_NUMBER &&
// i - PERIODS_NUMBER * Math.floor(i / PERIODS_NUMBER)
nextPeriods[i],
status:
i < nextPeriodsNumber
i < PERIODS_NUMBER
? ElementStatus.Default
: ElementStatus.Disabled,
},
@ -767,6 +744,7 @@ export default [
calculationStore.setTableRows(
'tablePayments',
0,
true,
)([
...payments,
{

View File

@ -1,8 +1,6 @@
import { TElementFilter } from 'core/types/Calculation/Store/filters';
import { TElements } from 'core/types/Calculation/Store/elements';
const initialFilters: TElements<TElementFilter> = {
radioGraphType: options => options.filter(x => x.value !== 100000003),
};
const initialFilters: TElements<TElementFilter> = {};
export default initialFilters;

View File

@ -85,34 +85,43 @@ const initialOptions: TElements<IBaseOption[]> = {
{
name: '6/6',
value: 100000000,
startPositions: [0, 6],
paymentsInStep: [6, 6],
stepsValues: [100, 50],
},
{
name: '8/4',
value: 100000001,
startPositions: [0, 8],
paymentsInStep: [8, 4],
stepsValues: [100, 50],
},
{
name: '4/4/4',
value: 100000002,
startPositions: [0, 4, 8],
paymentsInStep: [4, 4, 4],
stepsValues: [100, 75, 50],
},
{
name: '100.50.25',
value: 100000003,
steps: [100, 50, 25],
stepsValues: [100, 50, 25],
},
{
name: '100.30.10',
value: 100000004,
steps: [100, 30, 10],
stepsValues: [100, 30, 10],
},
{
name: '100.70.40',
value: 100000005,
steps: [100, 70, 40],
stepsValues: [100, 70, 40],
},
{
name: '100.7.3',
value: 100000006,
steps: [100, 7, 3],
stepsValues: [100, 7, 3],
},
],

View File

@ -1,5 +1,8 @@
import { rotateArrays } from 'core/tools/array';
import { ITable } from 'core/types/Calculation/Store/tables';
import { isEqual } from 'lodash';
import { inRange, isEqual } from 'lodash';
import valuesConstants from 'core/constants/values';
const { PERIODS_NUMBER } = valuesConstants;
const tablePayments: ITable = {
rows: [
@ -52,17 +55,67 @@ const tablePayments: ITable = {
if (graphType === 100000003) {
const { leasingPeriod } = calculationStore.values;
const periodsNumber = leasingPeriod <= 14 ? leasingPeriod - 2 : 12;
if (rowIndex >= 1 && rowIndex <= periodsNumber) {
for (let i = rowIndex; i < leasingPeriod - 1; i += periodsNumber) {
calculationStore.setTableRow(
tableName,
i,
)({
paymentRelation: {
value,
},
});
if (rowIndex >= 1 && rowIndex <= PERIODS_NUMBER) {
const { highSeasonStart } = calculationStore.values;
const highSeasonStartValue = parseInt(
calculationStore.options.selectHighSeasonStart?.find(
x => x.value === highSeasonStart,
)?.name || '2',
),
shiftNumber = highSeasonStartValue - 2;
const seasonTypeOptions = calculationStore.options.selectSeasonType?.find(
x => x.value === seasonType,
);
const startPositions =
seasonTypeOptions && seasonTypeOptions.startPositions,
endPositions =
seasonTypeOptions &&
seasonTypeOptions.paymentsInStep.map(
(x, i) => startPositions[i] + x,
);
const allBoundaries = rotateArrays(startPositions, endPositions);
const withUnshift = n => n - shiftNumber;
const withShift = n => n + shiftNumber;
const withFirstPayment = n => n + 1;
let index;
for (let i = 0; i < allBoundaries.length; i++) {
const [min, max] = allBoundaries[i].map(x => withFirstPayment(x));
let unshiftedRowIndex = withUnshift(rowIndex);
if (unshiftedRowIndex <= 0) {
unshiftedRowIndex += PERIODS_NUMBER;
}
if (inRange(unshiftedRowIndex, min, max)) {
index = i;
break;
}
}
const paymentsInStep =
seasonTypeOptions && seasonTypeOptions.paymentsInStep;
for (
let i =
withFirstPayment(withShift(allBoundaries[index][0])) -
PERIODS_NUMBER;
i < leasingPeriod - 1;
i += PERIODS_NUMBER
) {
const targetStartPosition = i;
for (
let j = targetStartPosition;
j < paymentsInStep[index] + targetStartPosition;
j++
) {
if (j > 0 && j < leasingPeriod - 1)
calculationStore.setTableRow(
tableName,
j,
)({ paymentRelation: { value } });
}
}
}
}

View File

@ -7,4 +7,5 @@ export default {
NDFL: 0.13,
MAX_VEHICLE_MASS: 3500,
MAX_VEHICLE_SEATS: 20,
PERIODS_NUMBER: 12,
};

View File

@ -13,3 +13,15 @@ export function shiftRight(arr, n) {
}
return arr;
}
export function rotateArrays(...arrs) {
let res = [];
for (let i = 0; i < arrs[0].length; i++) {
let boundaries = [];
for (let arr of arrs) {
boundaries.push(arr[i]);
}
res.push(boundaries);
}
return res;
}