From 7a58035d0ce35a0b30be1c86656231be41e6c38c Mon Sep 17 00:00:00 2001 From: acx Date: Sun, 24 Nov 2024 11:29:18 +0800 Subject: [PATCH] temp --- .../2024-07-07-151037_base_schema/down.sql | 1 + .../2024-07-07-151037_base_schema/up.sql | 7 ++ src/ledger/category.rs | 68 ++++++++++++++----- src/ledger/operation.rs | 32 ++++++++- src/model/db_model.rs | 11 ++- src/model/schema.rs | 10 +++ src/util/mod.rs | 3 +- src/util/operation.rs | 16 +++++ 8 files changed, 129 insertions(+), 19 deletions(-) create mode 100644 src/util/operation.rs diff --git a/migrations/2024-07-07-151037_base_schema/down.sql b/migrations/2024-07-07-151037_base_schema/down.sql index 142ca7a..fcb0c96 100644 --- a/migrations/2024-07-07-151037_base_schema/down.sql +++ b/migrations/2024-07-07-151037_base_schema/down.sql @@ -9,3 +9,4 @@ DROP TABLE IF EXISTS "accounts"; DROP TABLE IF EXISTS "amounts"; DROP TABLE IF EXISTS "users"; DROP TABLE IF EXISTS "operations"; +DROP TABLE IF EXISTS "operation_snapshots"; diff --git a/migrations/2024-07-07-151037_base_schema/up.sql b/migrations/2024-07-07-151037_base_schema/up.sql index 71a501f..d1f2ccd 100644 --- a/migrations/2024-07-07-151037_base_schema/up.sql +++ b/migrations/2024-07-07-151037_base_schema/up.sql @@ -103,3 +103,10 @@ CREATE TABLE "operations" ( "create_at" TIMESTAMP NOT NULL DEFAULT current_timestamp, "update_at" TIMESTAMP NOT NULL DEFAULT current_timestamp ); + +CREATE TABLE "operation_snapshots" ( + "id" BIGSERIAL PRIMARY KEY, + "uid" BIGINT NOT NULL, + "max_op_id" BIGINT NOT NULL, + "create_at" TIMESTAMP NOT NULL DEFAULT current_timestamp +); diff --git a/src/ledger/category.rs b/src/ledger/category.rs index 3781bd0..bea0bc2 100644 --- a/src/ledger/category.rs +++ b/src/ledger/category.rs @@ -1,3 +1,6 @@ +use std::cell::RefCell; +use std::rc::Rc; +use std::sync::Arc; // use std::sync::Arc; use axum::routing::{get, post}; use axum::{ @@ -19,15 +22,13 @@ use chrono::prelude::*; use tracing::info; use crate::middleware::auth; use crate::middleware::auth::Claims; +use crate::model::db_model::Category; +use crate::util::operation::{ + EntityType, ENTITY_CATEGORY, + ActionType, ACTION_CREATE, ACTION_UPDATE, ACTION_DELETE, +}; + -#[derive(Serialize)] -pub struct CreateCategoryResponse { - id: i64, - name: String, - level: i32, - parent_category_id: i64, - book_id: i64, -} pub fn get_nest_handlers() -> Router { Router::new() @@ -43,12 +44,17 @@ pub struct CreateCategoryRequest { book_id: i64, } +#[derive(Serialize)] +pub struct CreateCategoryResponse { + id: i64, +} + #[debug_handler] pub async fn create_category( State(app_state): State, claims: Claims, Json(payload): Json, -) -> Result, (StatusCode, String)> { +) -> Result, (StatusCode, String)> { let uid: i64 = claims.uid.clone(); // TODO replace with actual user id. // let ret = CreateCategoryResponse{id: 134132413541, name: "24532452".to_string()}; let conn = app_state @@ -63,18 +69,48 @@ pub async fn create_category( parent_category_id: payload.parent_category_id, book_id: payload.book_id, }; - let res = conn + let new_operation = db_model::CreateOperation{ + uid: uid, + entity_type: ENTITY_CATEGORY, + entity_id: 0, + action: ACTION_CREATE, + }; + let mut create_response = CreateCategoryResponse{ + id: 0, + }; + let cuid = uid; + conn .interact(move |conn| { - diesel::insert_into(schema::categories::table) - .values(&new_category) - .returning(db_model::Category::as_returning()) - .get_result(conn) + conn.transaction(|conn| { + let category = diesel::insert_into(schema::categories::table) + .values(&new_category) + .returning(db_model::Category::as_returning()) + .get_result(conn)?; + let operation = diesel::insert_into(schema::operations::table) + .values(&new_operation) + .returning(db_model::Operation::as_returning()) + .get_result(conn)?; + diesel::update(schema::categories::table) + .filter(schema::categories::id.eq(category.id)) + .filter(schema::categories::uid.eq(cuid)) + .set((schema::categories::op_id.eq(operation.id))) + .execute(conn)?; + diesel::update(schema::operations::table) + .filter(schema::operations::id.eq(operation.id)) + .filter(schema::operations::uid.eq(cuid)) + .set((schema::operations::entity_id.eq(category.id))) + .execute(conn)?; + diesel::result::QueryResult::Ok(()) + }) + // diesel::insert_into(schema::categories::table) + // .values(&new_category) + // .returning(db_model::Category::as_returning()) + // .get_result(conn) }) .await .map_err(util::req::internal_error)? .map_err(util::req::internal_error)?; - // let ret = CreateCategoryResponse{id: res.id, name: res.name}; - Ok(Json(res)) + Ok(Json(create_response)) } pub async fn update_category( diff --git a/src/ledger/operation.rs b/src/ledger/operation.rs index 94e0514..90f9e0e 100644 --- a/src/ledger/operation.rs +++ b/src/ledger/operation.rs @@ -2,9 +2,11 @@ use diesel::prelude::*; use serde::{Serialize, Deserialize}; use axum::{extract::{Path, State, Query}, http::StatusCode, Json, Router}; use axum::routing::get; +use diesel::dsl::max; use crate::model::{db_model, schema}; use crate::middleware::auth::Claims; use crate::model::db_model::Operation; +use crate::model::schema::operation_snapshots::max_op_id; use crate::util; #[derive(Serialize)] @@ -77,5 +79,33 @@ pub async fn get_operations( }; Ok(Json(resp)) // Ok(Json(res)) +} -} \ No newline at end of file +struct GetOperationSnapshotResponse { + max_op_id: i64, +} +pub async fn get_operation_snapshot( + State(app_state): State, + claims: Claims, +) -> Result, (StatusCode, String)> { + let uid: i64 = claims.uid.clone(); + let conn = app_state + .db + .get() + .await + .map_err(util::req::internal_error)?; + let res = conn.interact(move |conn| { + schema::operation_snapshots::table + .filter(schema::operation_snapshots::uid.eq(uid)) + .select(max(schema::operation_snapshots::max_op_id)) + .limit(1) + .get_result(conn) + .map(|x| x as i64) + }).await + .map_err(util::req::internal_error)? + .map_err(util::req::internal_error)?; + let resp = GetOperationSnapshotResponse{ + max_op_id: res, + }; + Ok(Json(resp)) +} diff --git a/src/model/db_model.rs b/src/model/db_model.rs index 6ce3211..bb28e9a 100644 --- a/src/model/db_model.rs +++ b/src/model/db_model.rs @@ -8,7 +8,7 @@ use crate::model::schema::operations::entity_id; #[diesel(check_for_backend(diesel::pg::Pg))] pub struct Category { #[serde(with = "string")] - id: i64, + pub id: i64, uid: i64, name: String, level: i32, @@ -193,6 +193,15 @@ pub struct Operation { create_at: chrono::NaiveDateTime, } +#[derive(Insertable)] +#[diesel(table_name = schema::operations)] +pub struct CreateOperation { + pub uid: i64, + pub entity_type: i64, + pub entity_id: i64, + pub action: i64, +} + mod string { use std::fmt::Display; use std::str::FromStr; diff --git a/src/model/schema.rs b/src/model/schema.rs index 6239846..1c7bbf3 100644 --- a/src/model/schema.rs +++ b/src/model/schema.rs @@ -56,6 +56,15 @@ diesel::table! { } } +diesel::table! { + operation_snapshots (id) { + id -> Int8, + uid -> Int8, + max_op_id -> Int8, + create_at -> Timestamp, + } +} + diesel::table! { operations (id) { id -> Int8, @@ -128,6 +137,7 @@ diesel::allow_tables_to_appear_in_same_query!( amounts, books, categories, + operation_snapshots, operations, tags, transaction_tag_rels, diff --git a/src/util/mod.rs b/src/util/mod.rs index 04a0187..73ea785 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,3 +1,4 @@ pub mod req; pub mod pass; -pub mod math; \ No newline at end of file +pub mod math; +pub mod operation; diff --git a/src/util/operation.rs b/src/util/operation.rs new file mode 100644 index 0000000..445c6e8 --- /dev/null +++ b/src/util/operation.rs @@ -0,0 +1,16 @@ + +pub type EntityType = i64; + +pub const ENTITY_CATEGORY: EntityType = 1; +pub const ENTITY_TAG: EntityType = 2; +pub const ENTITY_BOOK: EntityType = 3; +pub const ENTITY_ACCOUNT: EntityType = 4; +pub const ENTITY_TRANSACTION: EntityType = 5; +pub const ENTITY_AMOUNT: EntityType = 6; + + +pub type ActionType = i64; + +pub const ACTION_CREATE: ActionType = 1; +pub const ACTION_UPDATE: ActionType = 2; +pub const ACTION_DELETE: ActionType = 3;