From 8598af05e712978e185475f53386b4c7f4e248b2 Mon Sep 17 00:00:00 2001 From: Priec Date: Mon, 20 Jul 2026 18:13:49 +0200 Subject: [PATCH] accounting kernel5 - locking --- common/proto/accounting.proto | 12 ++++ common/src/proto/descriptor.bin | Bin 125619 -> 126405 bytes common/src/proto/komp_ac.accounting.rs | 87 +++++++++++++++++++++++++ server | 2 +- tui-pages | 2 +- 5 files changed, 101 insertions(+), 2 deletions(-) diff --git a/common/proto/accounting.proto b/common/proto/accounting.proto index 2671953..c61f0d8 100644 --- a/common/proto/accounting.proto +++ b/common/proto/accounting.proto @@ -8,6 +8,10 @@ service Accounting { // all supplied lines atomically when journal_id identifies an existing one. rpc PostJournal(PostJournalRequest) returns (Journal); + // Permanently lock a balanced journal. This is an explicit action; becoming + // balanced never locks a journal automatically. + rpc LockJournal(LockJournalRequest) returns (Journal); + // Return journal lines and credits-minus-debits informational balance. rpc GetJournal(GetJournalRequest) returns (Journal); @@ -58,6 +62,11 @@ message JournalLineInput { string description = 4; } +message LockJournalRequest { + string profile_name = 1; + int64 journal_id = 2; +} + message GetJournalRequest { string profile_name = 1; int64 journal_id = 2; @@ -149,4 +158,7 @@ message Journal { string total_credit = 8; // Informational difference calculated as credits minus debits. string balance = 9; + bool locked = 10; + string locked_at = 11; + string locked_by_user_id = 12; } diff --git a/common/src/proto/descriptor.bin b/common/src/proto/descriptor.bin index 57d2f0b34773387e1a872ed5c329411a808084f0..8346d4a8d5869dfb33adf0a368805326def1d4d9 100644 GIT binary patch delta 4693 zcmYM1%X1aS6^C#4oqO+0j~-}*gkHdv#3K$i!o;QUjE!7`ILH>}nSu&L5;sBUMS+AP zfiu_?4`Z7E69Wdj#N#hWQB-!RY@AK9N+qj!>y1}gWtqx%rn|4ISm?Wbey7hleNOlA z;$M|-{#_}WzrXv(;!9OIYLemE@yYDZ>Oi^gccx`u?e6P8dhs9ieOccwzW6rWtbUcW zoAMMkwbLD@s(uh2bd+?P$o_t6bgm<2DLNS1ANI^8ub39MIJR(V{zC2isfp7a4Y^U1 zT^L$8!q4xV&Wt&wzRk{>vC2Uc4@)$uSsln9FP@lxs_2`orjnEjh3DCa4ZW)C#Ztou zD!rjhP%dbd6dUxmuEpws+WG0xncB?U)IwGKS4XR3qf?_Z%(8B#cCmIo_lCrKsgBOi%}&2L zIyW&sIyJSh*_Z}Xl1L!#zd1nER_<|T0iw3m zJ3Jw3Z+^|ZlZ#48u`_$nyl_luito~D zX@!YRP%7v`QtZ`h#asYay}HX2u6kFmafU4Q={y?@rGkBWr886*_O0r0hCqMaht#cK zw>d+pTYpEVIc|&&2xmj#$I2K}3}oXCVV8Ia@|ZSS4+12*QHSC|2*Zt0?oWvHHsbFO zbQs9mrtEJm_qT7-`BBSHs5iy=xe19yOI|7=)SK3f*aosk$;Uq&sP85o2co=D zu-DiRtZXyy=9>Xqv!Aw(Y}#5kmlNL_B)ZBkMj$ii6o-TCb*q_27aszr{Wr zIr_n#UYBTqdT`x(s-sy5wikY4DA*o1FeC~4x0N`?; za|y|sa|z*cA1L_a?o{EN&Fqswh;mR9dhA8 z7#^zR_fr7j@6g(69!5zbKkUK)kR5ilfMhMSV+$cWY>y?y3$-|+`}2$ebVuqs@p&X% z9tvxq{WWv^=?U;>S$di=X5lz`ZclaU+1D^4v%R&b0r<5=#IH+f#{A!w)hab zW3Kq+BsgC9wJlZ|tK;GN++SIWb;4y0;O>NT2Vr=^6(7Rg39{Zo1C%APle)btyW8=~ z76{!*7d|A5p}lq>bSJrXW^*0I8q2=#n9Oc>wRg4V8J6>#X{>#fIgp!RU(2p_4yR=; zWvSKUk+Rg>b;g?5;a8fWk_2Z8AK3INSe>DG(%=#-;QROc86Dyk$~(=10kDshX)~>=I{pdqF{I~d$oJ(mWnRP-*u79 z(YeSzH>@E#*Sa!4mWt+fzL4GS9!~jF{&qJtgy=$3{^}BL8PNs%>Oz&IIH&En0qiwb z-%HMEF0z+DYsluhx?MfOq&Tnb*i>|gY`%VKVTx`(%wKXg2+_^=taiF6DPFACF+z8- zzFmauVq`n6q9bG%+wDaiCc#4CL)$zdRtw>V++8Tmv#4Lsn-rkfi@bfQ91BPd7Gpd1 z5W2;6uXo_03o~N?uSrX>9St!JW4BFwz;HiF1>U) z>hO!`E_e5^oerX;loqZkn~mh0hVp3`1QFQ;R}|gSNc<2NC>VO=k-nnn7q`l@aYfNE zR?6Z>iZPPKG?FBQE6$iKKqkp*Ndsh*td@81V?__xMG_J8QW60}>p7CC0BM5;QZY&S znkr=E67z{=u)LkqLlXzLFm z{lwQF%#B_BsYMdpQhd3H-xNd(d#!w6-BNtK*lp#>zoqzku_0sosbVPXBJ(cjr3^gC z?c!FEeyX@$td#6NQ`(oJj1)}E&X~D}D@`8Jex_RF8$`~BEBW)~A~X7eep_ZAWE$KtgZ7TBNLD~#3{%Sb`nHSJUA>;Cu zAGKKCNwA&(r?>~zO6D^Hi}Ewch1_wmZGJXMjs s2QfzbRJGYVG?rO;=0_Al3wo(^@iRZ7tRj8Jh+ci!|EHJz>VJRzKf=+U#{d8T delta 4057 zcmYM1-)~jN5y$WD-Fxmi=i0_T#y0pjHb1I5aa@-eI|3>ZMF?YXp+XfA5nzyzFtjmL zF;syAI4#hIq;L><%tK!)C8|`Rs#0GnMQZa<^(~buRjT@uf1~PWc4rT7_v@L@?9A-W z?(tv$-G2Gcb~FF;(LXf*XkPZ(skZ&SeYroIHPu)7dGn~6>a4x|SLb&o`^#+JE?SMo zXVv5GU1sp*7u}mC|55IehBZaAQ~h__saYexlHR;4Z^@r6s&6W)ChGP5`6-WJ>Z#86 zuFeVElk8L{D}Nu}9~DT?4_5P4k2DL{XN&4Ty~k&pKz+%mx;26N#@>nwsMz*;e#}Fz zXbx0A?mPO10~tt0)X9Mij4nn6GVu0t{;kPvt5LYo#$@%6zHiIXR&U99m_KBwsrK}4%)PTN!>h{AC?^YKJc-Zb%^8_!|eSN*#G#nL{T ztG|KX*YW#?zofmd&$mhx^uFGMGg+U;viQ$zAIMMm#SpVq zGO#)`Tf58V&1SwUgl~!mUAZ5^vtRSoy@9QAzD~|1{H+tyk$s#W-KC2;==t4y=#ItU z-fX-TIwd8%nfhKkBfGa?hdhEH+=A_n3de<>A}Ycy3=GoX(!pUnpdCigqXSw5N^II; z6x;ziEE{8F`xe8livU}!F$uYtZPVqXRf|QxVu+=1bim3c+)~X+&z7`j#`kQAo=MfV za0eT2hpHv|!8D{{rRqbPJ%VtDG#m=YLz+E`l@Dq5R$?5sLkm7d6x?Ckj!KMa=oU7( z!*uJnvUOIH5F1P)~KuS{B^2DU?uahi}Yd;WR$F(k$*wQdB zs1okDHiW{8=8B#6*(2aqYEELVq~p;Bwz6wVmqVPed(t-hYY+SCFle2MIHxnD! zWj1rcH-!bRR5!-v=MvkJ-!&vh z(47?S+US^aS<$>+_c4RJUN4t{UDp$r*bMCYV7M{cg?qp8vv7DMsrS>pK3rQ4&xZY; zUkO38H+Y0fSr|zVHag)NK*4S7el5BZedCQeje_Zh-WP3ulx}D-D6#2%fdads_eEQd z(oH+25#=b|47HRjE@$axwj&zhZjOxlNk|L#LF4D4m=v!M(r}TaQp~2F6$J4%wKpgn zH}$Nb2)C)XT`DWx(g8w%mA5o~q!@LAP;j?&f>KHUw(dLv?skny%-d<$d2C>}{mxsL z6|D~&zcL|x*|87P@ET^4{v9h1W!Z8l0^ZSpC_L|^;o}8Gz&qVNzWbT1b=QVYA;9j| zn52J~1!P09f!*a2l8MYD{Zh+Du-B!Y_pJ2YFZCM%BV0+@U7q6wyJu)~w~xsvi%g^B zljNSE(Q5V1bUL6saQ6-03BkxsFEXO?HFMwarO;ja$P6@^Z-v0({J?PX1Itj0j4V@) zW2WEo1xDn1CXaC_%SOyC+J}a?A9|i!WVbbUre4Hw0$BMaE^BB_t!K zR@jdW4Gt&=^%t*DW?W=MIl0IhWyq0=mYK~8_e*0ZH8687GO`>SWEQu8Nk@*!x4LAU z7w)0qY6&^zpvZQVpbrh-6>0^2XhviP1??2>k+Hi*h zRk+87e;7jGE>L7dyFecst~9lRJ~pFr{aKe6$;YPg86(l*gFnZ!{Me*22hQaTg?nO{ z3IS1sMTW3QoSzuRLal^-Vwj77V*Df?)LaHbWauH%TlJtKK|e8iP|KX*aGx5Uxe%D) z78zM44#`8OR@hGsFI`v`^_zH5b9vuIMwF)xsRtFSch-YSFADdR6BGK6ghfYI2IOfx zGFV}s#v{XjafN%v-f2!PLLp;kT8zLm(~0%SxI8mMqtTg2&kSFUp@5_;T=l8~nHOZt zg0~P^SHNS4tSew#p1Fd4be}DTwifAbr diff --git a/common/src/proto/komp_ac.accounting.rs b/common/src/proto/komp_ac.accounting.rs index 00f9434..2b83439 100644 --- a/common/src/proto/komp_ac.accounting.rs +++ b/common/src/proto/komp_ac.accounting.rs @@ -31,6 +31,13 @@ pub struct JournalLineInput { pub description: ::prost::alloc::string::String, } #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct LockJournalRequest { + #[prost(string, tag = "1")] + pub profile_name: ::prost::alloc::string::String, + #[prost(int64, tag = "2")] + pub journal_id: i64, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] pub struct GetJournalRequest { #[prost(string, tag = "1")] pub profile_name: ::prost::alloc::string::String, @@ -167,6 +174,12 @@ pub struct Journal { /// Informational difference calculated as credits minus debits. #[prost(string, tag = "9")] pub balance: ::prost::alloc::string::String, + #[prost(bool, tag = "10")] + pub locked: bool, + #[prost(string, tag = "11")] + pub locked_at: ::prost::alloc::string::String, + #[prost(string, tag = "12")] + pub locked_by_user_id: ::prost::alloc::string::String, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] @@ -313,6 +326,29 @@ pub mod accounting_client { .insert(GrpcMethod::new("komp_ac.accounting.Accounting", "PostJournal")); self.inner.unary(req, path, codec).await } + /// Permanently lock a balanced journal. This is an explicit action; becoming + /// balanced never locks a journal automatically. + pub async fn lock_journal( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/komp_ac.accounting.Accounting/LockJournal", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("komp_ac.accounting.Accounting", "LockJournal")); + self.inner.unary(req, path, codec).await + } /// Return journal lines and credits-minus-debits informational balance. pub async fn get_journal( &mut self, @@ -443,6 +479,12 @@ pub mod accounting_server { &self, request: tonic::Request, ) -> std::result::Result, tonic::Status>; + /// Permanently lock a balanced journal. This is an explicit action; becoming + /// balanced never locks a journal automatically. + async fn lock_journal( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; /// Return journal lines and credits-minus-debits informational balance. async fn get_journal( &self, @@ -593,6 +635,51 @@ pub mod accounting_server { }; Box::pin(fut) } + "/komp_ac.accounting.Accounting/LockJournal" => { + #[allow(non_camel_case_types)] + struct LockJournalSvc(pub Arc); + impl< + T: Accounting, + > tonic::server::UnaryService + for LockJournalSvc { + type Response = super::Journal; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::lock_journal(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = LockJournalSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } "/komp_ac.accounting.Accounting/GetJournal" => { #[allow(non_camel_case_types)] struct GetJournalSvc(pub Arc); diff --git a/server b/server index 3d145bf..58f10e0 160000 --- a/server +++ b/server @@ -1 +1 @@ -Subproject commit 3d145bfc4b79c9e96fc25bff21c645d869ef7f3f +Subproject commit 58f10e086a4c6b245748d0a031fce4c2c98daa9b diff --git a/tui-pages b/tui-pages index 5ff36b0..e0f2ccb 160000 --- a/tui-pages +++ b/tui-pages @@ -1 +1 @@ -Subproject commit 5ff36b0aea5d3b7fb5918da8d51997e6f1d4429a +Subproject commit e0f2ccb3be92d3baaff532bbfbd217b936ea3fc1