store: консолидация открытой версии и подпись консолидации у файла (#26)
Чистые функции findCurrentConsolidation, isInWork, consolidationLabel и хук useCurrentConsolidation; FileOut.consolidation_id; тесты vitest. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
490113cb06
commit
5b7b02a3f2
@ -35,6 +35,7 @@ describe('hasPendingFiles', () => {
|
||||
version_no: 1,
|
||||
size_bytes: null,
|
||||
uploaded_at: null,
|
||||
consolidation_id: null,
|
||||
job: null,
|
||||
documents: [],
|
||||
});
|
||||
|
||||
84
src/store/slices/consolidations/selectors.test.ts
Normal file
84
src/store/slices/consolidations/selectors.test.ts
Normal file
@ -0,0 +1,84 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import type { IConsolidation } from '../../../types/consolidations/consolidations';
|
||||
import { findCurrentConsolidation, isInWork } from './selectors';
|
||||
|
||||
const cons: IConsolidation[] = [
|
||||
{
|
||||
consolidation_id: 'c-2024q3',
|
||||
year: 2024,
|
||||
quarter: 'Q3',
|
||||
reporting_date: '2024-10-01',
|
||||
versions: [
|
||||
{
|
||||
id: 'v1',
|
||||
version_no: 1,
|
||||
status: 'VERIFIED',
|
||||
scenario: 'CREATE',
|
||||
approach: 'BASIC',
|
||||
lock: null,
|
||||
created_at: null,
|
||||
members_count: 2,
|
||||
},
|
||||
{
|
||||
id: 'v2',
|
||||
version_no: 2,
|
||||
status: 'INITIATED',
|
||||
scenario: 'CREATE',
|
||||
approach: 'BASIC',
|
||||
lock: null,
|
||||
created_at: null,
|
||||
members_count: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
consolidation_id: 'c-2024q4',
|
||||
year: 2024,
|
||||
quarter: 'Q4',
|
||||
reporting_date: '2025-01-01',
|
||||
versions: [
|
||||
{
|
||||
id: 'v3',
|
||||
version_no: 1,
|
||||
status: 'CANCELLED',
|
||||
scenario: 'CREATE',
|
||||
approach: 'BASIC',
|
||||
lock: null,
|
||||
created_at: null,
|
||||
members_count: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
describe('findCurrentConsolidation', () => {
|
||||
it('находит консолидацию и статус версии по id версии', () => {
|
||||
expect(findCurrentConsolidation(cons, 'v2')).toEqual({
|
||||
consolidation_id: 'c-2024q3',
|
||||
year: 2024,
|
||||
quarter: 'Q3',
|
||||
version_status: 'INITIATED',
|
||||
});
|
||||
expect(findCurrentConsolidation(cons, 'v3')).toEqual({
|
||||
consolidation_id: 'c-2024q4',
|
||||
year: 2024,
|
||||
quarter: 'Q4',
|
||||
version_status: 'CANCELLED',
|
||||
});
|
||||
});
|
||||
it('null без версии, при неизвестной версии и при пустом списке (прямая ссылка до загрузки)', () => {
|
||||
expect(findCurrentConsolidation(cons, null)).toBeNull();
|
||||
expect(findCurrentConsolidation(cons, 'nope')).toBeNull();
|
||||
expect(findCurrentConsolidation([], 'v2')).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('isInWork', () => {
|
||||
it('в работе — три статуса', () => {
|
||||
expect(isInWork('INITIATED')).toBe(true);
|
||||
expect(isInWork('DOCUMENTS_PROCESSING')).toBe(true);
|
||||
expect(isInWork('DATA_CORRECTION')).toBe(true);
|
||||
expect(isInWork('VERIFIED')).toBe(false);
|
||||
expect(isInWork('CANCELLED')).toBe(false);
|
||||
});
|
||||
});
|
||||
31
src/store/slices/consolidations/selectors.ts
Normal file
31
src/store/slices/consolidations/selectors.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import type { ConsStatus, QuarterEnum } from '../../../types/consolidations/common_types';
|
||||
import type { IConsolidation } from '../../../types/consolidations/consolidations';
|
||||
import { useAppSelector } from '../../store';
|
||||
|
||||
/** Консолидация открытой версии и статус этой версии (design D-1): выводится из списка ГК, в сторе не хранится. */
|
||||
export interface CurrentConsolidation {
|
||||
consolidation_id: string;
|
||||
year: number;
|
||||
quarter: QuarterEnum;
|
||||
version_status: ConsStatus;
|
||||
}
|
||||
|
||||
/** Статусы «в работе» (§9.1): только в них разрешена загрузка файлов в консолидацию. */
|
||||
export const IN_WORK_STATUSES: ReadonlySet<ConsStatus> = new Set<ConsStatus>(['INITIATED', 'DOCUMENTS_PROCESSING', 'DATA_CORRECTION']);
|
||||
|
||||
export const isInWork = (status: ConsStatus): boolean => IN_WORK_STATUSES.has(status);
|
||||
|
||||
export function findCurrentConsolidation(consolidations: IConsolidation[], versionId: string | null): CurrentConsolidation | null {
|
||||
if (!versionId) return null;
|
||||
for (const c of consolidations) {
|
||||
const version = c.versions.find((v) => v.id === versionId);
|
||||
if (version) return { consolidation_id: c.consolidation_id, year: c.year, quarter: c.quarter, version_status: version.status };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function useCurrentConsolidation(): CurrentConsolidation | null {
|
||||
const consolidations = useAppSelector((s) => s.consolidations.consolidations);
|
||||
const versionId = useAppSelector((s) => s.consolidations.current_version_id);
|
||||
return findCurrentConsolidation(consolidations, versionId);
|
||||
}
|
||||
@ -63,6 +63,8 @@ export interface FileOut {
|
||||
version_no: number;
|
||||
size_bytes: number | null;
|
||||
uploaded_at: string | null;
|
||||
/** консолидация, в контексте которой загружен файл (v5.18); null — без контекста */
|
||||
consolidation_id: string | null;
|
||||
job: JobBrief | null;
|
||||
documents: DocumentBrief[];
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import type { Approach, ConsRussianStatus, ConsStatus, LockOut, QuarterEnum, Scenario } from './common_types';
|
||||
|
||||
interface IConsolidationVersion {
|
||||
export interface IConsolidationVersion {
|
||||
id: string;
|
||||
version_no: number;
|
||||
status: ConsStatus;
|
||||
|
||||
25
src/widgets/FilesDrawer/consolidationLabel.test.ts
Normal file
25
src/widgets/FilesDrawer/consolidationLabel.test.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import type { IConsolidation } from '../../types/consolidations/consolidations';
|
||||
import { consolidationLabel } from './consolidationLabel';
|
||||
|
||||
const cons: IConsolidation[] = [
|
||||
{ consolidation_id: 'c-2024q3', year: 2024, quarter: 'Q3', reporting_date: '2024-10-01', versions: [] },
|
||||
{ consolidation_id: 'c-2025q1', year: 2025, quarter: 'Q1', reporting_date: '2025-04-01', versions: [] },
|
||||
];
|
||||
|
||||
describe('consolidationLabel', () => {
|
||||
it('файл текущей консоли — без подписи', () => {
|
||||
expect(consolidationLabel('c-2024q3', cons, 'c-2024q3')).toBeNull();
|
||||
});
|
||||
it('другая консоль из списка — год и квартал', () => {
|
||||
expect(consolidationLabel('c-2025q1', cons, 'c-2024q3')).toBe('2025 К1');
|
||||
});
|
||||
it('без контекста и неизвестный id', () => {
|
||||
expect(consolidationLabel(null, cons, 'c-2024q3')).toBe('вне консолидации');
|
||||
expect(consolidationLabel('ghost', cons, 'c-2024q3')).toBe('другая консолидация');
|
||||
});
|
||||
it('без текущей консоли подпись есть у всех, кроме null-текущей', () => {
|
||||
expect(consolidationLabel('c-2024q3', cons, null)).toBe('2024 К3');
|
||||
expect(consolidationLabel(null, cons, null)).toBe('вне консолидации');
|
||||
});
|
||||
});
|
||||
14
src/widgets/FilesDrawer/consolidationLabel.ts
Normal file
14
src/widgets/FilesDrawer/consolidationLabel.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import type { IConsolidation } from '../../types/consolidations/consolidations';
|
||||
import { quarterShortLabel } from '../../utils/labels';
|
||||
|
||||
/** Подпись консолидации у файла в режиме «Все документы организации» (design D-4): null — файл текущей консоли. */
|
||||
export function consolidationLabel(
|
||||
fileConsolidationId: string | null,
|
||||
consolidations: IConsolidation[],
|
||||
currentConsolidationId: string | null,
|
||||
): string | null {
|
||||
if (fileConsolidationId === null) return 'вне консолидации';
|
||||
if (fileConsolidationId === currentConsolidationId) return null;
|
||||
const found = consolidations.find((c) => c.consolidation_id === fileConsolidationId);
|
||||
return found ? `${found.year} ${quarterShortLabel(found.quarter)}` : 'другая консолидация';
|
||||
}
|
||||
@ -26,6 +26,7 @@ const file = (over: Partial<FileOut> = {}): FileOut => ({
|
||||
version_no: 1,
|
||||
size_bytes: 10,
|
||||
uploaded_at: '2024-03-12T10:00:00Z',
|
||||
consolidation_id: null,
|
||||
job: null,
|
||||
documents: [],
|
||||
...over,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user