transaction history
This commit is contained in:
123
src/main.rs
123
src/main.rs
@@ -1,3 +1,6 @@
|
||||
// This is a program which creates a server where you can access imaginary financial services. Enjoy!
|
||||
|
||||
// Imports
|
||||
use axum::{
|
||||
Router, extract::Json, http::StatusCode, response::IntoResponse, routing::get, routing::post,
|
||||
};
|
||||
@@ -8,6 +11,7 @@ use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::path::Path;
|
||||
|
||||
// Error structure
|
||||
#[derive(Debug)]
|
||||
enum AccError {
|
||||
WrongPassword,
|
||||
@@ -40,6 +44,7 @@ impl From<RusqliteError> for AccError {
|
||||
}
|
||||
}
|
||||
|
||||
// Structures for requests
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct NewPerson {
|
||||
name: String,
|
||||
@@ -51,11 +56,24 @@ struct GetID {
|
||||
name: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct Id {
|
||||
id: i32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct GetName {
|
||||
id: i32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct Transaction {
|
||||
trid: i64,
|
||||
sender: i32,
|
||||
reciever: i32,
|
||||
message: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct SendMoney {
|
||||
sender: i32,
|
||||
@@ -85,6 +103,16 @@ fn init_database() -> Result<()> {
|
||||
)",
|
||||
(),
|
||||
)?;
|
||||
conn.execute(
|
||||
"CREATE TABLE transactions (
|
||||
trid INTEGER PRIMARY KEY,
|
||||
sender INTEGER NOT NULL,
|
||||
reciever INTEGER NOT NULL,
|
||||
amount INTEGER NOT NULL,
|
||||
message TEXT
|
||||
)",
|
||||
(),
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -116,6 +144,17 @@ fn send_money_to_id(request: &SendMoney) -> Result<(), AccError> {
|
||||
"UPDATE persons SET money = money + ?1 WHERE id = ?2",
|
||||
params![request.amount, request.reciever],
|
||||
)?;
|
||||
|
||||
// Add the transaction into the history
|
||||
conn.execute(
|
||||
"INSERT INTO transactions (sender, reciever, amount, message) VALUES (?1, ?2, ?3, ?4)",
|
||||
params![
|
||||
&request.sender,
|
||||
&request.reciever,
|
||||
&request.amount,
|
||||
&request.message
|
||||
],
|
||||
)?;
|
||||
}
|
||||
Err(RusqliteError::QueryReturnedNoRows) => {
|
||||
let result2 = conn.query_row(
|
||||
@@ -194,6 +233,86 @@ async fn get_id_request(Json(payload): Json<GetID>) -> impl IntoResponse {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_money_by_id(name: &Id) -> Result<i64, AccError> {
|
||||
let conn = Connection::open("financials.db")?;
|
||||
println!("Getting money");
|
||||
let id = conn.query_row(
|
||||
"SELECT money FROM persons WHERE id = ?1",
|
||||
params![name.id],
|
||||
|row| row.get(0),
|
||||
)?;
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
async fn get_money_request(Json(payload): Json<Id>) -> impl IntoResponse {
|
||||
let id = get_money_by_id(&payload);
|
||||
match id {
|
||||
Ok(_) => (StatusCode::OK, id.unwrap().to_string()),
|
||||
Err(e) => (StatusCode::NOT_FOUND, format!("Error: {}", e)),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_transactions_by_id(id: &Id) -> Result<Vec<Transaction>, AccError> {
|
||||
let conn = Connection::open("financials.db")?;
|
||||
println!("Getting transactions by ID");
|
||||
let statement = format!(
|
||||
"SELECT trid, sender, reciever, message FROM transactions WHERE sender = {} OR reciever = {}",
|
||||
id.id.to_string(),
|
||||
id.id.to_string()
|
||||
);
|
||||
let mut tstate = conn.prepare(&statement)?;
|
||||
let rows = tstate.query_map([], |row| {
|
||||
Ok(Transaction {
|
||||
trid: row.get(0)?,
|
||||
sender: row.get(1)?,
|
||||
reciever: row.get(2)?,
|
||||
message: row.get(3)?,
|
||||
})
|
||||
})?;
|
||||
let mut transactions = Vec::new();
|
||||
for transaction_result in rows {
|
||||
transactions.push(transaction_result?);
|
||||
}
|
||||
Ok(transactions)
|
||||
}
|
||||
|
||||
async fn get_transactions_request(Json(payload): Json<Id>) -> impl IntoResponse {
|
||||
let transactions = get_transactions_by_id(&payload);
|
||||
let mut tjson: String = "{".to_string();
|
||||
let mut is_first = true;
|
||||
match transactions {
|
||||
Ok(_) => {
|
||||
for t in transactions.unwrap() {
|
||||
tjson += &format!(
|
||||
"{}
|
||||
\"trid-{}\": {{
|
||||
\"trid\": {},
|
||||
\"sender\": {},
|
||||
\"reciever\": {},
|
||||
\"message\": \"{}\"
|
||||
}}",
|
||||
{
|
||||
if is_first {
|
||||
is_first = false;
|
||||
"".to_string()
|
||||
} else {
|
||||
",".to_string()
|
||||
}
|
||||
},
|
||||
t.trid.to_string(),
|
||||
t.trid.to_string(),
|
||||
t.sender.to_string(),
|
||||
t.reciever.to_string(),
|
||||
t.message
|
||||
);
|
||||
}
|
||||
tjson += "\n}";
|
||||
(StatusCode::OK, tjson)
|
||||
}
|
||||
Err(e) => (StatusCode::NOT_FOUND, format!("Error: {}", e)),
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
println!("Server starting up...");
|
||||
@@ -208,7 +327,9 @@ async fn main() {
|
||||
.route("/", get(process_request))
|
||||
.route("/api/createperson", post(create_person_request))
|
||||
.route("/api/sendmoneytoid", post(send_money_request))
|
||||
.route("/api/getidfromname", post(get_id_request));
|
||||
.route("/api/getidfromname", post(get_id_request))
|
||||
.route("/api/getmoneyfromid", post(get_money_request))
|
||||
.route("/api/gettransactionsfromid", post(get_transactions_request));
|
||||
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||
axum::serve(listener, app).await.unwrap();
|
||||
}
|
||||
|
Reference in New Issue
Block a user