Compare commits

..

2 Commits

+51 -35
View File
@@ -1,28 +1,38 @@
# module_buchungen.R ##
## Datum : 2026-04-29_08-17
## Name : Christian Oswald
## Datei : buchungen_mod.R
## Projekt : gemfin-shiny
## Kommentar: Modul für die Anzeige der Buchungen - praktisch Hauptformular
##
## * UI ----
buchungenUI <- function(id) { buchungenUI <- function(id) {
ns <- NS(id) ns <- NS(id)
tagList( tagList(
useShinyjs(), useShinyjs(),
## ** Tabelle ----
h3("Hauptbuchungen"), h3("Hauptbuchungen"),
fluidRow( fluidRow(
column(8, reactableOutput(ns("buchungen_table")), column(8, reactableOutput(ns("buchungen_table")),
hr(), hr(),
## ** Gegenbuchungen ----
h3("Details / Gegenbuchungen"), h3("Details / Gegenbuchungen"),
uiOutput(ns("details_table")) , uiOutput(ns("details_table")) ,
),
## ** Eingabefelder ----
),
column(4, column(4,
selectizeInput(ns("contact"), label = "Kontakt", choices = get_contact_choices(conn), selectizeInput(ns("contact"), label = "Kontakt", choices = get_contact_choices(conn),
selected = NA, width = "100%"), selected = NA, width = "100%"),
textAreaInput(ns("note"), label = "Verwendungszweck", value = NA, width = "100%"), textAreaInput(ns("note"), label = "Verwendungszweck", value = NA, width = "100%"),
## ** Anhänge ----
h3("Dateien"), h3("Dateien"),
uiOutput(ns("attachments_ui")), uiOutput(ns("attachments_ui")),
fileInput(ns("anhang"), NULL, multiple = TRUE, fileInput(ns("anhang"), NULL, multiple = TRUE,
accept = c(".pdf", ".jpg", ".png", ".xlsx", ".docx"), accept = c(".pdf", ".jpg", ".png", ".xlsx", ".docx"),
width = "100%"), width = "100%"),
## ** Buttons ----
div( div(
style = "display: flex; flex-direction: column; gap: 10px; align-items: flex-start;", style = "display: flex; flex-direction: column; gap: 10px; align-items: flex-start;",
@@ -39,12 +49,7 @@ buchungenUI <- function(id) {
size = "sm", style = "material-flat", color = "success", block = TRUE, icon = icon("floppy-disk")), size = "sm", style = "material-flat", color = "success", block = TRUE, icon = icon("floppy-disk")),
) )
) )
), )
) )
} }
@@ -52,7 +57,7 @@ buchungenServer <- function(id, conn, r_global) {
moduleServer(id, function(input, output, session) { moduleServer(id, function(input, output, session) {
ns <- session$ns ns <- session$ns
# ── Reactive Variablen ---- ## ** Reactive Variablen ----
postings_data <- reactiveVal(read_buch_tabelle(conn)) postings_data <- reactiveVal(read_buch_tabelle(conn))
sel_details <- reactiveVal(NULL) sel_details <- reactiveVal(NULL)
selected_trans_id <- reactiveVal(NULL) selected_trans_id <- reactiveVal(NULL)
@@ -62,9 +67,8 @@ buchungenServer <- function(id, conn, r_global) {
# ── Filter ---- ## ** Filter ----
aktiver_filter <- reactive(r_global$buchungen_filter) aktiver_filter <- reactive(r_global$buchungen_filter)
gefilterte_daten <- reactive({ gefilterte_daten <- reactive({
d <- postings_data() d <- postings_data()
f <- aktiver_filter() f <- aktiver_filter()
@@ -79,8 +83,7 @@ buchungenServer <- function(id, conn, r_global) {
else d else d
}) })
## ** Haupttabelle rendern ----
# ── Haupttabelle rendern ----
output$buchungen_table <- renderReactable({ output$buchungen_table <- renderReactable({
reset_trigger() reset_trigger()
f_reactable( f_reactable(
@@ -91,15 +94,24 @@ buchungenServer <- function(id, conn, r_global) {
filterable = TRUE, filterable = TRUE,
) )
}) })
## ** Auswahl anzeigen ----
sel <- reactive(getReactableState("buchungen_table", "selected")) sel <- reactive(getReactableState("buchungen_table", "selected"))
observeEvent(sel(), ignoreInit = T, { observeEvent(sel(), ignoreInit = T, {
idwert <- gefilterte_daten()$id[sel()]
record <- read_posting(conn, idwert)
record_entry <- read_entry(conn, record$entry_id)
updateSelectizeInput(session, "contact", selected = record_entry$contact_id)
updateTextAreaInput(session, "note", value = record_entry$purpose)
output$details_table <- renderUI({ output$details_table <- renderUI({
req(sel()) req(sel())
# Daten laden ## *** Daten-Gegenbuchungen laden ----
df <- read_buch_entries(conn, gefilterte_daten()$entry_id[sel()]) df <- read_buch_entries(conn, gefilterte_daten()$entry_id[sel()])
sel_details(df) sel_details(df)
## *** Gegenbuchungen rendern ----
rows <- lapply(1:nrow(df), function(ind) { rows <- lapply(1:nrow(df), function(ind) {
fluidRow(class = "details-row", fluidRow(class = "details-row",
# HIER: Index an die ID hängen! # HIER: Index an die ID hängen!
@@ -116,15 +128,12 @@ buchungenServer <- function(id, conn, r_global) {
}) })
tagList(rows) tagList(rows)
}) })
}) })
observeEvent(input$save_trans, { observeEvent(input$save_trans, {
req(sel_details()) req(sel_details())
n_rows <- nrow(sel_details()) n_rows <- nrow(sel_details())
# Alle Zeilen in einer Liste sammeln
# Alle Zeilen in einer Liste sammeln
all_records <- lapply(1:n_rows, function(ind) { all_records <- lapply(1:n_rows, function(ind) {
data.frame( data.frame(
id = as.integer(input[[paste0("id_", ind)]]), id = as.integer(input[[paste0("id_", ind)]]),
@@ -135,10 +144,19 @@ buchungenServer <- function(id, conn, r_global) {
stringsAsFactors = FALSE stringsAsFactors = FALSE
) )
}) })
# Zu einem großen Dataframe zusammenfügen
# Zu einem großen Dataframe zusammenfügen
final_df <- do.call(rbind, all_records) final_df <- do.call(rbind, all_records)
browser()
# Datenbank-Update-Logik # Datenbank-Update-Logik
tryCatch({ tryCatch({
@@ -158,21 +176,19 @@ buchungenServer <- function(id, conn, r_global) {
}) })
# ── Anhänge ---- ## ** Anhänge ----
output$attachments_ui <- renderUI({ output$attachments_ui <- renderUI({
req(sel_details()) req(sel_details())
entry_id <- entry_id <-
dbxSelect(conn, paste0("SELECT entry_id FROM postings WHERE id=", dbxSelect(conn, paste0("SELECT entry_id FROM postings WHERE id=", sel_details()$id[1])) %>%
sel_details()$id[1])) %>% pull pull
att <- dbxSelect(conn, paste0( att <- dbxSelect(conn, paste0("SELECT * FROM attachments WHERE entry_id = ", entry_id ))
"SELECT * FROM attachments WHERE entry_id = ", entry_id
))
if (nrow(att) == 0) return(p("Keine Anhänge vorhanden.")) if (nrow(att) == 0) return(p("Keine Anhänge vorhanden."))
## *** Anhänge anzeigen ----
tagList(lapply(seq_len(nrow(att)), function(i) { tagList(lapply(seq_len(nrow(att)), function(i) {
ext <- tools::file_ext(att$original_name[i]) ext <- tools::file_ext(att$original_name[i])
filename <- paste0("attachments/", att$id[i], ".", ext) filename <- paste0("attachments/", att$id[i], ".", ext)
## *** Anhang öffnen ----
observeEvent(input[[paste0("open_att_", att$id[i])]], { observeEvent(input[[paste0("open_att_", att$id[i])]], {
showModal(modalDialog( showModal(modalDialog(
tags$iframe(src = filename, width = "100%", height = "600px", tags$iframe(src = filename, width = "100%", height = "600px",
@@ -183,7 +199,7 @@ buchungenServer <- function(id, conn, r_global) {
footer = modalButton("Schließen") footer = modalButton("Schließen")
)) ))
}, ignoreInit = TRUE, once = FALSE) }, ignoreInit = TRUE, once = FALSE)
## *** Buttons Anhänge ----
div( div(
actionLink(ns(paste0("open_att_", att$id[i])), att$original_name[i]), actionLink(ns(paste0("open_att_", att$id[i])), att$original_name[i]),
actionLink(ns(paste0("del_att_", att$id[i])), "✕", actionLink(ns(paste0("del_att_", att$id[i])), "✕",