From f915e72cf55c7223dca31c947d4b5cebd417c3b2 Mon Sep 17 00:00:00 2001 From: brian Date: Tue, 30 Sep 2025 10:45:16 +0800 Subject: [PATCH] temp --- .gitignore | 3 +- src/api/account.rs | 62 +++++++++ src/api/book_test.rs | 198 +++++++++++++++++++++++++++++ src/api/mod.rs | 3 +- src/model/http_body/account.rs | 14 ++ src/model/http_body/mod.rs | 3 +- src/model/http_body/transaction.rs | 6 +- 7 files changed, 285 insertions(+), 4 deletions(-) create mode 100644 src/api/account.rs create mode 100644 src/api/book_test.rs create mode 100644 src/model/http_body/account.rs diff --git a/.gitignore b/.gitignore index 8c92ba8..b2fb9fd 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ .DS_Store .env conf.toml -.fleet\ \ No newline at end of file +config.toml +.fleet\ diff --git a/src/api/account.rs b/src/api/account.rs new file mode 100644 index 0000000..4b9d5ec --- /dev/null +++ b/src/api/account.rs @@ -0,0 +1,62 @@ +use crate::middleware::auth::Claims; +use crate::model::db::account::{ + ActiveModel as AccountActiveModel, Column as AccountColumn, Model as AccountModel, +}; +use crate::model::db::prelude::Account as AccountPrelude; +use crate::model::http_body::account::{AccountReq, AccountResp}; +use crate::model::http_body::common::SimpleResponse; +use crate::AppState; +use axum::extract::{Path, State}; +use axum::http::StatusCode; +use axum::routing::{get, post}; +use axum::{Json, Router}; +use sea_orm::sqlx::types::chrono::Local; +use sea_orm::{ActiveModelTrait, DbErr, Iden, Set}; + +pub fn get_nest_handlers() -> Router { + Router::new() + .route("/{id}/update", post(update_account_handler)) + .route("/{id}", get(get_account_by_id_handler)) + .route( + "/", + post(create_account_handler).get(get_all_accounts_handler), + ) +} + +async fn update_account_handler( + Path(id): Path, + state: State, + claims: Claims, + Json(payload): Json, +) -> Result, (StatusCode, String)> { + let uid: i64 = claims.uid.clone(); + let mut active_model: AccountActiveModel = AccountPrelude::find_by_id(id) + .filter(AccountColumn::Uid.eq(uid)) + .filter(AccountColumn::IsDeleted.eq(false)) + .one(&state.conn) + .await + .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?; + match payload.name { + Some(n) => { + active_model.name = Set(n); + } + _ => {} + } + + active_model.updated_at = Set(Local::now().naive_utc()); + + active_model.update(&state.conn).await + .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?; + + let resp = SimpleResponse{ + code: 0, + message: "".to_string() + }; + Ok(Json(resp)) +} + +async fn get_account_by_id_handler() {} + +async fn create_account_handler() {} + +async fn get_all_accounts_handler() {} diff --git a/src/api/book_test.rs b/src/api/book_test.rs new file mode 100644 index 0000000..5313e14 --- /dev/null +++ b/src/api/book_test.rs @@ -0,0 +1,198 @@ +// #[cfg(test)] +// mod tests { +// use super::*; +// use axum::{ +// http::{Request, StatusCode}, +// Router, +// routing::{get, put}, +// body::Body, +// }; +// use sea_orm::{ +// MockDatabase, MockExecResult, DatabaseConnection, DatabaseTransaction, +// entity::prelude::*, +// QueryFilter, Condition, DbErr, EntityTrait, +// }; +// use serde_json::{json, Value}; +// use tower::ServiceExt; +// use std::sync::Arc; +// +// // 模拟 Book 实体 +// #[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +// #[sea_orm(table_name = "books")] +// pub struct Model { +// #[sea_orm(primary_key)] +// pub id: i32, +// pub title: String, +// pub author: String, +// } +// +// #[derive(Copy, Clone, Debug, EnumIter)] +// pub enum Relation {} +// +// impl Related for Entity { +// fn to() -> RelationDef { +// panic!("No relations defined") +// } +// } +// +// // 创建测试用的 Router +// async fn setup_router(db: DatabaseConnection) -> Router { +// Router::new() +// .route("/books/:id", get(get_book_by_id).put(update_book_by_id)) +// .route("/books", get(get_all_book)) +// .with_state(Arc::new(db)) +// } +// +// // 测试 get_book_by_id +// #[tokio::test] +// async fn test_get_book_by_id() { +// // 设置模拟数据库 +// let db = MockDatabase::new(DatabaseBackend::Postgres) +// .append_query_results(vec![vec![Model { +// id: 1, +// title: "Test Book".to_string(), +// author: "Test Author".to_string(), +// }]]) +// .into_connection(); +// +// let app = setup_router(db).await; +// +// // 构造请求 +// let request = Request::builder() +// .uri("/books/1") +// .method("GET") +// .body(Body::empty()) +// .unwrap(); +// +// // 发送请求 +// let response = app.oneshot(request).await.unwrap(); +// assert_eq!(response.status(), StatusCode::OK); +// +// // 解析响应 +// let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); +// let body: Value = serde_json::from_slice(&body).unwrap(); +// assert_eq!( +// body, +// json!({ +// "id": 1, +// "title": "Test Book", +// "author": "Test Author" +// }) +// ); +// } +// +// // 测试 get_book_by_id 未找到 +// #[tokio::test] +// async fn test_get_book_by_id_not_found() { +// let db = MockDatabase::new(DatabaseBackend::Postgres) +// .append_query_results(vec![vec![] as Vec]) +// .into_connection(); +// +// let app = setup_router(db).await; +// +// let request = Request::builder() +// .uri("/books/999") +// .method("GET") +// .body(Body::empty()) +// .unwrap(); +// +// let response = app.oneshot(request).await.unwrap(); +// assert_eq!(response.status(), StatusCode::NOT_FOUND); +// } +// +// // 测试 update_book_by_id +// #[tokio::test] +// async fn test_update_book_by_id() { +// let db = MockDatabase::new(DatabaseBackend::Postgres) +// .append_query_results(vec![vec![Model { +// id: 1, +// title: "Updated Book".to_string(), +// author: "Updated Author".to_string(), +// }]]) +// .append_exec_results(vec![MockExecResult { +// last_insert_id: 1, +// rows_affected: 1, +// }]) +// .into_connection(); +// +// let app = setup_router(db).await; +// +// // 构造请求 +// let request = Request::builder() +// .uri("/books/1") +// .method("PUT") +// .header("Content-Type", "application/json") +// .body(Body::from( +// json!({ +// "title": "Updated Book", +// "author": "Updated Author" +// }) +// .to_string(), +// )) +// .unwrap(); +// +// // 发送请求 +// let response = app.oneshot(request).await.unwrap(); +// assert_eq!(response.status(), StatusCode::OK); +// +// // 解析响应 +// let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); +// let body: Value = serde_json::from_slice(&body).unwrap(); +// assert_eq!( +// body, +// json!({ +// "id": 1, +// "title": "Updated Book", +// "author": "Updated Author" +// }) +// ); +// } +// +// // 测试 get_all_book +// #[tokio::test] +// async fn test_get_all_book() { +// let db = MockDatabase::new(DatabaseBackend::Postgres) +// .append_query_results(vec![vec![ +// Model { +// id: 1, +// title: "Book 1".to_string(), +// author: "Author 1".to_string(), +// }, +// Model { +// id: 2, +// title: "Book 2".to_string(), +// author: "Author 2".to_string(), +// }, +// ]]) +// .into_connection(); +// +// let app = setup_router(db).await; +// +// let request = Request::builder() +// .uri("/books") +// .method("GET") +// .body(Body::empty()) +// .unwrap(); +// +// let response = app.oneshot(request).await.unwrap(); +// assert_eq!(response.status(), StatusCode::OK); +// +// let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); +// let body: Value = serde_json::from_slice(&body).unwrap(); +// assert_eq!( +// body, +// json!([ +// { +// "id": 1, +// "title": "Book 1", +// "author": "Author 1" +// }, +// { +// "id": 2, +// "title": "Book 2", +// "author": "Author 2" +// } +// ]) +// ); +// } +// } \ No newline at end of file diff --git a/src/api/mod.rs b/src/api/mod.rs index b7fa515..44c8ad6 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -1,4 +1,5 @@ pub mod book; pub mod category; pub mod tag; -pub mod transaction; \ No newline at end of file +pub mod transaction; +pub mod account; \ No newline at end of file diff --git a/src/model/http_body/account.rs b/src/model/http_body/account.rs new file mode 100644 index 0000000..bbbea61 --- /dev/null +++ b/src/model/http_body/account.rs @@ -0,0 +1,14 @@ +use serde::{Serialize, Deserialize}; + +#[derive(Serialize)] +pub struct AccountResp { + pub id: String, + pub name: String, + pub account_type: String, +} + +#[derive(Deserialize, Serialize, Debug)] +pub struct AccountReq { + pub name: Option, + pub account_type: Option, +} \ No newline at end of file diff --git a/src/model/http_body/mod.rs b/src/model/http_body/mod.rs index d339fbd..894abff 100644 --- a/src/model/http_body/mod.rs +++ b/src/model/http_body/mod.rs @@ -2,4 +2,5 @@ pub mod book; pub mod common; pub mod category; pub mod tag; -pub mod transaction; \ No newline at end of file +pub mod transaction; +pub mod account; diff --git a/src/model/http_body/transaction.rs b/src/model/http_body/transaction.rs index a4c818a..96151e0 100644 --- a/src/model/http_body/transaction.rs +++ b/src/model/http_body/transaction.rs @@ -18,4 +18,8 @@ pub category_id: Option, pub tags: Vec, } - + + pub struct TransactionAmountReq { + pub id: Option, + pub account_id: Option, + }