Buchungen-popup funktioniert

This commit is contained in:
2026-02-24 11:17:17 +01:00
parent 32c0b8edb4
commit 622bdf0281
13 changed files with 304 additions and 48 deletions
+13
View File
@@ -0,0 +1,13 @@
read_accounts <- function(conn){
tbl(conn, "accounts")
}
get_account_choices <- function(conn) {
tbl(conn, "accounts") |>
select(id, konto) |>
collect() |>
arrange(konto) |>
(\(df) setNames(df$id, df$konto))()
}
+21
View File
@@ -0,0 +1,21 @@
read_buch_tabelle <- function(conn){
postings <- tbl(conn, "postings")
entries <- tbl(conn, "entries")
accounts <- tbl(conn, "accounts")
projects <- tbl(conn, "projects")
contacts <- tbl(conn, "contacts")
result <- postings |>
left_join(entries, by = c("entry_id" = "id")) |>
left_join(contacts, by = c("contact_id" = "id")) |> # contact_id jetzt verfügbar
left_join(accounts, by = c("account_id" = "id")) |>
left_join(projects, by = c("project_id" = "id")) |>
select(id, valuta, konto, projektname, display_name, amount, entry_id) |>
collect()
}
read_posting <- function(conn, id){
dbxSelect(conn, paste0("SELECT * FROM postings WHERE id =", id))
}
read_postings_by_entry <- function(conn, id){
dbxSelect(conn, paste0("SELECT * FROM postings WHERE entry_id =", id))
}
+92
View File
@@ -0,0 +1,92 @@
buchungenUI <- function(id) {
ns <- NS(id)
tagList(
reactableOutput(ns("buchungen_table"))
)
}
buchungenServer <- function(id) {
moduleServer( id, function(input, output, session) {
ns <- session$ns
postings <- reactiveVal(read_buch_tabelle(conn))
output$buchungen_table <- renderReactable({
reactable(
postings(),
onClick = "expand",
selection = "single",
details = function(index) {
entry_id <- postings()$entry_id[index]
detail_rows <- postings()[postings()$entry_id == entry_id, ]
div(
style = "padding: 10px; background: #f4f4f4; border-left: 4px solid #3c8dbc; max-width: 800px; margin-left: auto",
reactable(
dplyr::select(detail_rows, konto, projektname, amount),
fullWidth = TRUE,
columns = list(
konto = colDef(name = "Konto", minWidth = 150),
projektname = colDef(name = "Projekt", minWidth = 150),
amount = colDef(name = "Betrag", minWidth = 80)
)
)
)
},
columns = list(
id = colDef(name = "ID", minWidth = 80),
valuta = colDef(name = "Wertstellung", minWidth = 80),
konto = colDef(name = "Kontoname", minWidth = 200),
entry_id = colDef(show = FALSE)
)
)
})
# Modal zum editieren
selected <- reactive(getReactableState("buchungen_table", "selected"))
observeEvent(selected(),{
idwert <- postings()[selected(), "id"]
selected_row <- read_posting(conn, idwert) %>%
mutate(verzicht = ifelse(is.na(verzicht), F, verzicht))
showModal(modalDialog(
title = "Buchung bearbeiten",
size = "l",
tags$style(HTML(".modal-dialog { max-width: 90% !important; width: 90% !important; }")),
entryEditUI(ns("entry_edit")),
footer = tagList(
modalButton("Abbrechen"),
actionButton(ns("speichern"), "Speichern")
)
))
entryEditServer("entry_edit", entry_id = selected_row$entry_id, conn = conn)
}, ignoreInit = TRUE)
observeEvent(input$speichern, {
browser()
dbExecute(conn, "UPDATE postings SET
account_id = ?, project_id = ?, amount = ?, valuta = ?,
notiz = ?, rechnungsnummer = ?, betrag_muenzen = ?, verzicht = ?
WHERE id = ?",
params = list(
input$account_id, input$project_id, input$amount, input$valuta,
input$notiz, input$rechnungsnummer, input$betrag_muenzen, input$verzicht,
selected_row$id
)
)
removeModal()
buchungen(read_buch_tabelle(conn)) # Tabelle neu laden
})
}
)
}
+8
View File
@@ -0,0 +1,8 @@
get_contact_choices <- function(conn) {
tbl(conn, "contacts") |>
select(id, display_name) |>
collect() |>
arrange(display_name) |>
(\(df) setNames(df$id, df$display_name))()
}
+3
View File
@@ -0,0 +1,3 @@
read_entry <- function(conn, idwert) {
dbxSelect(conn, paste0("SELECT * FROM entries WHERE id=", idwert))
}
+93
View File
@@ -0,0 +1,93 @@
# entry_edit_mod.R
entryEditUI <- function(id) {
ns <- NS(id)
tagList(
uiOutput(ns("entry_ui")),
uiOutput(ns("postings_ui"))
)
}
entryEditServer <- function(id, entry_id, conn) {
moduleServer(id, function(input, output, session) {
ns <- session$ns
entry_postings <- reactiveVal(read_postings_by_entry(conn, entry_id))
entry_data <- reactiveVal(read_entry(conn, entry_id))
output$entry_ui <- renderUI({
e <- entry_data()
tagList(
fluidRow(
column(6, selectizeInput(ns("contact_id"), "Kontakt",
choices = get_contact_choices(conn),
selected = e$contact_id)),
column(6, textInput(ns("purpose"), "Verwendungszweck", value = e$purpose))
),
hr()
)
})
# Choices für contact nach dem Flush setzen
output$postings_ui <- renderUI({
alle <- entry_postings()
lapply(seq_len(nrow(alle)), function(i) {
print(paste("project selected:", alle$project_id[i]))
print(head(get_project_choices(conn)))
print(class(get_project_choices(conn)))
div(
style = "border-left: 3px solid #3c8dbc; padding: 5px; margin-bottom: 5px",
fluidRow(
column(3,
selectInput(ns(paste0("account_id_", i)), "Konto",
choices = get_account_choices(conn),
selected = as.character(alle$account_id[i]))
),
column(3, selectizeInput(ns(paste0("project_id_", i)), "Projekt",
choices = get_project_choices(conn),
selected = ifelse(is.na(alle$project_id[i]), "", as.character(alle$project_id[i])))
),
column(2, numericInput(ns(paste0("amount_", i)), "Betrag", value = alle$amount[i])),
column(3, textInput(ns(paste0("notiz_", i)), "Notiz", value = alle$notiz[i])),
column(1, actionButton(ns(paste0("delete_", i)), "", icon = icon("trash"), class = "btn-danger btn-sm"))
)
)
})
})
# Choices befüllen nachdem renderUI fertig ist
observe({
alle <- entry_postings()
e <- entry_data()
req(nrow(alle) > 0, nrow(e) > 0)
session$onFlushed(function() {
# Contact
updateSelectizeInput(session, "contact_id",
choices = get_contact_choices(conn),
selected = e$contact_id)
# Postings
lapply(seq_len(nrow(alle)), function(i) {
updateSelectizeInput(session, paste0("account_id_", i),
choices = get_account_choices(conn),
selected = alle$account_id[i])
updateSelectizeInput(session, paste0("project_id_", i),
choices = get_project_choices(conn),
selected = alle$project_id[i])
})
}, once = TRUE)
})
# Speichern-Logik
observeEvent(input$speichern, {
alle <- entry_postings()
lapply(seq_len(nrow(alle)), function(i) {
# update posting i in DB
})
})
})
}
+9
View File
@@ -0,0 +1,9 @@
get_project_choices <- function(conn) {
projekte <- tbl(conn, "projects") |>
select(id, projektname) |>
collect() |>
arrange(projektname)
choices <- setNames(as.character(projekte$id), projekte$projektname)
c("-" = "", choices)
}