Skip to content

Commit

Permalink
add migration to create initial tables for member, streaks and attend…
Browse files Browse the repository at this point in the history
…ance
  • Loading branch information
ivinjabraham committed Jan 14, 2025
1 parent 2be3d7e commit 82e7f3a
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 7 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ async-graphql-axum = "7.0.6"
axum = "0.7.3"
chrono = "0.4.38"
serde = { version = "1.0.188", features = ["derive"] }
sqlx = { version = "0.7.1", features = ["chrono"] }
sqlx = { version = "0.7.1", features = ["chrono", "postgres"] }
tokio = { version = "1.28.2", features = ["macros", "rt-multi-thread"] } # For async tests
hmac = "0.12.1"
sha2 = "0.10.8"
Expand All @@ -22,3 +22,4 @@ reqwest = { version = "0.11.27", features = ["json"] }
config = "0.13"
tracing = "0.1.41"
tracing-subscriber = "0.3.19"
dotenv = "0.15.0"
66 changes: 66 additions & 0 deletions migrations/20250114180047_create_tables.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
-- Creates member, attendance, attendance_summary and streaks tables

-- Custom type for sex
CREATE TYPE sex_type AS ENUM ('M', 'F', 'Other');

CREATE TABLE Member (
member_id SERIAL PRIMARY KEY,
roll_no VARCHAR(16) NOT NULL UNIQUE,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
sex sex_type NOT NULL,
year INT NOT NULL,
hostel VARCHAR(255) NOT NULL,
mac_address VARCHAR(255) NOT NULL UNIQUE,
discord_id VARCHAR(255) NOT NULL UNIQUE,
group_id INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CHECK (year BETWEEN 1 and 4)
);

CREATE TABLE Attendance (
attendance_id SERIAL PRIMARY KEY,
member_id INT REFERENCES Member(member_id) ON DELETE CASCADE,
date DATE NOT NULL,
is_present BOOLEAN NOT NULL DEFAULT FALSE,
time_in TIME,
time_out TIME,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CHECK (
(is_present = TRUE AND time_in IS NOT NULL AND time_out is NOT NULL) OR
(is_present = FALSE AND time_in IS NULL AND time_out IS NULL)
),
CHECK (is_present = FALSE OR date <= CURRENT_DATE),
CHECK (time_out IS NULL OR time_out > time_in),
UNIQUE (member_id, date)
);

CREATE OR REPLACE FUNCTION update_timestamp()
RETURNS TRIGGER AS
$$
BEGIN
NEW.updated_at = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER update_attendance_timestamp
BEFORE UPDATE ON Attendance
FOR EACH ROW
EXECUTE FUNCTION update_timestamp();

CREATE TABLE AttendanceSummary (
member_id INT REFERENCES Member(member_id) ON DELETE CASCADE,
year INT NOT NULL,
month INT NOT NULL,
days_attended INT NOT NULL DEFAULT 0,
primary key (member_id, year, month)
);

CREATE TABLE StatusUpdateStreaks (
member_id INT REFERENCES Member(member_id) ON DELETE CASCADE,
current_streak int NOT NULL DEFAULT 0,
max_streak INT NOT NULL,
PRIMARY KEY (member_id)
);
21 changes: 15 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,41 @@
use axum::{routing::get, Router};
use tower_http::cors::{Any, CorsLayer};
use tracing::info;

#[tokio::main]
async fn main() {
// 12/1/25: Going to assume this is only necessary for shuttle
// 9/1/25: TODO: Explain?
// env::set_var("PGOPTIONS", "-c ignore_version=true");

// sqlx::migrate!()
// .run(&pool)
// .await
// .expect("Failed to run migrations.");

// let schema = Schema::build(QueryRoot, MutationRoot, EmptySubscription)
// .data(pool.clone())
// .data(secret_key.clone())
// .finish();

tracing_subscriber::fmt::init();
dotenv::dotenv().ok();

let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
let pool = sqlx::postgres::PgPoolOptions::new()
.max_connections(5)
.connect(&database_url)
.await
.expect("Pool must be initialized properly.");

sqlx::migrate!()
.run(&pool)
.await
.expect("Failed to run migrations.");

// TODO: Restrict to amD and Home
let cors = CorsLayer::new()
.allow_origin(Any)
.allow_methods(tower_http::cors::Any)
.allow_headers(tower_http::cors::Any);

info!("Starting Root...");
let router = Router::new().route("/", get(root)).layer(cors);

let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, router).await.unwrap();

Expand Down

0 comments on commit 82e7f3a

Please sign in to comment.