From 7417736dafd6288422e978d1047da9c2201b01eb Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Mon, 20 Apr 2026 16:16:48 +0200 Subject: [PATCH] refactor(AdminService, EditUserView): streamline character data deletion and enhance confirmation dialog - Introduced a reusable `deleteIfTableExists` function in AdminService to simplify the deletion of character-related data across multiple tables, improving code maintainability. - Updated the deletion logic to check for table existence before executing delete queries, enhancing robustness. - Enhanced the EditUserView by integrating a `ChooseDialog` for user confirmation before proceeding with character death cleanup, improving user experience and interaction clarity. --- backend/services/adminService.js | 136 ++++++++---------- .../src/views/admin/falukant/EditUserView.vue | 11 +- 2 files changed, 67 insertions(+), 80 deletions(-) diff --git a/backend/services/adminService.js b/backend/services/adminService.js index ee3c25b..9150728 100644 --- a/backend/services/adminService.js +++ b/backend/services/adminService.js @@ -1203,6 +1203,25 @@ class AdminService { }; await sequelize.transaction(async (t) => { + const deleteIfTableExists = async (qualifiedTableName, deleteSql, replacements = {}) => { + const existsRow = await sequelize.query( + `SELECT to_regclass(:tableName) AS table_name`, + { + replacements: { tableName: qualifiedTableName }, + type: QueryTypes.SELECT, + transaction: t + } + ); + if (!existsRow?.[0]?.table_name) { + return 0; + } + return await sequelize.query(deleteSql, { + replacements, + type: QueryTypes.DELETE, + transaction: t + }); + }; + summary.knowledgeDeleted = await Knowledge.destroy({ where: { characterId: parsedCharacterId }, transaction: t @@ -1249,101 +1268,78 @@ class AdminService { transaction: t }); - await sequelize.query( + await deleteIfTableExists( + 'falukant_data.occupied_political_office', ` DELETE FROM falukant_data.occupied_political_office WHERE character_id = :characterId `, - { - replacements: { characterId: parsedCharacterId }, - type: QueryTypes.DELETE, - transaction: t - } + { characterId: parsedCharacterId } ); - await sequelize.query( + await deleteIfTableExists( + 'falukant_data.political_benefit_last_tick', ` DELETE FROM falukant_data.political_benefit_last_tick WHERE character_id = :characterId `, - { - replacements: { characterId: parsedCharacterId }, - type: QueryTypes.DELETE, - transaction: t - } + { characterId: parsedCharacterId } ); - await sequelize.query( + await deleteIfTableExists( + 'falukant_data.falukant_character_trait', ` DELETE FROM falukant_data.falukant_character_trait WHERE character_id = :characterId `, - { - replacements: { characterId: parsedCharacterId }, - type: QueryTypes.DELETE, - transaction: t - } + { characterId: parsedCharacterId } ); - await sequelize.query( + await deleteIfTableExists( + 'falukant_data.church_application', ` DELETE FROM falukant_data.church_application WHERE character_id = :characterId OR supervisor_id = :characterId `, - { - replacements: { characterId: parsedCharacterId }, - type: QueryTypes.DELETE, - transaction: t - } + { characterId: parsedCharacterId } ); - await sequelize.query( + await deleteIfTableExists( + 'falukant_data.church_office', ` DELETE FROM falukant_data.church_office WHERE character_id = :characterId OR supervisor_id = :characterId `, - { - replacements: { characterId: parsedCharacterId }, - type: QueryTypes.DELETE, - transaction: t - } + { characterId: parsedCharacterId } ); - await sequelize.query( + await deleteIfTableExists( + 'falukant_data.political_appointment', ` DELETE FROM falukant_data.political_appointment WHERE appointer_character_id = :characterId OR target_character_id = :characterId `, - { - replacements: { characterId: parsedCharacterId }, - type: QueryTypes.DELETE, - transaction: t - } + { characterId: parsedCharacterId } ); - await sequelize.query( + await deleteIfTableExists( + 'falukant_data.marriage_proposals', ` DELETE FROM falukant_data.marriage_proposals WHERE requester_character_id = :characterId OR proposed_character_id = :characterId `, - { - replacements: { characterId: parsedCharacterId }, - type: QueryTypes.DELETE, - transaction: t - } + { characterId: parsedCharacterId } ); - await sequelize.query( + await deleteIfTableExists( + 'falukant_data.child_relation', ` DELETE FROM falukant_data.child_relation WHERE father_character_id = :characterId OR mother_character_id = :characterId OR child_character_id = :characterId `, - { - replacements: { characterId: parsedCharacterId }, - type: QueryTypes.DELETE, - transaction: t - } + { characterId: parsedCharacterId } ); - await sequelize.query( + await deleteIfTableExists( + 'falukant_data.relationship_state', ` DELETE FROM falukant_data.relationship_state WHERE relationship_id IN ( @@ -1352,56 +1348,40 @@ class AdminService { OR character2_id = :characterId ) `, - { - replacements: { characterId: parsedCharacterId }, - type: QueryTypes.DELETE, - transaction: t - } + { characterId: parsedCharacterId } ); - await sequelize.query( + await deleteIfTableExists( + 'falukant_data.relationship', ` DELETE FROM falukant_data.relationship WHERE character1_id = :characterId OR character2_id = :characterId `, - { - replacements: { characterId: parsedCharacterId }, - type: QueryTypes.DELETE, - transaction: t - } + { characterId: parsedCharacterId } ); - await sequelize.query( + await deleteIfTableExists( + 'falukant_data.region_tax_history', ` DELETE FROM falukant_data.region_tax_history WHERE setter_character_id = :characterId `, - { - replacements: { characterId: parsedCharacterId }, - type: QueryTypes.DELETE, - transaction: t - } + { characterId: parsedCharacterId } ); - await sequelize.query( + await deleteIfTableExists( + 'falukant_log.health_activity', ` DELETE FROM falukant_log.health_activity WHERE character_id = :characterId `, - { - replacements: { characterId: parsedCharacterId }, - type: QueryTypes.DELETE, - transaction: t - } + { characterId: parsedCharacterId } ); - await sequelize.query( + await deleteIfTableExists( + 'falukant_log.political_office_history', ` DELETE FROM falukant_log.political_office_history WHERE character_id = :characterId `, - { - replacements: { characterId: parsedCharacterId }, - type: QueryTypes.DELETE, - transaction: t - } + { characterId: parsedCharacterId } ); const deletedCharacters = await FalukantCharacter.destroy({ diff --git a/frontend/src/views/admin/falukant/EditUserView.vue b/frontend/src/views/admin/falukant/EditUserView.vue index 3253566..f88becd 100644 --- a/frontend/src/views/admin/falukant/EditUserView.vue +++ b/frontend/src/views/admin/falukant/EditUserView.vue @@ -213,6 +213,7 @@ + @@ -220,13 +221,15 @@ import { mapState } from 'vuex'; import { mapActions } from 'vuex'; import SimpleTabs from '@/components/SimpleTabs.vue'; +import ChooseDialog from '@/dialogues/standard/ChooseDialog.vue'; import apiClient from '@/utils/axios.js'; import { showApiError, showError, showSuccess } from '@/utils/feedback.js'; export default { name: 'AdminFalukantEditUserView', components: { - SimpleTabs + SimpleTabs, + ChooseDialog }, data() { return { @@ -581,7 +584,11 @@ export default { if (!characterId) { return; } - if (!window.confirm(this.$t('admin.falukant.edituser.deathCleanup.confirm'))) { + const confirmed = await this.$refs.chooseDialog.open({ + title: this.$t('common.confirm'), + message: this.$t('admin.falukant.edituser.deathCleanup.confirm') + }); + if (!confirmed) { return; } try {