fix(number-fields): избегаем потери точности длинных чисел
- number-поля теперь рендерятся как text + inputMode=numeric, чтобы браузер не округлял значения через input type=number - пробелы при вставке в number-поля удаляются - бэкенд нормализует значения number-полей в строку перед сохранением - добавлен хелпер normalizeFieldValueForStorage Closes: искажение расчётного счёта и других длинных числовых полей
This commit is contained in:
98
migrations/0019_finance_tables.sql
Normal file
98
migrations/0019_finance_tables.sql
Normal file
@@ -0,0 +1,98 @@
|
||||
-- Finance module tables
|
||||
|
||||
CREATE TABLE IF NOT EXISTS income_categories (
|
||||
id SERIAL PRIMARY KEY,
|
||||
organization_id INTEGER NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
tree_id UUID NOT NULL DEFAULT gen_random_uuid(),
|
||||
name VARCHAR(200) NOT NULL,
|
||||
categories JSONB NOT NULL DEFAULT '[]',
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS income_categories_org_tree_idx ON income_categories(organization_id, tree_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS expense_categories (
|
||||
id SERIAL PRIMARY KEY,
|
||||
organization_id INTEGER NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
tree_id UUID NOT NULL DEFAULT gen_random_uuid(),
|
||||
name VARCHAR(200) NOT NULL,
|
||||
categories JSONB NOT NULL DEFAULT '[]',
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS expense_categories_org_tree_idx ON expense_categories(organization_id, tree_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS income_category_overrides (
|
||||
id SERIAL PRIMARY KEY,
|
||||
organization_id INTEGER NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
record_id VARCHAR(100) NOT NULL,
|
||||
category_id VARCHAR(100) NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW(),
|
||||
UNIQUE(organization_id, record_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS income_overrides_org_record_idx ON income_category_overrides(organization_id, record_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS expense_category_overrides (
|
||||
id SERIAL PRIMARY KEY,
|
||||
organization_id INTEGER NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
record_id VARCHAR(100) NOT NULL,
|
||||
category_id VARCHAR(100) NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW(),
|
||||
UNIQUE(organization_id, record_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS expense_overrides_org_record_idx ON expense_category_overrides(organization_id, record_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS auto_detect_trees (
|
||||
id SERIAL PRIMARY KEY,
|
||||
organization_id INTEGER NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
context VARCHAR(20) NOT NULL CHECK (context IN ('income', 'expense')),
|
||||
tree_id UUID NOT NULL DEFAULT gen_random_uuid(),
|
||||
name VARCHAR(200) NOT NULL,
|
||||
config JSONB NOT NULL DEFAULT '{}',
|
||||
is_primary BOOLEAN NOT NULL DEFAULT false,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW(),
|
||||
UNIQUE(organization_id, context, tree_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS auto_detect_trees_org_idx ON auto_detect_trees(organization_id, context);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS node_tags (
|
||||
id SERIAL PRIMARY KEY,
|
||||
organization_id INTEGER NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
color VARCHAR(20) NOT NULL DEFAULT '#2563eb',
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
UNIQUE(organization_id, name)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS node_tags_org_idx ON node_tags(organization_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS node_tag_assignments (
|
||||
id SERIAL PRIMARY KEY,
|
||||
organization_id INTEGER NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
node_id VARCHAR(100) NOT NULL,
|
||||
tag_id INTEGER NOT NULL REFERENCES node_tags(id) ON DELETE CASCADE,
|
||||
context VARCHAR(20) NOT NULL CHECK (context IN ('income', 'expense')),
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
UNIQUE(organization_id, node_id, tag_id, context)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS node_tag_assignments_org_idx ON node_tag_assignments(organization_id, context, node_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS finance_table_settings (
|
||||
id SERIAL PRIMARY KEY,
|
||||
organization_id INTEGER NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
section VARCHAR(20) NOT NULL CHECK (section IN ('income', 'expense')),
|
||||
visible_cols JSONB NOT NULL DEFAULT '[]',
|
||||
col_order JSONB NOT NULL DEFAULT '[]',
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW(),
|
||||
UNIQUE(organization_id, section)
|
||||
);
|
||||
Reference in New Issue
Block a user