feat: import reports from Excel
The /Import/StroyBot/Reports endpoint only validates the file, so the check now runs as soon as a file is picked. When there are no errors, "Import" builds the reports from the ids in the response and saves them with the same Dataverse code as the report form: one report per date, company, shift and object; resources nested under their work; idle and repair hours as separate rows. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import { ImportWorksPage } from '../pages/import/ImportWorksPage';
|
||||
import { ResourcesPage } from '../pages/resources/ResourcesPage';
|
||||
import { BinderPage } from '../pages/binder/BinderPage';
|
||||
import { WeatherPage } from '../pages/weather/WeatherPage';
|
||||
import { ReportImportPage } from '../pages/reportImport/ReportImportPage';
|
||||
|
||||
/** Показывает страницу текущего раздела (раздел берётся из ?page=). */
|
||||
export const PageOutlet: React.FC = () => {
|
||||
@@ -31,6 +32,8 @@ export const PageOutlet: React.FC = () => {
|
||||
return <BinderPage />;
|
||||
case 'weather':
|
||||
return <WeatherPage />;
|
||||
case 'reportImport':
|
||||
return <ReportImportPage />;
|
||||
case 'hub':
|
||||
default:
|
||||
return <HubPage />;
|
||||
|
||||
@@ -11,6 +11,7 @@ describe('buildSidebarItems', () => {
|
||||
'objects',
|
||||
'reports',
|
||||
'report',
|
||||
'reportImport',
|
||||
'import',
|
||||
'resources',
|
||||
'binder'
|
||||
|
||||
@@ -15,6 +15,7 @@ export const NAV_ITEMS: INavItem[] = [
|
||||
{ page: 'objects', title: 'Объекты', icon: 'folder', needsProject: true },
|
||||
{ page: 'reports', title: 'Отчёты по проекту', icon: 'clipboard', needsProject: true },
|
||||
{ page: 'report', title: 'Отправить отчёт', icon: 'send', needsProject: true },
|
||||
{ page: 'reportImport', title: 'Импорт отчёта из Excel', icon: 'upload', needsProject: true },
|
||||
{ page: 'import', title: 'Загрузить работы из сметы', icon: 'download', needsProject: true },
|
||||
{ page: 'resources', title: 'Ресурсы проекта', icon: 'people', needsProject: true },
|
||||
{ page: 'binder', title: 'Привязка к справочнику', icon: 'swap', needsProject: true }
|
||||
|
||||
@@ -119,4 +119,10 @@ describe('isSectionAvailable', () => {
|
||||
expect(isSectionAvailable('report', current)).toBe(true);
|
||||
expect(isSectionAvailable('binder', current)).toBe(true);
|
||||
});
|
||||
|
||||
it('импорт отчёта из Excel — по тем же правилам, что «Отправить отчёт»', () => {
|
||||
expect(isSectionAvailable('reportImport', project({ status: 'текущий', canEdit: true }))).toBe(true);
|
||||
expect(isSectionAvailable('reportImport', project({ status: 'текущий', canEdit: false }))).toBe(false);
|
||||
expect(isSectionAvailable('reportImport', project({ status: 'завершён', canEdit: true }))).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -73,6 +73,7 @@ export function getStatusKind(status: string | undefined): ProjectStatusKind {
|
||||
* - архивный проект — закрыто всё (кроме архива, он не раздел приложения);
|
||||
* - завершён — нельзя «Отправить отчёт»;
|
||||
* - нет права edit0 — нельзя «Отправить отчёт».
|
||||
* Импорт отчёта из Excel создаёт отчёты — те же правила, что у «Отправить отчёт».
|
||||
* Привязка к справочнику — только с правом редактирования (решение при объединении).
|
||||
*/
|
||||
export function isSectionAvailable(page: PageId, project: IAccessibleProject): boolean {
|
||||
@@ -80,7 +81,7 @@ export function isSectionAvailable(page: PageId, project: IAccessibleProject): b
|
||||
|
||||
const kind = getStatusKind(project.status);
|
||||
if (kind === 'archive') return false;
|
||||
if (page === 'report') return kind !== 'done' && project.canEdit;
|
||||
if (page === 'report' || page === 'reportImport') return kind !== 'done' && project.canEdit;
|
||||
if (page === 'binder') return project.canEdit;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@ export const PAGE_IDS = [
|
||||
'import',
|
||||
'resources',
|
||||
'binder',
|
||||
'weather'
|
||||
'weather',
|
||||
'reportImport'
|
||||
] as const;
|
||||
|
||||
export type PageId = (typeof PAGE_IDS)[number];
|
||||
|
||||
Reference in New Issue
Block a user