From 3fa7649877e2925fd510dbee6f3422df3ea29f6a Mon Sep 17 00:00:00 2001 From: acx Date: Tue, 5 Nov 2024 00:19:27 +0800 Subject: [PATCH] feat: operations model --- diesel.toml | 4 +- .../2024-07-07-151037_base_schema/down.sql | 2 +- .../2024-07-07-151037_base_schema/up.sql | 18 ++++- src/ledger/mod.rs | 1 + src/ledger/operation.rs | 81 +++++++++++++++++++ src/main.rs | 1 + src/model/db_model.rs | 18 +++++ src/model/schema.rs | 20 +++++ src/schema.rs | 20 +++++ 9 files changed, 161 insertions(+), 4 deletions(-) create mode 100644 src/ledger/operation.rs diff --git a/diesel.toml b/diesel.toml index 8c5a9d1..6d0d091 100644 --- a/diesel.toml +++ b/diesel.toml @@ -2,8 +2,8 @@ # see https://diesel.rs/guides/configuring-diesel-cli [print_schema] -file = "src/schema.rs" +file = "src/model/schema.rs" custom_type_derives = ["diesel::query_builder::QueryId", "Clone"] [migrations_directory] -dir = "/data/codes/helios-server-rs/migrations" +dir = "./migrations" diff --git a/migrations/2024-07-07-151037_base_schema/down.sql b/migrations/2024-07-07-151037_base_schema/down.sql index 6f4d1c0..142ca7a 100644 --- a/migrations/2024-07-07-151037_base_schema/down.sql +++ b/migrations/2024-07-07-151037_base_schema/down.sql @@ -7,5 +7,5 @@ DROP TABLE IF EXISTS "transactions"; DROP TABLE IF EXISTS "transaction_tag_rels"; DROP TABLE IF EXISTS "accounts"; DROP TABLE IF EXISTS "amounts"; - DROP TABLE IF EXISTS "users"; +DROP TABLE IF EXISTS "operations"; diff --git a/migrations/2024-07-07-151037_base_schema/up.sql b/migrations/2024-07-07-151037_base_schema/up.sql index a51dbd3..71a501f 100644 --- a/migrations/2024-07-07-151037_base_schema/up.sql +++ b/migrations/2024-07-07-151037_base_schema/up.sql @@ -1,5 +1,4 @@ -- Your SQL goes here --- Your SQL goes here CREATE TABLE "categories" ( "id" BIGSERIAL PRIMARY KEY, "uid" BIGINT NOT NULL, @@ -7,6 +6,7 @@ CREATE TABLE "categories" ( "name" TEXT NOT NULL, "level" INT NOT NULL DEFAULT 0, "parent_category_id" BIGINT NOT NULL DEFAULT 0, + "op_id" BIGINT NOT NULL DEFAULT 0, "is_delete" BOOLEAN NOT NULL DEFAULT FALSE, "create_at" TIMESTAMP NOT NULL DEFAULT current_timestamp, "update_at" TIMESTAMP NOT NULL DEFAULT current_timestamp @@ -19,6 +19,7 @@ CREATE TABLE "tags" ( "name" TEXT NOT NULL, "level" INT NOT NULL DEFAULT 0, "parent_tag_id" BIGINT NOT NULL DEFAULT 0, + "op_id" BIGINT NOT NULL DEFAULT 0, "is_delete" BOOLEAN NOT NULL DEFAULT FALSE, "create_at" TIMESTAMP NOT NULL DEFAULT current_timestamp, "update_at" TIMESTAMP NOT NULL DEFAULT current_timestamp @@ -28,6 +29,7 @@ CREATE TABLE "books" ( "id" BIGSERIAL PRIMARY KEY, "uid" BIGINT NOT NULL, "name" TEXT NOT NULL, + "op_id" BIGINT NOT NULL DEFAULT 0, "is_delete" BOOLEAN NOT NULL DEFAULT FALSE, "create_at" TIMESTAMP NOT NULL DEFAULT current_timestamp, "update_at" TIMESTAMP NOT NULL DEFAULT current_timestamp @@ -39,6 +41,7 @@ CREATE TABLE "transactions" ( "book_id" BIGINT NOT NULL, "description" TEXT NOT NULL, "category_id" BIGINT NOT NULL, + "op_id" BIGINT NOT NULL DEFAULT 0, "is_delete" BOOLEAN NOT NULL DEFAULT FALSE, "time" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT current_timestamp, "create_at" TIMESTAMP NOT NULL DEFAULT current_timestamp, @@ -50,6 +53,7 @@ CREATE TABLE "transaction_tag_rels" ( "uid" BIGINT NOT NULL, "transaction_id" BIGINT NOT NULL, "tag_id" BIGINT NOT NULL, + "op_id" BIGINT NOT NULL DEFAULT 0, "is_delete" BOOLEAN NOT NULL DEFAULT FALSE, "create_at" TIMESTAMP NOT NULL DEFAULT current_timestamp, "update_at" TIMESTAMP NOT NULL DEFAULT current_timestamp @@ -60,6 +64,7 @@ CREATE TABLE "accounts" ( "uid" BIGINT NOT NULL, "name" TEXT NOT NULL, "account_type" BIGINT NOT NULL DEFAULT 0, + "op_id" BIGINT NOT NULL DEFAULT 0, "is_delete" BOOLEAN NOT NULL DEFAULT FALSE, "create_at" TIMESTAMP NOT NULL DEFAULT current_timestamp, "update_at" TIMESTAMP NOT NULL DEFAULT current_timestamp @@ -73,6 +78,7 @@ CREATE TABLE "amounts" ( "value" BIGINT NOT NULL DEFAULT 0, "expo" BIGINT NOT NULL DEFAULT 5, "currency" TEXT NOT NULL DEFAULT '', + "op_id" BIGINT NOT NULL DEFAULT 0, "is_delete" BOOLEAN NOT NULL DEFAULT FALSE, "create_at" TIMESTAMP NOT NULL DEFAULT current_timestamp, "update_at" TIMESTAMP NOT NULL DEFAULT current_timestamp @@ -87,3 +93,13 @@ CREATE TABLE "users" ( "create_at" TIMESTAMP NOT NULL DEFAULT current_timestamp, "update_at" TIMESTAMP NOT NULL DEFAULT current_timestamp ); + +CREATE TABLE "operations" ( + "id" BIGSERIAL PRIMARY KEY, + "uid" BIGINT NOT NULL, + "entity_type" BIGINT NOT NULL, + "entity_id" BIGINT NOT NULL, + "action" BIGINT NOT NULL, + "create_at" TIMESTAMP NOT NULL DEFAULT current_timestamp, + "update_at" TIMESTAMP NOT NULL DEFAULT current_timestamp +); diff --git a/src/ledger/mod.rs b/src/ledger/mod.rs index a563d1f..2b9ada7 100644 --- a/src/ledger/mod.rs +++ b/src/ledger/mod.rs @@ -3,3 +3,4 @@ pub mod tag; pub mod book; pub mod account; pub mod transaction; +pub mod operation; diff --git a/src/ledger/operation.rs b/src/ledger/operation.rs new file mode 100644 index 0000000..94e0514 --- /dev/null +++ b/src/ledger/operation.rs @@ -0,0 +1,81 @@ +use diesel::prelude::*; +use serde::{Serialize, Deserialize}; +use axum::{extract::{Path, State, Query}, http::StatusCode, Json, Router}; +use axum::routing::get; +use crate::model::{db_model, schema}; +use crate::middleware::auth::Claims; +use crate::model::db_model::Operation; +use crate::util; + +#[derive(Serialize)] +pub struct GetOperationsResponse { + start: i64, + end: i64, + total: i64, + operations: Vec, +} + +#[derive(Deserialize)] +pub struct GetOperationsParam { + start: i64, + limit: i32, +} + +pub fn get_nest_handlers() -> Router { + Router::new() + .route("/", get(get_operations)) +} + +// get_single_operation + +pub async fn get_operations( + query_param: Query, + State(app_state): State, + claims: Claims, +) -> Result, (StatusCode, String)> { + let uid: i64 = claims.uid.clone(); + let start: i64 = match query_param.start { + ..0 => 0, + _ => query_param.start + }; + let limit: i32 = match query_param.limit { + ..0 => 0, + crate::model::req::MAX_QUERY_LIMIT.. => crate::model::req::MAX_QUERY_LIMIT, + _ => query_param.limit + }; + let conn = app_state + .db + .get() + .await + .map_err(util::req::internal_error)?; + let mut res = conn + .interact(move |conn| { + schema::operations::table + .filter(schema::operations::uid.eq(uid)) + .filter(schema::operations::id.ge(start)) + .limit(limit as i64) + .select(Operation::as_select()) + .load(conn) + }) + .await + .map_err(util::req::internal_error)? + .map_err(util::req::internal_error)?; + res.sort_by(|a,b| a.id.cmp(&b.id)); + let res_start: i64 = match res.first() { + Some(r) => r.id, + None => 0, + }; + let res_end = match res.last() { + Some(r) => r.id, + None => 0, + }; + let resp = GetOperationsResponse{ + start: res_start, + end: res_end, + total: res.len() as i64, + operations: res, + }; + Ok(Json(resp)) + // Ok(Json(res)) + +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 1bdb989..86231e5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -97,6 +97,7 @@ async fn main() { .nest("/api/v1/account", ledger::account::get_nest_handlers()) .nest("/api/v1/transaction", ledger::transaction::get_nest_handlers()) .nest("/api/v1/user", user::handler::get_nest_handlers()) + .nest("/api/v1/operation", ledger::operation::get_nest_handlers()) .with_state(shared_state) .layer(global_layer); diff --git a/src/model/db_model.rs b/src/model/db_model.rs index c606a0e..6ce3211 100644 --- a/src/model/db_model.rs +++ b/src/model/db_model.rs @@ -1,6 +1,7 @@ use crate::model::schema; use diesel::prelude::*; use chrono::{DateTime, Utc}; +use crate::model::schema::operations::entity_id; #[derive(Queryable, Selectable, serde::Serialize, serde::Deserialize)] #[diesel(table_name = schema::categories)] @@ -13,6 +14,7 @@ pub struct Category { level: i32, parent_category_id: i64, book_id: i64, + op_id: i64, #[serde(skip_serializing)] is_delete: bool, create_at: chrono::NaiveDateTime, @@ -39,6 +41,7 @@ pub struct Tag { name: String, level: i32, parent_tag_id: i64, + op_id: i64, #[serde(skip_serializing)] is_delete: bool, create_at: chrono::NaiveDateTime, @@ -63,6 +66,7 @@ pub struct Book { id: i64, uid: i64, name: String, + op_id: i64, #[serde(skip_serializing)] is_delete: bool, create_at: chrono::NaiveDateTime, @@ -84,6 +88,7 @@ pub struct Account { uid: i64, name: String, account_type: i64, + op_id: i64, #[serde(skip_serializing)] is_delete: bool, create_at: chrono::NaiveDateTime, @@ -111,6 +116,7 @@ pub struct Transaction { #[serde(with = "string")] pub category_id: i64, pub time: chrono::DateTime, + pub op_id: i64, #[serde(skip_serializing)] is_delete: bool, create_at: chrono::NaiveDateTime, @@ -139,6 +145,7 @@ pub struct Amount { value: i64, expo: i64, currency: String, + pub op_id: i64, #[serde(skip_serializing)] is_delete: bool, create_at: chrono::NaiveDateTime, @@ -175,6 +182,17 @@ pub struct UserForm { pub mail: String, } +#[derive(Insertable,Queryable, Selectable, serde::Serialize)] +#[diesel(table_name = schema::operations)] +pub struct Operation { + pub id: i64, + pub uid: i64, + pub entity_type: i64, + pub entity_id: i64, + pub action: i64, + create_at: chrono::NaiveDateTime, +} + mod string { use std::fmt::Display; use std::str::FromStr; diff --git a/src/model/schema.rs b/src/model/schema.rs index 9ee4a19..6239846 100644 --- a/src/model/schema.rs +++ b/src/model/schema.rs @@ -6,6 +6,7 @@ diesel::table! { uid -> Int8, name -> Text, account_type -> Int8, + op_id -> Int8, is_delete -> Bool, create_at -> Timestamp, update_at -> Timestamp, @@ -21,6 +22,7 @@ diesel::table! { value -> Int8, expo -> Int8, currency -> Text, + op_id -> Int8, is_delete -> Bool, create_at -> Timestamp, update_at -> Timestamp, @@ -32,6 +34,7 @@ diesel::table! { id -> Int8, uid -> Int8, name -> Text, + op_id -> Int8, is_delete -> Bool, create_at -> Timestamp, update_at -> Timestamp, @@ -46,12 +49,25 @@ diesel::table! { name -> Text, level -> Int4, parent_category_id -> Int8, + op_id -> Int8, is_delete -> Bool, create_at -> Timestamp, update_at -> Timestamp, } } +diesel::table! { + operations (id) { + id -> Int8, + uid -> Int8, + entity_type -> Int8, + entity_id -> Int8, + action -> Int8, + create_at -> Timestamp, + update_at -> Timestamp, + } +} + diesel::table! { tags (id) { id -> Int8, @@ -60,6 +76,7 @@ diesel::table! { name -> Text, level -> Int4, parent_tag_id -> Int8, + op_id -> Int8, is_delete -> Bool, create_at -> Timestamp, update_at -> Timestamp, @@ -72,6 +89,7 @@ diesel::table! { uid -> Int8, transaction_id -> Int8, tag_id -> Int8, + op_id -> Int8, is_delete -> Bool, create_at -> Timestamp, update_at -> Timestamp, @@ -85,6 +103,7 @@ diesel::table! { book_id -> Int8, description -> Text, category_id -> Int8, + op_id -> Int8, is_delete -> Bool, time -> Timestamptz, create_at -> Timestamp, @@ -109,6 +128,7 @@ diesel::allow_tables_to_appear_in_same_query!( amounts, books, categories, + operations, tags, transaction_tag_rels, transactions, diff --git a/src/schema.rs b/src/schema.rs index 9ee4a19..7c0e8ef 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -6,6 +6,7 @@ diesel::table! { uid -> Int8, name -> Text, account_type -> Int8, + version_v1 -> Int8, is_delete -> Bool, create_at -> Timestamp, update_at -> Timestamp, @@ -21,6 +22,7 @@ diesel::table! { value -> Int8, expo -> Int8, currency -> Text, + version_v1 -> Int8, is_delete -> Bool, create_at -> Timestamp, update_at -> Timestamp, @@ -32,6 +34,7 @@ diesel::table! { id -> Int8, uid -> Int8, name -> Text, + version_v1 -> Int8, is_delete -> Bool, create_at -> Timestamp, update_at -> Timestamp, @@ -46,6 +49,7 @@ diesel::table! { name -> Text, level -> Int4, parent_category_id -> Int8, + version_v1 -> Int8, is_delete -> Bool, create_at -> Timestamp, update_at -> Timestamp, @@ -60,6 +64,7 @@ diesel::table! { name -> Text, level -> Int4, parent_tag_id -> Int8, + version_v1 -> Int8, is_delete -> Bool, create_at -> Timestamp, update_at -> Timestamp, @@ -72,6 +77,7 @@ diesel::table! { uid -> Int8, transaction_id -> Int8, tag_id -> Int8, + version_v1 -> Int8, is_delete -> Bool, create_at -> Timestamp, update_at -> Timestamp, @@ -85,6 +91,7 @@ diesel::table! { book_id -> Int8, description -> Text, category_id -> Int8, + version_v1 -> Int8, is_delete -> Bool, time -> Timestamptz, create_at -> Timestamp, @@ -104,6 +111,18 @@ diesel::table! { } } +diesel::table! { + versions_v1 (id) { + id -> Int8, + uid -> Int8, + entity_type -> Int8, + entity_id -> Int8, + action -> Int8, + create_at -> Timestamp, + update_at -> Timestamp, + } +} + diesel::allow_tables_to_appear_in_same_query!( accounts, amounts, @@ -113,4 +132,5 @@ diesel::allow_tables_to_appear_in_same_query!( transaction_tag_rels, transactions, users, + versions_v1, );