diff --git a/client/Dockerfile b/client/Dockerfile index 345f01a..a2e623a 100644 --- a/client/Dockerfile +++ b/client/Dockerfile @@ -1,4 +1,4 @@ -FROM node:20-alpine AS build +FROM node:20-bookworm-slim AS build WORKDIR /app diff --git a/client/src/dataProvider.ts b/client/src/dataProvider.ts index 27240c1..3ebec51 100644 --- a/client/src/dataProvider.ts +++ b/client/src/dataProvider.ts @@ -54,6 +54,26 @@ function appendSearchParam( searchParams.append(key, String(value)); } +function parseListBody(json: unknown): { rows: unknown[]; totalHint?: number } { + if (Array.isArray(json)) { + return { rows: json }; + } + if ( + json !== null && + typeof json === "object" && + "data" in json && + Array.isArray((json as { data: unknown }).data) + ) { + const body = json as { data: unknown[]; total?: unknown }; + const totalHint = + typeof body.total === "number" && Number.isFinite(body.total) + ? body.total + : undefined; + return { rows: body.data, totalHint }; + } + return { rows: [] }; +} + function buildListUrl(resource: string, params: any): string { const resourcePath = resource === "equipment" ? "equipments" : resource; const searchParams = new URLSearchParams(); @@ -83,16 +103,16 @@ export const dataProvider: DataProvider = { return { data: [json], total: 1 }; } const { json, headers } = await fetchJson(buildListUrl(resource, params)); + const { rows, totalHint } = parseListBody(json); const contentRange = headers.get("Content-Range"); const total = contentRange ? Number( contentRange.split("/").pop() ?? - (Array.isArray(json) ? json.length : 0), + totalHint ?? + rows.length, ) - : Array.isArray(json) - ? json.length - : 0; - return { data: Array.isArray(json) ? json : [], total }; + : (totalHint ?? rows.length); + return { data: rows as any[], total }; }, getOne: async (resource, params) => { const resourcePath = resource === "equipment" ? "equipments" : resource; diff --git a/client/src/resources/shared/enums.ts b/client/src/resources/shared/enums.ts index fb65721..e4c77b1 100644 --- a/client/src/resources/shared/enums.ts +++ b/client/src/resources/shared/enums.ts @@ -7,28 +7,35 @@ export const equipmentStatusChoices = [ export const laborOperationChoices = ["Manual", "MachineManual", "Machine"].map( (value) => ({ id: value, name: value }), ); + +/** id = Prisma/API wire value; name = human label (matches DB enum @map). */ export const periodicityChoices = [ - "Ежедневное", - "Еженедельное", - "Ежемесячное", - "Полугодовое", - "Годовое", -].map((value) => ({ id: value, name: value })); -export const roleChoices = ["Исполнитель", "Подписант", "Пользователь"].map( - (value) => ({ id: value, name: value }), -); + { id: "EZHEDNEVNOE", name: "Ежедневное" }, + { id: "EZHENEDELNOE", name: "Еженедельное" }, + { id: "EZHEMESYACHNOE", name: "Ежемесячное" }, + { id: "POLUGODOVOE", name: "Полугодовое" }, + { id: "GODOVOE", name: "Годовое" }, +]; + +export const roleChoices = [ + { id: "ISPOLNITEL", name: "Исполнитель" }, + { id: "PODPISANT", name: "Подписант" }, + { id: "POLZOVATEL", name: "Пользователь" }, +]; + export const categoryPartChoices = [ - "Расходник", - "Запчасть", - "Инструмент", - "Спецодежда", -].map((value) => ({ id: value, name: value })); + { id: "RASKHODNIK", name: "Расходник" }, + { id: "ZAPCHAST", name: "Запчасть" }, + { id: "INSTRUMENT", name: "Инструмент" }, + { id: "SPETSODEZHDA", name: "Спецодежда" }, +]; + export const equipmentTypeChoices = [ - "Производственное", - "Энергетическое", - "Насосное", - "Компрессорное", -].map((value) => ({ id: value, name: value })); + { id: "PROIZVODSTVENNOE", name: "Производственное" }, + { id: "ENERGETICHESKOE", name: "Энергетическое" }, + { id: "NASOSNOE", name: "Насосное" }, + { id: "KOMPRESSORNOE", name: "Компрессорное" }, +]; export const equipmentOptionText = ( record?: Record | null, diff --git a/server/docker-entrypoint.sh b/server/docker-entrypoint.sh index 828a728..918fba0 100755 --- a/server/docker-entrypoint.sh +++ b/server/docker-entrypoint.sh @@ -12,7 +12,7 @@ fi export PRISMA_HIDE_UPDATE_MESSAGE=1 run_migrate() { - "$PRISMA_BIN" migrate deploy --schema "$SCHEMA" --skip-generate + "$PRISMA_BIN" migrate deploy --schema "$SCHEMA" } echo "Applying database migrations (schema=$SCHEMA)..." @@ -38,4 +38,4 @@ while [ "$i" -lt 15 ]; do done echo "Starting NestJS..." -exec node dist/main.js +exec node dist/src/main.js diff --git a/server/package.json b/server/package.json index 4f1a8d1..ffda97f 100644 --- a/server/package.json +++ b/server/package.json @@ -11,7 +11,7 @@ "start": "nest start", "start:dev": "nest start --watch", "start:debug": "nest start --debug --watch", - "start:prod": "node dist/main", + "start:prod": "node dist/src/main.js", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", "test": "jest", "test:watch": "jest --watch", diff --git a/server/src/modules/shared/dsl-enums.ts b/server/src/modules/shared/dsl-enums.ts index cc80170..7606217 100644 --- a/server/src/modules/shared/dsl-enums.ts +++ b/server/src/modules/shared/dsl-enums.ts @@ -11,30 +11,31 @@ export enum laborOperation { Machine = 'Machine', } +/** Values must match Prisma `$Enums` (schema variant names), not DB @map labels. */ export enum EnumPeriodicityTO { - EZHEDNEVNOE = 'Ежедневное', - EZHENEDELNOE = 'Еженедельное', - EZHEMESYACHNOE = 'Ежемесячное', - POLUGODOVOE = 'Полугодовое', - GODOVOE = 'Годовое', + EZHEDNEVNOE = 'EZHEDNEVNOE', + EZHENEDELNOE = 'EZHENEDELNOE', + EZHEMESYACHNOE = 'EZHEMESYACHNOE', + POLUGODOVOE = 'POLUGODOVOE', + GODOVOE = 'GODOVOE', } export enum Role { - ISPOLNITEL = 'Исполнитель', - PODPISANT = 'Подписант', - POLZOVATEL = 'Пользователь', + ISPOLNITEL = 'ISPOLNITEL', + PODPISANT = 'PODPISANT', + POLZOVATEL = 'POLZOVATEL', } export enum CategoryPart { - RASKHODNIK = 'Расходник', - ZAPCHAST = 'Запчасть', - INSTRUMENT = 'Инструмент', - SPETSODEZHDA = 'Спецодежда', + RASKHODNIK = 'RASKHODNIK', + ZAPCHAST = 'ZAPCHAST', + INSTRUMENT = 'INSTRUMENT', + SPETSODEZHDA = 'SPETSODEZHDA', } export enum EquipmentType { - PROIZVODSTVENNOE = 'Производственное', - ENERGETICHESKOE = 'Энергетическое', - NASOSNOE = 'Насосное', - KOMPRESSORNOE = 'Компрессорное', + PROIZVODSTVENNOE = 'PROIZVODSTVENNOE', + ENERGETICHESKOE = 'ENERGETICHESKOE', + NASOSNOE = 'NASOSNOE', + KOMPRESSORNOE = 'KOMPRESSORNOE', }