diff --git a/Cargo.lock b/Cargo.lock index 39a27e5..d94d539 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -492,9 +492,9 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" +checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" [[package]] name = "der" @@ -717,16 +717,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" -[[package]] -name = "errno" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" -dependencies = [ - "libc", - "windows-sys 0.61.2", -] - [[package]] name = "event-listener" version = "5.4.1" @@ -788,21 +778,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.2" @@ -1062,7 +1037,6 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "htycommons" version = "0.1.0" -source = "git+https://github.com/alchemy-studio/AuthCore.git#5a050a8fbe9b44f43e728c7be8ebbcb34e7fb4c2" dependencies = [ "aes", "anyhow", @@ -1076,12 +1050,12 @@ dependencies = [ "dotenv", "hex", "hex-literal", - "jsonwebtoken 9.3.1", + "jsonwebtoken", "log", "log4rs", - "rand 0.9.2", - "redis 0.24.0", - "reqwest 0.12.24", + "rand 0.10.0", + "redis", + "reqwest", "ring", "rust-crypto", "serde", @@ -1126,11 +1100,11 @@ dependencies = [ "htycommons", "htyuc_models", "htyws_models", - "jsonwebtoken 10.2.0", + "jsonwebtoken", "log", "log4rs", "rand 0.10.0", - "reqwest 0.13.2", + "reqwest", "ring", "rust-crypto", "serde", @@ -1157,8 +1131,8 @@ dependencies = [ "dotenv", "htycommons", "htyts_models", - "redis 1.1.0", - "reqwest 0.13.2", + "redis", + "reqwest", "serde", "serde_json", "tokio", @@ -1179,8 +1153,8 @@ dependencies = [ "htycommons", "htyts_models", "once_cell", - "redis 1.1.0", - "reqwest 0.13.2", + "redis", + "reqwest", "serde", "serde_json", "tokio", @@ -1205,14 +1179,13 @@ dependencies = [ [[package]] name = "htyuc_models" version = "0.1.0" -source = "git+https://github.com/alchemy-studio/AuthCore.git#5a050a8fbe9b44f43e728c7be8ebbcb34e7fb4c2" dependencies = [ "anyhow", "chrono", "diesel", "htycommons", "log", - "reqwest 0.12.24", + "reqwest", "serde", "serde_json", "tokio", @@ -1222,7 +1195,6 @@ dependencies = [ [[package]] name = "htyuc_remote" version = "0.1.0" -source = "git+https://github.com/alchemy-studio/AuthCore.git#5a050a8fbe9b44f43e728c7be8ebbcb34e7fb4c2" dependencies = [ "aes", "anyhow", @@ -1236,11 +1208,11 @@ dependencies = [ "hex-literal", "htycommons", "htyuc_models", - "jsonwebtoken 9.3.1", + "jsonwebtoken", "log", "log4rs", - "rand 0.9.2", - "reqwest 0.12.24", + "rand 0.10.0", + "reqwest", "ring", "rust-crypto", "serde", @@ -1270,7 +1242,7 @@ dependencies = [ "htyuc_models", "htyuc_remote", "htyws_models", - "reqwest 0.13.2", + "reqwest", "serde", "serde_json", "time 0.3.44", @@ -1340,22 +1312,6 @@ dependencies = [ "tower-service", ] -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - [[package]] name = "hyper-util" version = "0.1.18" @@ -1374,7 +1330,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.1", + "socket2", "system-configuration", "tokio", "tower-service", @@ -1606,21 +1562,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "jsonwebtoken" -version = "9.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" -dependencies = [ - "base64", - "js-sys", - "pem", - "ring", - "serde", - "serde_json", - "simple_asn1", -] - [[package]] name = "jsonwebtoken" version = "10.2.0" @@ -1671,12 +1612,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" -[[package]] -name = "linux-raw-sys" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" - [[package]] name = "litemap" version = "0.8.1" @@ -1786,23 +1721,6 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dce6dd36094cac388f119d2e9dc82dc730ef91c32a6222170d630e5414b956e6" -[[package]] -name = "native-tls" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe 0.1.6", - "openssl-sys", - "schannel", - "security-framework 2.11.1", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -1889,56 +1807,12 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" -[[package]] -name = "openssl" -version = "0.10.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" -dependencies = [ - "bitflags", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - [[package]] name = "openssl-probe" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" -[[package]] -name = "openssl-sys" -version = "0.9.111" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "ordered-float" version = "2.10.1" @@ -2141,7 +2015,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.6.1", + "socket2", "thiserror 2.0.17", "tokio", "tracing", @@ -2179,7 +2053,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.1", + "socket2", "tracing", "windows-sys 0.60.2", ] @@ -2339,21 +2213,6 @@ dependencies = [ "rand_core 0.3.1", ] -[[package]] -name = "redis" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c580d9cbbe1d1b479e8d67cf9daf6a62c957e6846048408b80b43ac3f6af84cd" -dependencies = [ - "combine", - "itoa", - "percent-encoding", - "ryu", - "sha1_smol", - "socket2 0.4.10", - "url", -] - [[package]] name = "redis" version = "1.1.0" @@ -2375,7 +2234,7 @@ dependencies = [ "pin-project-lite", "ryu", "sha1_smol", - "socket2 0.6.1", + "socket2", "tokio", "tokio-util", "url", @@ -2408,48 +2267,6 @@ version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" -[[package]] -name = "reqwest" -version = "0.12.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" -dependencies = [ - "base64", - "bytes", - "encoding_rs", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-tls", - "hyper-util", - "js-sys", - "log", - "mime", - "native-tls", - "percent-encoding", - "pin-project-lite", - "rustls-pki-types", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tokio-native-tls", - "tower", - "tower-http", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - [[package]] name = "reqwest" version = "0.13.2" @@ -2480,6 +2297,7 @@ dependencies = [ "rustls-platform-verifier", "serde", "serde_json", + "serde_urlencoded", "sync_wrapper", "tokio", "tokio-rustls", @@ -2570,19 +2388,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.61.2", -] - [[package]] name = "rustls" version = "0.23.35" @@ -2603,10 +2408,10 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ - "openssl-probe 0.2.1", + "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.5.1", + "security-framework", ] [[package]] @@ -2634,7 +2439,7 @@ dependencies = [ "rustls-native-certs", "rustls-platform-verifier-android", "rustls-webpki", - "security-framework 3.5.1", + "security-framework", "security-framework-sys", "webpki-root-certs", "windows-sys 0.61.2", @@ -2717,19 +2522,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags", - "core-foundation 0.9.4", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - [[package]] name = "security-framework" version = "3.5.1" @@ -2923,16 +2715,6 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" -[[package]] -name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "socket2" version = "0.6.1" @@ -3035,19 +2817,6 @@ dependencies = [ "libc", ] -[[package]] -name = "tempfile" -version = "3.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" -dependencies = [ - "fastrand", - "getrandom 0.3.4", - "once_cell", - "rustix", - "windows-sys 0.61.2", -] - [[package]] name = "thiserror" version = "1.0.69" @@ -3178,9 +2947,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.48.0" +version = "1.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" dependencies = [ "bytes", "libc", @@ -3188,7 +2957,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.6.1", + "socket2", "tokio-macros", "windows-sys 0.61.2", ] @@ -3204,16 +2973,6 @@ dependencies = [ "syn", ] -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.4" @@ -3439,13 +3198,13 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.18.1" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ - "getrandom 0.3.4", + "getrandom 0.4.2", "js-sys", - "serde", + "serde_core", "wasm-bindgen", ] diff --git a/Cargo.toml b/Cargo.toml index 6e74db2..5d31898 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,11 @@ members = [ ] resolver = "2" +[patch."https://github.com/alchemy-studio/AuthCore.git"] +htycommons = { path = "../AuthCore/htycommons" } +htyuc_models = { path = "../AuthCore/htyuc_models" } +htyuc_remote = { path = "../AuthCore/htyuc_remote" } + [workspace.package] version = "0.1.0" authors = ["阿男 ", "buddy"] @@ -42,7 +47,7 @@ tower-http = { version = "^0.6", features = ["trace"] } tracing = { version = "^0.1" } tracing-appender = "^0.2" tracing-subscriber = { version = "^0.3", features = ["env-filter", "local-time"] } -uuid = { version = "^1.16", features = ["serde", "v4"] } +uuid = { version = "^1.22", features = ["serde", "v4"] } url = "^2.5" string-builder = "*" redis = { version = "1.1", features = ["tokio-comp", "connection-manager"] } diff --git a/htykc/src/lib.rs b/htykc/src/lib.rs index 1e38bef..c987d67 100644 --- a/htykc/src/lib.rs +++ b/htykc/src/lib.rs @@ -1,5 +1,5 @@ -use crate::ws_kecheng::*; -use crate::ws_repeat_kecheng::{create_kecheng_repeat, update_kecheng_repeat}; +use crate::ws_clazz::*; +use crate::ws_clazz_repeat::{create_clazz_repeat, update_clazz_repeat}; use axum::extract::State; use axum::routing::{get, post}; use axum::{Json, Router}; @@ -16,8 +16,11 @@ use tower_http::trace::TraceLayer; use tracing::{debug, error}; mod notifications; -mod ws_kecheng; -mod ws_repeat_kecheng; +mod ws_clazz; +mod ws_clazz_repeat; +mod ws_xiaoke; + +use crate::ws_xiaoke::{batch_save_clazz_attendance, find_clazz_attendance_by_clazz_id}; #[debug_handler] async fn notify( @@ -41,54 +44,50 @@ async fn notify( } } -pub fn kc_rocket(db_url: &str) -> Router { +pub fn clazz_router(db_url: &str) -> Router { let db_state = DbState { pool: pool(db_url) }; let shared_db_state = Arc::new(db_state); // let app = Router::new() .route( - "/api/v1/kc/create_kecheng_with_kecheng_repeat", - post(create_kecheng_with_kecheng_repeat), + "/api/v1/clazz/create_with_repeat", + post(create_clazz_with_repeat), ) - .route("/api/v1/kc/update_kecheng", post(update_kecheng)) + .route("/api/v1/clazz/update", post(update_clazz)) + .route("/api/v1/clazz/repeat/create", post(create_clazz_repeat)) + .route("/api/v1/clazz/repeat/update", post(update_clazz_repeat)) + .route("/api/v1/clazz/find_by_daka_ids", post(find_by_daka_ids)) .route( - "/api/v1/kc/create_kecheng_repeat", - post(create_kecheng_repeat), + "/api/v1/clazz/repeat/{id}", + get(find_clazz_repeat_by_id), + ) + .route("/api/v1/clazz/find_by_hty_id", get(find_clazz_by_hty_id)) + .route( + "/api/v1/clazz/find_all_non_repeatable_within_date_range_by_hty_id", + get(find_all_non_repeatable_within_date_range_by_hty_id), ) .route( - "/api/v1/kc/update_kecheng_repeat", - post(update_kecheng_repeat), + "/api/v1/clazz/find_all_non_repeatable_within_date_range", + get(find_all_non_repeatable_within_date_range), ) .route( - "/api/v1/kc/find_kechengs_by_daka_ids", - post(find_kechengs_by_daka_ids), + "/api/v1/clazz/find_all_repeatable_within_date_range", + get(find_all_repeatable_within_date_range), ) .route( - "/api/v1/kc/find_kecheng_repeat_by_id/{id}", - get(find_kecheng_repeat_by_id), + "/api/v1/clazz/find_all_repeatable_within_date_range_by_hty_id", + get(find_all_repeatable_within_date_range_by_hty_id), + ) + .route("/api/v1/clazz/notify", post(notify)) + .route( + "/api/v1/clazz/attendance/{clazz_id}", + get(find_clazz_attendance_by_clazz_id), ) .route( - "/api/v1/kc/find_kechengs_by_hty_id", - get(find_kechengs_by_hty_id), + "/api/v1/clazz/batch_save_attendance", + post(batch_save_clazz_attendance), ) - .route( - "/api/v1/kc/find_all_non_repeatable_kechengs_within_date_range_by_hty_id", - get(find_all_non_repeatable_kechengs_within_date_range_by_hty_id), - ) - .route( - "/api/v1/kc/find_all_non_repeatable_kechengs_within_date_range", - get(find_all_non_repeatable_kechengs_within_date_range), - ) - .route( - "/api/v1/kc/find_all_repeatable_kechengs_within_date_range", - get(find_all_repeatable_kechengs_within_date_range), - ) - .route( - "/api/v1/kc/find_all_repeatable_kechengs_within_date_range_by_hty_id", - get(find_all_repeatable_kechengs_within_date_range_by_hty_id), - ) - .route("/api/v1/kc/notify", post(notify)) .layer(TraceLayer::new_for_http()) .with_state(shared_db_state); diff --git a/htykc/src/main.rs b/htykc/src/main.rs index 195bddd..601b853 100644 --- a/htykc/src/main.rs +++ b/htykc/src/main.rs @@ -2,7 +2,7 @@ use dotenv::dotenv; use htycommons::db::get_kc_db_url; use htycommons::logger::logger_init; use htycommons::web::{get_kc_port, launch_rocket}; -use htykc::kc_rocket; +use htykc::clazz_router; #[tokio::main] async fn main() { @@ -14,7 +14,7 @@ async fn main() { eprintln!("Failed to get KC_PORT: {}", e); std::process::exit(1); }); - let r = launch_rocket(port, kc_rocket(&get_kc_db_url())); + let r = launch_rocket(port, clazz_router(&get_kc_db_url())); let _ = r.await; // this is reachable only after `Shutdown::notify()` or `Ctrl+C`. diff --git a/htykc/src/notifications.rs b/htykc/src/notifications.rs index b8a9a16..538a067 100644 --- a/htykc/src/notifications.rs +++ b/htykc/src/notifications.rs @@ -96,8 +96,8 @@ pub async fn raw_notify( match notify_type { Some(notify_type) => match notify_type.as_str() { - "teacher_comment_kecheng" => { - let push_message = build_wx_push_message_for_teacher_comment_kecheng( + "teacher_comment_clazz" => { + let push_message = build_wx_push_message_for_teacher_comment_clazz( &to_user_openid, &from_app, &to_app, @@ -108,7 +108,7 @@ pub async fn raw_notify( ) .await?; debug!( - "raw_notify -> teacher_comment_kecheng / msg: {:?}", + "raw_notify -> teacher_comment_clazz / msg: {:?}", &push_message ); let req_hty_tongzhi = build_req_hty_tongzhi( @@ -121,7 +121,7 @@ pub async fn raw_notify( &db_pool, )?; debug!( - "raw_notify -> teacher_comment_kecheng: req_hty_tongzhi: {:?}", + "raw_notify -> teacher_comment_clazz: req_hty_tongzhi: {:?}", &req_hty_tongzhi ); remote_send_tongzhi_and_push_wx_message!( @@ -131,8 +131,8 @@ pub async fn raw_notify( push_message ); } - "create_or_update_kecheng" => { - let push_message = build_wx_push_message_for_create_or_update_kecheng( + "create_or_update_clazz" => { + let push_message = build_wx_push_message_for_create_or_update_clazz( &to_user_openid, &from_app, &to_app, @@ -143,7 +143,7 @@ pub async fn raw_notify( ) .await?; debug!( - "raw_notify -> create_or_update_kecheng: msg {:?}", + "raw_notify -> create_or_update_clazz: msg {:?}", &push_message ); let req_hty_tongzhi = build_req_hty_tongzhi( @@ -156,7 +156,7 @@ pub async fn raw_notify( &db_pool, )?; debug!( - "raw_notify -> create_or_update_kecheng: req_hty_tongzhi: {:?}", + "raw_notify -> create_or_update_clazz: req_hty_tongzhi: {:?}", &req_hty_tongzhi ); remote_send_tongzhi_and_push_wx_message!( @@ -166,8 +166,8 @@ pub async fn raw_notify( push_message ); } - "delete_kecheng" => { - let push_message = build_wx_push_message_for_delete_kecheng( + "delete_clazz" => { + let push_message = build_wx_push_message_for_delete_clazz( &to_user_openid, &from_app, &to_app, @@ -177,7 +177,7 @@ pub async fn raw_notify( &sudoer, ) .await?; - debug!("raw_notify -> delete_kecheng: msg {:?}", &push_message); + debug!("raw_notify -> delete_clazz: msg {:?}", &push_message); let req_hty_tongzhi = build_req_hty_tongzhi( ¬ify_type, &from_app.app_id, @@ -188,7 +188,7 @@ pub async fn raw_notify( &db_pool, )?; debug!( - "raw_notify -> delete_kecheng: req_hty_tongzhi: {:?}", + "raw_notify -> delete_clazz: req_hty_tongzhi: {:?}", &req_hty_tongzhi ); remote_send_tongzhi_and_push_wx_message!( @@ -276,7 +276,7 @@ fn build_req_hty_tongzhi( }; match notify_type.as_str() { - "create_or_update_kecheng" | "delete_kecheng" | _ => { + "create_or_update_clazz" | "delete_clazz" | _ => { content.content = None; } } @@ -285,7 +285,7 @@ fn build_req_hty_tongzhi( Ok(req_tongzhi) } -async fn build_wx_push_message_for_create_or_update_kecheng( +async fn build_wx_push_message_for_create_or_update_clazz( to_user_openid: &String, from_app: &HtyApp, to_app: &HtyApp, @@ -294,7 +294,7 @@ async fn build_wx_push_message_for_create_or_update_kecheng( _db_pool: &Arc, sudoer: &HtySudoerTokenHeader, ) -> anyhow::Result> { - debug!("build_wx_push_message_for_create_or_update_kecheng -> to_user_openid -> {:?} / from_app -> {:?} / to_app -> {:?} / notify_type -> {:?} / push_info: {:?}", + debug!("build_wx_push_message_for_create_or_update_clazz -> to_user_openid -> {:?} / from_app -> {:?} / to_app -> {:?} / notify_type -> {:?} / push_info: {:?}", to_user_openid, from_app, to_app, type_notify, push_info); let wx_mini_program = ReqWxMiniProgram { @@ -309,7 +309,7 @@ async fn build_wx_push_message_for_create_or_update_kecheng( get_template_with_data_by_key_and_app_id(type_notify, &to_app.app_id.clone(), &sudoer) .await?; debug!( - "build_wx_push_message_for_create_or_update_kecheng -> req_in_template -> {:?}", + "build_wx_push_message_for_create_or_update_clazz -> req_in_template -> {:?}", req_in_template ); @@ -319,7 +319,7 @@ async fn build_wx_push_message_for_create_or_update_kecheng( )?; debug!( - "build_wx_push_message_for_create_or_update_kecheng -> BEFORE wx_message_data -> {:?}", + "build_wx_push_message_for_create_or_update_clazz -> BEFORE wx_message_data -> {:?}", wx_message_data ); @@ -343,9 +343,9 @@ async fn build_wx_push_message_for_create_or_update_kecheng( value: val_thing2.replace( "KECHENG_NAME", push_info - .kecheng_name + .clazz_name .as_ref() - .ok_or_else(|| anyhow!("kecheng_name is required"))? + .ok_or_else(|| anyhow!("clazz_name is required"))? .as_str(), ), }; @@ -385,7 +385,7 @@ async fn build_wx_push_message_for_create_or_update_kecheng( }; debug!( - "build_wx_push_message_for_create_or_update_kecheng -> AFTER wx_message_data -> {:?}", + "build_wx_push_message_for_create_or_update_clazz -> AFTER wx_message_data -> {:?}", wx_message_data ); @@ -406,7 +406,7 @@ async fn build_wx_push_message_for_create_or_update_kecheng( }) } -async fn build_wx_push_message_for_delete_kecheng( +async fn build_wx_push_message_for_delete_clazz( to_user_openid: &String, from_app: &HtyApp, to_app: &HtyApp, @@ -415,7 +415,7 @@ async fn build_wx_push_message_for_delete_kecheng( _db_pool: &Arc, sudoer: &HtySudoerTokenHeader, ) -> anyhow::Result> { - debug!("build_wx_push_message_for_delete_kecheng -> to_user_openid -> {:?} / from_app -> {:?} / to_app -> {:?} / notify_type -> {:?} / push_info: {:?}", + debug!("build_wx_push_message_for_delete_clazz -> to_user_openid -> {:?} / from_app -> {:?} / to_app -> {:?} / notify_type -> {:?} / push_info: {:?}", to_user_openid, from_app, to_app, type_notify, push_info); let wx_mini_program = ReqWxMiniProgram { @@ -430,7 +430,7 @@ async fn build_wx_push_message_for_delete_kecheng( get_template_with_data_by_key_and_app_id(type_notify, &to_app.app_id.clone(), &sudoer) .await?; debug!( - "build_wx_push_message_for_delete_kecheng -> req_in_template -> {:?}", + "build_wx_push_message_for_delete_clazz -> req_in_template -> {:?}", req_in_template ); @@ -440,7 +440,7 @@ async fn build_wx_push_message_for_delete_kecheng( )?; debug!( - "build_wx_push_message_for_delete_kecheng -> BEFORE wx_message_data -> {:?}", + "build_wx_push_message_for_delete_clazz -> BEFORE wx_message_data -> {:?}", wx_message_data ); @@ -464,9 +464,9 @@ async fn build_wx_push_message_for_delete_kecheng( value: val_thing3.replace( "KECHENG_NAME", push_info - .kecheng_name + .clazz_name .as_ref() - .ok_or_else(|| anyhow!("kecheng_name is required"))? + .ok_or_else(|| anyhow!("clazz_name is required"))? .as_str(), ), }; @@ -503,7 +503,7 @@ async fn build_wx_push_message_for_delete_kecheng( }; debug!( - "build_wx_push_message_for_delete_kecheng -> AFTER wx_message_data -> {:?}", + "build_wx_push_message_for_delete_clazz -> AFTER wx_message_data -> {:?}", wx_message_data ); @@ -524,7 +524,7 @@ async fn build_wx_push_message_for_delete_kecheng( }) } -async fn build_wx_push_message_for_teacher_comment_kecheng( +async fn build_wx_push_message_for_teacher_comment_clazz( to_user_openid: &String, from_app: &HtyApp, to_app: &HtyApp, @@ -533,7 +533,7 @@ async fn build_wx_push_message_for_teacher_comment_kecheng( _db_pool: &Arc, sudoer: &HtySudoerTokenHeader, ) -> anyhow::Result> { - debug!("build_wx_push_message_for_teacher_comment_kecheng -> to_user_openid -> {:?} / from_app -> {:?} / to_app -> {:?} / notify_type -> {:?} / push_info: {:?}", + debug!("build_wx_push_message_for_teacher_comment_clazz -> to_user_openid -> {:?} / from_app -> {:?} / to_app -> {:?} / notify_type -> {:?} / push_info: {:?}", to_user_openid, from_app, to_app, type_notify, push_info); let comment_id = push_info.comment_id.clone().ok_or(HtyErr { @@ -542,7 +542,7 @@ async fn build_wx_push_message_for_teacher_comment_kecheng( })?; debug!( - "build_wx_push_message_for_teacher_comment_kecheng -> comment_id: {:?}", + "build_wx_push_message_for_teacher_comment_clazz -> comment_id: {:?}", comment_id ); @@ -558,7 +558,7 @@ async fn build_wx_push_message_for_teacher_comment_kecheng( get_template_with_data_by_key_and_app_id(type_notify, &to_app.app_id.clone(), &sudoer) .await?; debug!( - "build_wx_push_message_for_teacher_comment_kecheng -> req_in_template -> {:?}", + "build_wx_push_message_for_teacher_comment_clazz -> req_in_template -> {:?}", req_in_template ); @@ -568,7 +568,7 @@ async fn build_wx_push_message_for_teacher_comment_kecheng( )?; debug!( - "build_wx_push_message_for_teacher_comment_kecheng -> BEFORE wx_message_data -> {:?}", + "build_wx_push_message_for_teacher_comment_clazz -> BEFORE wx_message_data -> {:?}", wx_message_data ); @@ -606,9 +606,9 @@ async fn build_wx_push_message_for_teacher_comment_kecheng( .replace( "KECHENG_NAME", push_info - .kecheng_name + .clazz_name .as_ref() - .ok_or_else(|| anyhow!("kecheng_name is required"))? + .ok_or_else(|| anyhow!("clazz_name is required"))? .as_str(), ), }; @@ -638,7 +638,7 @@ async fn build_wx_push_message_for_teacher_comment_kecheng( wx_message_data.remark = ReqWxMessageDataValue { value: val_remark }; debug!( - "build_wx_push_message_for_teacher_comment_kecheng -> AFTER wx_message_data -> {:?}", + "build_wx_push_message_for_teacher_comment_clazz -> AFTER wx_message_data -> {:?}", wx_message_data ); diff --git a/htykc/src/ws_kecheng.rs b/htykc/src/ws_clazz.rs similarity index 65% rename from htykc/src/ws_kecheng.rs rename to htykc/src/ws_clazz.rs index 073db1a..bf95d5f 100644 --- a/htykc/src/ws_kecheng.rs +++ b/htykc/src/ws_clazz.rs @@ -14,32 +14,32 @@ use htycommons::web::{ HtySudoerTokenHeader, }; use htykc_models::models::{ - Kecheng, KechengRepeat, ReqKecheng, ReqKechengRepeat, ReqKechengWithRepeat, + Clazz, ClazzRepeat, ReqClazz, ReqClazzRepeat, ReqClazzWithRepeat, }; use std::collections::HashMap; use std::ops::DerefMut; use std::sync::Arc; use tracing::{debug, error}; -pub async fn find_all_non_repeatable_kechengs_within_date_range( +pub async fn find_all_non_repeatable_within_date_range( sudoer: HtySudoerTokenHeader, host: HtyHostHeader, auth: AuthorizationHeader, State(db_pool): State>, Query(params): Query>, -) -> Json>> { +) -> Json>> { debug!( - "find_all_non_repeatable_kechengs_within_date_range -> starts, params: {:?}", + "find_all_non_repeatable_within_date_range -> starts, params: {:?}", params ); - match raw_find_all_non_repeatable_kechengs_within_date_range( + match raw_find_all_non_repeatable_within_date_range( auth, sudoer, host, db_pool, ¶ms, ) { Ok(ok) => wrap_json_ok_resp(ok), Err(e) => { error!( - "find_all_non_repeatable_kechengs_within_date_range -> failed to find kecheng, e: {}", + "find_all_non_repeatable_within_date_range -> failed to find kecheng, e: {}", e ); wrap_json_anyhow_err(e) @@ -47,22 +47,22 @@ pub async fn find_all_non_repeatable_kechengs_within_date_range( } } -fn raw_find_all_non_repeatable_kechengs_within_date_range( +fn raw_find_all_non_repeatable_within_date_range( _token: AuthorizationHeader, _sudoer: HtySudoerTokenHeader, _host: HtyHostHeader, db_pool: Arc, params: &HashMap, -) -> anyhow::Result> { +) -> anyhow::Result> { let start_from = string_to_date(&get_some_from_query_params::("start_from", ¶ms))?; let end_by = string_to_date(&get_some_from_query_params::("end_by", ¶ms))?; debug!( - "raw_find_all_non_repeatable_kechengs_within_date_range -> start_from: {:?}", + "raw_find_all_non_repeatable_within_date_range -> start_from: {:?}", start_from ); debug!( - "raw_find_all_non_repeatable_kechengs_within_date_range -> end_by: {:?}", + "raw_find_all_non_repeatable_within_date_range -> end_by: {:?}", end_by ); @@ -73,7 +73,7 @@ fn raw_find_all_non_repeatable_kechengs_within_date_range( })); } - let some_kechengs = Kecheng::find_all_non_repeatable_by_date_range( + let some_kechengs = Clazz::find_all_non_repeatable_by_date_range( start_from .as_ref() .ok_or_else(|| anyhow!("start_from is required"))?, @@ -84,37 +84,37 @@ fn raw_find_all_non_repeatable_kechengs_within_date_range( )?; debug!( - "raw_find_all_non_repeatable_kechengs_within_date_range -> some_kechengs: {:?}", + "raw_find_all_non_repeatable_within_date_range -> some_kechengs: {:?}", some_kechengs ); if let Some(kechengs) = some_kechengs { - let res: Vec = kechengs.iter().map(|kc| kc.to_req()).collect(); + let res: Vec = kechengs.iter().map(|kc| kc.to_req()).collect(); Ok(res) } else { Ok(vec![]) } } -pub async fn find_all_non_repeatable_kechengs_within_date_range_by_hty_id( +pub async fn find_all_non_repeatable_within_date_range_by_hty_id( sudoer: HtySudoerTokenHeader, host: HtyHostHeader, auth: AuthorizationHeader, State(db_pool): State>, Query(params): Query>, -) -> Json>> { +) -> Json>> { debug!( - "find_all_non_repeatable_kechengs_within_date_range_by_hty_id -> starts, params: {:?}", + "find_all_non_repeatable_within_date_range_by_hty_id -> starts, params: {:?}", params ); - match raw_find_all_non_repeatable_kechengs_within_date_range_by_hty_id( + match raw_find_all_non_repeatable_within_date_range_by_hty_id( auth, sudoer, host, db_pool, ¶ms, ) { Ok(ok) => wrap_json_ok_resp(ok), Err(e) => { error!( - "find_all_non_repeatable_kechengs_within_date_range_by_hty_id -> failed to find kecheng, e: {}", + "find_all_non_repeatable_within_date_range_by_hty_id -> failed to find kecheng, e: {}", e ); wrap_json_anyhow_err(e) @@ -122,23 +122,23 @@ pub async fn find_all_non_repeatable_kechengs_within_date_range_by_hty_id( } } -fn raw_find_all_non_repeatable_kechengs_within_date_range_by_hty_id( +fn raw_find_all_non_repeatable_within_date_range_by_hty_id( _token: AuthorizationHeader, _sudoer: HtySudoerTokenHeader, _host: HtyHostHeader, db_pool: Arc, params: &HashMap, -) -> anyhow::Result> { +) -> anyhow::Result> { let start_from = string_to_datetime(&get_some_from_query_params::("start_from", ¶ms))?; let end_by = string_to_datetime(&get_some_from_query_params::("end_by", ¶ms))?; debug!( - "raw_find_all_non_repeatable_kechengs_within_date_range_by_hty_id -> start_from: {:?}", + "raw_find_all_non_repeatable_within_date_range_by_hty_id -> start_from: {:?}", start_from ); debug!( - "raw_find_all_non_repeatable_kechengs_within_date_range_by_hty_id -> end_by: {:?}", + "raw_find_all_non_repeatable_within_date_range_by_hty_id -> end_by: {:?}", end_by ); @@ -158,7 +158,7 @@ fn raw_find_all_non_repeatable_kechengs_within_date_range_by_hty_id( })); } - let some_kechengs = Kecheng::find_all_non_repeatable_by_date_range_and_user_id( + let some_kechengs = Clazz::find_all_non_repeatable_by_date_range_and_user_id( id_user .as_ref() .ok_or_else(|| anyhow!("id_user is required"))?, @@ -172,35 +172,35 @@ fn raw_find_all_non_repeatable_kechengs_within_date_range_by_hty_id( )?; debug!( - "raw_find_all_non_repeatable_kechengs_within_date_range_by_hty_id -> {:?}", + "raw_find_all_non_repeatable_within_date_range_by_hty_id -> {:?}", some_kechengs ); if let Some(kechengs) = some_kechengs { - let res: Vec = kechengs.iter().map(|kc| kc.to_req()).collect(); + let res: Vec = kechengs.iter().map(|kc| kc.to_req()).collect(); Ok(res) } else { Ok(vec![]) } } -pub async fn find_all_repeatable_kechengs_within_date_range( +pub async fn find_all_repeatable_within_date_range( sudoer: HtySudoerTokenHeader, host: HtyHostHeader, auth: AuthorizationHeader, State(db_pool): State>, Query(params): Query>, -) -> Json>> { +) -> Json>> { debug!( - "find_all_repeatable_kechengs_within_date_range -> starts, params: {:?}", + "find_all_repeatable_within_date_range -> starts, params: {:?}", params ); - match raw_find_all_repeatable_kechengs_within_date_range(auth, sudoer, host, db_pool, ¶ms) { + match raw_find_all_repeatable_within_date_range(auth, sudoer, host, db_pool, ¶ms) { Ok(kechengs) => wrap_json_ok_resp(kechengs), Err(e) => { error!( - "find_all_repeatable_kechengs_within_date_range -> failed to find kecheng, e: {}", + "find_all_repeatable_within_date_range -> failed to find kecheng, e: {}", e ); wrap_json_anyhow_err(e) @@ -208,22 +208,22 @@ pub async fn find_all_repeatable_kechengs_within_date_range( } } -fn raw_find_all_repeatable_kechengs_within_date_range( +fn raw_find_all_repeatable_within_date_range( _token: AuthorizationHeader, _sudoer: HtySudoerTokenHeader, _host: HtyHostHeader, db_pool: Arc, params: &HashMap, -) -> anyhow::Result> { +) -> anyhow::Result> { let start_from = string_to_date(&get_some_from_query_params::("start_from", ¶ms))?; let end_by = string_to_date(&get_some_from_query_params::("end_by", ¶ms))?; debug!( - "raw_find_all_repeatable_kechengs_within_date_range -> start_from: {:?}", + "raw_find_all_repeatable_within_date_range -> start_from: {:?}", start_from ); debug!( - "raw_find_all_repeatable_kechengs_within_date_range -> end_by: {:?}", + "raw_find_all_repeatable_within_date_range -> end_by: {:?}", end_by ); @@ -234,7 +234,7 @@ fn raw_find_all_repeatable_kechengs_within_date_range( })); } - let some_kechengs = Kecheng::find_all_repeatable_by_date_range( + let some_kechengs = Clazz::find_all_repeatable_by_date_range( start_from .as_ref() .ok_or_else(|| anyhow!("start_from is required"))?, @@ -245,13 +245,13 @@ fn raw_find_all_repeatable_kechengs_within_date_range( )?; debug!( - "raw_find_all_repeatable_kechengs_within_date_range -> some_kechengs: {:?}", + "raw_find_all_repeatable_within_date_range -> some_kechengs: {:?}", some_kechengs ); if let Some(kechengs) = some_kechengs { debug!( - "raw_find_all_repeatable_kechengs_within_date_range -> kechengs.len(): {:?}", + "raw_find_all_repeatable_within_date_range -> kechengs.len(): {:?}", kechengs.len() ); Ok(kechengs) @@ -260,25 +260,25 @@ fn raw_find_all_repeatable_kechengs_within_date_range( } } -pub async fn find_all_repeatable_kechengs_within_date_range_by_hty_id( +pub async fn find_all_repeatable_within_date_range_by_hty_id( sudoer: HtySudoerTokenHeader, host: HtyHostHeader, auth: AuthorizationHeader, State(db_pool): State>, Query(params): Query>, -) -> Json>> { +) -> Json>> { debug!( - "find_all_repeatable_kechengs_within_date_range_by_hty_id -> starts, params: {:?}", + "find_all_repeatable_within_date_range_by_hty_id -> starts, params: {:?}", params ); - match raw_find_all_repeatable_kechengs_within_date_range_by_hty_id( + match raw_find_all_repeatable_within_date_range_by_hty_id( auth, sudoer, host, db_pool, ¶ms, ) { Ok(ok) => wrap_json_ok_resp(ok), Err(e) => { error!( - "find_all_repeatable_kechengs_within_date_range_by_hty_id -> failed to find kecheng, e: {}", + "find_all_repeatable_within_date_range_by_hty_id -> failed to find kecheng, e: {}", e ); wrap_json_anyhow_err(e) @@ -293,28 +293,28 @@ pub async fn find_all_repeatable_kechengs_within_date_range_by_hty_id( * 2. start_from / end_by * 3. 实体kecheng数据 * 4. 需要显示在本周的重复课程的sudoer课程 (kecheng_repeat_status == `OPEN` && is_repeat == True && repeat_end 在本周范围内 or 为空) - * htykc_moicen=# select kecheng.is_repeat from kecheng join kecheng_repeat on kecheng.id = kecheng_repeat.kecheng_id where kecheng.is_repeat is not null; + * htykc_moicen=# select kecheng.is_repeat from kecheng join kecheng_repeat on kecheng.id = kecheng_repeat.clazz_id where kecheng.is_repeat is not null; * * a. 返回的kecheng里,如果`id == root_id`那么此条数据就是sudoer数据. * b. 如果此条kecheng的`start_from`和`end_by`落在本周,则说明是本周数据 */ -fn raw_find_all_repeatable_kechengs_within_date_range_by_hty_id( +fn raw_find_all_repeatable_within_date_range_by_hty_id( _token: AuthorizationHeader, _sudoer: HtySudoerTokenHeader, _host: HtyHostHeader, db_pool: Arc, params: &HashMap, -) -> anyhow::Result> { +) -> anyhow::Result> { let start_from = string_to_datetime(&get_some_from_query_params::("start_from", ¶ms))?; let end_by = string_to_datetime(&get_some_from_query_params::("end_by", ¶ms))?; debug!( - "raw_find_all_repeatable_kechengs_within_date_range_by_hty_id -> start_from: {:?}", + "raw_find_all_repeatable_within_date_range_by_hty_id -> start_from: {:?}", start_from ); debug!( - "raw_find_all_repeatable_kechengs_within_date_range_by_hty_id -> end_by: {:?}", + "raw_find_all_repeatable_within_date_range_by_hty_id -> end_by: {:?}", end_by ); @@ -334,7 +334,7 @@ fn raw_find_all_repeatable_kechengs_within_date_range_by_hty_id( })); } - let some_kechengs = Kecheng::find_all_repeatable_by_date_range_and_user_id( + let some_kechengs = Clazz::find_all_repeatable_by_date_range_and_user_id( id_user .as_ref() .ok_or_else(|| anyhow!("id_user is required"))?, @@ -348,13 +348,13 @@ fn raw_find_all_repeatable_kechengs_within_date_range_by_hty_id( )?; debug!( - "raw_find_all_repeatable_kechengs_within_date_range_by_hty_id -> some_kechengs: {:?}", + "raw_find_all_repeatable_within_date_range_by_hty_id -> some_kechengs: {:?}", some_kechengs ); if let Some(kechengs) = some_kechengs { debug!( - "raw_find_all_repeatable_kechengs_within_date_range_by_hty_id -> kechengs.len(): {:?}", + "raw_find_all_repeatable_within_date_range_by_hty_id -> kechengs.len(): {:?}", kechengs.len() ); Ok(kechengs) @@ -363,19 +363,19 @@ fn raw_find_all_repeatable_kechengs_within_date_range_by_hty_id( } } -pub async fn find_kechengs_by_daka_ids( +pub async fn find_by_daka_ids( sudoer: HtySudoerTokenHeader, host: HtyHostHeader, auth: AuthorizationHeader, State(db_pool): State>, daka_ids: Json>, -) -> Json>> { - debug!("find_kechengs_by_daka_ids -> starts: {:?}", daka_ids); - match raw_find_kechengs_by_daka_ids(auth, sudoer, host, db_pool, &daka_ids) { +) -> Json>> { + debug!("find_by_daka_ids -> starts: {:?}", daka_ids); + match raw_find_by_daka_ids(auth, sudoer, host, db_pool, &daka_ids) { Ok(ok) => wrap_json_ok_resp(ok), Err(e) => { error!( - "find_kechengs_by_daka_ids -> failed to find kecheng, e: {}", + "find_by_daka_ids -> failed to find kecheng, e: {}", e ); wrap_json_anyhow_err(e) @@ -383,44 +383,44 @@ pub async fn find_kechengs_by_daka_ids( } } -fn raw_find_kechengs_by_daka_ids( +fn raw_find_by_daka_ids( _auth: AuthorizationHeader, _sudoer: HtySudoerTokenHeader, _host: HtyHostHeader, db_pool: Arc, daka_ids: &Vec, -) -> anyhow::Result> { - let db_kechengs = Kecheng::find_kechengs_by_daka_ids( +) -> anyhow::Result> { + let db_kechengs = Clazz::find_by_daka_ids( daka_ids, extract_conn(fetch_db_conn(&db_pool)?).deref_mut(), )?; debug!( - "raw_find_kechengs_by_daka_ids -> db_kechengs: {:?}", + "raw_find_by_daka_ids -> db_kechengs: {:?}", db_kechengs ); let req_kechengs = db_kechengs.into_iter().map(|item| item.to_req()).collect(); debug!( - "raw_find_kechengs_by_daka_ids -> req_kechengs: {:?}", + "raw_find_by_daka_ids -> req_kechengs: {:?}", req_kechengs ); Ok(req_kechengs) } -pub async fn find_kecheng_repeat_by_id( +pub async fn find_clazz_repeat_by_id( sudoer: HtySudoerTokenHeader, host: HtyHostHeader, auth: AuthorizationHeader, State(db_pool): State>, Path(id): Path, -) -> Json> { - debug!("find_kecheng_repeat_by_id -> starts: {:?}", id); - match raw_find_kecheng_repeat_by_id(auth, sudoer, host, db_pool, &id) { +) -> Json> { + debug!("find_clazz_repeat_by_id -> starts: {:?}", id); + match raw_find_clazz_repeat_by_id(auth, sudoer, host, db_pool, &id) { Ok(ok) => wrap_json_ok_resp(ok), Err(e) => { error!( - "find_kecheng_repeat_by_id -> failed to find kecheng repeat, e: {}", + "find_clazz_repeat_by_id -> failed to find kecheng repeat, e: {}", e ); wrap_json_anyhow_err(e) @@ -428,14 +428,14 @@ pub async fn find_kecheng_repeat_by_id( } } -fn raw_find_kecheng_repeat_by_id( +fn raw_find_clazz_repeat_by_id( _auth: AuthorizationHeader, _sudoer: HtySudoerTokenHeader, _host: HtyHostHeader, db_pool: Arc, kecheng_repeat_id: &String, -) -> anyhow::Result { - let res = KechengRepeat::find_by_id( +) -> anyhow::Result { + let res = ClazzRepeat::find_by_id( kecheng_repeat_id, extract_conn(fetch_db_conn(&db_pool)?).deref_mut(), )?; @@ -445,26 +445,26 @@ fn raw_find_kecheng_repeat_by_id( return Err(anyhow!(HtyErr { code: HtyErrCode::NullErr, reason: Some(format!( - "raw_find_kecheng_repeat_by_id -> failed to find record according to id :{:?}.", + "raw_find_clazz_repeat_by_id -> failed to find record according to id :{:?}.", kecheng_repeat_id )), })); } } -pub async fn find_kechengs_by_hty_id( +pub async fn find_clazz_by_hty_id( sudoer: HtySudoerTokenHeader, host: HtyHostHeader, auth: AuthorizationHeader, State(db_pool): State>, Query(params): Query>, -) -> Json>> { - debug!("find_kechengs_by_hty_id -> starts: {:?}", params); - match raw_find_kechengs_by_hty_id(auth, sudoer, host, db_pool, ¶ms) { +) -> Json>> { + debug!("find_clazz_by_hty_id -> starts: {:?}", params); + match raw_find_clazz_by_hty_id(auth, sudoer, host, db_pool, ¶ms) { Ok(ok) => wrap_json_ok_resp(ok), Err(e) => { error!( - "find_kechengs_by_hty_id -> failed to find kechengs, e: {}", + "find_clazz_by_hty_id -> failed to find kechengs, e: {}", e ); wrap_json_anyhow_err(e) @@ -472,22 +472,22 @@ pub async fn find_kechengs_by_hty_id( } } -fn raw_find_kechengs_by_hty_id( +fn raw_find_clazz_by_hty_id( _auth: AuthorizationHeader, _sudoer: HtySudoerTokenHeader, _host: HtyHostHeader, db_pool: Arc, params: &HashMap, -) -> anyhow::Result> { +) -> anyhow::Result> { let start_date = string_to_datetime(&get_some_from_query_params::("start_date", ¶ms))?; let end_date = string_to_datetime(&get_some_from_query_params::("end_date", ¶ms))?; debug!( - "raw_find_kechengs_by_hty_id -> start_date: {:?}", + "raw_find_clazz_by_hty_id -> start_date: {:?}", start_date ); - debug!("raw_find_kechengs_by_hty_id -> end_date: {:?}", end_date); + debug!("raw_find_clazz_by_hty_id -> end_date: {:?}", end_date); if start_date.is_none() || end_date.is_none() { return Err(anyhow!(HtyErr { @@ -504,7 +504,7 @@ fn raw_find_kechengs_by_hty_id( })); } - let kechengs = Kecheng::find_kecheng_by_user_id( + let kechengs = Clazz::find_by_user_id( id_user .as_ref() .ok_or_else(|| anyhow!("id_user is required"))?, @@ -514,38 +514,38 @@ fn raw_find_kechengs_by_hty_id( )?; let res = kechengs.into_iter().map(|item| item.to_req()).collect(); - debug!("raw_find_kechengs_by_hty_id -> {:?}", res); + debug!("raw_find_clazz_by_hty_id -> {:?}", res); Ok(res) } -pub async fn update_kecheng( +pub async fn update_clazz( sudoer: HtySudoerTokenHeader, host: HtyHostHeader, auth: AuthorizationHeader, State(db_pool): State>, - Json(in_kecheng): Json, + Json(in_kecheng): Json, ) -> Json> { - debug!("update_kecheng -> in_kecheng: {:?}", in_kecheng); - match raw_update_kecheng(auth, sudoer, host, db_pool, &in_kecheng).await { + debug!("update_clazz -> in_kecheng: {:?}", in_kecheng); + match raw_update_clazz(auth, sudoer, host, db_pool, &in_kecheng).await { Ok(ok) => wrap_json_ok_resp(ok), Err(e) => { - error!("update_kecheng -> failed to update kecheng, e: {}", e); + error!("update_clazz -> failed to update clazz, e: {}", e); wrap_json_anyhow_err(e) } } } -async fn raw_update_kecheng( +async fn raw_update_clazz( _token: AuthorizationHeader, _sudoer: HtySudoerTokenHeader, _host: HtyHostHeader, db_pool: Arc, - in_kecheng: &ReqKecheng, + in_kecheng: &ReqClazz, ) -> anyhow::Result<()> { if in_kecheng.id.is_none() { return Err(anyhow!(HtyErr { code: HtyErrCode::WebErr, - reason: Some("kecheng_id is none".into()), + reason: Some("clazz_id is none".into()), })); } @@ -553,16 +553,16 @@ async fn raw_update_kecheng( .id .clone() .ok_or_else(|| anyhow!("id is required"))?; - let mut db_kecheng = Kecheng::find_by_id( + let mut db_kecheng = Clazz::find_by_id( &id_kecheng, extract_conn(fetch_db_conn(&db_pool)?).deref_mut(), )?; - if let Some(kecheng_name) = &in_kecheng.kecheng_name { - db_kecheng.kecheng_name = kecheng_name.clone(); + if let Some(clazz_name) = &in_kecheng.clazz_name { + db_kecheng.clazz_name = clazz_name.clone(); } - if let Some(kecheng_status) = &in_kecheng.kecheng_status { - db_kecheng.kecheng_status = kecheng_status.clone(); + if let Some(clazz_status) = &in_kecheng.clazz_status { + db_kecheng.clazz_status = clazz_status.clone(); } if let Some(start_from) = &in_kecheng.start_from { db_kecheng.start_from = start_from.clone(); @@ -577,9 +577,9 @@ async fn raw_update_kecheng( db_kecheng.parent_id = parent_id.clone(); } - db_kecheng.kecheng_desc = in_kecheng.kecheng_desc.clone(); + db_kecheng.clazz_desc = in_kecheng.clazz_desc.clone(); db_kecheng.duration = in_kecheng.duration.clone(); - db_kecheng.kecheng_type = in_kecheng.kecheng_type.clone(); + db_kecheng.clazz_type = in_kecheng.clazz_type.clone(); db_kecheng.students = in_kecheng.students.clone(); db_kecheng.teachers = in_kecheng.teachers.clone(); db_kecheng.jihuas = in_kecheng.jihuas.clone(); @@ -589,9 +589,9 @@ async fn raw_update_kecheng( db_kecheng.course_sections = in_kecheng.course_sections.clone(); db_kecheng.is_notified = in_kecheng.is_notified.clone(); - debug!("raw_update_kecheng -> {:?}", db_kecheng); + debug!("raw_update_clazz -> {:?}", db_kecheng); - let _ = Kecheng::update( + let _ = Clazz::update( &db_kecheng, extract_conn(fetch_db_conn(&db_pool)?).deref_mut(), )?; @@ -599,18 +599,18 @@ async fn raw_update_kecheng( Ok(()) } -/*async fn find_group_users_by_group_id(_p0: &String, _p1: &HtyHostHeader, _p2: &HtySudoerTokenHeader) -> anyhow::Result>> { +/*async fn find_group_users_by_group_id(_p0: &String, _p1: &HtyHostHeader, _p2: &HtySudoerTokenHeader) -> anyhow::Result>> { unimplemented!() } */ -fn raw_create_kecheng_with_repeat_tx( - params: HashMap)>, +fn raw_create_clazz_with_repeat_tx( + params: HashMap)>, db_pool: Arc, -) -> anyhow::Result { - let task = move |in_params: Option)>>, +) -> anyhow::Result { + let task = move |in_params: Option)>>, conn: &mut PgConnection| - -> anyhow::Result { + -> anyhow::Result { let the_params = in_params.ok_or_else(|| anyhow!("params is required"))?; let (to_create_kecheng, to_create_kecheng_repeat) = the_params .clone() @@ -618,23 +618,23 @@ fn raw_create_kecheng_with_repeat_tx( .ok_or_else(|| anyhow!("params key not found"))? .clone(); - let created_kecheng = Kecheng::create(&to_create_kecheng, conn)?; + let created_kecheng = Clazz::create(&to_create_kecheng, conn)?; debug!( - "raw_create_kecheng_with_repeat_tx -> created_kecheng: {:?}", + "raw_create_clazz_with_repeat_tx -> created_kecheng: {:?}", created_kecheng ); let mut created_kecheng_repeat = None; if let Some(kecheng_repeat) = &to_create_kecheng_repeat { - created_kecheng_repeat = Some(KechengRepeat::create(kecheng_repeat, conn)?); + created_kecheng_repeat = Some(ClazzRepeat::create(kecheng_repeat, conn)?); debug!( - "raw_create_kecheng_with_repeat_tx -> created_kecheng_repeat: {:?}", + "raw_create_clazz_with_repeat_tx -> created_kecheng_repeat: {:?}", created_kecheng_repeat ); } let out = - ReqKecheng::from_kecheng_and_repeat(&Some(created_kecheng), &created_kecheng_repeat); - debug!("raw_create_kecheng_with_repeat_tx -> out: {:?}", out); + ReqClazz::from_clazz_and_repeat(&Some(created_kecheng), &created_kecheng_repeat); + debug!("raw_create_clazz_with_repeat_tx -> out: {:?}", out); Ok(out) }; @@ -645,22 +645,22 @@ fn raw_create_kecheng_with_repeat_tx( ) } -pub async fn create_kecheng_with_kecheng_repeat( +pub async fn create_clazz_with_repeat( sudoer: HtySudoerTokenHeader, host: HtyHostHeader, auth: AuthorizationHeader, State(db_pool): State>, - Json(in_kecheng): Json, -) -> Json> { + Json(in_kecheng): Json, +) -> Json> { debug!( - "create_kecheng_with_kecheng_repeat -> in_kecheng: {:?}", + "create_clazz_with_repeat -> in_kecheng: {:?}", in_kecheng ); - match raw_create_kecheng_with_kecheng_repeat(auth, sudoer, host, db_pool, &in_kecheng).await { + match raw_create_clazz_with_repeat(auth, sudoer, host, db_pool, &in_kecheng).await { Ok(out) => wrap_json_ok_resp(out), Err(e) => { error!( - "create_kecheng_with_kecheng_repeat -> failed to create kecheng, e: {}", + "create_clazz_with_repeat -> failed to create clazz, e: {}", e ); wrap_json_anyhow_err(e) @@ -668,14 +668,14 @@ pub async fn create_kecheng_with_kecheng_repeat( } } -async fn raw_create_kecheng_with_kecheng_repeat( +async fn raw_create_clazz_with_repeat( token: AuthorizationHeader, _sudoer: HtySudoerTokenHeader, _host: HtyHostHeader, db_pool: Arc, - in_kecheng: &ReqKecheng, -) -> anyhow::Result { - if in_kecheng.kecheng_name.is_none() + in_kecheng: &ReqClazz, +) -> anyhow::Result { + if in_kecheng.clazz_name.is_none() || in_kecheng.start_from.is_none() || in_kecheng.end_by.is_none() || in_kecheng.duration.is_none() @@ -683,8 +683,7 @@ async fn raw_create_kecheng_with_kecheng_repeat( return Err(anyhow!(HtyErr { code: HtyErrCode::WebErr, reason: Some( - "kecheng_name or start_from or name or end_by() or duration or users is none" - .into() + "clazz_name or start_from or end_by or duration or users is none".into(), ), })); } @@ -693,33 +692,33 @@ async fn raw_create_kecheng_with_kecheng_repeat( .hty_id .ok_or_else(|| anyhow!("hty_id is required"))?; debug!( - "raw_create_kecheng_with_kecheng_repeat -> id_user: {:?}", + "raw_create_clazz_with_repeat -> id_user: {:?}", id_user ); - let kecheng_id = uuid(); + let new_clazz_id = uuid(); let id_sudoer = in_kecheng .root_id .clone() - .unwrap_or_else(|| kecheng_id.clone()); + .unwrap_or_else(|| new_clazz_id.clone()); let id_parent = in_kecheng .parent_id .clone() - .unwrap_or_else(|| kecheng_id.clone()); + .unwrap_or_else(|| new_clazz_id.clone()); - let to_create_kecheng = Kecheng { - id: kecheng_id.clone(), - kecheng_name: in_kecheng - .kecheng_name + let to_create_kecheng = Clazz { + id: new_clazz_id.clone(), + clazz_name: in_kecheng + .clazz_name .clone() - .ok_or_else(|| anyhow!("kecheng_name is required"))?, - kecheng_status: in_kecheng - .kecheng_status + .ok_or_else(|| anyhow!("clazz_name is required"))?, + clazz_status: in_kecheng + .clazz_status .clone() - .ok_or_else(|| anyhow!("kecheng_status is required"))?, - kecheng_desc: in_kecheng.kecheng_desc.clone(), + .ok_or_else(|| anyhow!("clazz_status is required"))?, + clazz_desc: in_kecheng.clazz_desc.clone(), start_from: in_kecheng .start_from .clone() @@ -730,7 +729,7 @@ async fn raw_create_kecheng_with_kecheng_repeat( .ok_or_else(|| anyhow!("end_by is required"))?, duration: in_kecheng.duration.clone(), root_id: id_sudoer.clone(), - kecheng_type: in_kecheng.kecheng_type.clone(), + clazz_type: in_kecheng.clazz_type.clone(), parent_id: id_parent.clone(), created_by: in_kecheng.created_by.clone(), created_at: Some(current_local_datetime()), @@ -745,24 +744,24 @@ async fn raw_create_kecheng_with_kecheng_repeat( }; debug!( - "raw_create_kecheng_with_kecheng_repeat -> to_create_kecheng: {:?}", + "raw_create_clazz_with_repeat -> to_create_kecheng: {:?}", to_create_kecheng ); - let mut to_create_kecheng_repeat: Option = None; + let mut to_create_kecheng_repeat: Option = None; - if let Some(kecheng_repeat) = &in_kecheng.kecheng_repeat { + if let Some(kecheng_repeat) = &in_kecheng.clazz_repeat { let kecheng_repeat_copy = kecheng_repeat.clone(); - to_create_kecheng_repeat = Some(KechengRepeat { + to_create_kecheng_repeat = Some(ClazzRepeat { id: uuid(), - kecheng_id: Some(kecheng_id.clone()), + clazz_id: Some(new_clazz_id.clone()), start_from: kecheng_repeat_copy.start_from.clone(), end_by: kecheng_repeat_copy.end_by.clone(), repeat_start: kecheng_repeat_copy.repeat_start.clone(), repeat_cycle_days: kecheng_repeat_copy.repeat_cycle_days.clone(), repeat_end: kecheng_repeat_copy.repeat_end.clone(), repeat_status: kecheng_repeat_copy.repeat_status.clone(), - latest_kc_created_at: kecheng_repeat_copy.latest_kc_created_at.clone(), + latest_clazz_created_at: kecheng_repeat_copy.latest_clazz_created_at.clone(), }) } @@ -772,7 +771,7 @@ async fn raw_create_kecheng_with_kecheng_repeat( (to_create_kecheng, to_create_kecheng_repeat), ); - let out_result = raw_create_kecheng_with_repeat_tx(params, db_pool); + let out_result = raw_create_clazz_with_repeat_tx(params, db_pool); match out_result { Ok(out) => { @@ -781,7 +780,7 @@ async fn raw_create_kecheng_with_kecheng_repeat( } Err(e) => Err(anyhow!(HtyErr { code: HtyErrCode::WebErr, - reason: Some("fail to create kecheng e: ".to_string() + &e.to_string()), + reason: Some("fail to create clazz e: ".to_string() + &e.to_string()), })), } } diff --git a/htykc/src/ws_repeat_kecheng.rs b/htykc/src/ws_clazz_repeat.rs similarity index 68% rename from htykc/src/ws_repeat_kecheng.rs rename to htykc/src/ws_clazz_repeat.rs index 67bac06..578597a 100644 --- a/htykc/src/ws_repeat_kecheng.rs +++ b/htykc/src/ws_clazz_repeat.rs @@ -9,24 +9,24 @@ use htycommons::web::{ wrap_json_anyhow_err, wrap_json_ok_resp, AuthorizationHeader, HtyHostHeader, HtySudoerTokenHeader, }; -use htykc_models::models::{KechengRepeat, ReqKechengRepeat}; +use htykc_models::models::{ClazzRepeat, ReqClazzRepeat}; use std::ops::DerefMut; use std::sync::Arc; use tracing::{debug, error}; -pub async fn create_kecheng_repeat( +pub async fn create_clazz_repeat( sudoer: HtySudoerTokenHeader, host: HtyHostHeader, auth: AuthorizationHeader, State(db_pool): State>, - Json(in_kecheng_repeat): Json, -) -> Json> { - debug!("create_kecheng_repeat -> starts"); - match raw_create_kecheng_repeat(auth, sudoer, host, db_pool, &in_kecheng_repeat).await { + Json(in_kecheng_repeat): Json, +) -> Json> { + debug!("create_clazz_repeat -> starts"); + match raw_create_clazz_repeat(auth, sudoer, host, db_pool, &in_kecheng_repeat).await { Ok(created_kecheng) => wrap_json_ok_resp(created_kecheng.to_req()), Err(e) => { error!( - "create_kecheng_repeat -> failed to create kecheng_repeat, e: {}", + "create_clazz_repeat -> failed to create kecheng_repeat, e: {}", e ); wrap_json_anyhow_err(e) @@ -34,14 +34,14 @@ pub async fn create_kecheng_repeat( } } -async fn raw_create_kecheng_repeat( +async fn raw_create_clazz_repeat( token: AuthorizationHeader, _sudoer: HtySudoerTokenHeader, _host: HtyHostHeader, db_pool: Arc, - in_kecheng_repeat: &ReqKechengRepeat, -) -> anyhow::Result { - if in_kecheng_repeat.kecheng_id.is_none() + in_kecheng_repeat: &ReqClazzRepeat, +) -> anyhow::Result { + if in_kecheng_repeat.clazz_id.is_none() || in_kecheng_repeat.start_from.is_none() || in_kecheng_repeat.end_by.is_none() || in_kecheng_repeat.repeat_cycle_days.is_none() @@ -49,7 +49,7 @@ async fn raw_create_kecheng_repeat( return Err(anyhow!(HtyErr { code: HtyErrCode::WebErr, reason: Some( - "kecheng_id or start_from or name or end_by or duration or repeat_cycle_days is none".into() + "clazz_id or start_from or end_by or repeat_cycle_days is none".into() ), })); } @@ -57,23 +57,23 @@ async fn raw_create_kecheng_repeat( let id_user = jwt_decode_token(&token.0)? .hty_id .ok_or_else(|| anyhow!("hty_id is required"))?; - debug!("raw_create_kecheng_repeat -> {:?}", id_user); + debug!("raw_create_clazz_repeat -> {:?}", id_user); let kecheng_repeat_id = uuid(); - let db_kecheng_repeat = KechengRepeat { + let db_kecheng_repeat = ClazzRepeat { id: kecheng_repeat_id.clone(), - kecheng_id: in_kecheng_repeat.kecheng_id.clone(), + clazz_id: in_kecheng_repeat.clazz_id.clone(), start_from: in_kecheng_repeat.start_from.clone(), end_by: in_kecheng_repeat.end_by.clone(), repeat_start: in_kecheng_repeat.repeat_start.clone(), repeat_cycle_days: in_kecheng_repeat.repeat_cycle_days.clone(), repeat_end: in_kecheng_repeat.repeat_end.clone(), repeat_status: in_kecheng_repeat.repeat_status.clone(), - latest_kc_created_at: in_kecheng_repeat.latest_kc_created_at.clone(), + latest_clazz_created_at: in_kecheng_repeat.latest_clazz_created_at.clone(), }; - let created_kecheng_repeat_result = KechengRepeat::create( + let created_kecheng_repeat_result = ClazzRepeat::create( &db_kecheng_repeat, extract_conn(fetch_db_conn(&db_pool)?).deref_mut(), ); @@ -87,19 +87,19 @@ async fn raw_create_kecheng_repeat( } } -pub async fn update_kecheng_repeat( +pub async fn update_clazz_repeat( sudoer: HtySudoerTokenHeader, host: HtyHostHeader, auth: AuthorizationHeader, State(db_pool): State>, - Json(in_kecheng_repeat): Json, -) -> Json> { - debug!("update_kecheng_repeat -> starts"); - match raw_update_kecheng_repeat(auth, sudoer, host, db_pool, &in_kecheng_repeat).await { + Json(in_kecheng_repeat): Json, +) -> Json> { + debug!("update_clazz_repeat -> starts"); + match raw_update_clazz_repeat(auth, sudoer, host, db_pool, &in_kecheng_repeat).await { Ok(ok) => wrap_json_ok_resp(ok), Err(e) => { error!( - "update_kecheng_repeat -> failed to update kecheng, e: {}", + "update_clazz_repeat -> failed to update kecheng, e: {}", e ); wrap_json_anyhow_err(e) @@ -107,15 +107,15 @@ pub async fn update_kecheng_repeat( } } -async fn raw_update_kecheng_repeat( +async fn raw_update_clazz_repeat( _token: AuthorizationHeader, _sudoer: HtySudoerTokenHeader, _host: HtyHostHeader, db_pool: Arc, - in_kecheng_repeat: &ReqKechengRepeat, -) -> anyhow::Result { + in_kecheng_repeat: &ReqClazzRepeat, +) -> anyhow::Result { debug!( - "raw_update_kecheng_repeat -> in_kecheng_repeat: {:?}", + "raw_update_clazz_repeat -> in_kecheng_repeat: {:?}", in_kecheng_repeat ); if in_kecheng_repeat.id.is_none() { @@ -129,20 +129,20 @@ async fn raw_update_kecheng_repeat( .id .as_ref() .ok_or_else(|| anyhow!("id is required"))?; - let some_db_kecheng_repeat = KechengRepeat::find_by_id( + let some_db_kecheng_repeat = ClazzRepeat::find_by_id( id_kecheng_repeat, extract_conn(fetch_db_conn(&db_pool)?).deref_mut(), )?; debug!( - "raw_update_kecheng_repeat -> some_db_kecheng_repeat: {:?}", + "raw_update_clazz_repeat -> some_db_kecheng_repeat: {:?}", some_db_kecheng_repeat ); if let Some(mut c_kecheng_repeat) = some_db_kecheng_repeat { // set new values of kecheng_repeat - c_kecheng_repeat.kecheng_id = in_kecheng_repeat.kecheng_id.clone(); + c_kecheng_repeat.clazz_id = in_kecheng_repeat.clazz_id.clone(); c_kecheng_repeat.repeat_cycle_days = in_kecheng_repeat.repeat_cycle_days.clone(); c_kecheng_repeat.repeat_start = in_kecheng_repeat.repeat_start.clone(); @@ -154,11 +154,11 @@ async fn raw_update_kecheng_repeat( c_kecheng_repeat.end_by = in_kecheng_repeat.end_by.clone(); debug!( - "raw_update_kecheng_repeat -> updated kecheng_repeat: {:?}", + "raw_update_clazz_repeat -> updated kecheng_repeat: {:?}", c_kecheng_repeat ); - let res = KechengRepeat::update( + let res = ClazzRepeat::update( &c_kecheng_repeat, extract_conn(fetch_db_conn(&db_pool)?).deref_mut(), )?; diff --git a/htykc/src/ws_xiaoke.rs b/htykc/src/ws_xiaoke.rs new file mode 100644 index 0000000..b40e5c6 --- /dev/null +++ b/htykc/src/ws_xiaoke.rs @@ -0,0 +1,102 @@ +//! 消课(排课出勤)相关 API + +use anyhow::anyhow; +use axum::extract::{Path, State}; +use axum::Json; +use htycommons::common::{HtyErr, HtyErrCode, HtyResponse}; +use htycommons::jwt::jwt_decode_token; +use htycommons::web::{ + wrap_json_anyhow_err, wrap_json_ok_resp, AuthorizationHeader, HtyHostHeader, + HtySudoerTokenHeader, +}; +use htykc_models::models::{ + Clazz, ClazzAttendance, ReqBatchClazzAttendance, +}; +use std::ops::DerefMut; +use std::sync::Arc; +use tracing::{debug, error}; + +use htycommons::db::{extract_conn, fetch_db_conn, DbState}; + +pub async fn find_clazz_attendance_by_clazz_id( + _sudoer: HtySudoerTokenHeader, + _host: HtyHostHeader, + _auth: AuthorizationHeader, + State(db_pool): State>, + Path(clazz_id): Path, +) -> Json>> { + debug!( + "find_clazz_attendance_by_clazz_id -> clazz_id: {:?}", + clazz_id + ); + match raw_find_clazz_attendance_by_clazz_id(db_pool, &clazz_id) { + Ok(ok) => wrap_json_ok_resp(ok), + Err(e) => { + error!( + "find_clazz_attendance_by_clazz_id -> failed, e: {}", + e + ); + wrap_json_anyhow_err(e) + } + } +} + +fn raw_find_clazz_attendance_by_clazz_id( + db_pool: Arc, + clazz_id: &String, +) -> anyhow::Result> { + ClazzAttendance::find_all_active_by_clazz_id( + clazz_id, + extract_conn(fetch_db_conn(&db_pool)?).deref_mut(), + ) +} + +pub async fn batch_save_clazz_attendance( + _sudoer: HtySudoerTokenHeader, + _host: HtyHostHeader, + auth: AuthorizationHeader, + State(db_pool): State>, + Json(body): Json, +) -> Json>> { + debug!("batch_save_clazz_attendance -> {:?}", body.clazz_id); + match raw_batch_save_clazz_attendance(auth, db_pool, body) { + Ok(ok) => wrap_json_ok_resp(ok), + Err(e) => { + error!( + "batch_save_clazz_attendance -> failed, e: {}", + e + ); + wrap_json_anyhow_err(e) + } + } +} + +fn raw_batch_save_clazz_attendance( + token: AuthorizationHeader, + db_pool: Arc, + body: ReqBatchClazzAttendance, +) -> anyhow::Result> { + let operator_hty_id = jwt_decode_token(&(*token).clone())? + .hty_id + .ok_or_else(|| anyhow!("hty_id is required"))?; + + let mut conn_holder = extract_conn(fetch_db_conn(&db_pool)?); + let conn = conn_holder.deref_mut(); + + let kc = Clazz::find_by_id(&body.clazz_id, conn)?; + let allowed = kc.created_by.as_deref() == Some(operator_hty_id.as_str()); + + if !allowed { + return Err(anyhow!(HtyErr { + code: HtyErrCode::WebErr, + reason: Some("only kecheng creator may save attendance (MVP)".into()), + })); + } + + ClazzAttendance::replace_for_clazz( + &body.clazz_id, + Some(operator_hty_id), + &body.items, + conn, + ) +} diff --git a/htykc_models/migrations/2026-04-24-120000_xiaoke_hour_and_attendance/down.sql b/htykc_models/migrations/2026-04-24-120000_xiaoke_hour_and_attendance/down.sql new file mode 100644 index 0000000..a1e0f06 --- /dev/null +++ b/htykc_models/migrations/2026-04-24-120000_xiaoke_hour_and_attendance/down.sql @@ -0,0 +1,3 @@ +DROP TABLE IF EXISTS kecheng_attendance; +DROP TABLE IF EXISTS hour_transaction; +DROP TABLE IF EXISTS course_hour_package; diff --git a/htykc_models/migrations/2026-04-24-120000_xiaoke_hour_and_attendance/up.sql b/htykc_models/migrations/2026-04-24-120000_xiaoke_hour_and_attendance/up.sql new file mode 100644 index 0000000..093a6ab --- /dev/null +++ b/htykc_models/migrations/2026-04-24-120000_xiaoke_hour_and_attendance/up.sql @@ -0,0 +1,56 @@ +-- 消课 / 课时包 / 流水(MVP 表结构;排课外键列统一为 kecheng_id) + +CREATE TABLE course_hour_package ( + id VARCHAR NOT NULL PRIMARY KEY, + student_id VARCHAR NOT NULL, + ws_course_id VARCHAR, + total_hours DOUBLE PRECISION NOT NULL DEFAULT 0, + used_hours DOUBLE PRECISION NOT NULL DEFAULT 0, + remaining_hours DOUBLE PRECISION NOT NULL DEFAULT 0, + expire_date TIMESTAMP, + package_status VARCHAR NOT NULL DEFAULT 'ACTIVE', + created_at TIMESTAMP NOT NULL, + created_by VARCHAR, + updated_at TIMESTAMP, + is_delete BOOLEAN DEFAULT FALSE +); + +COMMENT ON TABLE course_hour_package IS '学员课时包(教学域 course.id 可选记在 ws_course_id)'; +COMMENT ON COLUMN course_hour_package.ws_course_id IS '可选:关联 htyws.course.id,跨库不加 FK'; + +CREATE INDEX idx_course_hour_package_student ON course_hour_package (student_id); + +CREATE TABLE hour_transaction ( + id VARCHAR NOT NULL PRIMARY KEY, + student_id VARCHAR NOT NULL, + package_id VARCHAR NOT NULL REFERENCES course_hour_package (id), + amount DOUBLE PRECISION NOT NULL, + transaction_type VARCHAR NOT NULL, + kecheng_id VARCHAR REFERENCES kecheng (id), + operator_hty_id VARCHAR, + remark VARCHAR, + created_at TIMESTAMP NOT NULL +); + +COMMENT ON TABLE hour_transaction IS '课时变动流水;消课关联 kecheng_id'; +CREATE INDEX idx_hour_transaction_student ON hour_transaction (student_id); +CREATE INDEX idx_hour_transaction_package ON hour_transaction (package_id); +CREATE INDEX idx_hour_transaction_kecheng ON hour_transaction (kecheng_id); + +CREATE TABLE kecheng_attendance ( + id VARCHAR NOT NULL PRIMARY KEY, + kecheng_id VARCHAR NOT NULL REFERENCES kecheng (id), + student_id VARCHAR NOT NULL, + course_hour_package_id VARCHAR REFERENCES course_hour_package (id), + status VARCHAR NOT NULL, + deducted_hours DOUBLE PRECISION NOT NULL DEFAULT 0, + sign_time TIMESTAMP NOT NULL, + sign_method VARCHAR, + created_at TIMESTAMP NOT NULL, + created_by VARCHAR, + is_delete BOOLEAN DEFAULT FALSE +); + +COMMENT ON TABLE kecheng_attendance IS '排课消课记录;status 如 NORMAL/LEAVE/ABSENT/MANUAL'; +CREATE INDEX idx_kecheng_attendance_kecheng ON kecheng_attendance (kecheng_id); +CREATE INDEX idx_kecheng_attendance_student ON kecheng_attendance (student_id); diff --git a/htykc_models/migrations/2026-04-25-100000_rename_kecheng_tables_to_clazz/down.sql b/htykc_models/migrations/2026-04-25-100000_rename_kecheng_tables_to_clazz/down.sql new file mode 100644 index 0000000..0db2f49 --- /dev/null +++ b/htykc_models/migrations/2026-04-25-100000_rename_kecheng_tables_to_clazz/down.sql @@ -0,0 +1,18 @@ +ALTER INDEX IF EXISTS idx_hour_transaction_clazz RENAME TO idx_hour_transaction_kecheng; +ALTER INDEX IF EXISTS idx_clazz_attendance_clazz RENAME TO idx_kecheng_attendance_kecheng; + +ALTER TABLE clazz_attendance RENAME TO kecheng_attendance; +ALTER TABLE kecheng_attendance RENAME COLUMN clazz_id TO kecheng_id; + +ALTER TABLE hour_transaction RENAME COLUMN clazz_id TO kecheng_id; + +ALTER TABLE clazz_repeat RENAME TO kecheng_repeat; +ALTER TABLE kecheng_repeat RENAME COLUMN clazz_id TO kecheng_id; +ALTER TABLE kecheng_repeat RENAME COLUMN latest_clazz_created_at TO latest_kc_created_at; + +ALTER TABLE clazz RENAME COLUMN class_name TO kecheng_name; +ALTER TABLE clazz RENAME COLUMN class_status TO kecheng_status; +ALTER TABLE clazz RENAME COLUMN class_desc TO kecheng_desc; +ALTER TABLE clazz RENAME COLUMN class_type TO kecheng_type; + +ALTER TABLE clazz RENAME TO kecheng; diff --git a/htykc_models/migrations/2026-04-25-100000_rename_kecheng_tables_to_clazz/up.sql b/htykc_models/migrations/2026-04-25-100000_rename_kecheng_tables_to_clazz/up.sql new file mode 100644 index 0000000..1fb66c4 --- /dev/null +++ b/htykc_models/migrations/2026-04-25-100000_rename_kecheng_tables_to_clazz/up.sql @@ -0,0 +1,34 @@ +-- 排课域:kecheng → 表 clazz(避免关键字 class);列 kecheng_* → class_*;外键列 *kecheng_id → clazz_id + +ALTER TABLE kecheng RENAME TO clazz; + +ALTER TABLE clazz RENAME COLUMN kecheng_name TO class_name; +ALTER TABLE clazz RENAME COLUMN kecheng_status TO class_status; +ALTER TABLE clazz RENAME COLUMN kecheng_desc TO class_desc; +ALTER TABLE clazz RENAME COLUMN kecheng_type TO class_type; + +ALTER TABLE kecheng_repeat RENAME COLUMN kecheng_id TO clazz_id; +ALTER TABLE kecheng_repeat RENAME COLUMN latest_kc_created_at TO latest_clazz_created_at; + +ALTER TABLE kecheng_repeat RENAME TO clazz_repeat; + +ALTER TABLE hour_transaction RENAME COLUMN kecheng_id TO clazz_id; + +ALTER TABLE kecheng_attendance RENAME COLUMN kecheng_id TO clazz_id; + +ALTER TABLE kecheng_attendance RENAME TO clazz_attendance; + +-- 索引重命名(若不存在则跳过由部署侧处理) +DO $$ +BEGIN + IF EXISTS (SELECT 1 FROM pg_class WHERE relname = 'idx_hour_transaction_kecheng') THEN + ALTER INDEX idx_hour_transaction_kecheng RENAME TO idx_hour_transaction_clazz; + END IF; + IF EXISTS (SELECT 1 FROM pg_class WHERE relname = 'idx_kecheng_attendance_kecheng') THEN + ALTER INDEX idx_kecheng_attendance_kecheng RENAME TO idx_clazz_attendance_clazz; + END IF; +END $$; + +COMMENT ON TABLE clazz IS '日历排课(一次课节);原表 kecheng'; +COMMENT ON TABLE clazz_repeat IS '重复排课规则;原表 kecheng_repeat'; +COMMENT ON TABLE clazz_attendance IS '排课点名/消课;原表 kecheng_attendance'; diff --git a/htykc_models/migrations/2026-04-26-120000_rename_clazz_columns_to_clazz_prefix/down.sql b/htykc_models/migrations/2026-04-26-120000_rename_clazz_columns_to_clazz_prefix/down.sql new file mode 100644 index 0000000..fc85b03 --- /dev/null +++ b/htykc_models/migrations/2026-04-26-120000_rename_clazz_columns_to_clazz_prefix/down.sql @@ -0,0 +1,4 @@ +ALTER TABLE clazz RENAME COLUMN clazz_name TO class_name; +ALTER TABLE clazz RENAME COLUMN clazz_status TO class_status; +ALTER TABLE clazz RENAME COLUMN clazz_desc TO class_desc; +ALTER TABLE clazz RENAME COLUMN clazz_type TO class_type; diff --git a/htykc_models/migrations/2026-04-26-120000_rename_clazz_columns_to_clazz_prefix/up.sql b/htykc_models/migrations/2026-04-26-120000_rename_clazz_columns_to_clazz_prefix/up.sql new file mode 100644 index 0000000..cdec5d9 --- /dev/null +++ b/htykc_models/migrations/2026-04-26-120000_rename_clazz_columns_to_clazz_prefix/up.sql @@ -0,0 +1,5 @@ +-- clazz 表:列 class_* → clazz_*(与表名语义一致) +ALTER TABLE clazz RENAME COLUMN class_name TO clazz_name; +ALTER TABLE clazz RENAME COLUMN class_status TO clazz_status; +ALTER TABLE clazz RENAME COLUMN class_desc TO clazz_desc; +ALTER TABLE clazz RENAME COLUMN class_type TO clazz_type; diff --git a/htykc_models/src/models.rs b/htykc_models/src/models.rs index 1a7d48c..4b83395 100644 --- a/htykc_models/src/models.rs +++ b/htykc_models/src/models.rs @@ -1,14 +1,16 @@ use anyhow::anyhow; use chrono::NaiveDateTime; use diesel::{ - insert_into, sql_query, update, ExpressionMethods, OptionalExtension, PgConnection, QueryDsl, - RunQueryDsl, + delete, insert_into, sql_query, update, + BoolExpressionMethods, Connection, ExpressionMethods, OptionalExtension, PgConnection, + QueryDsl, RunQueryDsl, }; use log::debug; use string_builder::Builder; use crate::schema::*; -use htycommons::common::{date_to_string, HtyErr, HtyErrCode}; +use htycommons::common::{current_local_datetime, date_to_string, HtyErr, HtyErrCode}; +use htycommons::uuid; use htycommons::db::SingleVal; use htycommons::models::*; use htyuc_models::models::ReqHtyUserGroup; @@ -26,17 +28,17 @@ use htyws_models::models::{CourseSectionJsonData, ReqDakaWithCourseSectionIds2, Clone, QueryableByName, )] -#[diesel(table_name = kecheng)] -pub struct Kecheng { +#[diesel(table_name = clazz)] +pub struct Clazz { pub id: String, - pub kecheng_name: String, - pub kecheng_status: String, - pub kecheng_desc: Option, + pub clazz_name: String, + pub clazz_status: String, + pub clazz_desc: Option, pub start_from: NaiveDateTime, pub end_by: NaiveDateTime, pub duration: Option, pub root_id: String, // 是对应root kecheng - pub kecheng_type: Option, + pub clazz_type: Option, pub parent_id: String, pub created_by: Option, pub created_at: Option, @@ -52,51 +54,51 @@ pub struct Kecheng { // https://weinan.io/2024/02/23/rust-diesel.html #[derive(QueryableByName, Default, Serialize, Deserialize, Debug, Clone, PartialEq)] -pub struct ReqKechengWithRepeat { +pub struct ReqClazzWithRepeat { // kecheng #[diesel(sql_type = diesel::sql_types::Varchar)] - pub kc_id: String, + pub clz_id: String, #[diesel(sql_type = diesel::sql_types::Varchar)] - pub kc_kecheng_name: String, + pub clz_clazz_name: String, #[diesel(sql_type = diesel::sql_types::Varchar)] - pub kc_kecheng_status: String, + pub clz_clazz_status: String, #[diesel(sql_type = diesel::sql_types::Nullable < diesel::sql_types::Varchar >)] - pub kc_kecheng_desc: Option, + pub clz_clazz_desc: Option, #[diesel(sql_type = diesel::sql_types::Timestamp)] - pub kc_start_from: NaiveDateTime, + pub clz_start_from: NaiveDateTime, #[diesel(sql_type = diesel::sql_types::Timestamp)] - pub kc_end_by: NaiveDateTime, + pub clz_end_by: NaiveDateTime, #[diesel(sql_type = diesel::sql_types::Nullable < diesel::sql_types::Int4 >)] - pub kc_duration: Option, + pub clz_duration: Option, #[diesel(sql_type = diesel::sql_types::Varchar)] - pub kc_root_id: String, + pub clz_root_id: String, #[diesel(sql_type = diesel::sql_types::Nullable < diesel::sql_types::Varchar >)] - pub kc_kecheng_type: Option, + pub clz_clazz_type: Option, #[diesel(sql_type = diesel::sql_types::Varchar)] - pub kc_parent_id: String, + pub clz_parent_id: String, #[diesel(sql_type = diesel::sql_types::Nullable < diesel::sql_types::Varchar >)] - pub kc_created_by: Option, + pub clz_created_by: Option, #[diesel(sql_type = diesel::sql_types::Nullable < diesel::sql_types::Timestamp >)] - pub kc_created_at: Option, + pub clz_created_at: Option, #[diesel(sql_type = diesel::sql_types::Nullable < diesel::sql_types::Jsonb >)] - pub kc_students: Option>, + pub clz_students: Option>, #[diesel(sql_type = diesel::sql_types::Nullable < diesel::sql_types::Jsonb >)] - pub kc_teachers: Option>, + pub clz_teachers: Option>, #[diesel(sql_type = diesel::sql_types::Nullable < diesel::sql_types::Jsonb >)] - pub kc_jihuas: Option>, + pub clz_jihuas: Option>, #[diesel(sql_type = diesel::sql_types::Nullable < diesel::sql_types::Jsonb >)] - pub kc_dakas: Option>, + pub clz_dakas: Option>, #[diesel(sql_type = diesel::sql_types::Nullable < diesel::sql_types::Bool >)] - pub kc_is_delete: Option, + pub clz_is_delete: Option, #[diesel(sql_type = diesel::sql_types::Nullable < diesel::sql_types::Bool >)] - pub kc_is_repeat: Option, + pub clz_is_repeat: Option, #[diesel(sql_type = diesel::sql_types::Nullable < diesel::sql_types::Jsonb >)] - pub kc_course_sections: Option>, + pub clz_course_sections: Option>, // // kc_repeat #[diesel(sql_type = diesel::sql_types::Varchar)] pub re_id: String, #[diesel(sql_type = diesel::sql_types::Nullable < diesel::sql_types::Varchar >)] - pub re_kecheng_id: Option, + pub re_clazz_id: Option, #[diesel(sql_type = diesel::sql_types::Nullable < diesel::sql_types::Timestamp >)] pub re_start_from: Option, #[diesel(sql_type = diesel::sql_types::Nullable < diesel::sql_types::Timestamp >)] @@ -110,27 +112,27 @@ pub struct ReqKechengWithRepeat { #[diesel(sql_type = diesel::sql_types::Nullable < diesel::sql_types::Varchar >)] pub re_repeat_status: Option, #[diesel(sql_type = diesel::sql_types::Nullable < diesel::sql_types::Timestamp >)] - pub re_latest_kc_created_at: Option, + pub re_latest_clazz_created_at: Option, } -impl ReqKechengWithRepeat { - pub fn from_kecheng_and_repeat( - in_kecheng: &Option, - in_kecheng_repeat: &Option, - ) -> ReqKechengWithRepeat { +impl ReqClazzWithRepeat { + pub fn from_clazz_and_repeat( + in_kecheng: &Option, + in_kecheng_repeat: &Option, + ) -> ReqClazzWithRepeat { let the_kecheng = if let Some(k) = in_kecheng { k.clone() } else { - Kecheng { + Clazz { id: "".to_string(), - kecheng_name: "".to_string(), - kecheng_status: "".to_string(), - kecheng_desc: None, + clazz_name: "".to_string(), + clazz_status: "".to_string(), + clazz_desc: None, start_from: Default::default(), end_by: Default::default(), duration: None, root_id: "".to_string(), - kecheng_type: None, + clazz_type: None, parent_id: "".to_string(), created_by: None, created_at: None, @@ -148,54 +150,54 @@ impl ReqKechengWithRepeat { let the_kecheng_repeat = if let Some(kr) = in_kecheng_repeat { kr.clone() } else { - KechengRepeat { + ClazzRepeat { id: "".to_string(), - kecheng_id: None, + clazz_id: None, start_from: None, end_by: None, repeat_start: None, repeat_cycle_days: None, repeat_end: None, repeat_status: None, - latest_kc_created_at: None, + latest_clazz_created_at: None, } }; - ReqKechengWithRepeat { - kc_id: the_kecheng.id.clone(), - kc_kecheng_name: the_kecheng.kecheng_name.clone(), - kc_kecheng_status: the_kecheng.kecheng_status.clone(), - kc_kecheng_desc: the_kecheng.kecheng_desc.clone(), - kc_start_from: the_kecheng.start_from.clone(), - kc_end_by: the_kecheng.end_by.clone(), - kc_duration: the_kecheng.duration.clone(), - kc_root_id: the_kecheng.root_id.clone(), - kc_kecheng_type: the_kecheng.kecheng_type.clone(), - kc_parent_id: the_kecheng.parent_id.clone(), - kc_created_by: the_kecheng.created_by.clone(), - kc_created_at: the_kecheng.created_at.clone(), - kc_students: the_kecheng.students.clone(), - kc_teachers: the_kecheng.teachers.clone(), - kc_jihuas: the_kecheng.jihuas.clone(), - kc_dakas: the_kecheng.dakas.clone(), - kc_is_delete: the_kecheng.is_delete.clone(), - kc_is_repeat: the_kecheng.is_repeat.clone(), - kc_course_sections: the_kecheng.course_sections.clone(), - re_id: the_kecheng.id.clone(), - re_kecheng_id: the_kecheng_repeat.kecheng_id.clone(), + ReqClazzWithRepeat { + clz_id: the_kecheng.id.clone(), + clz_clazz_name: the_kecheng.clazz_name.clone(), + clz_clazz_status: the_kecheng.clazz_status.clone(), + clz_clazz_desc: the_kecheng.clazz_desc.clone(), + clz_start_from: the_kecheng.start_from.clone(), + clz_end_by: the_kecheng.end_by.clone(), + clz_duration: the_kecheng.duration.clone(), + clz_root_id: the_kecheng.root_id.clone(), + clz_clazz_type: the_kecheng.clazz_type.clone(), + clz_parent_id: the_kecheng.parent_id.clone(), + clz_created_by: the_kecheng.created_by.clone(), + clz_created_at: the_kecheng.created_at.clone(), + clz_students: the_kecheng.students.clone(), + clz_teachers: the_kecheng.teachers.clone(), + clz_jihuas: the_kecheng.jihuas.clone(), + clz_dakas: the_kecheng.dakas.clone(), + clz_is_delete: the_kecheng.is_delete.clone(), + clz_is_repeat: the_kecheng.is_repeat.clone(), + clz_course_sections: the_kecheng.course_sections.clone(), + re_id: the_kecheng_repeat.id.clone(), + re_clazz_id: the_kecheng_repeat.clazz_id.clone(), re_start_from: the_kecheng_repeat.start_from.clone(), re_end_by: the_kecheng_repeat.end_by.clone(), re_repeat_start: the_kecheng_repeat.repeat_start.clone(), re_repeat_cycle_days: the_kecheng_repeat.repeat_cycle_days.clone(), re_repeat_end: the_kecheng_repeat.repeat_end.clone(), re_repeat_status: the_kecheng_repeat.repeat_status.clone(), - re_latest_kc_created_at: the_kecheng_repeat.latest_kc_created_at.clone(), + re_latest_clazz_created_at: the_kecheng_repeat.latest_clazz_created_at.clone(), } } } -impl Kecheng { - pub fn to_req(&self) -> ReqKecheng { - let req_res = ReqKecheng { +impl Clazz { + pub fn to_req(&self) -> ReqClazz { + let req_res = ReqClazz { created_at: self.created_at.clone(), created_by: self.created_by.clone(), dakas: self.dakas.clone(), @@ -205,11 +207,11 @@ impl Kecheng { is_delete: self.is_delete.clone(), is_repeat: self.is_repeat.clone(), jihuas: self.jihuas.clone(), - kecheng_desc: self.kecheng_desc.clone(), - kecheng_name: Some(self.kecheng_name.clone()), - kecheng_repeat: None, // todo: fill in? - kecheng_status: Some(self.kecheng_status.clone()), - kecheng_type: self.kecheng_type.clone(), + clazz_desc: self.clazz_desc.clone(), + clazz_name: Some(self.clazz_name.clone()), + clazz_repeat: None, // todo: fill in? + clazz_status: Some(self.clazz_status.clone()), + clazz_type: self.clazz_type.clone(), parent_id: Some(self.parent_id.clone()), root_id: Some(self.root_id.clone()), start_from: Some(self.start_from.clone()), @@ -221,11 +223,11 @@ impl Kecheng { req_res } - pub fn find_by_id(id_kecheng: &String, conn: &mut PgConnection) -> anyhow::Result { - // use crate::schema::kecheng::dsl::*; - match kecheng::table - .filter(kecheng::id.eq(id_kecheng)) - .first::(conn) + pub fn find_by_id(id_kecheng: &String, conn: &mut PgConnection) -> anyhow::Result { + // use crate::schema::clazz::dsl::*; + match clazz::table + .filter(clazz::id.eq(id_kecheng)) + .first::(conn) { Ok(q) => Ok(q), Err(e) => Err(anyhow!(HtyErr { @@ -235,9 +237,9 @@ impl Kecheng { } } - pub fn create(in_kecheng: &Kecheng, conn: &mut PgConnection) -> anyhow::Result { - use crate::schema::kecheng::dsl::*; - match insert_into(kecheng).values(in_kecheng).get_result(conn) { + pub fn create(in_kecheng: &Clazz, conn: &mut PgConnection) -> anyhow::Result { + use crate::schema::clazz::dsl::*; + match insert_into(clazz).values(in_kecheng).get_result(conn) { Ok(res) => Ok(res), Err(e) => Err(anyhow!(HtyErr { code: HtyErrCode::DbErr, @@ -246,9 +248,9 @@ impl Kecheng { } } - pub fn update(in_kecheng: &Kecheng, conn: &mut PgConnection) -> anyhow::Result { - let result = update(kecheng::table) - .filter(kecheng::id.eq(in_kecheng.clone().id)) + pub fn update(in_kecheng: &Clazz, conn: &mut PgConnection) -> anyhow::Result { + let result = update(clazz::table) + .filter(clazz::id.eq(in_kecheng.clone().id)) .set(in_kecheng) .get_result(conn) .map_err(|e| { @@ -260,36 +262,36 @@ impl Kecheng { result } - pub fn find_kecheng_by_user_id( + pub fn find_by_user_id( id_user: &String, date_start: &Option, date_end: &Option, conn: &mut PgConnection, - ) -> anyhow::Result> { + ) -> anyhow::Result> { use diesel::prelude::*; let q; if date_start.is_some() && date_end.is_some() { - q = format!("SELECT * FROM kecheng WHERE (jsonb_path_exists(students, '$.val.users.vals[*].user_id ? (@ == \"{}\")') OR jsonb_path_exists(teachers, '$.val.users.vals[*].user_id ? (@ == \"{}\")')) AND (start_from <= '{}' AND end_by >= '{}' );", id_user.clone(), id_user.clone(), &date_end.as_ref().ok_or_else(|| anyhow!("date_end is required"))?, &date_start.as_ref().ok_or_else(|| anyhow!("date_start is required"))?); + q = format!("SELECT * FROM clazz WHERE (jsonb_path_exists(students, '$.val.users.vals[*].user_id ? (@ == \"{}\")') OR jsonb_path_exists(teachers, '$.val.users.vals[*].user_id ? (@ == \"{}\")')) AND (start_from <= '{}' AND end_by >= '{}' );", id_user.clone(), id_user.clone(), &date_end.as_ref().ok_or_else(|| anyhow!("date_end is required"))?, &date_start.as_ref().ok_or_else(|| anyhow!("date_start is required"))?); } else { - q = format!("SELECT * FROM kecheng WHERE (jsonb_path_exists(students, '$.val.users.vals[*].user_id ? (@ == \"{}\")') OR jsonb_path_exists(teachers, '$.val.users.vals[*].user_id ? (@ == \"{}\")'));", id_user.clone(), id_user.clone()); + q = format!("SELECT * FROM clazz WHERE (jsonb_path_exists(students, '$.val.users.vals[*].user_id ? (@ == \"{}\")') OR jsonb_path_exists(teachers, '$.val.users.vals[*].user_id ? (@ == \"{}\")'));", id_user.clone(), id_user.clone()); } - debug!("find_kecheng_by_user_id -> q: {:?}", q); + debug!("find_by_user_id -> q: {:?}", q); let res = sql_query(q.clone()).load(conn)?; - debug!("find_kecheng_by_user_id -> res: {:?}", res); + debug!("find_by_user_id -> res: {:?}", res); Ok(res) } - pub fn find_kecheng_by_daka_id( + pub fn find_by_daka_id( id_daka: &String, conn: &mut PgConnection, - ) -> anyhow::Result { + ) -> anyhow::Result { use diesel::prelude::*; - let q = format!("SELECT * FROM kecheng WHERE (jsonb_path_exists(dakas, '$.vals[*].id ? (@ == \"{}\")'));", id_daka.clone()); + let q = format!("SELECT * FROM clazz WHERE (jsonb_path_exists(dakas, '$.vals[*].id ? (@ == \"{}\")'));", id_daka.clone()); - let query_res: Vec = sql_query(q.clone()).load(conn)?; + let query_res: Vec = sql_query(q.clone()).load(conn)?; let res = query_res .first() .ok_or_else(|| anyhow!("No kecheng found"))? @@ -297,10 +299,10 @@ impl Kecheng { Ok(res) } - pub fn find_kechengs_by_daka_ids( + pub fn find_by_daka_ids( id_dakas: &Vec, conn: &mut PgConnection, - ) -> anyhow::Result> { + ) -> anyhow::Result> { use diesel::prelude::*; let mut query_seg_builder = Builder::default(); @@ -312,10 +314,10 @@ impl Kecheng { query_seg_builder.append("@ == false"); let q = format!( - "SELECT * FROM kecheng WHERE (jsonb_path_exists(dakas, '$.vals[*].id ? ({})'));", + "SELECT * FROM clazz WHERE (jsonb_path_exists(dakas, '$.vals[*].id ? ({})'));", query_seg_builder.string()? ); - debug!("find_kechengs_by_daka_ids -> q: {:?}", q); + debug!("find_by_daka_ids -> q: {:?}", q); let query_res = sql_query(q.clone()).load(conn)?; Ok(query_res) @@ -328,8 +330,8 @@ impl Kecheng { start_from: &NaiveDateTime, end_by: &NaiveDateTime, conn: &mut PgConnection, - ) -> anyhow::Result>> { - let q = format!("SELECT kecheng.id AS kc_id, kecheng.kecheng_name AS kc_kecheng_name, kecheng.kecheng_status AS kc_kecheng_status, kecheng.kecheng_desc AS kc_kecheng_desc, kecheng.start_from AS kc_start_from, kecheng.end_by AS kc_end_by, kecheng.duration AS kc_duration, kecheng.root_id AS kc_root_id, kecheng.kecheng_type AS kc_kecheng_type, kecheng.parent_id AS kc_parent_id, kecheng.created_by AS kc_created_by, kecheng.created_at AS kc_created_at, kecheng.students AS kc_students, kecheng.teachers AS kc_teachers, kecheng.jihuas AS kc_jihuas, kecheng.dakas AS kc_dakas, kecheng.is_delete AS kc_is_delete, kecheng.is_repeat AS kc_is_repeat, kecheng.course_sections AS kc_course_sections, kecheng_repeat.id AS re_id, kecheng_repeat.kecheng_id AS re_kecheng_id, kecheng_repeat.start_from AS re_start_from, kecheng_repeat.end_by AS re_end_by, kecheng_repeat.repeat_start AS re_repeat_start, kecheng_repeat.repeat_cycle_days AS re_repeat_cycle_days, kecheng_repeat.repeat_end AS re_repeat_end, kecheng_repeat.repeat_status AS re_repeat_status, kecheng_repeat.latest_kc_created_at AS re_latest_kc_created_at FROM kecheng JOIN kecheng_repeat ON kecheng.id = kecheng_repeat.kecheng_id WHERE (kecheng.is_repeat IS NOT NULL AND kecheng.is_repeat IS TRUE) AND ((kecheng_repeat.repeat_start <= '{}' AND kecheng_repeat.repeat_end >= '{}') OR (kecheng.start_from <= '{}' AND kecheng.end_by >= '{}'));", date_to_string(end_by), date_to_string(start_from), date_to_string(end_by), date_to_string(start_from)).to_string(); + ) -> anyhow::Result>> { + let q = format!("SELECT clazz.id AS clz_id, clazz.clazz_name AS clz_clazz_name, clazz.clazz_status AS clz_clazz_status, clazz.clazz_desc AS clz_clazz_desc, clazz.start_from AS clz_start_from, clazz.end_by AS clz_end_by, clazz.duration AS clz_duration, clazz.root_id AS clz_root_id, clazz.clazz_type AS clz_clazz_type, clazz.parent_id AS clz_parent_id, clazz.created_by AS clz_created_by, clazz.created_at AS clz_created_at, clazz.students AS clz_students, clazz.teachers AS clz_teachers, clazz.jihuas AS clz_jihuas, clazz.dakas AS clz_dakas, clazz.is_delete AS clz_is_delete, clazz.is_repeat AS clz_is_repeat, clazz.course_sections AS clz_course_sections, clazz_repeat.id AS re_id, clazz_repeat.clazz_id AS re_clazz_id, clazz_repeat.start_from AS re_start_from, clazz_repeat.end_by AS re_end_by, clazz_repeat.repeat_start AS re_repeat_start, clazz_repeat.repeat_cycle_days AS re_repeat_cycle_days, clazz_repeat.repeat_end AS re_repeat_end, clazz_repeat.repeat_status AS re_repeat_status, clazz_repeat.latest_clazz_created_at AS re_latest_clazz_created_at FROM clazz JOIN clazz_repeat ON clazz.id = clazz_repeat.clazz_id WHERE (clazz.is_repeat IS NOT NULL AND clazz.is_repeat IS TRUE) AND ((clazz_repeat.repeat_start <= '{}' AND clazz_repeat.repeat_end >= '{}') OR (clazz.start_from <= '{}' AND clazz.end_by >= '{}'));", date_to_string(end_by), date_to_string(start_from), date_to_string(end_by), date_to_string(start_from)).to_string(); debug!("find_all_repeatable_by_date_range -> q: {:?}", q); @@ -343,14 +345,14 @@ impl Kecheng { Ok(some_kechengs) } - // select kecheng.is_repeat from kecheng join kecheng_repeat on kecheng.id = kecheng_repeat.kecheng_id where kecheng.is_repeat is not null; + // select clazz.is_repeat from kecheng JOIN clazz_repeat on clazz.id = clazz_repeat.clazz_id where clazz.is_repeat is not null; pub fn find_all_repeatable_by_date_range_and_user_id( id_user: &String, start_from: &NaiveDateTime, end_by: &NaiveDateTime, conn: &mut PgConnection, - ) -> anyhow::Result>> { - let q = format!("SELECT kecheng.id AS kc_id, kecheng.kecheng_name AS kc_kecheng_name, kecheng.kecheng_status AS kc_kecheng_status, kecheng.kecheng_desc AS kc_kecheng_desc, kecheng.start_from AS kc_start_from, kecheng.end_by AS kc_end_by, kecheng.duration AS kc_duration, kecheng.root_id AS kc_root_id, kecheng.kecheng_type AS kc_kecheng_type, kecheng.parent_id AS kc_parent_id, kecheng.created_by AS kc_created_by, kecheng.created_at AS kc_created_at, kecheng.students AS kc_students, kecheng.teachers AS kc_teachers, kecheng.jihuas AS kc_jihuas, kecheng.dakas AS kc_dakas, kecheng.is_delete AS kc_is_delete, kecheng.is_repeat AS kc_is_repeat, kecheng.course_sections AS kc_course_sections, kecheng_repeat.id AS re_id, kecheng_repeat.kecheng_id AS re_kecheng_id, kecheng_repeat.start_from AS re_start_from, kecheng_repeat.end_by AS re_end_by, kecheng_repeat.repeat_start AS re_repeat_start, kecheng_repeat.repeat_cycle_days AS re_repeat_cycle_days, kecheng_repeat.repeat_end AS re_repeat_end, kecheng_repeat.repeat_status AS re_repeat_status, kecheng_repeat.latest_kc_created_at AS re_latest_kc_created_at FROM kecheng JOIN kecheng_repeat ON kecheng.id = kecheng_repeat.kecheng_id WHERE (jsonb_path_exists(kecheng.students, '$.val.users.vals[*].user_id ? (@ == \"{}\")') OR jsonb_path_exists(kecheng.teachers, '$.val.users.vals[*].user_id ? (@ == \"{}\")')) AND (kecheng.is_repeat IS NOT NULL AND kecheng.is_repeat IS TRUE) AND ((kecheng_repeat.repeat_start <= '{}' AND kecheng_repeat.repeat_end >= '{}') OR (kecheng.start_from <= '{}' AND kecheng.end_by >= '{}'));", id_user.clone(), id_user.clone(), date_to_string(end_by), date_to_string(start_from), date_to_string(end_by), date_to_string(start_from)).to_string(); + ) -> anyhow::Result>> { + let q = format!("SELECT clazz.id AS clz_id, clazz.clazz_name AS clz_clazz_name, clazz.clazz_status AS clz_clazz_status, clazz.clazz_desc AS clz_clazz_desc, clazz.start_from AS clz_start_from, clazz.end_by AS clz_end_by, clazz.duration AS clz_duration, clazz.root_id AS clz_root_id, clazz.clazz_type AS clz_clazz_type, clazz.parent_id AS clz_parent_id, clazz.created_by AS clz_created_by, clazz.created_at AS clz_created_at, clazz.students AS clz_students, clazz.teachers AS clz_teachers, clazz.jihuas AS clz_jihuas, clazz.dakas AS clz_dakas, clazz.is_delete AS clz_is_delete, clazz.is_repeat AS clz_is_repeat, clazz.course_sections AS clz_course_sections, clazz_repeat.id AS re_id, clazz_repeat.clazz_id AS re_clazz_id, clazz_repeat.start_from AS re_start_from, clazz_repeat.end_by AS re_end_by, clazz_repeat.repeat_start AS re_repeat_start, clazz_repeat.repeat_cycle_days AS re_repeat_cycle_days, clazz_repeat.repeat_end AS re_repeat_end, clazz_repeat.repeat_status AS re_repeat_status, clazz_repeat.latest_clazz_created_at AS re_latest_clazz_created_at FROM clazz JOIN clazz_repeat ON clazz.id = clazz_repeat.clazz_id WHERE (jsonb_path_exists(clazz.students, '$.val.users.vals[*].user_id ? (@ == \"{}\")') OR jsonb_path_exists(clazz.teachers, '$.val.users.vals[*].user_id ? (@ == \"{}\")')) AND (clazz.is_repeat IS NOT NULL AND clazz.is_repeat IS TRUE) AND ((clazz_repeat.repeat_start <= '{}' AND clazz_repeat.repeat_end >= '{}') OR (clazz.start_from <= '{}' AND clazz.end_by >= '{}'));", id_user.clone(), id_user.clone(), date_to_string(end_by), date_to_string(start_from), date_to_string(end_by), date_to_string(start_from)).to_string(); debug!( "find_all_repeatable_by_date_range_and_user_id -> q: {:?}", @@ -374,8 +376,8 @@ impl Kecheng { start_from: &NaiveDateTime, end_by: &NaiveDateTime, conn: &mut PgConnection, - ) -> anyhow::Result>> { - let q = format!("SELECT * FROM kecheng WHERE (is_repeat IS NULL OR is_repeat IS FALSE) AND (start_from <= '{}' AND end_by >= '{}');", date_to_string(end_by), date_to_string(start_from)).to_string(); + ) -> anyhow::Result>> { + let q = format!("SELECT * FROM clazz WHERE (is_repeat IS NULL OR is_repeat IS FALSE) AND (start_from <= '{}' AND end_by >= '{}');", date_to_string(end_by), date_to_string(start_from)).to_string(); debug!("find_all_non_repeatable_by_date_range -> q: {:?}", q); @@ -394,8 +396,8 @@ impl Kecheng { start_from: &NaiveDateTime, end_by: &NaiveDateTime, conn: &mut PgConnection, - ) -> anyhow::Result>> { - let q = format!("SELECT * FROM kecheng WHERE (is_repeat IS NULL OR is_repeat IS FALSE) AND (start_from <= '{}' AND end_by >= '{}') AND (jsonb_path_exists(kecheng.students, '$.val.users.vals[*].user_id ? (@ == \"{}\")') OR jsonb_path_exists(kecheng.teachers, '$.val.users.vals[*].user_id ? (@ == \"{}\")'));", date_to_string(end_by), date_to_string(start_from), id_user.clone(), id_user.clone()).to_string(); + ) -> anyhow::Result>> { + let q = format!("SELECT * FROM clazz WHERE (is_repeat IS NULL OR is_repeat IS FALSE) AND (start_from <= '{}' AND end_by >= '{}') AND (jsonb_path_exists(clazz.students, '$.val.users.vals[*].user_id ? (@ == \"{}\")') OR jsonb_path_exists(clazz.teachers, '$.val.users.vals[*].user_id ? (@ == \"{}\")'));", date_to_string(end_by), date_to_string(start_from), id_user.clone(), id_user.clone()).to_string(); debug!( "find_all_non_repeatable_by_date_range_and_user_id -> q: {:?}", @@ -425,27 +427,27 @@ impl Kecheng { Insertable, Clone, )] -#[diesel(table_name = kecheng_repeat)] -#[diesel(belongs_to(Kecheng, foreign_key = kecheng_id))] -pub struct KechengRepeat { +#[diesel(table_name = clazz_repeat)] +#[diesel(belongs_to(Clazz, foreign_key = clazz_id))] +pub struct ClazzRepeat { pub id: String, - pub kecheng_id: Option, + pub clazz_id: Option, pub start_from: Option, pub end_by: Option, pub repeat_start: Option, pub repeat_cycle_days: Option, pub repeat_end: Option, pub repeat_status: Option, - pub latest_kc_created_at: Option, + pub latest_clazz_created_at: Option, } -impl KechengRepeat { +impl ClazzRepeat { pub fn update( - in_kecheng_repeat: &KechengRepeat, + in_kecheng_repeat: &ClazzRepeat, conn: &mut PgConnection, - ) -> anyhow::Result { - let result = update(kecheng_repeat::table) - .filter(kecheng_repeat::id.eq(in_kecheng_repeat.clone().id)) + ) -> anyhow::Result { + let result = update(clazz_repeat::table) + .filter(clazz_repeat::id.eq(in_kecheng_repeat.clone().id)) .set(in_kecheng_repeat) .get_result(conn) .map_err(|e| { @@ -457,27 +459,27 @@ impl KechengRepeat { Ok(result) } - pub fn to_req(&self) -> ReqKechengRepeat { - let req_repeat = ReqKechengRepeat { + pub fn to_req(&self) -> ReqClazzRepeat { + let req_repeat = ReqClazzRepeat { id: Some(self.id.clone()), - kecheng_id: self.kecheng_id.clone(), - start_from: self.end_by.clone(), + clazz_id: self.clazz_id.clone(), + start_from: self.start_from.clone(), end_by: self.end_by.clone(), repeat_start: self.repeat_start.clone(), repeat_cycle_days: self.repeat_cycle_days.clone(), repeat_end: self.repeat_end.clone(), repeat_status: self.repeat_status.clone(), - latest_kc_created_at: self.latest_kc_created_at.clone(), + latest_clazz_created_at: self.latest_clazz_created_at.clone(), }; req_repeat } pub fn create( - in_kecheng_repeat: &KechengRepeat, + in_kecheng_repeat: &ClazzRepeat, conn: &mut PgConnection, - ) -> anyhow::Result { - use crate::schema::kecheng_repeat::dsl::*; - match insert_into(kecheng_repeat) + ) -> anyhow::Result { + use crate::schema::clazz_repeat::dsl::*; + match insert_into(clazz_repeat) .values(in_kecheng_repeat) .get_result(conn) { @@ -489,14 +491,14 @@ impl KechengRepeat { } } - pub fn find_by_kecheng_id( + pub fn find_by_clazz_id( id_kecheng: &String, conn: &mut PgConnection, - ) -> anyhow::Result> { - use crate::schema::kecheng_repeat::dsl::*; - match kecheng_repeat - .filter(kecheng_id.eq(id_kecheng)) - .first::(conn) + ) -> anyhow::Result> { + use crate::schema::clazz_repeat::dsl::*; + match clazz_repeat + .filter(clazz_id.eq(id_kecheng)) + .first::(conn) .optional() { Ok(q) => Ok(q), @@ -510,10 +512,10 @@ impl KechengRepeat { pub fn find_by_id( id_kecheng_repeat: &String, conn: &mut PgConnection, - ) -> anyhow::Result> { - match kecheng_repeat::table - .filter(kecheng_repeat::id.eq(id_kecheng_repeat)) - .first::(conn) + ) -> anyhow::Result> { + match clazz_repeat::table + .filter(clazz_repeat::id.eq(id_kecheng_repeat)) + .first::(conn) .optional() { Ok(q) => Ok(q), @@ -538,12 +540,12 @@ impl KechengRepeat { // Clone, // )] // #[diesel(table_name = kecheng_users)] -// #[diesel(belongs_to(Kecheng, foreign_key = kecheng_id))] +// #[diesel(belongs_to(Clazz, foreign_key = clazz_id))] // pub struct KechengUser { // pub id: String, // pub user_id: String, -// pub kecheng_id: String, -// pub kecheng_status: String, +// pub clazz_id: String, +// pub clazz_status: String, // pub user_type: String, // } // @@ -559,13 +561,13 @@ impl KechengRepeat { // } // } // -// pub fn find_linked_kecheng_by_user_id(id_user: &String, conn: &mut PgConnection) -> anyhow::Result> { +// pub fn find_linked_kecheng_by_user_id(id_user: &String, conn: &mut PgConnection) -> anyhow::Result> { // use crate::schema::kecheng_users::dsl::*; // match kecheng_users // .filter(user_id.eq(id_user)) -// .inner_join(kecheng::table) -// .select(kecheng::all_columns) -// .load::(conn) +// .inner_join(clazz::table) +// .select(clazz::all_columns) +// .load::(conn) // { // Ok(res) => Ok(res), // Err(e) => Err(anyhow!(HtyErr { @@ -577,7 +579,7 @@ impl KechengRepeat { // } #[derive(Serialize, Deserialize, Debug, Clone)] -pub struct ReqKecheng { +pub struct ReqClazz { pub created_at: Option, pub created_by: Option, pub dakas: Option>, @@ -587,12 +589,12 @@ pub struct ReqKecheng { pub is_delete: Option, pub is_repeat: Option, pub jihuas: Option>, - pub kecheng_desc: Option, - pub kecheng_name: Option, - pub kecheng_repeat: Option, + pub clazz_desc: Option, + pub clazz_name: Option, + pub clazz_repeat: Option, // 如果包含本数据, 则可以使用 - pub kecheng_status: Option, - pub kecheng_type: Option, + pub clazz_status: Option, + pub clazz_type: Option, pub parent_id: Option, pub root_id: Option, pub start_from: Option, @@ -602,24 +604,24 @@ pub struct ReqKecheng { pub is_notified: Option, } -impl ReqKecheng { - pub fn from_kecheng_and_repeat( - in_kecheng: &Option, - in_kecheng_repeat: &Option, - ) -> ReqKecheng { +impl ReqClazz { + pub fn from_clazz_and_repeat( + in_kecheng: &Option, + in_kecheng_repeat: &Option, + ) -> ReqClazz { let the_kecheng = if let Some(k) = in_kecheng { k.clone() } else { - Kecheng { + Clazz { id: "".to_string(), - kecheng_name: "".to_string(), - kecheng_status: "".to_string(), - kecheng_desc: None, + clazz_name: "".to_string(), + clazz_status: "".to_string(), + clazz_desc: None, start_from: Default::default(), end_by: Default::default(), duration: None, root_id: "".to_string(), - kecheng_type: None, + clazz_type: None, parent_id: "".to_string(), created_by: None, created_at: None, @@ -644,7 +646,7 @@ impl ReqKecheng { debug!("some_kecheng_repeat -> {:?}", some_kecheng_repeat); - ReqKecheng { + ReqClazz { created_at: the_kecheng.created_at, created_by: the_kecheng.created_by, dakas: the_kecheng.dakas, @@ -654,11 +656,11 @@ impl ReqKecheng { is_delete: the_kecheng.is_delete, is_repeat: the_kecheng.is_repeat, jihuas: the_kecheng.jihuas, - kecheng_desc: the_kecheng.kecheng_desc, - kecheng_name: Some(the_kecheng.kecheng_name), - kecheng_repeat: some_kecheng_repeat, - kecheng_status: Some(the_kecheng.kecheng_status), - kecheng_type: the_kecheng.kecheng_type, + clazz_desc: the_kecheng.clazz_desc, + clazz_name: Some(the_kecheng.clazz_name), + clazz_repeat: some_kecheng_repeat, + clazz_status: Some(the_kecheng.clazz_status), + clazz_type: the_kecheng.clazz_type, parent_id: Some(the_kecheng.parent_id), root_id: Some(the_kecheng.root_id), start_from: Some(the_kecheng.start_from), @@ -671,23 +673,156 @@ impl ReqKecheng { } #[derive(Serialize, Deserialize, Debug, Clone)] -pub struct ReqKechengRepeat { +pub struct ReqClazzRepeat { pub id: Option, - pub kecheng_id: Option, + pub clazz_id: Option, pub start_from: Option, pub end_by: Option, pub repeat_start: Option, pub repeat_cycle_days: Option, pub repeat_end: Option, pub repeat_status: Option, - pub latest_kc_created_at: Option, + pub latest_clazz_created_at: Option, } #[derive(Serialize, Deserialize, Debug, Clone)] -pub struct ReqKechengUser { +pub struct ReqClazzUser { pub id: Option, pub user_id: Option, - pub kecheng_id: Option, - pub kecheng_status: Option, + pub clazz_id: Option, + pub clazz_status: Option, pub user_type: Option, } + +// --- 消课 / 课时包(xiaoke)--- + +#[derive(Queryable, Serialize, Deserialize, Debug, Clone)] +pub struct CourseHourPackage { + pub id: String, + pub student_id: String, + pub ws_course_id: Option, + pub total_hours: f64, + pub used_hours: f64, + pub remaining_hours: f64, + pub expire_date: Option, + pub package_status: String, + pub created_at: NaiveDateTime, + pub created_by: Option, + pub updated_at: Option, + pub is_delete: Option, +} + +#[derive(Queryable, Serialize, Deserialize, Debug, Clone)] +pub struct HourTransaction { + pub id: String, + pub student_id: String, + pub package_id: String, + pub amount: f64, + pub transaction_type: String, + pub clazz_id: Option, + pub operator_hty_id: Option, + pub remark: Option, + pub created_at: NaiveDateTime, +} + +#[derive(Queryable, Serialize, Deserialize, Debug, Clone)] +pub struct ClazzAttendance { + pub id: String, + pub clazz_id: String, + pub student_id: String, + pub course_hour_package_id: Option, + pub status: String, + pub deducted_hours: f64, + pub sign_time: NaiveDateTime, + pub sign_method: Option, + pub created_at: NaiveDateTime, + pub created_by: Option, + pub is_delete: Option, +} + +#[derive(Insertable, Clone, Debug)] +#[diesel(table_name = clazz_attendance)] +pub struct NewClazzAttendance { + pub id: String, + pub clazz_id: String, + pub student_id: String, + pub course_hour_package_id: Option, + pub status: String, + pub deducted_hours: f64, + pub sign_time: NaiveDateTime, + pub sign_method: Option, + pub created_at: NaiveDateTime, + pub created_by: Option, + pub is_delete: Option, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct ReqClazzAttendanceItem { + pub student_id: String, + pub status: String, + pub deducted_hours: f64, + pub sign_method: Option, + pub course_hour_package_id: Option, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct ReqBatchClazzAttendance { + pub clazz_id: String, + pub items: Vec, +} + +impl ClazzAttendance { + pub fn find_all_active_by_clazz_id( + clazz_id_in: &String, + conn: &mut PgConnection, + ) -> anyhow::Result> { + use crate::schema::clazz_attendance::dsl::*; + Ok(clazz_attendance + .filter(clazz_id.eq(clazz_id_in)) + .filter( + is_delete + .is_null() + .or(is_delete.eq(false)), + ) + .load::(conn)?) + } + + pub fn replace_for_clazz( + clazz_id_in: &String, + operator_id: Option, + items: &[ReqClazzAttendanceItem], + conn: &mut PgConnection, + ) -> anyhow::Result> { + use crate::schema::clazz_attendance::dsl::*; + let now = current_local_datetime(); + conn.transaction(|conn| { + delete( + clazz_attendance.filter(clazz_id.eq(clazz_id_in)), + ) + .execute(conn)?; + + let rows: Vec = items + .iter() + .map(|it| NewClazzAttendance { + id: uuid(), + clazz_id: clazz_id_in.clone(), + student_id: it.student_id.clone(), + course_hour_package_id: it.course_hour_package_id.clone(), + status: it.status.clone(), + deducted_hours: it.deducted_hours, + sign_time: now, + sign_method: it.sign_method.clone(), + created_at: now, + created_by: operator_id.clone(), + is_delete: Some(false), + }) + .collect(); + + if !rows.is_empty() { + insert_into(clazz_attendance).values(&rows).execute(conn)?; + } + + ClazzAttendance::find_all_active_by_clazz_id(clazz_id_in, conn) + }) + } +} diff --git a/htykc_models/src/schema.rs b/htykc_models/src/schema.rs index 0d04641..02a319b 100644 --- a/htykc_models/src/schema.rs +++ b/htykc_models/src/schema.rs @@ -1,16 +1,16 @@ // @generated automatically by Diesel CLI. diesel::table! { - kecheng (id) { + clazz (id) { id -> Varchar, - kecheng_name -> Varchar, - kecheng_status -> Varchar, - kecheng_desc -> Nullable, + clazz_name -> Varchar, + clazz_status -> Varchar, + clazz_desc -> Nullable, start_from -> Timestamp, end_by -> Timestamp, duration -> Nullable, root_id -> Varchar, - kecheng_type -> Nullable, + clazz_type -> Nullable, parent_id -> Varchar, created_by -> Nullable, created_at -> Nullable, @@ -26,19 +26,76 @@ diesel::table! { } diesel::table! { - kecheng_repeat (id) { + clazz_attendance (id) { id -> Varchar, - kecheng_id -> Nullable, + clazz_id -> Varchar, + student_id -> Varchar, + course_hour_package_id -> Nullable, + status -> Varchar, + deducted_hours -> Float8, + sign_time -> Timestamp, + sign_method -> Nullable, + created_at -> Timestamp, + created_by -> Nullable, + is_delete -> Nullable, + } +} + +diesel::table! { + clazz_repeat (id) { + id -> Varchar, + clazz_id -> Nullable, start_from -> Nullable, end_by -> Nullable, repeat_start -> Nullable, repeat_cycle_days -> Nullable, repeat_end -> Nullable, repeat_status -> Nullable, - latest_kc_created_at -> Nullable, + latest_clazz_created_at -> Nullable, } } -diesel::joinable!(kecheng_repeat -> kecheng (kecheng_id)); +diesel::table! { + course_hour_package (id) { + id -> Varchar, + student_id -> Varchar, + ws_course_id -> Nullable, + total_hours -> Float8, + used_hours -> Float8, + remaining_hours -> Float8, + expire_date -> Nullable, + package_status -> Varchar, + created_at -> Timestamp, + created_by -> Nullable, + updated_at -> Nullable, + is_delete -> Nullable, + } +} -diesel::allow_tables_to_appear_in_same_query!(kecheng, kecheng_repeat,); +diesel::table! { + hour_transaction (id) { + id -> Varchar, + student_id -> Varchar, + package_id -> Varchar, + amount -> Float8, + transaction_type -> Varchar, + clazz_id -> Nullable, + operator_hty_id -> Nullable, + remark -> Nullable, + created_at -> Timestamp, + } +} + +diesel::joinable!(clazz_attendance -> clazz (clazz_id)); +diesel::joinable!(clazz_attendance -> course_hour_package (course_hour_package_id)); +diesel::joinable!(clazz_repeat -> clazz (clazz_id)); +diesel::joinable!(hour_transaction -> clazz (clazz_id)); +diesel::joinable!(hour_transaction -> course_hour_package (package_id)); + +diesel::allow_tables_to_appear_in_same_query!( + clazz, + clazz_attendance, + clazz_repeat, + course_hour_package, + hour_transaction, +); diff --git a/htyws/src/lib.rs b/htyws/src/lib.rs index b65b9ec..1ff7e18 100644 --- a/htyws/src/lib.rs +++ b/htyws/src/lib.rs @@ -140,7 +140,7 @@ pub fn ws_rocket(db_url: &str) -> Router { get(get_resource_note_group_by_ref_id), ) .route( - "/api/v1/ws/find_section_by_coursename", + "/api/v1/ws/find_section_by_coursename/{name_course}", get(find_section_by_coursename), ) .route(