Initial work

This commit is contained in:
Joshua Coles 2023-09-04 15:29:21 +01:00
commit 554e645f92
15 changed files with 3478 additions and 0 deletions

1
.env Normal file
View File

@ -0,0 +1 @@
DATABASE_URL=postgres://postgres@localhost/logos_neu

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
/.idea

3166
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

21
Cargo.toml Normal file
View File

@ -0,0 +1,21 @@
[package]
name = "monzo-ingestion"
version = "0.1.0"
edition = "2021"
[dependencies]
axum = "0.6.20"
tokio = { version = "1.32.0", features = ["full"] }
sea-orm = { version = "0.12", features = [
"sqlx-postgres",
"runtime-tokio-rustls",
"macros"
] }
serde = { version = "1.0.188", features = ["derive"] }
serde_json = "1.0.105"
tracing-subscriber = "0.3.17"
tracing = "0.1.37"
[workspace]
members = [".", "migration", "entity"]

13
entity/Cargo.toml Normal file
View File

@ -0,0 +1,13 @@
[package]
name = "entity"
version = "0.1.0"
edition = "2021"
publish = false
[lib]
name = "entity"
path = "src/lib.rs"
[dependencies]
sea-orm = { version = "^0" }
serde = { version = "1.0.158", features = ["derive"] }

19
entity/src/expenditure.rs Normal file
View File

@ -0,0 +1,19 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.2
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)]
#[sea_orm(table_name = "expenditure")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub transaction_id: i32,
#[sea_orm(primary_key, auto_increment = false)]
pub category: String,
pub amount: Decimal,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}

6
entity/src/mod.rs Normal file
View File

@ -0,0 +1,6 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.2
pub mod prelude;
pub mod expenditure;
pub mod transaction;

4
entity/src/prelude.rs Normal file
View File

@ -0,0 +1,4 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.2
pub use super::expenditure::Entity as Expenditure;
pub use super::transaction::Entity as Transaction;

24
entity/src/transaction.rs Normal file
View File

@ -0,0 +1,24 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.2
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)]
#[sea_orm(table_name = "transaction")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub id: String,
pub transaction_type: String,
pub total_amount: Decimal,
pub timestamp: DateTime,
pub title: String,
pub emoji: Option<String>,
pub notes: Option<String>,
pub receipt: Option<String>,
pub description: Option<String>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}

19
migration/Cargo.toml Normal file
View File

@ -0,0 +1,19 @@
[package]
name = "migration"
version = "0.1.0"
edition = "2021"
publish = false
[lib]
name = "migration"
path = "src/lib.rs"
[dependencies]
async-std = { version = "1", features = ["attributes", "tokio1"] }
[dependencies.sea-orm-migration]
version = "0.12.0"
features = [
"runtime-tokio-rustls", # `ASYNC_RUNTIME` feature
"sqlx-postgres", # `DATABASE_DRIVER` feature
]

41
migration/README.md Normal file
View File

@ -0,0 +1,41 @@
# Running Migrator CLI
- Generate a new migration file
```sh
cargo run -- generate MIGRATION_NAME
```
- Apply all pending migrations
```sh
cargo run
```
```sh
cargo run -- up
```
- Apply first 10 pending migrations
```sh
cargo run -- up -n 10
```
- Rollback last applied migrations
```sh
cargo run -- down
```
- Rollback last 10 applied migrations
```sh
cargo run -- down -n 10
```
- Drop all tables from the database, then reapply all migrations
```sh
cargo run -- fresh
```
- Rollback all applied migrations, then reapply all migrations
```sh
cargo run -- refresh
```
- Rollback all applied migrations
```sh
cargo run -- reset
```
- Check the status of all migrations
```sh
cargo run -- status
```

12
migration/src/lib.rs Normal file
View File

@ -0,0 +1,12 @@
pub use sea_orm_migration::prelude::*;
pub mod m20230904_141851_create_monzo_tables;
pub struct Migrator;
#[async_trait::async_trait]
impl MigratorTrait for Migrator {
fn migrations() -> Vec<Box<dyn MigrationTrait>> {
vec![Box::new(m20230904_141851_create_monzo_tables::Migration)]
}
}

View File

@ -0,0 +1,114 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager.create_table(
Table::create()
.table(Transaction::Table)
.if_not_exists()
.col(
ColumnDef::new(Transaction::Id)
.string()
.not_null()
.primary_key(),
)
.col(
ColumnDef::new(Transaction::TransactionType)
.string()
.not_null(),
)
.col(
ColumnDef::new(Transaction::TotalAmount)
.decimal()
.not_null(),
)
.col(
ColumnDef::new(Transaction::Timestamp)
.timestamp()
.not_null(),
)
.col(
ColumnDef::new(Transaction::Title)
.string()
.not_null(),
)
.col(
ColumnDef::new(Transaction::Emoji)
.string(),
)
.col(
ColumnDef::new(Transaction::Notes)
.string(),
)
.col(
ColumnDef::new(Transaction::Receipt)
.string(),
)
.col(
ColumnDef::new(Transaction::Description)
.string(),
)
.to_owned()
).await?;
manager
.create_table(
Table::create()
.table(Expenditure::Table)
.if_not_exists()
.col(
ColumnDef::new(Expenditure::TransactionId)
.integer()
.not_null(),
)
.col(ColumnDef::new(Expenditure::Category).string().not_null())
.primary_key(
Index::create()
.col(Expenditure::TransactionId)
.col(Expenditure::Category),
)
.col(ColumnDef::new(Expenditure::Amount).decimal().not_null())
.to_owned(),
).await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(Expenditure::Table).to_owned())
.await?;
manager
.drop_table(Table::drop().table(Transaction::Table).to_owned())
.await?;
Ok(())
}
}
#[derive(DeriveIden)]
enum Transaction {
Table,
Id,
TransactionType,
Timestamp,
Title,
Emoji,
Notes,
Receipt,
TotalAmount,
Description,
}
#[derive(DeriveIden)]
enum Expenditure {
Table,
Category,
Amount,
TransactionId,
}

6
migration/src/main.rs Normal file
View File

@ -0,0 +1,6 @@
use sea_orm_migration::prelude::*;
#[async_std::main]
async fn main() {
cli::run_cli(migration::Migrator).await;
}

30
src/main.rs Normal file
View File

@ -0,0 +1,30 @@
use axum::{
routing::{get, post},
http::StatusCode,
response::IntoResponse,
Json, Router,
};
use serde::{Deserialize, Serialize};
use std::net::SocketAddr;
#[tokio::main]
async fn main() {
// initialize tracing
tracing_subscriber::fmt::init();
// build our application with a route
let app = Router::new()
// `GET /` goes to `root`
.route("/", get(root))
// `POST /users` goes to `create_user`
.route("/users", post(create_user));
// run our app with hyper
// `axum::Server` is a re-export of `hyper::Server`
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
tracing::debug!("listening on {}", addr);
axum::Server::bind(&addr)
.serve(app.into_make_service())
.await
.unwrap();
}