fix(number-fields): избегаем потери точности длинных чисел
- number-поля теперь рендерятся как text + inputMode=numeric, чтобы браузер не округлял значения через input type=number - пробелы при вставке в number-поля удаляются - бэкенд нормализует значения number-полей в строку перед сохранением - добавлен хелпер normalizeFieldValueForStorage Closes: искажение расчётного счёта и других длинных числовых полей
This commit is contained in:
109
server/storage/user-statuses.storage.ts
Normal file
109
server/storage/user-statuses.storage.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
import { userStatuses, users, type UserStatus, type InsertUserStatus } from "@shared/schema";
|
||||
import { db } from "../db";
|
||||
import { eq, and, asc, sql } from "drizzle-orm";
|
||||
|
||||
export class UserStatusesStorage {
|
||||
async getById(id: number): Promise<UserStatus | undefined> {
|
||||
const [status] = await db.select().from(userStatuses).where(eq(userStatuses.id, id));
|
||||
return status || undefined;
|
||||
}
|
||||
|
||||
async listByOrganization(organizationId: number): Promise<UserStatus[]> {
|
||||
return await db
|
||||
.select()
|
||||
.from(userStatuses)
|
||||
.where(eq(userStatuses.organizationId, organizationId))
|
||||
.orderBy(asc(userStatuses.position), asc(userStatuses.name));
|
||||
}
|
||||
|
||||
async getDefaultByOrganization(organizationId: number): Promise<UserStatus | undefined> {
|
||||
const [status] = await db
|
||||
.select()
|
||||
.from(userStatuses)
|
||||
.where(and(eq(userStatuses.organizationId, organizationId), eq(userStatuses.isDefault, true)))
|
||||
.limit(1);
|
||||
return status || undefined;
|
||||
}
|
||||
|
||||
async create(data: InsertUserStatus): Promise<UserStatus> {
|
||||
const { organizationId, isDefault } = data;
|
||||
|
||||
if (isDefault) {
|
||||
await db
|
||||
.update(userStatuses)
|
||||
.set({ isDefault: false })
|
||||
.where(eq(userStatuses.organizationId, organizationId));
|
||||
}
|
||||
|
||||
const [status] = await db.insert(userStatuses).values(data).returning();
|
||||
return status;
|
||||
}
|
||||
|
||||
async update(id: number, organizationId: number, data: Partial<InsertUserStatus>): Promise<UserStatus> {
|
||||
if (data.isDefault) {
|
||||
await db
|
||||
.update(userStatuses)
|
||||
.set({ isDefault: false })
|
||||
.where(eq(userStatuses.organizationId, organizationId));
|
||||
}
|
||||
|
||||
const [status] = await db
|
||||
.update(userStatuses)
|
||||
.set(data)
|
||||
.where(and(eq(userStatuses.id, id), eq(userStatuses.organizationId, organizationId)))
|
||||
.returning();
|
||||
return status;
|
||||
}
|
||||
|
||||
async delete(id: number, organizationId: number): Promise<void> {
|
||||
const status = await this.getById(id);
|
||||
if (!status || status.organizationId !== organizationId) return;
|
||||
|
||||
const defaultStatus = await this.getDefaultByOrganization(organizationId);
|
||||
|
||||
await db.transaction(async (tx) => {
|
||||
if (defaultStatus && defaultStatus.id !== id) {
|
||||
await tx
|
||||
.update(users)
|
||||
.set({ statusId: defaultStatus.id })
|
||||
.where(eq(users.statusId, id));
|
||||
} else {
|
||||
await tx
|
||||
.update(users)
|
||||
.set({ statusId: null })
|
||||
.where(eq(users.statusId, id));
|
||||
}
|
||||
|
||||
await tx
|
||||
.delete(userStatuses)
|
||||
.where(and(eq(userStatuses.id, id), eq(userStatuses.organizationId, organizationId)));
|
||||
});
|
||||
}
|
||||
|
||||
async ensureDefaultStatus(organizationId: number): Promise<UserStatus> {
|
||||
const existing = await this.getDefaultByOrganization(organizationId);
|
||||
if (existing) return existing;
|
||||
|
||||
const [status] = await db
|
||||
.insert(userStatuses)
|
||||
.values({
|
||||
organizationId,
|
||||
name: "Зарегистрирован",
|
||||
color: "#e5e7eb",
|
||||
isDefault: true,
|
||||
position: 0,
|
||||
})
|
||||
.returning();
|
||||
return status;
|
||||
}
|
||||
|
||||
async getUsageCount(statusId: number): Promise<number> {
|
||||
const [result] = await db
|
||||
.select({ total: sql<number>`count(*)::int` })
|
||||
.from(users)
|
||||
.where(eq(users.statusId, statusId));
|
||||
return result?.total || 0;
|
||||
}
|
||||
}
|
||||
|
||||
export const userStatusesStorage = new UserStatusesStorage();
|
||||
Reference in New Issue
Block a user