diff --git a/Cargo.lock b/Cargo.lock index c1837db2..c54a26b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -104,7 +104,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -238,7 +238,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -353,9 +353,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.18" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" [[package]] name = "android-tzdata" @@ -374,9 +374,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.89" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "argon2" @@ -426,7 +426,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -497,9 +497,9 @@ dependencies = [ [[package]] name = "async-io" -version = "2.3.4" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" +checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" dependencies = [ "async-lock", "cfg-if", @@ -603,7 +603,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -792,9 +792,9 @@ dependencies = [ [[package]] name = "built" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "236e6289eda5a812bc6b53c3b024039382a2895fbbeef2d748b2931546d392c4" +checksum = "c360505aed52b7ec96a3636c3f039d99103c37d1d9b4f7a8c743d3ea9ffcd03b" [[package]] name = "bumpalo" @@ -810,24 +810,24 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "bytestring" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d80203ea6b29df88012294f62733de21cfeab47f17b41af3a38bc30a03ee72" +checksum = "e465647ae23b2823b0753f50decb2d5a86d2bb2cac04788fafd1f80e45378e5f" dependencies = [ "bytes", ] [[package]] name = "cc" -version = "1.1.30" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" +checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" dependencies = [ "jobserver", "libc", @@ -936,9 +936,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -1023,7 +1023,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -1034,7 +1034,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -1064,7 +1064,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -1074,7 +1074,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -1087,7 +1087,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -1129,7 +1129,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -1152,9 +1152,9 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "email-encoding" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60d1d33cdaede7e24091f039632eb5d3c7469fe5b066a985281a34fc70fa317f" +checksum = "ea3d894bbbab314476b265f9b2d46bf24b123a36dd0e96b06a1b49545b9d9dcc" dependencies = [ "base64 0.22.1", "memchr", @@ -1168,9 +1168,9 @@ checksum = "e079f19b08ca6239f47f8ba8509c11cf3ea30095831f7fed61441475edd8c449" [[package]] name = "encoding_rs" -version = "0.8.34" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] @@ -1183,12 +1183,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1231,15 +1231,15 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "flate2" -version = "1.0.34" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", "miniz_oxide", @@ -1310,9 +1310,9 @@ checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" -version = "2.3.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +checksum = "cef40d21ae2c515b51041df9ed313ed21e572df340ea58a922a0aefe7e8891a1" dependencies = [ "fastrand", "futures-core", @@ -1329,7 +1329,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -1464,9 +1464,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "hashlink" @@ -1486,12 +1486,6 @@ dependencies = [ "unicode-segmentation", ] -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "hermit-abi" version = "0.4.0" @@ -1709,7 +1703,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -1720,24 +1714,23 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", ] [[package]] -name = "idna" -version = "1.0.2" +name = "idna_adapter" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd69211b9b519e98303c015e21a007e293db403b6c85b9b124e133d25e242cdd" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" dependencies = [ "icu_normalizer", "icu_properties", - "smallvec", - "utf8_iter", ] [[package]] @@ -1763,7 +1756,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.15.0", + "hashbrown 0.15.2", ] [[package]] @@ -1795,9 +1788,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jobserver" @@ -1810,10 +1803,11 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "a865e038f7f6ed956f788f0d7d60c541fff74c7bd74272c5d4cf15c63743e705" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -1840,9 +1834,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "lettre" -version = "0.11.9" +version = "0.11.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f204773bab09b150320ea1c83db41dc6ee606a4bc36dc1f43005fe7b58ce06" +checksum = "0161e452348e399deb685ba05e55ee116cae9410f4f51fe42d597361444521d9" dependencies = [ "base64 0.22.1", "chumsky", @@ -1852,7 +1846,7 @@ dependencies = [ "futures-util", "hostname", "httpdate", - "idna 1.0.2", + "idna", "mime", "native-tls", "nom", @@ -1865,15 +1859,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.160" +version = "0.2.167" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0b21006cd1874ae9e650973c565615676dc4a274c965bb0a73796dac838ce4f" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" [[package]] name = "libm" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libredox" @@ -1893,9 +1887,9 @@ checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "litemap" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "local-channel" @@ -1982,11 +1976,10 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "hermit-abi 0.3.9", "libc", "log", "wasi", @@ -2079,7 +2072,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -2200,9 +2193,9 @@ checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -2229,13 +2222,13 @@ checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "polling" -version = "3.7.3" +version = "3.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" +checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" dependencies = [ "cfg-if", "concurrent-queue", - "hermit-abi 0.4.0", + "hermit-abi", "pin-project-lite", "rustix", "tracing", @@ -2271,18 +2264,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.88" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] [[package]] name = "psm" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa37f80ca58604976033fae9515a8a2989fc13797d953f7c04fb8fa36a11f205" +checksum = "200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810" dependencies = [ "cc", ] @@ -2373,9 +2366,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -2385,9 +2378,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -2453,9 +2446,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.37" +version = "0.38.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" dependencies = [ "bitflags 2.6.0", "errno", @@ -2493,9 +2486,9 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "schannel" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ "windows-sys 0.59.0", ] @@ -2531,9 +2524,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.12.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" dependencies = [ "core-foundation-sys", "libc", @@ -2547,29 +2540,29 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.210" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", "memchr", @@ -2643,9 +2636,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -2831,9 +2824,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.79" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -2848,14 +2841,14 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] name = "tempfile" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", "fastrand", @@ -2866,22 +2859,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.64" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -2942,9 +2935,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.40.0" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", @@ -2972,9 +2965,9 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", @@ -2983,9 +2976,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", ] @@ -2998,12 +2991,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicase" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] +checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" [[package]] name = "unicode-bidi" @@ -3013,9 +3003,9 @@ checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-normalization" @@ -3068,12 +3058,12 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.2" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", - "idna 0.5.0", + "idna", "percent-encoding", ] @@ -3097,9 +3087,9 @@ checksum = "4e8257fbc510f0a46eb602c10215901938b5c2a7d5e70fc11483b1d3c9b5b18c" [[package]] name = "value-bag" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" +checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2" [[package]] name = "vcpkg" @@ -3127,9 +3117,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "d15e63b4482863c109d70a7b8706c1e364eb6ea449b201a76c5b89cedcec2d5c" dependencies = [ "cfg-if", "once_cell", @@ -3138,36 +3128,37 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "8d36ef12e3aaca16ddd3f67922bc63e48e953f126de60bd33ccc0101ef9998cd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.45" +version = "0.4.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" +checksum = "9dfaf8f50e5f293737ee323940c7d8b08a66a95a419223d9f41610ca08b0833d" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "705440e08b42d3e4b36de7d66c944be628d579796b8090bfa3471478a2260051" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3175,28 +3166,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "98c9ae5a76e46f4deecd0f0255cc223cfa18dc9b261213b8aa0c7b36f61b3f1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "6ee99da9c5ba11bd675621338ef6fa52296b76b83305e9b6e5c77d4c286d6d49" [[package]] name = "web-sys" -version = "0.3.72" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +checksum = "a98bc3c33f0fe7e59ad7cd041b89034fa82a7c2d4365ca538dda6cdaf513863c" dependencies = [ "js-sys", "wasm-bindgen", @@ -3369,9 +3360,9 @@ checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" [[package]] name = "yoke" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" dependencies = [ "serde", "stable_deref_trait", @@ -3381,13 +3372,13 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", "synstructure", ] @@ -3409,27 +3400,27 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] name = "zerofrom" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", "synstructure", ] @@ -3452,7 +3443,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] diff --git a/src/endpoints/assignment/delete.rs b/src/endpoints/assignment/delete.rs new file mode 100644 index 00000000..dd4e1c31 --- /dev/null +++ b/src/endpoints/assignment/delete.rs @@ -0,0 +1,65 @@ +use actix_web::{web, HttpResponse, Responder}; +use askama_actix::TemplateToResponse; +use serde::Deserialize; +use sqlx::PgPool; + +use crate::{ + endpoints::assignment::PlanEventPersonalTablePartialTemplate, + models::{Assignment, Event, Role, User}, + utils::{ + event_planning_template::{ + generate_availabillity_assignment_list, generate_status_whether_staff_is_required, + }, + ApplicationError, + }, +}; + +#[derive(Deserialize)] +struct AssignmentDeleteQuery { + availabillity: i32, + event: i32, +} + +#[actix_web::delete("/assignments/delete")] +pub async fn delete( + user: web::ReqData, + pool: web::Data, + query: web::Query, +) -> Result { + let Some(event) = Event::read_by_id_including_location(pool.get_ref(), query.event).await? + else { + return Ok(HttpResponse::NotFound().finish()); + }; + + let user_is_admin_or_area_manager_of_event_area = user.role == Role::Admin + || (user.role == Role::AreaManager + && user.area_id == event.location.as_ref().unwrap().area_id); + + if !user_is_admin_or_area_manager_of_event_area { + return Err(ApplicationError::Unauthorized); + } + + let Some(assignment) = Assignment::read(pool.get_ref(), event.id, query.availabillity).await? + else { + return Ok(HttpResponse::NotFound().finish()); + }; + + Assignment::delete(pool.get_ref(), event.id, assignment.availabillity_id).await?; + + let availabillities = generate_availabillity_assignment_list(pool.get_ref(), &event).await?; + let ( + further_posten_required, + further_fuehrungsassistent_required, + further_wachhabender_required, + ) = generate_status_whether_staff_is_required(pool.get_ref(), &event).await?; + + let template = PlanEventPersonalTablePartialTemplate { + event, + availabillities, + further_posten_required, + further_fuehrungsassistent_required, + further_wachhabender_required, + }; + + Ok(template.to_response()) +} diff --git a/src/endpoints/assignment/get_new.rs b/src/endpoints/assignment/get_new.rs deleted file mode 100644 index 264d397a..00000000 --- a/src/endpoints/assignment/get_new.rs +++ /dev/null @@ -1,46 +0,0 @@ -use actix_identity::Identity; -use actix_web::{web, HttpResponse, Responder}; -use askama::Template; -use askama_actix::TemplateToResponse; -use serde::Deserialize; -use sqlx::PgPool; - -use crate::models::{Availabillity, Event, Function, Role, User}; - -#[derive(Deserialize)] -pub struct EventQuery { - event: i32 -} - -#[derive(Template)] -#[template(path = "assignment/new.html")] -pub struct NewAssignmentTemplate { - user: User, - event: Event, - available_wachhabende: Vec, - available_posten: Vec, - all: Vec -} - -#[actix_web::get("/assignments/new")] -pub async fn get(user: Identity, pool: web::Data, query: web::Query) -> impl Responder { - //let current_user = User::read_by_id(pool.get_ref(), user.id().unwrap().parse().unwrap()) - // .await - // .unwrap(); - // - //if let Ok(event) = Event::read_by_id_including_location(pool.get_ref(), query.event).await { - // if current_user.role == Role::Admin || current_user.role == Role::AreaManager && event.location.as_ref().unwrap().area_id == current_user.area_id { - // let all = Availabillity::read_not_assigned_by_date_including_user(pool.get_ref(), event.date).await.unwrap(); - // let available_posten = Availabillity::read_not_assigned_by_date_including_user(pool.get_ref(), event.date).await.unwrap(); - // let available_wachhabende = available_posten.iter().filter(|a| a.user.as_ref().unwrap().function == Function::Wachhabender).map(|avl| avl.clone()).collect(); - // - // let template = NewAssignmentTemplate { user: current_user, event, available_wachhabende, available_posten, all }; - // - // return template.to_response(); - // } - // - // return HttpResponse::Unauthorized().finish(); - //} - - HttpResponse::BadRequest().body("Fehler beim Laden für Assignment") -} diff --git a/src/endpoints/assignment/mod.rs b/src/endpoints/assignment/mod.rs index 661e73cf..2a3db9c2 100644 --- a/src/endpoints/assignment/mod.rs +++ b/src/endpoints/assignment/mod.rs @@ -1,2 +1,19 @@ -pub mod get_new; +use askama::Template; + +use crate::{ + filters, + models::{Availabillity, AvailabillityAssignmentState, Event, Function}, +}; + +pub mod delete; pub mod post_new; + +#[derive(Template)] +#[template(path = "events/plan_personal_table.html")] +pub struct PlanEventPersonalTablePartialTemplate { + event: Event, + availabillities: Vec<(Availabillity, AvailabillityAssignmentState)>, + further_posten_required: bool, + further_fuehrungsassistent_required: bool, + further_wachhabender_required: bool, +} diff --git a/src/endpoints/assignment/post_new.rs b/src/endpoints/assignment/post_new.rs index 465f1ba1..4aec4261 100644 --- a/src/endpoints/assignment/post_new.rs +++ b/src/endpoints/assignment/post_new.rs @@ -1,59 +1,112 @@ +use std::ops::AddAssign; + use actix_web::{web, HttpResponse, Responder}; +use askama_actix::TemplateToResponse; use serde::Deserialize; use sqlx::PgPool; -use crate::models::{Assignment, Event, Function}; +use crate::{ + endpoints::assignment::PlanEventPersonalTablePartialTemplate, + models::{Assignment, Availabillity, Event, Function, Role, User}, + utils::{ + event_planning_template::{ + generate_availabillity_assignment_list, generate_status_whether_staff_is_required, + }, + ApplicationError, + }, +}; #[derive(Deserialize)] -pub struct NewAssignmentsForm { +pub struct AssignmentQuery { + availabillity: i32, + function: u8, event: i32, - wachhabender: Option, - posten: Vec } #[actix_web::post("/assignments/new")] -pub async fn post(pool: web::Data, form: web::Form>) -> impl Responder { - //let event_id = form.iter().find(|x| x.0 == "event").unwrap().1.parse().unwrap(); - //let wachhabender = form.iter().find(|x| x.0 == "wachhabender"); - //let posten: Vec = form.iter().filter(|x| x.0 == "posten").map(|x| x.1.parse().unwrap()).collect(); - // - //let event = Event::read_by_id_including_location(&pool, event_id).await.unwrap(); // TODO: Check if location is needed - // - //if event.voluntary_wachhabender && wachhabender.is_some() && posten.contains(&wachhabender.unwrap().1.parse().unwrap()) { - // return HttpResponse::BadRequest().body("Wachhabender kann nicht zugleich Posten sein!"); - //} - // - //let mut joined_ids = posten.clone(); - //if let Some((_,id)) = wachhabender { - // joined_ids.push(id.parse().unwrap()); - //} - // - //for availabillity_id in joined_ids { - // let assignments = Assignment::read_by_availabillity(pool.get_ref(), availabillity_id).await.unwrap(); - // - // let mut can_be_used = true; - // - // - // for assignment in assignments { - // if event.start_time >= assignment.start_time && event.start_time <= assignment.end_time { - // } else { - // can_be_used = false; - // break; - // } - // } - // - // if !can_be_used { - // return HttpResponse::BadRequest().body("availabillity time slot bereits genutzt!"); - // } - //} - // - //if let Some((_,id)) = wachhabender { - // Assignment::create(pool.get_ref(), event.id, id.parse().unwrap(), Function::Wachhabender, event.start_time, event.end_time).await.unwrap(); - //} - // - //for id in posten { - // Assignment::create(pool.get_ref(), event.id, id, Function::Posten, event.start_time, event.end_time).await.unwrap(); - //} - // - HttpResponse::Ok().finish() +pub async fn post( + user: web::ReqData, + pool: web::Data, + query: web::Query, +) -> Result { + let Some(event) = Event::read_by_id_including_location(pool.get_ref(), query.event).await? + else { + return Ok(HttpResponse::NotFound().finish()); + }; + + let user_is_admin_or_area_manager_of_event_area = user.role == Role::Admin + || (user.role == Role::AreaManager + && user.area_id == event.location.as_ref().unwrap().area_id); + + if !user_is_admin_or_area_manager_of_event_area { + return Err(ApplicationError::Unauthorized); + } + + let Some(availability) = + Availabillity::read_by_id_including_user(pool.get_ref(), query.availabillity).await? + else { + return Ok(HttpResponse::NotFound().finish()); + }; + + let availability_user_not_in_event_location_area = + availability.user.as_ref().unwrap().area_id != event.location.as_ref().unwrap().area_id; + + let existing_assignments_for_availabillity = + Assignment::read_all_by_availabillity(pool.get_ref(), availability.id).await?; + let has_start_time_during_event = + |a: &Assignment| a.start_time >= event.start_time && a.start_time <= event.end_time; + let has_end_time_during_event = + |a: &Assignment| a.end_time >= event.start_time && a.end_time <= event.end_time; + + let availability_already_assigned = existing_assignments_for_availabillity + .iter() + .any(|a| has_start_time_during_event(a) || has_end_time_during_event(a)); + + let function = Function::try_from(query.function)?; + let user_not_qualified_for_assigned_function = + availability.user.as_ref().unwrap().function < function; + + let a = Assignment::count_by_event_and_function(pool.get_ref(), event.id, function).await?; + let event_already_has_enough_assignments_for_function = match function { + Function::Posten => a >= event.amount_of_posten as i64, + Function::Fuehrungsassistent => event.voluntary_wachhabender && a >= 1, + Function::Wachhabender => event.voluntary_wachhabender && a >= 1, + }; + + if availability_user_not_in_event_location_area + || availability_already_assigned + || user_not_qualified_for_assigned_function + || event_already_has_enough_assignments_for_function + { + // TODO: Fehlermeldung verbessern + return Ok(HttpResponse::BadRequest().body(format!("{availability_user_not_in_event_location_area} {availability_already_assigned} {user_not_qualified_for_assigned_function} {event_already_has_enough_assignments_for_function}"))); + } + + Assignment::create( + pool.get_ref(), + event.id, + availability.id, + function, + event.start_time, + event.end_time, + ) + .await?; + + let availabillities = generate_availabillity_assignment_list(pool.get_ref(), &event).await?; + + let ( + further_posten_required, + further_fuehrungsassistent_required, + further_wachhabender_required, + ) = generate_status_whether_staff_is_required(pool.get_ref(), &event).await?; + + let template = PlanEventPersonalTablePartialTemplate { + event, + availabillities, + further_posten_required, + further_fuehrungsassistent_required, + further_wachhabender_required, + }; + + Ok(template.to_response()) } diff --git a/src/endpoints/events/get_plan.rs b/src/endpoints/events/get_plan.rs index cc786cea..b5717bc1 100644 --- a/src/endpoints/events/get_plan.rs +++ b/src/endpoints/events/get_plan.rs @@ -1,13 +1,18 @@ use actix_web::{web, HttpResponse, Responder}; use askama::Template; use askama_actix::TemplateToResponse; -use chrono::NaiveDate; use sqlx::PgPool; use crate::{ - endpoints::{IdPath, NaiveDateQuery}, - models::{Assignment, Availabillity, Event, Function, Location, Role, User}, - utils::ApplicationError, + endpoints::IdPath, + filters, + models::{Availabillity, AvailabillityAssignmentState, Event, Function, Role, User}, + utils::{ + event_planning_template::{ + generate_availabillity_assignment_list, generate_status_whether_staff_is_required, + }, + ApplicationError, + }, }; #[derive(Template)] @@ -15,20 +20,10 @@ use crate::{ pub struct PlanEventTemplate { user: User, event: Event, - availabillities: Vec<(Availabillity, AssignmentState)>, -} - -enum AssignmentState { - // availabillity is not assigned at all or at least not timely conflicting - Unassigned, - // availabillity is assigned for another event that is timely conflicting - Conflicting, - // availabillity is assigned to this event as Posten - AssignedPosten, - // availabillity is assigned to this event as Führungsassistent - AssignedFührungsassistent, - // availabillity is assigned to this event as Wachhabender - AssignedWachahabender, + availabillities: Vec<(Availabillity, AvailabillityAssignmentState)>, + further_posten_required: bool, + further_fuehrungsassistent_required: bool, + further_wachhabender_required: bool, } #[actix_web::get("/events/{id}/plan")] @@ -49,52 +44,21 @@ pub async fn get( return Err(ApplicationError::Unauthorized); } - let availabillities_in_db = Availabillity::read_by_date_and_area_including_user( - pool.get_ref(), - event.date, - event.location.as_ref().unwrap().area_id, - ) - .await?; + let availabillities = generate_availabillity_assignment_list(pool.get_ref(), &event).await?; - let mut availabillities = Vec::new(); - for availabillity in availabillities_in_db { - let assignments = - Assignment::read_all_by_availabillity(pool.get_ref(), availabillity.id).await?; - - if let Some(assignment) = assignments - .iter() - .find(|assignment| assignment.event_id == event.id) - { - let state = match assignment.function { - Function::Posten => AssignmentState::AssignedPosten, - Function::Fuehrungsassistent => AssignmentState::AssignedFührungsassistent, - Function::Wachhabender => AssignmentState::AssignedWachahabender, - }; - - availabillities.push((availabillity, state)); - continue; - } - - let has_start_time_during_event = - |a: &Assignment| a.start_time >= event.start_time && a.start_time <= event.end_time; - let has_end_time_during_event = - |a: &Assignment| a.end_time >= event.start_time && a.end_time <= event.end_time; - - if assignments - .iter() - .any(|a| has_start_time_during_event(a) || has_end_time_during_event(a)) - { - availabillities.push((availabillity, AssignmentState::Conflicting)); - continue; - } - - availabillities.push((availabillity, AssignmentState::Unassigned)); - } + let ( + further_posten_required, + further_fuehrungsassistent_required, + further_wachhabender_required, + ) = generate_status_whether_staff_is_required(pool.get_ref(), &event).await?; let template = PlanEventTemplate { user: user.into_inner(), event, availabillities, + further_posten_required, + further_fuehrungsassistent_required, + further_wachhabender_required, }; Ok(template.to_response()) diff --git a/src/endpoints/mod.rs b/src/endpoints/mod.rs index bbdc2bce..f4c6b645 100644 --- a/src/endpoints/mod.rs +++ b/src/endpoints/mod.rs @@ -59,8 +59,8 @@ pub fn init(cfg: &mut ServiceConfig) { cfg.service(events::post_new::post); cfg.service(events::get_plan::get); - cfg.service(assignment::get_new::get); cfg.service(assignment::post_new::post); + cfg.service(assignment::delete::delete); cfg.service(area::get_new::get); cfg.service(area::post_new::post); diff --git a/src/endpoints/user/post_register.rs b/src/endpoints/user/post_register.rs index 129ad1b1..b11b208e 100644 --- a/src/endpoints/user/post_register.rs +++ b/src/endpoints/user/post_register.rs @@ -31,7 +31,7 @@ async fn post( let response = handle_password_change_request( pool.get_ref(), Some(&token), - token.id, + token.userid, &form.password, &form.passwordretyped, None, diff --git a/src/endpoints/user/post_reset.rs b/src/endpoints/user/post_reset.rs index 016b1a6d..4a2d3e43 100644 --- a/src/endpoints/user/post_reset.rs +++ b/src/endpoints/user/post_reset.rs @@ -57,7 +57,7 @@ async fn post( let response = handle_password_change_request( pool.get_ref(), Some(&token), - token.id, + token.userid, form.password.as_ref().unwrap(), form.passwordretyped.as_ref().unwrap(), None, diff --git a/src/models/assignement.rs b/src/models/assignement.rs index 23155a4d..638fb861 100644 --- a/src/models/assignement.rs +++ b/src/models/assignement.rs @@ -70,4 +70,97 @@ impl Assignment { Ok(assignemnets) } + + pub async fn read_all_by_event(pool: &PgPool, event_id: i32) -> Result> { + let records = query!( + r##" + SELECT + assignment.eventId, + assignment.availabillityId, + assignment.function AS "function: Function", + assignment.startTime, + assignment.endTime + FROM assignment + WHERE assignment.eventId = $1; + "##, + event_id, + ) + .fetch_all(pool) + .await?; + + let assignemnets = records + .iter() + .map(|r| Assignment { + event_id: r.eventid, + availabillity_id: r.availabillityid, + function: r.function, + start_time: r.starttime, + end_time: r.endtime, + }) + .collect(); + + Ok(assignemnets) + } + + pub async fn count_by_event_and_function( + pool: &PgPool, + event_id: i32, + function: Function, + ) -> Result { + let result = query!("SELECT count(*) FROM assignment WHERE assignment.eventId = $1 AND assignment.function = $2;", + event_id, + function as Function + ) + .fetch_one(pool) + .await?; + + Ok(result.count.unwrap_or(0)) + } + + pub async fn read( + pool: &PgPool, + event_id: i32, + availabillity_id: i32, + ) -> Result> { + let record = query!( + r##" + SELECT + assignment.eventId, + assignment.availabillityId, + assignment.function AS "function: Function", + assignment.startTime, + assignment.endTime + FROM assignment + WHERE + assignment.eventId = $1 AND + assignment.availabillityId = $2; + "##, + event_id, + availabillity_id + ) + .fetch_optional(pool) + .await?; + + let assignemnet = record.and_then(|r| { + Some(Assignment { + event_id: r.eventid, + availabillity_id: r.availabillityid, + function: r.function, + start_time: r.starttime, + end_time: r.endtime, + }) + }); + + Ok(assignemnet) + } + + pub async fn delete(pool: &PgPool, event_id: i32, availabillity_id: i32) -> Result<()> { + query!("DELETE FROM assignment WHERE assignment.eventId = $1 AND assignment.availabillityId = $2;", + event_id, + availabillity_id + ) + .execute(pool) + .await?; + Ok(()) + } } diff --git a/src/models/availabillity.rs b/src/models/availabillity.rs index 37a767ff..d05d877b 100644 --- a/src/models/availabillity.rs +++ b/src/models/availabillity.rs @@ -1,9 +1,11 @@ +use std::fmt::Display; + use chrono::{NaiveDate, NaiveTime}; use sqlx::{query, PgPool}; use super::{Area, Function, Result, Role, User}; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct Availabillity { pub id: i32, pub user_id: i32, @@ -14,6 +16,32 @@ pub struct Availabillity { pub comment: Option, } +#[derive(PartialEq, Eq, Debug)] +pub enum AvailabillityAssignmentState { + // availabillity is not assigned at all or at least not timely conflicting + Unassigned, + // availabillity is assigned for another event that is timely conflicting + Conflicting, + // availabillity is assigned to this event as Posten + AssignedPosten(i32), + // availabillity is assigned to this event as Führungsassistent + AssignedFührungsassistent(i32), + // availabillity is assigned to this event as Wachhabender + AssignedWachahabender(i32), +} + +impl Display for AvailabillityAssignmentState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + AvailabillityAssignmentState::Unassigned => write!(f, "nicht zugewiesen"), + AvailabillityAssignmentState::Conflicting => write!(f, "bereits anders zugewiesen"), + AvailabillityAssignmentState::AssignedPosten(_) => write!(f, "zugewiesen als Posten"), + AvailabillityAssignmentState::AssignedFührungsassistent(_) => write!(f, "zugewiesen als Führungsassistent"), + AvailabillityAssignmentState::AssignedWachahabender(_) => write!(f, "zugewiesen als Wachhabender"), + } + } +} + impl Availabillity { pub async fn create( pool: &PgPool, @@ -104,11 +132,11 @@ impl Availabillity { Ok(availabillities) } - pub async fn read_not_assigned_by_date_including_user( + pub async fn read_by_id_including_user( pool: &PgPool, - date: NaiveDate, - ) -> Result> { - let records = query!( + id: i32, + ) -> Result> { + let record = query!( r##" SELECT availabillity.id, @@ -130,16 +158,15 @@ impl Availabillity { FROM availabillity LEFT JOIN assignment ON availabillity.Id = assignment.availabillityId JOIN user_ ON availabillity.userId = user_.id - WHERE availabillity.date = $1; + WHERE availabillity.id = $1; "##, - date + id ) - .fetch_all(pool) + .fetch_optional(pool) .await?; - let availabillities = records - .iter() - .map(|r| Availabillity { + let availabillity = record.and_then(|r| { + Some(Availabillity { id: r.id, user_id: r.userid, user: Some(User { @@ -161,9 +188,9 @@ impl Availabillity { end_time: r.endtime, comment: r.comment.clone(), }) - .collect(); + }); - Ok(availabillities) + Ok(availabillity) } pub async fn read_by_id(pool: &PgPool, id: i32) -> Result> { diff --git a/src/models/function.rs b/src/models/function.rs index b03bed16..584d99e7 100644 --- a/src/models/function.rs +++ b/src/models/function.rs @@ -4,7 +4,7 @@ use serde::Serialize; use crate::utils::ApplicationError; -#[derive(sqlx::Type, Debug, Clone, Copy, PartialEq, Eq, Serialize)] +#[derive(sqlx::Type, Debug, Clone, Copy, PartialEq, Eq, Serialize, PartialOrd, Ord)] #[sqlx(type_name = "function", rename_all = "lowercase")] pub enum Function { Posten = 1, diff --git a/src/models/location.rs b/src/models/location.rs index ed8983a8..7d2bacd1 100644 --- a/src/models/location.rs +++ b/src/models/location.rs @@ -19,7 +19,7 @@ impl Location { name, area_id ) - .fetch_one(pool) + .execute(pool) .await?; Ok(()) diff --git a/src/models/mod.rs b/src/models/mod.rs index 95b7a2d3..12262251 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -12,7 +12,7 @@ mod registration; mod vehicle_assignement; pub use area::Area; -pub use availabillity::Availabillity; +pub use availabillity::{Availabillity, AvailabillityAssignmentState}; pub use event::Event; pub use function::Function; pub use location::Location; diff --git a/src/utils/event_planning_template.rs b/src/utils/event_planning_template.rs new file mode 100644 index 00000000..14e3f284 --- /dev/null +++ b/src/utils/event_planning_template.rs @@ -0,0 +1,93 @@ +use sqlx::PgPool; + +use crate::models::{Assignment, Availabillity, AvailabillityAssignmentState, Event, Function}; + +use super::ApplicationError; + +pub async fn generate_availabillity_assignment_list( + pool: &PgPool, + event: &Event, +) -> Result, ApplicationError> { + let availabillities_in_db = Availabillity::read_by_date_and_area_including_user( + pool, + event.date, + event.location.as_ref().unwrap().area_id, + ) + .await?; + + let mut availabillities = Vec::new(); + for availabillity in availabillities_in_db { + let assignments = Assignment::read_all_by_availabillity(pool, availabillity.id).await?; + + if let Some(assignment) = assignments + .iter() + .find(|assignment| assignment.event_id == event.id) + { + let state = match assignment.function { + Function::Posten => { + AvailabillityAssignmentState::AssignedPosten(assignment.availabillity_id) + } + Function::Fuehrungsassistent => { + AvailabillityAssignmentState::AssignedFührungsassistent( + assignment.availabillity_id, + ) + } + Function::Wachhabender => { + AvailabillityAssignmentState::AssignedWachahabender(assignment.availabillity_id) + } + }; + + availabillities.push((availabillity, state)); + continue; + } + + let has_start_time_during_event = + |a: &Assignment| a.start_time >= event.start_time && a.start_time <= event.end_time; + let has_end_time_during_event = + |a: &Assignment| a.end_time >= event.start_time && a.end_time <= event.end_time; + + if assignments + .iter() + .any(|a| has_start_time_during_event(a) || has_end_time_during_event(a)) + { + availabillities.push((availabillity, AvailabillityAssignmentState::Conflicting)); + continue; + } + + availabillities.push((availabillity, AvailabillityAssignmentState::Unassigned)); + } + + //println!(" {availabillities:#?}"); + Ok(availabillities) +} + +pub async fn generate_status_whether_staff_is_required( + pool: &PgPool, + event: &Event, +) -> Result<(bool, bool, bool), ApplicationError> { + let existing_assignments_for_event = Assignment::read_all_by_event(pool, event.id).await?; + + let further_posten_required = existing_assignments_for_event + .iter() + .filter(|a| a.function == Function::Posten) + .count() + < event.amount_of_posten as usize; + + // TODO change to Fuehrungsassistent + let further_fuehrungsassistent_required = event.voluntary_wachhabender + && existing_assignments_for_event + .iter() + .all(|a| a.function != Function::Fuehrungsassistent); + + let further_wachhabender_required = event.voluntary_wachhabender + && existing_assignments_for_event + .iter() + .all(|a| a.function != Function::Wachhabender); + + //println!("further_posten {further_posten_required}"); + Ok(( + further_posten_required, + further_fuehrungsassistent_required, + further_wachhabender_required, + )) +} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 7de1757e..4f1ebc57 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -2,6 +2,7 @@ pub mod email; pub mod manage_commands; pub mod password_help; pub mod token_generation; +pub mod event_planning_template; mod application_error; pub use application_error::ApplicationError; diff --git a/static/style.scss b/static/style.scss index 11ebc158..846eaea3 100644 --- a/static/style.scss +++ b/static/style.scss @@ -38,6 +38,7 @@ $primary: $crimson, @forward "bulma/sass/helpers/spacing"; @forward "bulma/sass/helpers/flexbox"; +@forward "bulma/sass/helpers/color"; // Import the themes so that all CSS variables have a value @forward "bulma/sass/themes"; diff --git a/templates/events/plan.html b/templates/events/plan.html index cd8052ce..02ab6ff7 100644 --- a/templates/events/plan.html +++ b/templates/events/plan.html @@ -51,8 +51,14 @@
Einteilung Personal
- +
+ + + + Alle Plätze verplant! +
+ {% include "plan_personal_table.html" %}
diff --git a/templates/events/plan_personal_table.html b/templates/events/plan_personal_table.html new file mode 100644 index 00000000..52858e8f --- /dev/null +++ b/templates/events/plan_personal_table.html @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + {% for (availabillity, status) in availabillities %} + {% let u = availabillity.user.as_ref().unwrap() %} + + + + + + + + + + {% endfor %} + +
NameFunktionZeitraumKommentarStatusPlanen als
{{ u.name }} + {{ u.function|show_tree|safe }} + + {% if availabillity.start_time.is_some() && availabillity.end_time.is_some() %} + {{ availabillity.start_time.as_ref().unwrap().format("%R") }} bis {{ + availabillity.end_time.as_ref().unwrap().format("%R") }} + {% else %} + ganztägig + {% endif %} + + {{ availabillity.comment.as_deref().unwrap_or("") }} + + {{ status }} + +
+ + {% if u.function == Function::Wachhabender || u.function == Function::Fuehrungsassistent %} + + {% endif %} + {% if u.function == Function::Wachhabender %} + + {% endif %} +
+
+ {% if status != AvailabillityAssignmentState::Unassigned|as_ref && status != + AvailabillityAssignmentState::Conflicting|as_ref %} + + {% endif %} +