From d0a5cebdcd0ef7aae372887c38d37d5b406bb034 Mon Sep 17 00:00:00 2001 From: Christian Oswald Date: Tue, 28 Apr 2026 10:23:20 +0200 Subject: [PATCH] umsatzliste verbessert --- .gitignore | 0 R/_funktionen/f_airdatepicker.R | 0 R/_funktionen/f_leer_from_tabelle.R | 0 R/_funktionen/f_max_id.R | 0 R/_funktionen/f_table.R | 0 R/_funktionen/scroll_to_Row.R | 0 R/_funktionen/sync_hibiscus.R | 0 R/_funktionen/tree_helpers.R | 0 R/accounts/accounts.R | 0 R/accounts/accounts_tab.R | 0 R/contacts/contacts.R | 8 ++-- R/entries/entries.R | 0 R/entries/entry_edit_modal.R | 0 R/entries/todo.R | 0 R/postings/buchungen.R | 0 R/postings/buchungen_mod.R | 0 R/projects/projects.R | 0 R/umsatz/bank_connections.R | 3 +- R/umsatz/module_umsatz.R | 47 +++++++++++-------- db/data_transfer.R | 0 db/development.sqlite | Bin 995328 -> 1024000 bytes db/development.sqlite3 => development.sqlite | 0 gemfin-shiny.Rproj | 0 global.R | 2 + server.R | 0 ui.R | 0 www/main.css | 0 27 files changed, 37 insertions(+), 23 deletions(-) mode change 100644 => 100755 .gitignore mode change 100644 => 100755 R/_funktionen/f_airdatepicker.R mode change 100644 => 100755 R/_funktionen/f_leer_from_tabelle.R mode change 100644 => 100755 R/_funktionen/f_max_id.R mode change 100644 => 100755 R/_funktionen/f_table.R mode change 100644 => 100755 R/_funktionen/scroll_to_Row.R mode change 100644 => 100755 R/_funktionen/sync_hibiscus.R mode change 100644 => 100755 R/_funktionen/tree_helpers.R mode change 100644 => 100755 R/accounts/accounts.R mode change 100644 => 100755 R/accounts/accounts_tab.R mode change 100644 => 100755 R/contacts/contacts.R mode change 100644 => 100755 R/entries/entries.R mode change 100644 => 100755 R/entries/entry_edit_modal.R mode change 100644 => 100755 R/entries/todo.R mode change 100644 => 100755 R/postings/buchungen.R mode change 100644 => 100755 R/postings/buchungen_mod.R mode change 100644 => 100755 R/projects/projects.R mode change 100644 => 100755 R/umsatz/bank_connections.R mode change 100644 => 100755 R/umsatz/module_umsatz.R mode change 100644 => 100755 db/data_transfer.R mode change 100644 => 100755 db/development.sqlite rename db/development.sqlite3 => development.sqlite (100%) mode change 100644 => 100755 gemfin-shiny.Rproj mode change 100644 => 100755 global.R mode change 100644 => 100755 server.R mode change 100644 => 100755 ui.R mode change 100644 => 100755 www/main.css diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/R/_funktionen/f_airdatepicker.R b/R/_funktionen/f_airdatepicker.R old mode 100644 new mode 100755 diff --git a/R/_funktionen/f_leer_from_tabelle.R b/R/_funktionen/f_leer_from_tabelle.R old mode 100644 new mode 100755 diff --git a/R/_funktionen/f_max_id.R b/R/_funktionen/f_max_id.R old mode 100644 new mode 100755 diff --git a/R/_funktionen/f_table.R b/R/_funktionen/f_table.R old mode 100644 new mode 100755 diff --git a/R/_funktionen/scroll_to_Row.R b/R/_funktionen/scroll_to_Row.R old mode 100644 new mode 100755 diff --git a/R/_funktionen/sync_hibiscus.R b/R/_funktionen/sync_hibiscus.R old mode 100644 new mode 100755 diff --git a/R/_funktionen/tree_helpers.R b/R/_funktionen/tree_helpers.R old mode 100644 new mode 100755 diff --git a/R/accounts/accounts.R b/R/accounts/accounts.R old mode 100644 new mode 100755 diff --git a/R/accounts/accounts_tab.R b/R/accounts/accounts_tab.R old mode 100644 new mode 100755 diff --git a/R/contacts/contacts.R b/R/contacts/contacts.R old mode 100644 new mode 100755 index 63b155f..ca4e2f4 --- a/R/contacts/contacts.R +++ b/R/contacts/contacts.R @@ -1,8 +1,10 @@ get_contact_choices <- function(conn) { - tbl(conn, "contacts") |> + contacts <- tbl(conn, "contacts") |> select(id, display_name) |> collect() |> - arrange(display_name) |> - (\(df) setNames(df$id, df$display_name))() + arrange(display_name) + + choices <- setNames(as.character(contacts$id), contacts$display_name) + return(c("Kein Kontakt" = 0, choices)) } diff --git a/R/entries/entries.R b/R/entries/entries.R old mode 100644 new mode 100755 diff --git a/R/entries/entry_edit_modal.R b/R/entries/entry_edit_modal.R old mode 100644 new mode 100755 diff --git a/R/entries/todo.R b/R/entries/todo.R old mode 100644 new mode 100755 diff --git a/R/postings/buchungen.R b/R/postings/buchungen.R old mode 100644 new mode 100755 diff --git a/R/postings/buchungen_mod.R b/R/postings/buchungen_mod.R old mode 100644 new mode 100755 diff --git a/R/projects/projects.R b/R/projects/projects.R old mode 100644 new mode 100755 diff --git a/R/umsatz/bank_connections.R b/R/umsatz/bank_connections.R old mode 100644 new mode 100755 index 6ede76c..64cfd27 --- a/R/umsatz/bank_connections.R +++ b/R/umsatz/bank_connections.R @@ -15,7 +15,8 @@ read_hibiscus <- function(conn) { datum = as.Date(datum), # einfach as.Date reicht da Text "2023-12-25" valuta = as.Date(valuta), gebucht = !is.na(posting_id) - ) + ) %>% + filter(datum >= "2026-01-01") } # R/read_functions.R — Kontakt aus bank_connections auflösen diff --git a/R/umsatz/module_umsatz.R b/R/umsatz/module_umsatz.R old mode 100644 new mode 100755 index 8e38b77..e1a0091 --- a/R/umsatz/module_umsatz.R +++ b/R/umsatz/module_umsatz.R @@ -2,15 +2,20 @@ umsatzUI <- function(id) { ns <- NS(id) tagList( useShinyjs(), + # Sync-Button oben div( style = "display: flex; justify-content: flex-end; margin-bottom: 8px;", actionBttn(ns("sync"), "Sync Hibiscus", size = "xs", style = "minimal", icon = icon("rotate"), color = "primary") ), - reactableOutput(ns("umsatz_table")), - hr(), - uiOutput(ns("buchungs_panel")) + # Buchungspanel immer sichtbar unten + uiOutput(ns("buchungs_panel")), + # Tabelle mit begrenzter Höhe und Scroll + div( + style = "max-height: 70vh; overflow-y: auto;", + reactableOutput(ns("umsatz_table")) + ) ) } @@ -18,7 +23,7 @@ umsatzServer <- function(id, conn, r_global) { moduleServer(id, function(input, output, session) { ns <- session$ns - # ── Daten ────────────────────────────────────────────────────────────────── + # ── Daten ---- refresh <- reactiveVal(0) zeige_alle <- reactiveVal(FALSE) @@ -30,7 +35,7 @@ umsatzServer <- function(id, conn, r_global) { }) - # ── Filter-Buttons ───────────────────────────────────────────────────────── + # ── Filter-Buttons ---- observeEvent(input$filter_ungebucht, { zeige_alle(FALSE) }) observeEvent(input$filter_alle, { zeige_alle(TRUE) }) @@ -55,6 +60,7 @@ umsatzServer <- function(id, conn, r_global) { striped = TRUE, highlight = TRUE, filterable = TRUE, # ← das reicht + pagination = F, selection = "single", onClick = "select", defaultSorted = list(valuta = "desc"), @@ -110,34 +116,37 @@ umsatzServer <- function(id, conn, r_global) { tagList( h4("Buchen"), fluidRow( - column(6, + column(4, selectizeInput(ns("konto"), "Konto:", choices = get_account_choices(conn), selected = 0, width = "100%") ), - column(6, + column(3, selectizeInput(ns("projekt"), "Projekt:", choices = get_project_choices(conn), width = "100%") - ) - ), - fluidRow( - column(6, + ), + column(3, selectizeInput(ns("kontakt"), "Kontakt:", choices = get_contact_choices(conn), selected = resolve_contact(conn, u$empfaenger_name, u$empfaenger_konto), width = "100%") ), - column(6, - br(), - actionBttn(ns("new_contact"), "Neuer Kontakt", - size = "xs", style = "minimal", icon = icon("plus")) + column(1, + div(style = "margin-top: 25px;", # Label-Höhe ausgleichen + actionBttn(ns("new_contact"), "Neuer Kontakt", + size = "xs", style = "minimal", icon = icon("plus"), color = "warning") + ) + ), + column(1, + div(style = "margin-top: 25px;", + actionBttn(ns("buchen"), "Buchen", + size = "sm", style = "minimal", color = "success", + icon = icon("check")) + ) ) - ), - actionBttn(ns("buchen"), "Buchen", - size = "sm", style = "minimal", color = "success", - icon = icon("check")) + ) ) } }) diff --git a/db/data_transfer.R b/db/data_transfer.R old mode 100644 new mode 100755 diff --git a/db/development.sqlite b/db/development.sqlite old mode 100644 new mode 100755 index 5c93b04bcade22e04f704eea49c865f20c1b5984..3b131ee0507cf110ca2c3bb14dc42cbe3f8f8afd GIT binary patch delta 12639 zcmb_id3;pWy}vVa@7!6E41p{JOfn%XVM(~ltSlxI2uXnKgnb*52}H7y1qIYFxS>@R zwfQyI4HW8g0io7~7B#>J#T^x^6{=vXB3dn4>e7e2-?{hB%$>}J%|ozSsZmt_6g`nmP2^&{&k z>s!_nPj|1IXPJPzKS>Mm=Z{hu{`^7m;Lm?aB(D-5SW5f@O9}|Ae__5%}ik}4hBtG}urlg^JM%k#3DVsSdKXG9~m35BgRx_B^ zv-QRn=1zK&{$1T3>f?L(lh4z^;{J7TQlFRxlh4zoL&bc-EpUP>pCiBdO!NuZ`KmE9 z*Tso~n-@5T(;>Jxj+?^XeFynF%`ybXFvI9A6Z$*glk@Z)o+dHibUHZR>vDMeT4J{UgLcXajO? zHRtL3+u*C4&8<-WIi1Q>_ye6AA-|Vi5u;0^BQ7>aQ6GAGUy8v_{(>H7SlZtTI|A%F z;4URGLj+ftSC`Mca3bhVm@{QwT^#Z$@?KO4!Fwdvrs9P+pyn4g#SrLkf#h7vW>xkm zyo#xC@ehevg+z82CvYO~a*(sm{h)Mz7%j3~Sv9Y^wrYO)%#xW~GW*wNQf6=NI5t=V zJNM9OFmQ&+pSUP+boC zOX>8P=R5&derB%n5w4uPi$}I(t|)5PB150bmv$qXuWMw!cs5w7@U{LCTFCKl=*NGO zhA+F|atdxvw6AY(weucG92kQL7?Rjg% z+(b4s+yvM5H^aVP8|!9v>C*M`;N2>-?v9r`sMyeM9kU0gq-48g)%j(lDy;DiF+S>W}E9nxT^}@q?hsnVgFl+wdAhXH1@bMl*S5F%+a}p7+x=@M+3T8H+uQ7mo4eMw zuMf1@C)&aH0yBJgM4rfRKJ#27yjW_=@(`lvV~`t%K>Puo!%vR&DmU5<%{gpg`kSC* zt9f^Zss}CbjQQtE_oqP3UUPbp0!}1zx!p2&-|Mg47zU4QXuyLt{ei0}^NieaxhUEfL8IBF$jb0Po7t1Z*u4L38=jCb83y1kqL{2$pR@rYQSfrF1&hI0xL(cxB%Ku8D_y&fhKS$2dF z;i*(>mZ74*7Y;6>TNOes7w-h0msvh^uqd{DG8J(U6$}Z_9pCgzEFE5%G@_Ge>*~hX!Sj>ss8`-=uk-smS9Kmc+^`m1g(@B& z@HRCydIU#<=sI|;Qj-h;HLgfL0jN| z9q0*k+WkFU#KmI>5GOe}dzpV#plxGwTbI29H$|?16AK70_Br$HJm>a`0`HvD-qzjT z+_nb)v@@@{Z9M7`G`e>{_th;~&)0li*WS|HSdhQCr>kL2i+^=k76&)U07uVyIFK8Sf%7+%Q9??(b~wKDMX3Yop4;AVCC7;mVos7Y9f6Z-5ssSZAzlRF1+| zTsH$_a9y3fx}?@F@*zDBQeBAVRFt>YFvhovNZQlY6-x%~=11Y;7s1y4>o5#>a|`ti z!1pngdiq1StBaj@ReWTtog@T6JUEGIB06vpvn1XlTjG~#mor18G#eTp9xUs>7S^%m zD)_RC9*Rkedgcn_?B7<(Y5Zsfn!|AEA^{DV{h;Zi--My%4LF!#Nj0qQUk`=TjJ--K z5RGFk3q0q+Fs1Nz=jDc@L9xFZj#Mz~V!u4_%b(wx-tou>P<7Clnn{?^etq^6 zpFMj+f7ewMsit7_?<{GphJkxGqW|gGGw9UAw=2R}OQH!zK))exPhqlCDoYk*H6YY;D4l?u6;GiDO%hk1+%ExAX+Va{ax!x2Yd6M!!l2 z=SeBB^Ella6VOVIL-L=DB$LA+%=4lPLnPjGk)nRpK3?WgvjH{B%_#<-Gz@lpX_6De z!SS)ELWaXKBnnQTsQ;R{`wLkV%?7M{oE>JEB@G4cU2A#Y=SgWX{1q;X%O3{ZTPxR2 z83YLY7E_9$OiG527n)bb3u)d=8BR$>BI0uP?O&J%gPq%iHIh#n0)nx@$IGbVe#6_%^5fwX8 z5J`cFcJlCMdPFpPJor8~rWgvP1n_;Ev@qsOdBx_mq7p1LlFdc?o1(Fx=Cmo*P%c@a z$ZA~?k2B60qd0D--CGBtC7(gGQpo~GHk+2kLmM?FuAF$MzxRIjel!{nx*j~$ zDUuodoUuM0+*SJ^XNolo^Q^GOc}yt8#?8S&2O%$Oo%mA81n27MjWO!WxGOHEVBB$Y z`yd99l%T~dkyy|@Y>9g{hCdJ&me(!*yCoKu*TPmwM&JvXSnraa7#EZ4sPPVs#pJY@ z#S#M#{DD~*Ppd=T)E<%tD_#$&$Y??gpBcm(DV>J(4baBC3d$xVwIn`~@MXeS>s-r5^RuRlrhK-; zc+{9lUou?Kf1*#*jif3tG-T7k+0r<;5!h9#Y6Jo+=fi@}ly3umHcL8w4h(RZ2=a0g z!c~4!rF8rv%ZeYlRvHU0{*-h#(M%N5_-{2x7*`yKMEsk1?OTUcLGVBFGOU}8j<-Y_ z12wzYxR*36VnCb#rFoZ*ZdYm^IR7e>2Lt;O@<=)}n1R9w1Je}-uwURI#faWvnyVonTGo;u zEsc`N2iV{kh5X*d%-pnlFUcwTEPrcrOEWeS{EY!Dr+}|CWLyyL;lu$7b~e_Jdw28*)w=YvSo}tCA=vZb8jDFqs#} zW?V=nkeX!413A;s!xTwb@Kq^07gmgB5@X!VP4yZ#6Tw6OchjX$tD+I1{c%hdd{QQy zo5oha3m1}N@itu2_?ZYEhR{Ftl}(GrbHi>cUe6-wDm7s^V=RDOk202cg0FMRz)|Uz zQpIfjqHj|aFz9x(X@*K^B;<@^R>z3kmMSAfC6;K2PKx^5j$K=#kQ{CY=uDB-ls3JE= zNwC4c7*%++G#r8tTC!keAsaX6T7F#SG0JQZQ>fGBH^gu#r_$4R`cm%9zYt zMGN}>)*Ye%_zq)RLYCx_ed2UBI2C;J(Ip>nnX=)0qA_FS)M6Y>Tsjt>0r*-Po8|7m z;8wc-MI+ffMX9{Z3-MmO=rcXi2?yJanOLSfFg#+w$5yLi;D7FU zD2WifmkAZHQRsJF8%Zt5jMK&AhzZg8oA3EX6(F>%*mR*JfIl@MF4$zbvY4t)zv zS4bZ5S0xj57q<&U%jqsUA3443G%%AMEH2k4Uc!j;D zY!HV^alK69VAnlNmwNb7a5z>Y+2UY0JegxJee$QlaHPD}uaTfA)gm{R$mvGd^qDrX zv1laAqo^&JZ$CH~P0ksMr2^n5u%TQ!3a;}D?OAZxnD<~?lfZrW`|D4K;p7dl3rs4y z`+OKEGKbuK6x!M-%_(Ta3MuO52abOhjpii7aN_PK!OF==X??F5ua2j^x<@tg;?=<$ zpw84zr(K*Gf>bv^Zcfxo6CwMkH5A~Y67KTJG8~RdII`mP=)DZauRiMRwD?Ivd8&;PjbJ!Ol%dSwsZ%sHlC;<3jVrgy7UQEsrXM zLmP1JCTvUaQYi$F;Ny$U=d39(kZv1=vP5H^m;eV^CVNyAq|kFuA(`YxQBqoK)1_H3 z@OP#@9)HJS_gzU@*td-Wc_S1~2c0>K}D0h7%Y$sz)8-p$V|Eh8gZw2;&SA zC(FcZ%&FZxE=)MGTs5z(7Q=P~`l8M@#xP7O2LEs9T43+j(DlI5`{_W;5&vRz0^~QJ>F~ReBg2G3 zL?gf?hT}F`7pP$$!(L=rqtRfkR0IRNnJlPgnW`Az=SRsVn&ZIlV?EE|0}q64Gz#yi z`U)+}Em8AosZe$^HIO{dI2_9UP5aE$Kh&WhT=@$-T(yTN?)M*+xtG(f5T2r>U%Fn} zIEWD0(DFZ3x*A%G%@tWY{2iUma>GDL=fWm{iQS{c5&hr*21An|5AJIn*Q#A-bkC7x zE&lb=bU4?;+^sSml`l$1W$olT@Y@{ca-u;YcNF!PbBF$+vK`uhoGvU9lBH>|i?tmf zdX7dK1rOCRBk^4VVxeDmIj{_sv0iy;wweY-ZD?6sBTbdHp08U6=Qc3uu)T?$47LPY zj^17Ye1a_%8zLHd*a~`}xC#HsLn(X|gxM}WzQM%MLtYt;(Qi{-Y1FcY;+70)N~j@H zr!-)yUbK$O8dze-i3~-}2{f#=mvpuSR<$*Eb>rBOC}R@okW?!Ldo(lmKP)q&bZ0P2 z^Ws2OHeXcb#}^m;psG^45zUNOW(Hp|&~AOqa<6%x z=>&V3H8DTXCk#jQ_vu=xz1W?*fey};7D7jvaj{}dq4#(W@*dA@JR^_ZNWLXtwt(g& zVrf9k>C*GJt1Y7N2I*Ck7kSbGDH$n^t)P0jCSyp~yA5{Qhv2 z5Jl2-B|#okEzpuARY+BCqUsOB1j#bK$oo%pwv3YI<6-3Ea5T7tSVju`?jY?LdZo8k zp6GX?IdpfE2V-#lAUz5ke`Qj<#U<#RTsR{Wy)GxdsIeE9&zNGLSG%CRxTKiJ)HrmN zHQZxJ{^>eMT!GKE(21jW!Z$Ihx(@&B+o_mL)P~k%3{pL;TWQ&?oDBrR}(e_QY~;K;p4aoS^JNu z(rK5qY$Qr`vOj3X$A!CZFsH*quQH>-{yCjjTcqAl`7|~bU|rF$HeY*FXSR2A1X?!w zaR!cuv>qR3I14yOLFjqnU@mpr!j2WWC(T3`CL0`=^zDsmRur|Y;SwvvTBy0(x>Y>` zyi-cZ7VsUzFQLo`2gZUZVrfjAq2s_DRuw(GEEloXQmICkI9D&i#mhLH&CW25&!={T zUZc(K!4AM8(jE7AnmdiyFsdgj)&=9VjoeMXCId_Nku>s zQG$uRRN^i^&)@W9G^)IzLEVxpRmz5%qYG9j{(IAMIy+B&n1gS0-t+Zzk>0L7>^|!- zx^_o(QBE$WNvEAW^;DBBtmi+vChW^y4jx~cU>Ab(kTi~>p6Ge}4Gm*BKdFH7 zWZTLZ+|%!d0~Q&-ApkxMb$E%yoNM!Qhr+m#Wi4)@G#A>sLQR6`bo8U*a2k#sJ$&DZ zdgcUn?~LUtD9%ZgWhD(Sk>xdn&Y4bp7j zyO|A&(L_VNHzkx@gubJMq1#>>9m?rK8)U|UW04V3xqPZPrl?Z_;r}%%$D{wwtWX$4 zGWc3rwlh4%w+$H^B8rhW{(CnQt0=}G=XcS7>h{7GFxB1VIynUv0(yG)Ohi*vUc zUEr!>^7Lm1U}Y7rr9^O;Ekl zIDD46oiBf-0N+u$G4Q!v^PYM18S0=xuG$rV!GE!3th7Yd(|9%*AoG-Tuw67`0z8^Y znlK>Z*a8O^A^Wex*FeV(cXb6?@C_C|Rl_G+`09ytV_^4kc1+*x@*U6wCXD2Xt>p2P zJZ*B2SdOhPhZ~mSe1R=XZ+Z=C3T(MU6z#a|oV&o`DiCl0 z^($jK46LVFyd+w}MMox$mDO`Fo5`3KQV;nW&RRSL__i8fYU11K+sm6Z>cu`y)E{6! vZ4nIl(3l0wt{Ah@37 zj6lo;#LPg<0>rF9%m&2lK+FNeoIuP4#N0s41H`=BKUMPyE#Y9|(`Df2