fix(number-fields): избегаем потери точности длинных чисел

- number-поля теперь рендерятся как text + inputMode=numeric,
  чтобы браузер не округлял значения через input type=number
- пробелы при вставке в number-поля удаляются
- бэкенд нормализует значения number-полей в строку перед сохранением
- добавлен хелпер normalizeFieldValueForStorage

Closes: искажение расчётного счёта и других длинных числовых полей
This commit is contained in:
2026-07-07 21:03:40 +03:00
commit 1f5ecb6da4
1089 changed files with 237546 additions and 0 deletions

View File

@@ -0,0 +1,92 @@
import * as storage from "../storage/documents.storage";
import { db } from "../db";
import { documentSignatures, documentGenerations } from "@shared/schema";
import { eq, and, desc } from "drizzle-orm";
import type { DocumentSignature } from "@shared/schema";
export class SignatureService {
async listByGeneration(generationId: number): Promise<DocumentSignature[]> {
return storage.listDocumentSignatures(generationId);
}
async createPendingSignature(
generationId: number,
signedBy: number,
comment?: string,
): Promise<DocumentSignature> {
// Сбрасываем флаг isCurrent у предыдущих подписей
await db
.update(documentSignatures)
.set({ isCurrent: false })
.where(eq(documentSignatures.documentGenerationId, generationId));
const signature = await storage.createDocumentSignature({
documentGenerationId: generationId,
type: "manual",
status: "pending",
signedBy,
comment,
isCurrent: true,
});
// Обновляем статус генерации
const generation = await storage.getDocumentGeneration(generationId, 0);
if (generation) {
await db
.update(documentGenerations)
.set({ signatureStatus: "pending" })
.where(eq(documentGenerations.id, generationId));
}
return signature;
}
async sign(generationId: number, userId: number, comment?: string): Promise<DocumentSignature> {
// Сбрасываем флаг isCurrent
await db
.update(documentSignatures)
.set({ isCurrent: false })
.where(eq(documentSignatures.documentGenerationId, generationId));
const signature = await storage.createDocumentSignature({
documentGenerationId: generationId,
type: "manual",
status: "signed",
signedBy: userId,
signedAt: new Date(),
comment,
isCurrent: true,
});
await db
.update(documentGenerations)
.set({ signatureStatus: "signed" })
.where(eq(documentGenerations.id, generationId));
return signature;
}
async reject(generationId: number, userId: number, comment?: string): Promise<DocumentSignature> {
await db
.update(documentSignatures)
.set({ isCurrent: false })
.where(eq(documentSignatures.documentGenerationId, generationId));
const signature = await storage.createDocumentSignature({
documentGenerationId: generationId,
type: "manual",
status: "rejected",
signedBy: userId,
signedAt: new Date(),
comment,
isCurrent: true,
});
await db
.update(documentGenerations)
.set({ signatureStatus: "unsigned" })
.where(eq(documentGenerations.id, generationId));
return signature;
}
}