浏览代码

Create route for searching transactions by account and date.

Lee Morgan 1 年之前
父节点
当前提交
dd93a53453

+ 19 - 0
bruno/Suma/Transaction/Create.bru

@@ -0,0 +1,19 @@
+meta {
+  name: Create
+  type: http
+  seq: 3
+}
+
+post {
+  url: http://localhost:8000/api/transaction
+  body: json
+  auth: inherit
+}
+
+body:json {
+  {
+    "account": "687e9a90bcba589fa1a138b5",
+    "date": "2025-06-20",
+    "data": "Something"
+  }
+}

+ 18 - 0
bruno/Suma/Transaction/Search.bru

@@ -0,0 +1,18 @@
+meta {
+  name: Search
+  type: http
+  seq: 2
+}
+
+post {
+  url: http://localhost:8000/api/transaction/search
+  body: json
+  auth: inherit
+}
+
+body:json {
+  {
+    "account": "687e9a90bcba589fa1a138b5",
+    "from": "2025-05-10"
+  }
+}

+ 31 - 3
src/controllers/transaction.rs

@@ -1,11 +1,12 @@
 use actix_web::{post, web, HttpResponse, HttpRequest};
 use mongodb::Database;
+use bson::oid::ObjectId;
 
-use crate::models::transaction::Transaction;
+use crate::models::transaction::{Transaction, ResponseTransaction};
 use crate::models::account::Account;
 use crate::app_error::AppError;
 use crate::auth::user_auth;
-use crate::dto::transaction::CreateInput;
+use crate::dto::transaction::{CreateInput, SearchInput};
 
 #[post("/api/transaction")]
 pub async fn create_route(
@@ -14,8 +15,8 @@ pub async fn create_route(
     request: HttpRequest
 ) -> Result<HttpResponse, AppError> {
     let user = user_auth(&db, &request).await?;
-    let transaction_collection = db.collection::<Transaction>("transactions");
 
+    let transaction_collection = db.collection::<Transaction>("transactions");
     let account_collection = db.collection::<Account>("accounts");
     Account::user_owns(&account_collection, &user, &body.account).await?;
 
@@ -23,3 +24,30 @@ pub async fn create_route(
     let transaction = Transaction::find_one(&transaction_collection, id).await?;
     Ok(HttpResponse::Ok().json(transaction.response()))
 }
+
+#[post("/api/transaction/search")]
+pub async fn get_many_route(
+    db: web::Data<Database>,
+    body: web::Json<SearchInput>,
+    request: HttpRequest
+) -> Result<HttpResponse, AppError> {
+    let user = user_auth(&db, &request).await?;
+
+    let transaction_collection = db.collection::<Transaction>("transactions");
+    let account_collection = db.collection::<Account>("accounts");
+    Account::user_owns(&account_collection, &user, &body.account).await?;
+
+    let account = ObjectId::parse_str(body.account.clone())?;
+    let transactions = Transaction::find(
+        &transaction_collection,
+        account,
+        body.from.clone(),
+        body.to.clone())
+        .await?;
+    let response_transactions: Vec<ResponseTransaction> = transactions
+        .into_iter()
+        .map(Transaction::response)
+        .collect();
+
+    Ok(HttpResponse::Ok().json(response_transactions))
+}

+ 7 - 0
src/dto/transaction.rs

@@ -6,3 +6,10 @@ pub struct CreateInput {
     pub date: String,
     pub data: String
 }
+
+#[derive(Deserialize)]
+pub struct SearchInput {
+    pub account: String,
+    pub from: Option<String>,
+    pub to: Option<String>
+}

+ 22 - 1
src/models/transaction.rs

@@ -1,6 +1,7 @@
 use serde::{Serialize, Deserialize};
 use mongodb::Collection;
-use bson::{doc, oid::ObjectId};
+use bson::{doc, Document, oid::ObjectId};
+use futures::stream::TryStreamExt;
 
 use crate::app_error::AppError;
 use crate::dto::transaction::CreateInput;
@@ -46,6 +47,26 @@ impl Transaction {
         }
     }
 
+    pub async fn find(
+        collection: &Collection<Transaction>,
+        account: ObjectId,
+        from: Option<String>,
+        to: Option<String>
+    ) -> Result<Vec<Transaction>, AppError> {
+        let mut filter = doc! {"account": account};
+        let mut date_filter = Document::new();
+
+        if let Some(f) = from {date_filter.insert("$gte", f);}
+        if let Some(t) = to {date_filter.insert("$lte", t);}
+        if !date_filter.is_empty() {filter.insert("date", date_filter);}
+
+        Ok(collection
+            .find(filter, None)
+            .await?
+            .try_collect::<Vec<_>>()
+            .await?)
+    }
+
     pub fn response(self) -> ResponseTransaction {
         ResponseTransaction {
             id: self.id.to_hex(),

+ 3 - 1
src/routes/transaction.rs

@@ -1,9 +1,11 @@
 use actix_web::web;
 
 use crate::controllers::transaction::{
-    create_route
+    create_route,
+    get_many_route,
 };
 
 pub fn config(cfg: &mut web::ServiceConfig) {
     cfg.service(create_route);
+    cfg.service(get_many_route);
 }