Compare commits

..

12 Commits

Author SHA1 Message Date
cosw 479f455f86 pfad geändert
Merge branch 'main' of https://git.oswaldonline.de/cosw/gemfin-shiny

# Conflicts:
#	db/data_transfer.R
#	db/development.sqlite
#	www/documents/1028.jpg
#	www/documents/1069.PDF
2026-06-19 11:12:34 +02:00
cosw f960e390d9 beispieldateien hinzu 2026-06-19 11:08:06 +02:00
cosw dc7effe9b7 sqlite transfer überarbeitet 2026-06-19 11:06:26 +02:00
cosw e28c8b6a9c Hibiscus Transfer eingerichtet 2026-05-13 09:59:01 +02:00
cosw e27ee5fd0b Dokumente hinzu und Anzeigefehler korrigiert 2026-05-13 09:31:44 +02:00
cosw 2e7933ad58 Unnötig 2026-05-04 12:57:23 +02:00
cosw 88de12e0b0 Merge branch 'main' of https://git.oswaldonline.de/cosw/gemfin-shiny 2026-05-04 12:56:51 +02:00
cosw 6ae86577aa Saldo Berechnung angegfangen 2026-05-04 12:53:13 +02:00
cosw b5d7e435c1 belege umbenannt 2026-04-30 17:40:13 +02:00
cosw f52d5fa3dd contact feld und note(purpose) in buchungen_mod eintragen 2026-04-29 08:31:24 +02:00
cosw 4175690455 Gegenbuchungen unter Haupttabelle, speichern angefangen. 2026-04-29 08:16:24 +02:00
cosw 12ef7693d5 Dokumente hinzugefügt und data.transfer mit attachments-transfer erweitert 2026-04-28 20:37:19 +02:00
770 changed files with 31463 additions and 409 deletions
+1
View File
@@ -5,3 +5,4 @@
.Ruserdata .Ruserdata
www/attachments/ www/attachments/
.positai
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>gemfin-shiny</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.statet.r.resourceProjects.RBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.statet.ide.resourceProjects.Statet</nature>
<nature>org.eclipse.statet.r.resourceProjects.R</nature>
</natures>
</projectDescription>
+13
View File
@@ -0,0 +1,13 @@
num_inp <- function(id, betrag, ro = FALSE){
autonumericInput(
inputId = id,
label = NULL,
width = "100%",
value = betrag,
currencySymbol = "",
currencySymbolPlacement = "s",
align = "right",
readOnly = ro,
style = "height: 15px !important; padding: 1px 1px;"
)
}
+59 -35
View File
@@ -1,28 +1,43 @@
# 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(), num_inp(ns("saldo"), 0, ro = T),
h3("Details / Gegenbuchungen"), div(
uiOutput(ns("details_table")) , style = "display: flex; justify-content: flex-end; margin-top: 5px;",
), ),
hr(),
## ** Gegenbuchungen ----
h3("Details / Gegenbuchungen"),
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 +54,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,19 +62,18 @@ 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_entry_id <- reactiveVal(NULL)
reset_trigger <- reactiveVal(NULL) reset_trigger <- reactiveVal(NULL)
current_main_idx <- reactiveVal(NULL) current_main_idx <- reactiveVal(NULL)
# ── 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 +88,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 +99,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,14 +133,11 @@ 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(
@@ -135,10 +149,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 +181,21 @@ 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 <- selected_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( print(selected_entry_id())
"SELECT * FROM attachments WHERE entry_id = ", entry_id att <- dbxSelect(conn, paste0("SELECT * FROM attachments WHERE entry_id = ", selected_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("documents/", 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",
@@ -184,6 +207,7 @@ buchungenServer <- function(id, conn, r_global) {
)) ))
}, 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])), "✕",
+1
View File
@@ -27,3 +27,4 @@ resolve_contact <- function(conn, empfaenger_name, empfaenger_konto) {
collect() collect()
if (nrow(bc) > 0) bc$contact_id[1] else NA_integer_ if (nrow(bc) > 0) bc$contact_id[1] else NA_integer_
} }
+36
View File
@@ -0,0 +1,36 @@
##
## Datum : 2026-05-13_09-37
## Name : Christian Oswald
## Datei : sync_hibiscus.R
## Projekt : gemfin-shiny
## Kommentar: Liest Daten aus der Hibiscus Datenbank
##
## * Initialisierung ----
sync_hibiscus <- function(){
if (as.character(Sys.info())[1] == "Linux") {
jdbc_url <- "jdbc:h2:/home/cosw/.jameica/hibiscus/h2db/hibiscus;IFEXISTS=TRUE;CIPHER=AES"
pw <- "LsOX6Ytldl4lJBcVoA6j+MDLzaA= LsOX6Ytldl4lJBcVoA6j+MDLzaA="
}
if(as.character(Sys.info())[1] == "Windows"){
source("c:/Users/chris/R/rfunc/fehler_add.R")
url <- "jdbc:h2:~/Insync/Projekte/Gemeindefinanzen/jameica/hibiscus/h2db/hibiscus;IFEXISTS=TRUE;CIPHER=AES"
h2jar <- "C:/Users/chris/bin/jameica/lib/h2/migration-h2/disabled/h2-1.4.199.jar"
}
# JDBC - Verbindung ----
if (as.character(Sys.info())[1] == "Darwin") {
source("/Users/cosw/R/rfunc/fehler_add.R")
h2jar <- "/Users/cosw/bin/jameica.app/lib/h2/migration-h2/disabled/h2-1.4.199.jar"
url <- "jdbc:h2:/Users/cosw/insync/Projekte/Gemeindefinanzen/jameica/hibiscus/h2db/hibiscus;IFEXISTS=TRUE;CIPHER=AES"
}
user <- "hibiscus"
pw <- "FbvGoL+yJlH1GtUojnC8ZajYuTA= FbvGoL+yJlH1GtUojnC8ZajYuTA="
drv <- JDBC("org.h2.Driver", h2jar, identifier.quote="`")
con_j <- dbConnect(drv, url, user, pw)
originaldaten <- dbReadTable(con_j, "UMSATZ")
dbDisconnect(con_j)
return(originaldaten)
}
+388 -367
View File
@@ -26,30 +26,14 @@ fm_driver_jar <- "~/R/fmjdbc.jar"
sqlite_path <- "db/development.sqlite" sqlite_path <- "db/development.sqlite"
# optional future switch
USE_CENTS <- FALSE
# Helpers ---- # Helpers ----
exec_sql <- function(sql) dbExecute(con_s, sql)
to_cents <- function(x) { f_anzahl <- function(tabelle){
if (is.null(x)) return(NA_integer_) dbxSelect(con_s, paste0("SELECt count(id) FROM ", tabelle)) %>% pull
if (is.factor(x)) x <- as.character(x)
if (is.character(x)) {
x <- trimws(x)
x[x == ""] <- NA
x <- gsub("\\.", "", x)
x <- gsub(",", ".", x)
}
d <- suppressWarnings(as.numeric(x))
ifelse(is.na(d), NA_integer_, as.integer(round(d * 100)))
} }
exec_sql <- function(sql) dbExecute(con_s, sql)
# Connections ---- # Connections ----
if (ok) { if (ok) {
drv <- JDBC(fm_driver_class, fm_driver_jar) drv <- JDBC(fm_driver_class, fm_driver_jar)
con_f <- dbConnect( con_f <- dbConnect(
@@ -69,126 +53,395 @@ if (ok) {
error_f <- fehler_add("SQLite connection established", TRUE, error_f) error_f <- fehler_add("SQLite connection established", TRUE, error_f)
} }
# Schema creation ---- ## * Transfer Accounts ----
if (ok) { if (ok) {
exec_sql("DROP TABLE IF EXISTS konten;")
exec_sql("CREATE TABLE accounts ( exec_sql("CREATE TABLE konten (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
account_name TEXT NOT NULL, kontoname TEXT NOT NULL,
bank_name TEXT, bank_name TEXT,
hibiscus_account_id INTEGER, hibiscus_konto_id INTEGER,
budget_id INTEGER, budget_id INTEGER,
wiso_account TEXT, wiso_kategorie TEXT,
bank_account_no TEXT, bank_konto_nr TEXT,
is_donations INTEGER, ist_spende INTEGER,
notes TEXT, notiz TEXT,
created_at TEXT, created_at TEXT,
updated_at TEXT updated_at TEXT
);") );")
konten <- dbxSelect(con_f, "
SELECT id, konto, budget_id, bankname, updated_at, created_at,
konto_hibiscus, konto_wiso, kontonummer_bank, notizen, ist_spende
FROM Konten
") %>%
transmute(
id = as.integer(id),
kontoname = konto,
bank_name = bankname,
hibiscus_konto_id = as.integer(konto_hibiscus),
budget_id = as.integer(budget_id),
wiso_kategorie = konto_wiso,
bank_konto_nr = kontonummer_bank,
ist_spende = as.integer(ist_spende),
notiz = notizen,
created_at = created_at,
updated_at = updated_at
)
dbWriteTable(con_s, "konten", konten, append = TRUE)
ok <- dbExistsTable(con_s, "konten")
ok <- f_anzahl("konten") == nrow(konten) & ok
error_f <- fehler_add("Konten übertragen", TRUE, error_f)
}
## * Transfer Projekte ----
if (ok) {
exec_sql("DROP TABLE IF EXISTS projekte;")
exec_sql("CREATE TABLE projekte (
id INTEGER PRIMARY KEY,
projektname TEXT NOT NULL,
jahr INTEGER,
projekt_wiso TEXT,
bereich TEXT,
notiz TEXT,
created_at TEXT,
updated_at TEXT
);")
projekte <- dbxSelect(con_f, "
SELECT id, projektname, bereich, notiz, jahr, created_at, updated_at from Projekte") %>%
transmute(
id = as.integer(id),
projektname = projektname,
bereich = bereich,
notiz = notiz,
jahr = as.integer(jahr),
created_at = created_at,
updated_at = updated_at
)
dbWriteTable(con_s, "projekte", projekte, append = TRUE)
ok <- dbExistsTable(con_s, "projekte")
ok <- f_anzahl("projekte") == nrow(projekte) & ok
error_f <- fehler_add("Projekte übertragen", TRUE, error_f)
}
## * Transfer Budgets ----
if (ok) {
exec_sql("DROP TABLE IF EXISTS budgets;")
exec_sql("CREATE TABLE budgets ( exec_sql("CREATE TABLE budgets (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
row_no INTEGER, reihe INTEGER,
area TEXT, bereich TEXT,
label TEXT, bezeichnung TEXT,
direction TEXT, richtung TEXT,
created_at TEXT, created_at TEXT,
updated_at TEXT updated_at TEXT
);") );")
budgets <- dbxSelect(con_f, "
SELECT id, richtung, bereich, bezeichnung, reihe
FROM Budgets
") %>%
transmute(
id = as.integer(id),
reihe = as.integer(reihe),
bereich = bereich,
bezeichnung = bezeichnung,
richtung = richtung,
created_at = format(Sys.time(), ""),
updated_at = format(Sys.time(), "")
)
dbWriteTable(con_s, "budgets", budgets, append = TRUE)
ok <- dbExistsTable(con_s, "budgets")
ok <- f_anzahl("budgets") == nrow(budgets) & ok
error_f <- fehler_add("Budgets übertragen", TRUE, error_f)
}
exec_sql("CREATE TABLE contacts ( ### ** Transfer Budget-Werte
if(ok){
exec_sql("DROP TABLE IF EXISTS budget_werte;")
exec_sql("CREATE TABLE budget_werte (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
first_name TEXT, budget_id INTEGER,
last_name TEXT, jahr INTEGER,
street TEXT, betrag DECIMAL,
postal_code TEXT, budget_listen_nr INTEGER,
city TEXT, created_at TEXT,
country TEXT, updated_at TEXT
phone TEXT, );")
mobile TEXT, budget_werte <- dbReadTable(con_f, "Budgets_werte") %>%
transmute(
id = as.integer(id),
budget_id = as.integer(budget_id),
jahr = as.integer(jahr),
betrag = betrag,
budget_listen_nr = as.integer(budget_listen_nr),
created_at = format(Sys.time(), ""),
updated_at = format(Sys.time(), "")
)
dbWriteTable(con_s, "budget_werte", budget_werte, append = TRUE)
ok <- dbExistsTable(con_s, "budget_werte")
ok <- f_anzahl("budget_werte") == nrow(budget_werte) & ok
error_f <- fehler_add("budget_werte übertragen", TRUE, error_f)
} ## ------------------------------------------------------- 2026-06-19 08:52
## * Transfer Adressen ----
if (ok) {
exec_sql("DROP TABLE IF EXISTS adressen;")
exec_sql("CREATE TABLE adressen (
id INTEGER PRIMARY KEY,
vorname TEXT,
nachname TEXT,
strasse TEXT,
plz TEXT,
ort TEXT,
land TEXT,
telefon TEXT,
mobil TEXT,
email TEXT, email TEXT,
salutation TEXT, anrede TEXT,
gender TEXT, geschlecht TEXT,
donor TEXT, ist_mitglied INTEGER,
member INTEGER, ist_firma INTEGER,
notes TEXT, quittung_anrede TEXT,
receipt_salutation TEXT, quittung_name TEXT,
receipt_name TEXT,
display_name TEXT, display_name TEXT,
partner_id INTEGER, partner_id INTEGER,
is_couple INTEGER, notiz TEXT,
is_company INTEGER,
created_at TEXT, created_at TEXT,
updated_at TEXT updated_at TEXT
);") );")
exec_sql("CREATE TABLE bank_connections ( adressen <- dbxSelect(con_f, "
SELECT id, vorname, nachname, strasse, plz, ort, Land,
telefon, mobil, email, anrede, geschlecht, mitglied, notiz,
quittung_anrede, quittung_name, bezeichnung, partner_id, b_paar, b_firma
FROM Adressen
") %>%
as_tibble() %>%
transmute(
id = as.integer(id),
vorname = vorname,
nachname = nachname,
strasse = strasse,
plz = plz,
ort = ort,
land = Land,
telefon = telefon,
mobil = mobil,
email = email,
anrede = anrede,
geschlecht = geschlecht,
ist_mitglied = as.integer(mitglied),
ist_firma = as.integer(b_firma),
quittung_anrede = quittung_anrede,
quittung_name = quittung_name,
display_name = bezeichnung,
partner_id = as.integer(partner_id),
notiz = notiz,
created_at = format(Sys.time(), ""),
updated_at = format(Sys.time(), "")
)
dbWriteTable(con_s, "adressen", adressen, append = TRUE)
ok <- dbExistsTable(con_s, "adressen")
ok <- f_anzahl("adressen") == nrow(adressen) & ok
error_f <- fehler_add("adressen übertragen", TRUE, error_f)
}
## * Transfer Transaktionen ----
if (ok) {
exec_sql("DROP TABLE IF EXISTS transaktionen;")
exec_sql("CREATE TABLE transaktionen (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
contact_id INTEGER, adress_id INTEGER,
contact_text TEXT, vwz TEXT,
notiz TEXT,
bank_kontakt TEXT,
created_at TEXT,
updated_at TEXT
);")
transaktionen <- dbxSelect(con_f, "
SELECT id, adress_id, verwendungszweck, notiz, kontakt, created_at, updated_at
FROM trans
") %>%
as_tibble() %>%
transmute(
id = as.integer(id),
adress_id = as.integer(adress_id),
vwz = verwendungszweck,
notiz = notiz,
bank_kontakt = kontakt,
created_at = created_at,
updated_at = updated_at
)
dbWriteTable(con_s, "transaktionen", transaktionen, append = TRUE)
ok <- dbExistsTable(con_s, "transaktionen")
ok <- f_anzahl("transaktionen") == nrow(transaktionen) & ok
error_f <- fehler_add("transaktionen übertragen", TRUE, error_f)
}
## * Transfer Postings ----
if (ok) {
exec_sql("DROP TABLE IF EXISTS buchungen;")
exec_sql("CREATE TABLE buchungen (
id INTEGER PRIMARY KEY,
trans_id INTEGER NOT NULL,
konto_id INTEGER NOT NULL,
valuta TEXT NOT NULL,
buchungsdatum TEXT,
betrag DECIMAL,
rechnungsnummer TEXT,
notiz TEXT,
status TEXT,
ist_verzicht INTEGER,
umsatz_id INTEGER,
wiso_id INTEGER,
quittung_id INTEGER,
projekt_id INTEGER,
betrag_muenzen DECIMAL,
created_at TEXT,
updated_at TEXT
);")
buchungen <- dbxSelect(con_f, "
SELECT id, trans_id, konto_id, wertstellung, buchungsdatum, betrag,
rechnungsnummer, notiz, status, b_verzicht, umsatz_id, wiso_id,
quittung_id, projekt_id, betrag_muenzen, created_at, updated_at
FROM buchungen
") %>%
as_tibble()
buchungen <- buchungen %>%
transmute(
id = as.integer(id),
trans_id = as.integer(trans_id),
konto_id = as.integer(konto_id),
valuta = as.character(wertstellung),
buchungsdatum = as.character(buchungsdatum),
betrag = betrag,
rechnungsnummer = rechnungsnummer,
notiz = notiz,
status = status,
ist_verzicht = as.integer(b_verzicht),
umsatz_id = as.integer(umsatz_id),
wiso_id = as.integer(wiso_id),
quittung_id = as.integer(quittung_id),
projekt_id = as.integer(projekt_id),
betrag_muenzen = betrag_muenzen,
created_at = created_at,
updated_at = updated_at
)
dbWriteTable(con_s, "buchungen", buchungen, append = TRUE)
ok <- dbExistsTable(con_s, "buchungen")
ok <- f_anzahl("buchungen") == nrow(buchungen) & ok
error_f <- fehler_add("buchungen übertragen", TRUE, error_f)
}
## * Transfer Attachments ----
if(ok){
exec_sql("DROP TABLE IF EXISTS attachments;")
exec_sql("CREATE TABLE attachments (
id INTEGER PRIMARY KEY AUTOINCREMENT,
trans_id INTEGER,
quittung_id INTEGER,
adress_id INTEGER,
wiso_id INTEGER,
btisch_id TEXT,
original_name TEXT,
kategorie TEXT,
ext TEXT NOT NULL,
notiz TEXT,
created_at TEXT DEFAULT (datetime('now')),
updated_at TEXT DEFAULT (datetime('now'))
);")
att <- dbxSelect(con_f, "SELECT id, trans_id, quittung_id, wiso_id, btisch_id,
adress_id, ft_dateiname, beschreibung, created_at, updated_at, ft_extension FROM Dokumente") %>%
transmute(
id = as.integer(id),
trans_id = as.integer(trans_id),
quittung_id = as.integer(quittung_id),
wiso_id = as.integer(wiso_id),
btisch_id = as.integer(btisch_id),
adress_id = as.integer(adress_id),
created_at = as.character(created_at),
updated_at = as.character(updated_at),
original_name = ft_dateiname,
ext = paste0(id,".", ft_extension)
)
dbWriteTable(con_s, "attachments", att, append = T)
ok <- dbExistsTable(con_s, "attachments")
ok <- f_anzahl("attachments") == nrow(att) & ok
error_f <- fehler_add("attachments übertragen", TRUE, error_f)
} ## ------------------------------------------------------- 2026-03-19 16:38
### ** Dateien übertragen ----
if(ok){
pfad <- "~/Insync/Projekte/Gemeindefinanzen/gemfin-fm/gemfin04/Dokumente/datei/"
zielpfad <- "~/Documents/workspace/gemfin-shiny/www/documents/"
vorhanden <- list.files(pfad, pattern = "pdf")
eintraege <- att$original_name
anz <- length(eintraege)
for(ind in 1:length(eintraege)){
if( exists(paste0(zielpfad, eintraege[ind])) ){
cat(ind, " von ", anz, "\n")
file.copy(
from = paste0(pfad, vorhanden[ind]),
to = "~/Documents/workspace/gemfin-shiny/www/documents/")
}
}
neue_dateien <- list.files("~/Documents/workspace/gemfin-shiny/www/documents/")
length(neue_dateien)
eintraege <- att$original_name
length(eintraege)
nv <- att[-which(eintraege %in% neue_dateien),]
error_f <- fehler_add("Alle Dateien übertragen", nrow(nv) == 0, error_f)
} ## ------------------------------------------------------- 2026-04-28 18:40
## * Transfer Bankverbindungen ----
if (ok) {
exec_sql("DROP TABLE IF EXISTS bvb;")
exec_sql("CREATE TABLE bvb (
id INTEGER PRIMARY KEY,
adress_id INTEGER,
remote_name TEXT,
iban TEXT, iban TEXT,
bic TEXT, bic TEXT,
bank_name TEXT, kreditinstitut TEXT,
remote_name TEXT,
created_at TEXT, created_at TEXT,
updated_at TEXT updated_at TEXT
);") );")
bvb <- dbxSelect(con_f, "
SELECT id, adress_id, kontakt, iban, bic, kreditinstitut,
created_at, updated_at
FROM Bankverbindungen
") %>%
transmute(
id = as.integer(id),
adress_id = as.integer(adress_id),
remote_name = kontakt,
iban = iban,
bic = bic,
kreditinstitut = kreditinstitut,
created_at = as.character(created_at),
updated_at = as.character(updated_at)
)
dbWriteTable(con_s, "bvb", bvb, append = TRUE)
ok <- dbExistsTable(con_s, "bvb")
ok <- f_anzahl("bvb") == nrow(bvb) & ok
error_f <- fehler_add("bvb übertragen", TRUE, error_f)
}
exec_sql("CREATE TABLE entries (
id INTEGER PRIMARY KEY,
contact_id INTEGER,
purpose TEXT,
note TEXT,
remote_name TEXT,
created_at TEXT,
updated_at TEXT
);")
if (!USE_CENTS) { ## * Transfer Hibiscus ----
exec_sql("CREATE TABLE postings ( if(ok){
id INTEGER PRIMARY KEY, exec_sql("DROP TABLE IF EXISTS umsatz;")
entry_id INTEGER NOT NULL, exec_sql("CREATE TABLE umsatz (
account_id INTEGER NOT NULL,
valuta TEXT NOT NULL,
booking_date TEXT,
amount NUMERIC NOT NULL,
invoice_no TEXT,
note TEXT,
status TEXT,
waived INTEGER,
bank_transaction_id INTEGER,
wiso_id INTEGER,
receipt_id INTEGER,
project_id INTEGER,
coin_share_amount NUMERIC,
created_at TEXT,
updated_at TEXT
);")
} else {
exec_sql("CREATE TABLE postings (
id INTEGER PRIMARY KEY,
entry_id INTEGER NOT NULL,
account_id INTEGER NOT NULL,
valuta TEXT NOT NULL,
booking_date TEXT,
amount_cents INTEGER NOT NULL,
invoice_no TEXT,
note TEXT,
status TEXT,
waived INTEGER,
bank_transaction_id INTEGER,
wiso_id INTEGER,
receipt_id INTEGER,
project_id INTEGER,
coin_share_cents INTEGER,
created_at TEXT,
updated_at TEXT
);")
}
# Hibiscus payload unchanged ----
exec_sql("CREATE TABLE hibiscus_transactions (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
konto_id INTEGER, konto_id INTEGER,
empfaenger_konto TEXT, empfaenger_konto TEXT,
@@ -201,275 +454,43 @@ if (ok) {
datum TEXT, datum TEXT,
valuta TEXT, valuta TEXT,
saldo REAL, saldo REAL,
primanota INTEGER,
art TEXT,
customerref TEXT, customerref TEXT,
kommentar TEXT, kommentar TEXT,
checksum REAL, endtoendid TEXT
umsatztyp_id INTEGER,
flags REAL,
gvcode INTEGER,
addkey INTEGER,
txid TEXT,
purposecode TEXT,
endtoendid TEXT,
mandateid TEXT,
empfaenger_name2 TEXT,
creditorid TEXT
);") );")
umsatz <- dbReadTable(con_f, "Umsatz") %>%
# Attachments ----
exec_sql("CREATE TABLE attachments (
id INTEGER PRIMARY KEY AUTOINCREMENT,
entry_id INTEGER,
quittung_id INTEGER,
adress_id INTEGER,
wiso_id INTEGER,
btisch_id TEXT,
original_name TEXT,
kategorie TEXT,
path TEXT NOT NULL,
note TEXT,
created_at TEXT DEFAULT (datetime('now')),
updated_at TEXT DEFAULT (datetime('now'))
);")
error_f <- fehler_add("Schema created", TRUE, error_f)
}
# Transfer Accounts ----
if (ok) {
accounts <- dbxSelect(con_f, "
SELECT id, konto, budget_id, bankname, updated_at, created_at,
konto_hibiscus, konto_wiso, kontonummer_bank, notizen, b_spenden
FROM Konten
") %>%
transmute(
id = as.integer(id),
account_name = konto,
bank_name = bankname,
hibiscus_account_id = as.integer(konto_hibiscus),
budget_id = as.integer(budget_id),
wiso_account = konto_wiso,
bank_account_no = kontonummer_bank,
is_donations = as.integer(b_spenden),
notes = notizen,
created_at = created_at,
updated_at = updated_at
)
dbWriteTable(con_s, "accounts", accounts, append = TRUE)
}
if (ok) {
projects <- dbxSelect(con_f, "
SELECT id, projektname, bereich, notiz, jahr, created_at, updated_at from Projekte") %>%
transmute(
id = as.integer(id),
projektname = projektname,
bereich = bereich,
notiz = notiz,
jahr = as.integer(jahr),
created_at = created_at,
updated_at = updated_at
)
dbWriteTable(con_s, "projects", projects, append = TRUE)
}
# Transfer Budgets ----
if (ok) {
budgets <- dbxSelect(con_f, "
SELECT id, richtung, bereich, bezeichnung, reihe
FROM Budgets
") %>%
transmute(
id = as.integer(id),
row_no = as.integer(reihe),
area = bereich,
label = bezeichnung,
direction = richtung,
created_at = format(Sys.time(), ""),
updated_at = format(Sys.time(), "")
)
dbWriteTable(con_s, "budgets", budgets, append = TRUE)
}
# Transfer Contacts
if (ok) {
contacts <- dbxSelect(con_f, "
SELECT id, vorname, nachname, strasse, plz, ort, Land,
telefon, mobil, email, anrede, geschlecht, spender, mitglied, notiz,
quittung_anrede, quittung_name, bezeichnung, partner_id, b_paar, b_firma
FROM Adressen
") %>%
as_tibble() %>%
transmute(
id = as.integer(id),
first_name = vorname,
last_name = nachname,
street = strasse,
postal_code = plz,
city = ort,
country = Land,
phone = telefon,
mobile = mobil,
email = email,
salutation = anrede,
gender = geschlecht,
donor = spender,
member = as.integer(mitglied),
notes = notiz,
receipt_salutation = quittung_anrede,
receipt_name = quittung_name,
display_name = bezeichnung,
partner_id = as.integer(partner_id),
is_couple = as.integer(b_paar),
is_company = as.integer(b_firma),
created_at = format(Sys.time(), ""),
updated_at = format(Sys.time(), "")
)
dbWriteTable(con_s, "contacts", contacts, append = TRUE)
}
# Transfer Entries ----
if (ok) {
entries <- dbxSelect(con_f, "
SELECT id, adress_id, verwendungszweck, notiz, kontakt, created_at, updated_at
FROM trans
") %>%
as_tibble() %>%
transmute(
id = as.integer(id),
contact_id = as.integer(adress_id),
purpose = verwendungszweck,
note = notiz,
remote_name = kontakt,
created_at = created_at,
updated_at = updated_at
)
dbWriteTable(con_s, "entries", entries, append = TRUE)
}
# Transfer Postings ----
if (ok) {
postings <- dbxSelect(con_f, "
SELECT id, trans_id, konto_id, wertstellung, buchungsdatum, betrag,
rechnungsnummer, notiz, status, b_verzicht, umsatz_id, wiso_id,
quittung_id, projekt_id, betrag_muenzen, created_at, updated_at
FROM buchungen
") %>%
as_tibble()
if (!USE_CENTS) {
postings <- postings %>%
transmute( transmute(
id = as.integer(id), id = as.integer(id),
entry_id = as.integer(trans_id), konto_id = as.integer(konto_id),
account_id = as.integer(konto_id), empfaenger_konto = empfaenger_konto,
valuta = as.character(wertstellung), empfaenger_blz = empfaenger_blz,
booking_date = as.character(buchungsdatum), empfaenger_name = empfaenger_name,
amount = betrag, betrag = betrag,
invoice_no = rechnungsnummer, zweck = zweck,
note = notiz, zweck2 = zweck2,
status = status, zweck3 = zweck2,
waived = as.integer(b_verzicht), datum = datum,
bank_transaction_id = as.integer(umsatz_id), valuta = valuta,
wiso_id = as.integer(wiso_id), saldo = saldo,
receipt_id = as.integer(quittung_id), kommentar = kommentar,
project_id = as.integer(projekt_id), endtoendid = endtoendid
coin_share_amount = betrag_muenzen, )
created_at = created_at, dbWriteTable(con_s, "umsatz", umsatz, append = TRUE)
updated_at = updated_at ok <- sum(duplicated(umsatz$id)) == 0
) ok <- dbExistsTable(con_s, "umsatz") & ok
} else { ok <- f_anzahl("umsatz") == nrow(umsatz) & ok
postings <- postings %>% error_f <- fehler_add("Tabelle Umsatz existiert", ok, error_f)
transmute( } ## ------------------------------------------------------- 2026-06-19 08:34
id = as.integer(id),
entry_id = as.integer(trans_id),
account_id = as.integer(konto_id),
valuta = as.character(wertstellung),
booking_date = as.character(buchungsdatum),
amount_cents = to_cents(betrag),
invoice_no = rechnungsnummer,
note = notiz,
status = status,
waived = as.integer(b_verzicht),
bank_transaction_id = as.integer(umsatz_id),
wiso_id = as.integer(wiso_id),
receipt_id = as.integer(quittung_id),
project_id = as.integer(projekt_id),
coin_share_cents = to_cents(betrag_muenzen),
created_at = created_at,
updated_at = updated_at
)
}
dbWriteTable(con_s, "postings", postings, append = TRUE)
}
# Daten aus Attachments Tabelle übertragen ----
if(ok){
att <- dbxSelect(con_f, "SELECT id, trans_id, quittung_id, wiso_id, btisch_id,
adress_id, ft_dateiname, beschreibung, created_at, updated_at, ft_extension FROM Attachments") %>%
mutate(
id = as.integer(id),
trans_id = as.integer(trans_id),
quittung_id = as.integer(quittung_id),
wiso_id = as.integer(wiso_id),
btisch_id = as.integer(btisch_id),
adress_id = as.integer(adress_id),
created_at = as.character(created_at),
updated_at = as.character(updated_at),
path = paste0(id,".", ft_extension)
) %>%
rename(
entry_id = trans_id,
note = beschreibung,
original_name = ft_dateiname
) %>%
select(-ft_extension)
dbWriteTable(con_s, "Attachments", att, append = T)
} ## ------------------------------------------------------- 2026-03-19 16:38
# Transfer Bankverbindungen ----
if (ok) {
bank_connections <- dbxSelect(con_f, "
SELECT id, adress_id, kontakt, iban, bic, kreditinstitut,
remote_name, created_at, updated_at
FROM Bankverbindungen
") %>%
transmute(
id = as.integer(id),
contact_id = as.integer(adress_id),
contact_text = kontakt,
iban = iban,
bic = bic,
bank_name = kreditinstitut,
remote_name = remote_name,
created_at = as.character(created_at),
updated_at = as.character(updated_at)
)
dbWriteTable(con_s, "bank_connections", bank_connections, append = TRUE)
error_f <- fehler_add(
paste(nrow(bank_connections), "Bankverbindungen übertragen"), TRUE, error_f
)
}
# Close ---- # Close ----
dbListTables(con_s)
dbDisconnect(con_s) dbDisconnect(con_s)
dbDisconnect(con_f) dbDisconnect(con_f)
print("Migration finished.") print("Migration finished.")
Binary file not shown.
+24 -2
View File
@@ -12,8 +12,8 @@ library("conflicted")
library("R.utils") library("R.utils")
library("shinyjs") library("shinyjs")
conflicts_prefer(dplyr::select) conflicts_prefer()
conflicts_prefer(dplyr::filter) conflicts_prefer()
conn <- dbConnect(RSQLite::SQLite(), "db/development.sqlite") conn <- dbConnect(RSQLite::SQLite(), "db/development.sqlite")
@@ -21,3 +21,25 @@ sourceDirectory("R/")
source("~/R/rfunc/fehler_add.R") source("~/R/rfunc/fehler_add.R")
conflicts_prefer(
ggplot2::`%+%`,
shinyjs::alert,
shinydashboard::box,
rJava::clone,
dplyr::select,
dplyr::filter,
tidyr::extract,
shinyjs::hidden,
dplyr::ident,
dplyr::lag,
shiny::printStackTrace,
shinyjs::removeClass,
shinyjs::reset,
shiny::runExample,
shiny::setProgress,
shinyjs::show,
dplyr::sql,
shiny::validate,
.quiet = TRUE
)
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More