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::{
|
use axum::{
|
||||||
Router, extract::Json, http::StatusCode, response::IntoResponse, routing::get, routing::post,
|
Router, extract::Json, http::StatusCode, response::IntoResponse, routing::get, routing::post,
|
||||||
};
|
};
|
||||||
@@ -8,6 +11,7 @@ use std::error::Error;
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
// Error structure
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum AccError {
|
enum AccError {
|
||||||
WrongPassword,
|
WrongPassword,
|
||||||
@@ -40,6 +44,7 @@ impl From<RusqliteError> for AccError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Structures for requests
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct NewPerson {
|
struct NewPerson {
|
||||||
name: String,
|
name: String,
|
||||||
@@ -51,11 +56,24 @@ struct GetID {
|
|||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
struct Id {
|
||||||
|
id: i32,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct GetName {
|
struct GetName {
|
||||||
id: i32,
|
id: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
struct Transaction {
|
||||||
|
trid: i64,
|
||||||
|
sender: i32,
|
||||||
|
reciever: i32,
|
||||||
|
message: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct SendMoney {
|
struct SendMoney {
|
||||||
sender: i32,
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,6 +144,17 @@ fn send_money_to_id(request: &SendMoney) -> Result<(), AccError> {
|
|||||||
"UPDATE persons SET money = money + ?1 WHERE id = ?2",
|
"UPDATE persons SET money = money + ?1 WHERE id = ?2",
|
||||||
params![request.amount, request.reciever],
|
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) => {
|
Err(RusqliteError::QueryReturnedNoRows) => {
|
||||||
let result2 = conn.query_row(
|
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]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
println!("Server starting up...");
|
println!("Server starting up...");
|
||||||
@@ -208,7 +327,9 @@ async fn main() {
|
|||||||
.route("/", get(process_request))
|
.route("/", get(process_request))
|
||||||
.route("/api/createperson", post(create_person_request))
|
.route("/api/createperson", post(create_person_request))
|
||||||
.route("/api/sendmoneytoid", post(send_money_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();
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
axum::serve(listener, app).await.unwrap();
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user