transaction history

This commit is contained in:
2025-07-29 14:50:21 +10:00
parent 57e44f0a2b
commit c01ea7995a

View File

@@ -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();
}