From 549920974d5d217947f4a507ee564aa3a7c0a817 Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Fri, 24 Jul 2026 11:19:10 +0200 Subject: [PATCH] feat(falukant): implement backfill for falukant visual settings and add SQL scripts for default values --- .../backfill-falukant-visual-settings.js | 94 ++++++++++ backend/sql/add_falukant_visual_settings.sql | 166 ++++++++++++++++++ 2 files changed, 260 insertions(+) create mode 100644 backend/scripts/backfill-falukant-visual-settings.js create mode 100644 backend/sql/add_falukant_visual_settings.sql diff --git a/backend/scripts/backfill-falukant-visual-settings.js b/backend/scripts/backfill-falukant-visual-settings.js new file mode 100644 index 0000000..6360ac6 --- /dev/null +++ b/backend/scripts/backfill-falukant-visual-settings.js @@ -0,0 +1,94 @@ +import { sequelize } from '../utils/sequelize.js'; +import { encrypt } from '../utils/encryption.js'; +import UserParamType from '../models/type/user_param.js'; +import UserParamValue from '../models/type/user_param_value.js'; + +const DEFAULT_SETTINGS = [ + { description: 'falukantPortraitStyle', optionValue: 'classic' }, + { description: 'falukantFigureMode', optionValue: 'both' }, +]; + +async function resolveParamDefinition(description, optionValue) { + const paramType = await UserParamType.findOne({ + where: { description }, + raw: true, + }); + + if (!paramType) { + throw new Error( + `Parametertyp '${description}' fehlt. Zuerst backend/sql/add_falukant_visual_settings.sql ausfuehren.` + ); + } + + const option = await UserParamValue.findOne({ + where: { + userParamTypeId: paramType.id, + value: optionValue, + }, + raw: true, + }); + + if (!option) { + throw new Error( + `Option '${optionValue}' fuer '${description}' fehlt. Zuerst backend/sql/add_falukant_visual_settings.sql ausfuehren.` + ); + } + + return { + paramTypeId: paramType.id, + encryptedOptionId: encrypt(String(option.id)), + }; +} + +async function insertMissingDefaults({ description, optionValue }) { + const { paramTypeId, encryptedOptionId } = await resolveParamDefinition(description, optionValue); + + const [rows] = await sequelize.query( + ` + INSERT INTO community.user_param (user_id, param_type_id, value, created_at, updated_at) + SELECT + u.id, + :paramTypeId, + :encryptedOptionId, + NOW(), + NOW() + FROM community."user" u + LEFT JOIN community.user_param existing + ON existing.user_id = u.id + AND existing.param_type_id = :paramTypeId + WHERE existing.id IS NULL + RETURNING user_id + `, + { + replacements: { + paramTypeId, + encryptedOptionId, + }, + } + ); + + console.log( + `✅ ${description}: ${rows.length} fehlende Default-Eintraege mit '${optionValue}' angelegt` + ); +} + +async function main() { + try { + await sequelize.authenticate(); + console.log('🔌 Datenbankverbindung hergestellt'); + + for (const setting of DEFAULT_SETTINGS) { + await insertMissingDefaults(setting); + } + + console.log('🏁 Falukant-Visual-Settings-Defaults abgeschlossen'); + await sequelize.close(); + process.exit(0); + } catch (error) { + console.error('❌ Backfill fehlgeschlagen:', error); + await sequelize.close(); + process.exit(1); + } +} + +main(); diff --git a/backend/sql/add_falukant_visual_settings.sql b/backend/sql/add_falukant_visual_settings.sql new file mode 100644 index 0000000..668f873 --- /dev/null +++ b/backend/sql/add_falukant_visual_settings.sql @@ -0,0 +1,166 @@ +-- Falukant-Visual-Settings: +-- - neue Settings-Gruppe: type.settings.name = 'falukant' +-- - neue Param-Typen: falukantPortraitStyle, falukantFigureMode +-- - neue Select-Werte: +-- falukantPortraitStyle -> classic, medieval +-- falukantFigureMode -> portraits, 3d, both +-- +-- Hinweis: +-- Für diese Änderung sind nach heutigem Stand keine ALTER TABLEs nötig. +-- Es werden nur fehlende Typ-/Wertetabellen-Einträge angelegt. +-- +-- Absichtlich ohne UPDATEs: +-- Auf manchen Servern existieren zusätzliche DB-Trigger/Regeln auf Tabellen, +-- die bei UPDATE implizit ein fehlendes `updated_at` erwarten. Darum hier nur +-- INSERT ... WHERE NOT EXISTS, damit das Script maximal robust bleibt. + +BEGIN; + +-- Settings-Gruppe anlegen +INSERT INTO type.settings (name) +SELECT 'falukant' +WHERE NOT EXISTS ( + SELECT 1 + FROM type.settings + WHERE name = 'falukant' +); + +-- Param-Typ: Portrait-Stil +INSERT INTO type.user_param ( + description, + datatype, + settings_id, + order_id, + immutable, + min_age, + gender, + unit +) +SELECT + 'falukantPortraitStyle', + 'singleselect', + s.id, + 920, + false, + NULL, + NULL, + NULL +FROM type.settings s +WHERE s.name = 'falukant' + AND NOT EXISTS ( + SELECT 1 + FROM type.user_param p + WHERE p.description = 'falukantPortraitStyle' + ); + +-- Param-Typ: Anzeige-Modus +INSERT INTO type.user_param ( + description, + datatype, + settings_id, + order_id, + immutable, + min_age, + gender, + unit +) +SELECT + 'falukantFigureMode', + 'singleselect', + s.id, + 921, + false, + NULL, + NULL, + NULL +FROM type.settings s +WHERE s.name = 'falukant' + AND NOT EXISTS ( + SELECT 1 + FROM type.user_param p + WHERE p.description = 'falukantFigureMode' + ); + +-- Select-Werte: falukantPortraitStyle +INSERT INTO type.user_param_value (user_param_type_id, value, order_id) +SELECT p.id, 'classic', 1 +FROM type.user_param p +WHERE p.description = 'falukantPortraitStyle' + AND NOT EXISTS ( + SELECT 1 + FROM type.user_param_value v + WHERE v.user_param_type_id = p.id + AND v.value = 'classic' + ); + +INSERT INTO type.user_param_value (user_param_type_id, value, order_id) +SELECT p.id, 'medieval', 2 +FROM type.user_param p +WHERE p.description = 'falukantPortraitStyle' + AND NOT EXISTS ( + SELECT 1 + FROM type.user_param_value v + WHERE v.user_param_type_id = p.id + AND v.value = 'medieval' + ); + +-- Select-Werte: falukantFigureMode +INSERT INTO type.user_param_value (user_param_type_id, value, order_id) +SELECT p.id, 'portraits', 1 +FROM type.user_param p +WHERE p.description = 'falukantFigureMode' + AND NOT EXISTS ( + SELECT 1 + FROM type.user_param_value v + WHERE v.user_param_type_id = p.id + AND v.value = 'portraits' + ); + +INSERT INTO type.user_param_value (user_param_type_id, value, order_id) +SELECT p.id, '3d', 2 +FROM type.user_param p +WHERE p.description = 'falukantFigureMode' + AND NOT EXISTS ( + SELECT 1 + FROM type.user_param_value v + WHERE v.user_param_type_id = p.id + AND v.value = '3d' + ); + +INSERT INTO type.user_param_value (user_param_type_id, value, order_id) +SELECT p.id, 'both', 3 +FROM type.user_param p +WHERE p.description = 'falukantFigureMode' + AND NOT EXISTS ( + SELECT 1 + FROM type.user_param_value v + WHERE v.user_param_type_id = p.id + AND v.value = 'both' + ); + +COMMIT; + +-- Prüfung 1: Gruppe + Param-Typen +SELECT + s.name AS settings_group, + p.id AS param_type_id, + p.description, + p.datatype, + p.order_id +FROM type.user_param p +JOIN type.settings s + ON s.id = p.settings_id +WHERE s.name = 'falukant' +ORDER BY p.order_id, p.id; + +-- Prüfung 2: Select-Werte +SELECT + p.description, + v.id AS value_id, + v.value, + v.order_id +FROM type.user_param_value v +JOIN type.user_param p + ON p.id = v.user_param_type_id +WHERE p.description IN ('falukantPortraitStyle', 'falukantFigureMode') +ORDER BY p.description, v.order_id, v.id;