use chrono::NaiveDateTime; use std::str::FromStr; use htyts_models::{ReqTask, TaskStatus, TaskType}; use serde_json::{json, Value}; use crate::DbTaskRow; pub fn apply_write_defaults(req: &mut ReqTask, host: &str, now: NaiveDateTime) { if req.task_status.is_none() { req.task_status = Some(TaskStatus::Pending); } if req.created_by.as_ref().map(|s| s.is_empty()).unwrap_or(true) { req.created_by = Some(host.to_string()); } if req.created_at.is_none() { req.created_at = Some(now); } req.updated_by = Some(host.to_string()); req.updated_at = Some(now); } /// Build DB row + optional Redis JSON string from request (after [`apply_write_defaults`]). pub fn split_req_for_persist(req: &ReqTask, task_id: String) -> anyhow::Result<(DbTaskRow, Option)> { let tt = req .task_type .ok_or_else(|| anyhow::anyhow!("task_type is required"))?; let ts = req .task_status .ok_or_else(|| anyhow::anyhow!("task_status is required"))?; let created_by = req .created_by .clone() .ok_or_else(|| anyhow::anyhow!("created_by is required"))?; let created_at = req .created_at .ok_or_else(|| anyhow::anyhow!("created_at is required"))?; let updated_by = req .updated_by .clone() .ok_or_else(|| anyhow::anyhow!("updated_by is required"))?; let updated_at = req .updated_at .ok_or_else(|| anyhow::anyhow!("updated_at is required"))?; let row = DbTaskRow { task_id, hty_id: req.hty_id.clone(), task_type: tt.as_db_str().to_string(), task_status: ts.as_db_str().to_string(), duration: req.duration, created_by, created_at, updated_by, updated_at, meta: req.meta.clone(), }; let redis_str = if let Some(ref p) = req.payload { Some(serde_json::to_string(p)?) } else { None }; Ok((row, redis_str)) } /// Injects `hty_id` into JSON object payload for `UPLOAD_PICTURE` (Java `TaskService.createOrUpdateTask`). pub fn inject_hty_id_for_upload_picture( req: &mut ReqTask, hty_id: Option, ) -> anyhow::Result<()> { if req.task_type != Some(TaskType::UploadPicture) { return Ok(()); } let Some(hty_id) = hty_id else { return Ok(()); }; let Some(ref mut payload) = req.payload else { return Ok(()); }; match payload { Value::Object(map) => { map.insert("hty_id".to_string(), json!(hty_id)); } _ => { *payload = json!({ "hty_id": hty_id }); } } Ok(()) } pub fn row_to_req_task(row: &DbTaskRow, payload_json: Option<&str>) -> anyhow::Result { let task_type = TaskType::from_str(&row.task_type).map_err(|e| anyhow::anyhow!("task_type: {e}"))?; let task_status = TaskStatus::from_str(&row.task_status).map_err(|e| anyhow::anyhow!("task_status: {e}"))?; let payload = if let Some(s) = payload_json { if s.is_empty() { None } else { Some(serde_json::from_str(s)?) } } else { None }; Ok(ReqTask { task_id: Some(row.task_id.clone()), hty_id: row.hty_id.clone(), created_by: Some(row.created_by.clone()), created_at: Some(row.created_at), updated_by: Some(row.updated_by.clone()), updated_at: Some(row.updated_at), task_type: Some(task_type), task_status: Some(task_status), duration: row.duration, meta: row.meta.clone(), payload, }) }