diff --git a/app.R b/app.R index 393f9fa..d4bc5d7 100644 --- a/app.R +++ b/app.R @@ -1227,13 +1227,15 @@ server <- function(input, output, session) { append = TRUE ) - message <- glue::glue("Данные таблицы '{table_name}' успешно обновлены (добавлено {nrow(df)} записей)") + message <- glue::glue("Данные таблицы '{table_name}' успешно загружены (добавлено {nrow(df)} записей)") showNotification( message, type = "message" ) cli::cli_alert_success(message) } + + db$db_clean_orphans(mhcs(), con) log_action_to_db("importing data from xlsx", con = con) removeModal() }) diff --git a/app/tasks.R b/app/tasks.R index 2a2bce3..4493808 100644 --- a/app/tasks.R +++ b/app/tasks.R @@ -409,14 +409,11 @@ server <- function(id, values, scheme, mhcs) { } else { # get key - new_main_key <- values$tasks_data[input$dt_todays_tasks_rows_selected,]$task_main_key - values$main_key <- new_main_key + main_key_to_jump <- values$tasks_data[input$dt_todays_tasks_rows_selected,]$task_main_key + values$main_key <- main_key_to_jump - showNotification("TODO: если ключа нет в таблице?!", type = "warning", duration = NULL) removeModal() - # log_action_to_db("loading data", values$main_key, con = con) - } }) diff --git a/modules/db.R b/modules/db.R index 661c984..ec5ba1d 100644 --- a/modules/db.R +++ b/modules/db.R @@ -52,6 +52,7 @@ check_if_table_is_exist_and_init_if_not = function( schm = schm ) + # инициализируем все таблицы } else { if (table_name == "main") { @@ -61,6 +62,7 @@ check_if_table_is_exist_and_init_if_not = function( .before = 1 ) } + if (table_name != "main") { dummy_df <- get_dummy_df(forms_id_type_list) |> dplyr::mutate( @@ -401,4 +403,61 @@ local_db_backup <- function( } } ) -} \ No newline at end of file +} + +#' @export +db_clean_orphans = function(schm, con) { + + main_key <- schm$get_main_key_id + nested_tables <- schm$nested_tables_names + + all_main_keys <- DBI::dbGetQuery(con, glue::glue("SELECT DISTINCT {main_key} FROM main")) + all_main_keys <- dplyr::pull(all_main_keys) + + purrr::walk( + .x = nested_tables, + .f = \(table_name) clear_orphans(table_name = table_name, main_key = main_key, all_main_keys = all_main_keys, con = con) + ) + + clear_orphans(table_name = "tasks", main_key = "task_main_key", all_main_keys = all_main_keys, con = con, drop_na_keys = FALSE) + clear_orphans(table_name = "log", main_key = "key", all_main_keys = all_main_keys, con = con, drop_na_keys = FALSE) + +} + +clear_orphans <- function( + table_name, + main_key, + all_main_keys, + con, + drop_na_keys = TRUE +) { + + if (!table_name %in% DBI::dbListTables(con)) return(invisible()) + + all_main_keys_from_nested <- DBI::dbGetQuery(con, glue::glue("SELECT DISTINCT {main_key} FROM {table_name}")) + all_main_keys_from_nested <- dplyr::pull(all_main_keys_from_nested) + + if (!drop_na_keys) { + all_main_keys_from_nested <- all_main_keys_from_nested[!is.na(all_main_keys_from_nested)] + } + + if (all(all_main_keys_from_nested %in% all_main_keys)) { + cli::cli_alert_success("Все ключи в таблице '{table_name}' соответствуют действующим") + } else { + + orphaned_keys <- all_main_keys_from_nested[!all_main_keys_from_nested %in% all_main_keys] + cli::cli_alert_warning(c("В таблице '{table_name}' найдены орфанные записи для следующих ID: ", paste("\n -", orphaned_keys))) + + orphaned_keys <- paste0("'", orphaned_keys, "'", collapse = ", ") + del_query <- glue::glue("DELETE FROM {table_name} WHERE {main_key} IN ({orphaned_keys})") + deleted <- DBI::dbExecute(con, del_query) + + if (drop_na_keys) { + deleted <- deleted + DBI::dbExecute(con, glue::glue("DELETE FROM {table_name} WHERE {main_key} IS NULL")) + } + + cli::cli_alert_success("Из таблицы '{table_name}' было удалено {deleted} орфанных записей") + + } + +} diff --git a/modules/global_options.R b/modules/global_options.R index 632bb79..2e1c798 100644 --- a/modules/global_options.R +++ b/modules/global_options.R @@ -110,6 +110,7 @@ init_scheme = function(scheme_file) { if (!dir.exists(db_path)) dir.create(db_path) cli::cli_h1("Инициализация схемы") + schms <- purrr::map2( .x = scheme_file, .y = names(scheme_file), @@ -118,8 +119,15 @@ init_scheme = function(scheme_file) { con <- db$make_db_connection(y) on.exit(db$close_db_connection(con), add = TRUE) + # новый объект schm <- scheme_R6$new(x) + + # проверка схемы с существующей базой данных и инициализация таблиц db$check_if_table_is_exist_and_init_if_not(schm, con) + + # удаление орфанных записей + + db$db_clean_orphans(schm = schm, con = con) schm } ) @@ -129,13 +137,13 @@ init_scheme = function(scheme_file) { names(schms), \(x) schms[[x]]$nested_tables_names ) + nested_tables_ids <- unlist(nested_tables_ids) tab <- table(nested_tables_ids) # если встречается хоть одно значение несколько раз - начать истошно кричать (могут возникнуть пробемы при вызове всплывающих окон в формах) if (!all(!tab > 1)) { cli::cli_abort(c("В одной или нескольких схемах наименования вложенных форм совпадают:", paste("-", names(tab)[tab > 1]))) - } saveRDS(schms, "scheme.rds") diff --git a/modules/scheme_generator.R b/modules/scheme_generator.R index 6a85333..fd837ac 100644 --- a/modules/scheme_generator.R +++ b/modules/scheme_generator.R @@ -48,7 +48,7 @@ scheme_R6 <- R6::R6Class( "task_status", "select_one", "Статус задачи", NA, "completed", "task_status", "select_one", "Статус задачи", NA, "deleted", "task_title", "text", "Название задачи", NA, NA, - "task_description", "text", "Описание задачи", "краткое описание", "2", + "task_description", "text", "Описание задачи", "краткое описание", "3", "task_due_date", "date", "Дата выполнения задачи", NA, NA, ) |> dplyr::mutate(condition = NA)