fix(number-fields): избегаем потери точности длинных чисел
- number-поля теперь рендерятся как text + inputMode=numeric, чтобы браузер не округлял значения через input type=number - пробелы при вставке в number-поля удаляются - бэкенд нормализует значения number-полей в строку перед сохранением - добавлен хелпер normalizeFieldValueForStorage Closes: искажение расчётного счёта и других длинных числовых полей
This commit is contained in:
43
server/finance/overrides.ts
Normal file
43
server/finance/overrides.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { type Express } from "express";
|
||||
import { query } from "./db-client";
|
||||
import { authenticateToken, requirePermission, type AuthenticatedRequest } from "../middleware/auth.middleware";
|
||||
|
||||
export function registerOverrideRoutes(app: Express): void {
|
||||
// GET /api/overrides?type=income|expense
|
||||
app.get("/api/overrides", authenticateToken, requirePermission('finance.manage'), async (req: AuthenticatedRequest, res) => {
|
||||
try {
|
||||
const type = req.query.type as string;
|
||||
const table = type === "expense" ? "expense_category_overrides" : "income_category_overrides";
|
||||
const result = await query(`SELECT record_id, category_id, created_at FROM "${table}"`);
|
||||
res.json({ success: true, overrides: result.rows });
|
||||
} catch (err: any) {
|
||||
res.status(500).json({ success: false, error: err.message });
|
||||
}
|
||||
});
|
||||
|
||||
// POST /api/overrides
|
||||
app.post("/api/overrides", authenticateToken, requirePermission('finance.manage'), async (req: AuthenticatedRequest, res) => {
|
||||
try {
|
||||
const { type, recordId, categoryId } = req.body;
|
||||
const table = type === "expense" ? "expense_category_overrides" : "income_category_overrides";
|
||||
await query(
|
||||
`INSERT INTO "${table}" (record_id, category_id) VALUES ($1, $2) ON CONFLICT (record_id) DO UPDATE SET category_id = EXCLUDED.category_id`,
|
||||
[recordId, categoryId]
|
||||
);
|
||||
res.json({ success: true });
|
||||
} catch (err: any) {
|
||||
res.status(500).json({ success: false, error: err.message });
|
||||
}
|
||||
});
|
||||
|
||||
// DELETE /api/overrides/:type/:recordId
|
||||
app.delete("/api/overrides/:type/:recordId", authenticateToken, requirePermission('finance.manage'), async (req: AuthenticatedRequest, res) => {
|
||||
try {
|
||||
const table = req.params.type === "expense" ? "expense_category_overrides" : "income_category_overrides";
|
||||
await query(`DELETE FROM "${table}" WHERE record_id = $1`, [req.params.recordId]);
|
||||
res.json({ success: true });
|
||||
} catch (err: any) {
|
||||
res.status(500).json({ success: false, error: err.message });
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user