feat(htykc): clazz 命名迁移、消课点名与 Diesel 迁移
将课程相关表与 API 从 kecheng 迁至 clazz;新增消课/点名迁移;htyws 路由同步;工作区依赖 patch AuthCore。 Made-with: Cursor
This commit is contained in:
@@ -0,0 +1,786 @@
|
||||
use anyhow::anyhow;
|
||||
use axum::extract::{Path, Query, State};
|
||||
use axum::Json;
|
||||
use diesel::PgConnection;
|
||||
use htycommons::common::{
|
||||
current_local_datetime, get_some_from_query_params, string_to_date, string_to_datetime, HtyErr,
|
||||
HtyErrCode, HtyResponse,
|
||||
};
|
||||
use htycommons::db::*;
|
||||
use htycommons::jwt::jwt_decode_token;
|
||||
use htycommons::uuid;
|
||||
use htycommons::web::{
|
||||
wrap_json_anyhow_err, wrap_json_ok_resp, AuthorizationHeader, HtyHostHeader,
|
||||
HtySudoerTokenHeader,
|
||||
};
|
||||
use htykc_models::models::{
|
||||
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_within_date_range(
|
||||
sudoer: HtySudoerTokenHeader,
|
||||
host: HtyHostHeader,
|
||||
auth: AuthorizationHeader,
|
||||
State(db_pool): State<Arc<DbState>>,
|
||||
Query(params): Query<HashMap<String, String>>,
|
||||
) -> Json<HtyResponse<Vec<ReqClazz>>> {
|
||||
debug!(
|
||||
"find_all_non_repeatable_within_date_range -> starts, params: {:?}",
|
||||
params
|
||||
);
|
||||
|
||||
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_within_date_range -> failed to find kecheng, e: {}",
|
||||
e
|
||||
);
|
||||
wrap_json_anyhow_err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn raw_find_all_non_repeatable_within_date_range(
|
||||
_token: AuthorizationHeader,
|
||||
_sudoer: HtySudoerTokenHeader,
|
||||
_host: HtyHostHeader,
|
||||
db_pool: Arc<DbState>,
|
||||
params: &HashMap<String, String>,
|
||||
) -> anyhow::Result<Vec<ReqClazz>> {
|
||||
let start_from = string_to_date(&get_some_from_query_params::<String>("start_from", ¶ms))?;
|
||||
let end_by = string_to_date(&get_some_from_query_params::<String>("end_by", ¶ms))?;
|
||||
|
||||
debug!(
|
||||
"raw_find_all_non_repeatable_within_date_range -> start_from: {:?}",
|
||||
start_from
|
||||
);
|
||||
debug!(
|
||||
"raw_find_all_non_repeatable_within_date_range -> end_by: {:?}",
|
||||
end_by
|
||||
);
|
||||
|
||||
if start_from.is_none() || end_by.is_none() {
|
||||
return Err(anyhow!(HtyErr {
|
||||
code: HtyErrCode::WebErr,
|
||||
reason: Some("start_from or end_by is none".into()),
|
||||
}));
|
||||
}
|
||||
|
||||
let some_kechengs = Clazz::find_all_non_repeatable_by_date_range(
|
||||
start_from
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("start_from is required"))?,
|
||||
end_by
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("end_by is required"))?,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
|
||||
debug!(
|
||||
"raw_find_all_non_repeatable_within_date_range -> some_kechengs: {:?}",
|
||||
some_kechengs
|
||||
);
|
||||
|
||||
if let Some(kechengs) = some_kechengs {
|
||||
let res: Vec<ReqClazz> = kechengs.iter().map(|kc| kc.to_req()).collect();
|
||||
Ok(res)
|
||||
} else {
|
||||
Ok(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn find_all_non_repeatable_within_date_range_by_hty_id(
|
||||
sudoer: HtySudoerTokenHeader,
|
||||
host: HtyHostHeader,
|
||||
auth: AuthorizationHeader,
|
||||
State(db_pool): State<Arc<DbState>>,
|
||||
Query(params): Query<HashMap<String, String>>,
|
||||
) -> Json<HtyResponse<Vec<ReqClazz>>> {
|
||||
debug!(
|
||||
"find_all_non_repeatable_within_date_range_by_hty_id -> starts, params: {:?}",
|
||||
params
|
||||
);
|
||||
|
||||
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_within_date_range_by_hty_id -> failed to find kecheng, e: {}",
|
||||
e
|
||||
);
|
||||
wrap_json_anyhow_err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn raw_find_all_non_repeatable_within_date_range_by_hty_id(
|
||||
_token: AuthorizationHeader,
|
||||
_sudoer: HtySudoerTokenHeader,
|
||||
_host: HtyHostHeader,
|
||||
db_pool: Arc<DbState>,
|
||||
params: &HashMap<String, String>,
|
||||
) -> anyhow::Result<Vec<ReqClazz>> {
|
||||
let start_from =
|
||||
string_to_datetime(&get_some_from_query_params::<String>("start_from", ¶ms))?;
|
||||
let end_by = string_to_datetime(&get_some_from_query_params::<String>("end_by", ¶ms))?;
|
||||
|
||||
debug!(
|
||||
"raw_find_all_non_repeatable_within_date_range_by_hty_id -> start_from: {:?}",
|
||||
start_from
|
||||
);
|
||||
debug!(
|
||||
"raw_find_all_non_repeatable_within_date_range_by_hty_id -> end_by: {:?}",
|
||||
end_by
|
||||
);
|
||||
|
||||
let id_user = get_some_from_query_params::<String>("hty_id", ¶ms);
|
||||
|
||||
if start_from.is_none() || end_by.is_none() {
|
||||
return Err(anyhow!(HtyErr {
|
||||
code: HtyErrCode::WebErr,
|
||||
reason: Some("start_from or end_by is none".into()),
|
||||
}));
|
||||
}
|
||||
|
||||
if id_user.is_none() {
|
||||
return Err(anyhow!(HtyErr {
|
||||
code: HtyErrCode::WebErr,
|
||||
reason: Some("hty_id is none".into()),
|
||||
}));
|
||||
}
|
||||
|
||||
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"))?,
|
||||
start_from
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("start_from is required"))?,
|
||||
end_by
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("end_by is required"))?,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
|
||||
debug!(
|
||||
"raw_find_all_non_repeatable_within_date_range_by_hty_id -> {:?}",
|
||||
some_kechengs
|
||||
);
|
||||
|
||||
if let Some(kechengs) = some_kechengs {
|
||||
let res: Vec<ReqClazz> = kechengs.iter().map(|kc| kc.to_req()).collect();
|
||||
Ok(res)
|
||||
} else {
|
||||
Ok(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn find_all_repeatable_within_date_range(
|
||||
sudoer: HtySudoerTokenHeader,
|
||||
host: HtyHostHeader,
|
||||
auth: AuthorizationHeader,
|
||||
State(db_pool): State<Arc<DbState>>,
|
||||
Query(params): Query<HashMap<String, String>>,
|
||||
) -> Json<HtyResponse<Vec<ReqClazzWithRepeat>>> {
|
||||
debug!(
|
||||
"find_all_repeatable_within_date_range -> starts, params: {:?}",
|
||||
params
|
||||
);
|
||||
|
||||
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_within_date_range -> failed to find kecheng, e: {}",
|
||||
e
|
||||
);
|
||||
wrap_json_anyhow_err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn raw_find_all_repeatable_within_date_range(
|
||||
_token: AuthorizationHeader,
|
||||
_sudoer: HtySudoerTokenHeader,
|
||||
_host: HtyHostHeader,
|
||||
db_pool: Arc<DbState>,
|
||||
params: &HashMap<String, String>,
|
||||
) -> anyhow::Result<Vec<ReqClazzWithRepeat>> {
|
||||
let start_from = string_to_date(&get_some_from_query_params::<String>("start_from", ¶ms))?;
|
||||
let end_by = string_to_date(&get_some_from_query_params::<String>("end_by", ¶ms))?;
|
||||
|
||||
debug!(
|
||||
"raw_find_all_repeatable_within_date_range -> start_from: {:?}",
|
||||
start_from
|
||||
);
|
||||
debug!(
|
||||
"raw_find_all_repeatable_within_date_range -> end_by: {:?}",
|
||||
end_by
|
||||
);
|
||||
|
||||
if start_from.is_none() || end_by.is_none() {
|
||||
return Err(anyhow!(HtyErr {
|
||||
code: HtyErrCode::WebErr,
|
||||
reason: Some("start_from or end_by is none".into()),
|
||||
}));
|
||||
}
|
||||
|
||||
let some_kechengs = Clazz::find_all_repeatable_by_date_range(
|
||||
start_from
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("start_from is required"))?,
|
||||
end_by
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("end_by is required"))?,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
|
||||
debug!(
|
||||
"raw_find_all_repeatable_within_date_range -> some_kechengs: {:?}",
|
||||
some_kechengs
|
||||
);
|
||||
|
||||
if let Some(kechengs) = some_kechengs {
|
||||
debug!(
|
||||
"raw_find_all_repeatable_within_date_range -> kechengs.len(): {:?}",
|
||||
kechengs.len()
|
||||
);
|
||||
Ok(kechengs)
|
||||
} else {
|
||||
Ok(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn find_all_repeatable_within_date_range_by_hty_id(
|
||||
sudoer: HtySudoerTokenHeader,
|
||||
host: HtyHostHeader,
|
||||
auth: AuthorizationHeader,
|
||||
State(db_pool): State<Arc<DbState>>,
|
||||
Query(params): Query<HashMap<String, String>>,
|
||||
) -> Json<HtyResponse<Vec<ReqClazzWithRepeat>>> {
|
||||
debug!(
|
||||
"find_all_repeatable_within_date_range_by_hty_id -> starts, params: {:?}",
|
||||
params
|
||||
);
|
||||
|
||||
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_within_date_range_by_hty_id -> failed to find kecheng, e: {}",
|
||||
e
|
||||
);
|
||||
wrap_json_anyhow_err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 找到前端给定时间范围内的所有kecheng数据
|
||||
* 本周的重复课程如果存在,返回重复课程对应的sudoer课程
|
||||
* 1. hty_user_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.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_within_date_range_by_hty_id(
|
||||
_token: AuthorizationHeader,
|
||||
_sudoer: HtySudoerTokenHeader,
|
||||
_host: HtyHostHeader,
|
||||
db_pool: Arc<DbState>,
|
||||
params: &HashMap<String, String>,
|
||||
) -> anyhow::Result<Vec<ReqClazzWithRepeat>> {
|
||||
let start_from =
|
||||
string_to_datetime(&get_some_from_query_params::<String>("start_from", ¶ms))?;
|
||||
let end_by = string_to_datetime(&get_some_from_query_params::<String>("end_by", ¶ms))?;
|
||||
|
||||
debug!(
|
||||
"raw_find_all_repeatable_within_date_range_by_hty_id -> start_from: {:?}",
|
||||
start_from
|
||||
);
|
||||
debug!(
|
||||
"raw_find_all_repeatable_within_date_range_by_hty_id -> end_by: {:?}",
|
||||
end_by
|
||||
);
|
||||
|
||||
let id_user = get_some_from_query_params::<String>("hty_id", ¶ms);
|
||||
|
||||
if start_from.is_none() || end_by.is_none() {
|
||||
return Err(anyhow!(HtyErr {
|
||||
code: HtyErrCode::WebErr,
|
||||
reason: Some("start_from or end_by is none".into()),
|
||||
}));
|
||||
}
|
||||
|
||||
if id_user.is_none() {
|
||||
return Err(anyhow!(HtyErr {
|
||||
code: HtyErrCode::WebErr,
|
||||
reason: Some("hty_id is none".into()),
|
||||
}));
|
||||
}
|
||||
|
||||
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"))?,
|
||||
start_from
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("start_from is required"))?,
|
||||
end_by
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("end_by is required"))?,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
|
||||
debug!(
|
||||
"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_within_date_range_by_hty_id -> kechengs.len(): {:?}",
|
||||
kechengs.len()
|
||||
);
|
||||
Ok(kechengs)
|
||||
} else {
|
||||
Ok(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn find_by_daka_ids(
|
||||
sudoer: HtySudoerTokenHeader,
|
||||
host: HtyHostHeader,
|
||||
auth: AuthorizationHeader,
|
||||
State(db_pool): State<Arc<DbState>>,
|
||||
daka_ids: Json<Vec<String>>,
|
||||
) -> Json<HtyResponse<Vec<ReqClazz>>> {
|
||||
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_by_daka_ids -> failed to find kecheng, e: {}",
|
||||
e
|
||||
);
|
||||
wrap_json_anyhow_err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn raw_find_by_daka_ids(
|
||||
_auth: AuthorizationHeader,
|
||||
_sudoer: HtySudoerTokenHeader,
|
||||
_host: HtyHostHeader,
|
||||
db_pool: Arc<DbState>,
|
||||
daka_ids: &Vec<String>,
|
||||
) -> anyhow::Result<Vec<ReqClazz>> {
|
||||
let db_kechengs = Clazz::find_by_daka_ids(
|
||||
daka_ids,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
debug!(
|
||||
"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_by_daka_ids -> req_kechengs: {:?}",
|
||||
req_kechengs
|
||||
);
|
||||
Ok(req_kechengs)
|
||||
}
|
||||
|
||||
pub async fn find_clazz_repeat_by_id(
|
||||
sudoer: HtySudoerTokenHeader,
|
||||
host: HtyHostHeader,
|
||||
auth: AuthorizationHeader,
|
||||
State(db_pool): State<Arc<DbState>>,
|
||||
Path(id): Path<String>,
|
||||
) -> Json<HtyResponse<ReqClazzRepeat>> {
|
||||
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_clazz_repeat_by_id -> failed to find kecheng repeat, e: {}",
|
||||
e
|
||||
);
|
||||
wrap_json_anyhow_err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn raw_find_clazz_repeat_by_id(
|
||||
_auth: AuthorizationHeader,
|
||||
_sudoer: HtySudoerTokenHeader,
|
||||
_host: HtyHostHeader,
|
||||
db_pool: Arc<DbState>,
|
||||
kecheng_repeat_id: &String,
|
||||
) -> anyhow::Result<ReqClazzRepeat> {
|
||||
let res = ClazzRepeat::find_by_id(
|
||||
kecheng_repeat_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
if let Some(kecheng_repeat) = res {
|
||||
return Ok(kecheng_repeat.to_req());
|
||||
} else {
|
||||
return Err(anyhow!(HtyErr {
|
||||
code: HtyErrCode::NullErr,
|
||||
reason: Some(format!(
|
||||
"raw_find_clazz_repeat_by_id -> failed to find record according to id :{:?}.",
|
||||
kecheng_repeat_id
|
||||
)),
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn find_clazz_by_hty_id(
|
||||
sudoer: HtySudoerTokenHeader,
|
||||
host: HtyHostHeader,
|
||||
auth: AuthorizationHeader,
|
||||
State(db_pool): State<Arc<DbState>>,
|
||||
Query(params): Query<HashMap<String, String>>,
|
||||
) -> Json<HtyResponse<Vec<ReqClazz>>> {
|
||||
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_clazz_by_hty_id -> failed to find kechengs, e: {}",
|
||||
e
|
||||
);
|
||||
wrap_json_anyhow_err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn raw_find_clazz_by_hty_id(
|
||||
_auth: AuthorizationHeader,
|
||||
_sudoer: HtySudoerTokenHeader,
|
||||
_host: HtyHostHeader,
|
||||
db_pool: Arc<DbState>,
|
||||
params: &HashMap<String, String>,
|
||||
) -> anyhow::Result<Vec<ReqClazz>> {
|
||||
let start_date =
|
||||
string_to_datetime(&get_some_from_query_params::<String>("start_date", ¶ms))?;
|
||||
let end_date = string_to_datetime(&get_some_from_query_params::<String>("end_date", ¶ms))?;
|
||||
|
||||
debug!(
|
||||
"raw_find_clazz_by_hty_id -> start_date: {:?}",
|
||||
start_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 {
|
||||
code: HtyErrCode::WebErr,
|
||||
reason: Some("start_date or end_date is none".into()),
|
||||
}));
|
||||
}
|
||||
let id_user = get_some_from_query_params::<String>("hty_id", ¶ms);
|
||||
|
||||
if id_user.is_none() {
|
||||
return Err(anyhow!(HtyErr {
|
||||
code: HtyErrCode::WebErr,
|
||||
reason: Some("hty_id is none".into()),
|
||||
}));
|
||||
}
|
||||
|
||||
let kechengs = Clazz::find_by_user_id(
|
||||
id_user
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("id_user is required"))?,
|
||||
&start_date,
|
||||
&end_date,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
|
||||
let res = kechengs.into_iter().map(|item| item.to_req()).collect();
|
||||
debug!("raw_find_clazz_by_hty_id -> {:?}", res);
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub async fn update_clazz(
|
||||
sudoer: HtySudoerTokenHeader,
|
||||
host: HtyHostHeader,
|
||||
auth: AuthorizationHeader,
|
||||
State(db_pool): State<Arc<DbState>>,
|
||||
Json(in_kecheng): Json<ReqClazz>,
|
||||
) -> Json<HtyResponse<()>> {
|
||||
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_clazz -> failed to update clazz, e: {}", e);
|
||||
wrap_json_anyhow_err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn raw_update_clazz(
|
||||
_token: AuthorizationHeader,
|
||||
_sudoer: HtySudoerTokenHeader,
|
||||
_host: HtyHostHeader,
|
||||
db_pool: Arc<DbState>,
|
||||
in_kecheng: &ReqClazz,
|
||||
) -> anyhow::Result<()> {
|
||||
if in_kecheng.id.is_none() {
|
||||
return Err(anyhow!(HtyErr {
|
||||
code: HtyErrCode::WebErr,
|
||||
reason: Some("clazz_id is none".into()),
|
||||
}));
|
||||
}
|
||||
|
||||
let id_kecheng = in_kecheng
|
||||
.id
|
||||
.clone()
|
||||
.ok_or_else(|| anyhow!("id is required"))?;
|
||||
let mut db_kecheng = Clazz::find_by_id(
|
||||
&id_kecheng,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
|
||||
if let Some(clazz_name) = &in_kecheng.clazz_name {
|
||||
db_kecheng.clazz_name = clazz_name.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();
|
||||
}
|
||||
if let Some(end_by) = &in_kecheng.end_by {
|
||||
db_kecheng.end_by = end_by.clone();
|
||||
}
|
||||
if let Some(root_id) = &in_kecheng.root_id {
|
||||
db_kecheng.root_id = root_id.clone();
|
||||
}
|
||||
if let Some(parent_id) = &in_kecheng.parent_id {
|
||||
db_kecheng.parent_id = parent_id.clone();
|
||||
}
|
||||
|
||||
db_kecheng.clazz_desc = in_kecheng.clazz_desc.clone();
|
||||
db_kecheng.duration = in_kecheng.duration.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();
|
||||
db_kecheng.dakas = in_kecheng.dakas.clone();
|
||||
db_kecheng.is_delete = in_kecheng.is_delete.clone();
|
||||
db_kecheng.is_repeat = in_kecheng.is_repeat.clone();
|
||||
db_kecheng.course_sections = in_kecheng.course_sections.clone();
|
||||
db_kecheng.is_notified = in_kecheng.is_notified.clone();
|
||||
|
||||
debug!("raw_update_clazz -> {:?}", db_kecheng);
|
||||
|
||||
let _ = Clazz::update(
|
||||
&db_kecheng,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/*async fn find_group_users_by_group_id(_p0: &String, _p1: &HtyHostHeader, _p2: &HtySudoerTokenHeader) -> anyhow::Result<Option<Vec<ReqClazzUser>>> {
|
||||
unimplemented!()
|
||||
}
|
||||
*/
|
||||
|
||||
fn raw_create_clazz_with_repeat_tx(
|
||||
params: HashMap<String, (Clazz, Option<ClazzRepeat>)>,
|
||||
db_pool: Arc<DbState>,
|
||||
) -> anyhow::Result<ReqClazz> {
|
||||
let task = move |in_params: Option<HashMap<String, (Clazz, Option<ClazzRepeat>)>>,
|
||||
conn: &mut PgConnection|
|
||||
-> anyhow::Result<ReqClazz> {
|
||||
let the_params = in_params.ok_or_else(|| anyhow!("params is required"))?;
|
||||
let (to_create_kecheng, to_create_kecheng_repeat) = the_params
|
||||
.clone()
|
||||
.get("params")
|
||||
.ok_or_else(|| anyhow!("params key not found"))?
|
||||
.clone();
|
||||
|
||||
let created_kecheng = Clazz::create(&to_create_kecheng, conn)?;
|
||||
debug!(
|
||||
"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(ClazzRepeat::create(kecheng_repeat, conn)?);
|
||||
debug!(
|
||||
"raw_create_clazz_with_repeat_tx -> created_kecheng_repeat: {:?}",
|
||||
created_kecheng_repeat
|
||||
);
|
||||
}
|
||||
|
||||
let out =
|
||||
ReqClazz::from_clazz_and_repeat(&Some(created_kecheng), &created_kecheng_repeat);
|
||||
debug!("raw_create_clazz_with_repeat_tx -> out: {:?}", out);
|
||||
Ok(out)
|
||||
};
|
||||
|
||||
exec_read_write_task(
|
||||
Box::new(task),
|
||||
Some(params),
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn create_clazz_with_repeat(
|
||||
sudoer: HtySudoerTokenHeader,
|
||||
host: HtyHostHeader,
|
||||
auth: AuthorizationHeader,
|
||||
State(db_pool): State<Arc<DbState>>,
|
||||
Json(in_kecheng): Json<ReqClazz>,
|
||||
) -> Json<HtyResponse<ReqClazz>> {
|
||||
debug!(
|
||||
"create_clazz_with_repeat -> in_kecheng: {:?}",
|
||||
in_kecheng
|
||||
);
|
||||
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_clazz_with_repeat -> failed to create clazz, e: {}",
|
||||
e
|
||||
);
|
||||
wrap_json_anyhow_err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn raw_create_clazz_with_repeat(
|
||||
token: AuthorizationHeader,
|
||||
_sudoer: HtySudoerTokenHeader,
|
||||
_host: HtyHostHeader,
|
||||
db_pool: Arc<DbState>,
|
||||
in_kecheng: &ReqClazz,
|
||||
) -> anyhow::Result<ReqClazz> {
|
||||
if in_kecheng.clazz_name.is_none()
|
||||
|| in_kecheng.start_from.is_none()
|
||||
|| in_kecheng.end_by.is_none()
|
||||
|| in_kecheng.duration.is_none()
|
||||
{
|
||||
return Err(anyhow!(HtyErr {
|
||||
code: HtyErrCode::WebErr,
|
||||
reason: Some(
|
||||
"clazz_name or start_from or end_by or duration or users is none".into(),
|
||||
),
|
||||
}));
|
||||
}
|
||||
|
||||
let id_user = jwt_decode_token(&(*token).clone())?
|
||||
.hty_id
|
||||
.ok_or_else(|| anyhow!("hty_id is required"))?;
|
||||
debug!(
|
||||
"raw_create_clazz_with_repeat -> id_user: {:?}",
|
||||
id_user
|
||||
);
|
||||
|
||||
let new_clazz_id = uuid();
|
||||
|
||||
let id_sudoer = in_kecheng
|
||||
.root_id
|
||||
.clone()
|
||||
.unwrap_or_else(|| new_clazz_id.clone());
|
||||
|
||||
let id_parent = in_kecheng
|
||||
.parent_id
|
||||
.clone()
|
||||
.unwrap_or_else(|| new_clazz_id.clone());
|
||||
|
||||
let to_create_kecheng = Clazz {
|
||||
id: new_clazz_id.clone(),
|
||||
clazz_name: in_kecheng
|
||||
.clazz_name
|
||||
.clone()
|
||||
.ok_or_else(|| anyhow!("clazz_name is required"))?,
|
||||
clazz_status: in_kecheng
|
||||
.clazz_status
|
||||
.clone()
|
||||
.ok_or_else(|| anyhow!("clazz_status is required"))?,
|
||||
clazz_desc: in_kecheng.clazz_desc.clone(),
|
||||
start_from: in_kecheng
|
||||
.start_from
|
||||
.clone()
|
||||
.ok_or_else(|| anyhow!("start_from is required"))?,
|
||||
end_by: in_kecheng
|
||||
.end_by
|
||||
.clone()
|
||||
.ok_or_else(|| anyhow!("end_by is required"))?,
|
||||
duration: in_kecheng.duration.clone(),
|
||||
root_id: id_sudoer.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()),
|
||||
students: in_kecheng.students.clone(),
|
||||
teachers: in_kecheng.teachers.clone(),
|
||||
jihuas: in_kecheng.jihuas.clone(),
|
||||
dakas: in_kecheng.dakas.clone(),
|
||||
is_delete: in_kecheng.is_delete.clone(),
|
||||
is_repeat: in_kecheng.is_repeat.clone(),
|
||||
course_sections: in_kecheng.course_sections.clone(),
|
||||
is_notified: in_kecheng.is_notified.clone(),
|
||||
};
|
||||
|
||||
debug!(
|
||||
"raw_create_clazz_with_repeat -> to_create_kecheng: {:?}",
|
||||
to_create_kecheng
|
||||
);
|
||||
|
||||
let mut to_create_kecheng_repeat: Option<ClazzRepeat> = None;
|
||||
|
||||
if let Some(kecheng_repeat) = &in_kecheng.clazz_repeat {
|
||||
let kecheng_repeat_copy = kecheng_repeat.clone();
|
||||
to_create_kecheng_repeat = Some(ClazzRepeat {
|
||||
id: uuid(),
|
||||
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_clazz_created_at: kecheng_repeat_copy.latest_clazz_created_at.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
let mut params = HashMap::new();
|
||||
params.insert(
|
||||
"params".to_string(),
|
||||
(to_create_kecheng, to_create_kecheng_repeat),
|
||||
);
|
||||
|
||||
let out_result = raw_create_clazz_with_repeat_tx(params, db_pool);
|
||||
|
||||
match out_result {
|
||||
Ok(out) => {
|
||||
debug!("created_kecheng: {:?}", out);
|
||||
Ok(out)
|
||||
}
|
||||
Err(e) => Err(anyhow!(HtyErr {
|
||||
code: HtyErrCode::WebErr,
|
||||
reason: Some("fail to create clazz e: ".to_string() + &e.to_string()),
|
||||
})),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user