Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions docs/mutations.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
- [editMember](#editmember)
- [markAttendance](#markattendance)
- [addAttendance](#addattendance)
- [setActiveProject](#setactiveproject)
- [removeActiveProject](#re)

---

Expand Down Expand Up @@ -141,4 +143,46 @@ date: NaiveDate!
timein: NaiveTime!
timeout: NaiveTime!
isPresent: Boolean!
```
---

### setActiveProject
Set active project for a member.

#### GraphQL Mutation
```graphql
mutation {
setActiveProject(id:0,projectName:"project_name") {
id
memberId
projectTitle
}
}
```

#### Arguments (all required)
```graphql
id: Int!
projectName: String!
```

---

### removeActiveProject
Remove active project for a member.

#### GraphQL Mutation
```graphql
mutation {
removeActiveProject(projectId:0) {
id
memberId
projectTitle
}
}
```

#### Arguments (all required)
```graphql
projectId: Int!
```
143 changes: 143 additions & 0 deletions docs/queries.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
## Contents
- [getMember](#getmember)
- [getAttendance](#getattendance)
- [getAttendanceStreak](#getattendancestreak)
- [getAttendanceSummary](#getattendancesummary)
- [getNonWorkingDays](#getnonworkingdays)
- [getProjects](#getprojects)
- [getUpdateStreak](#getupdatestreak)

---

Expand Down Expand Up @@ -62,3 +67,141 @@ timein: NaiveTime!
timeout: NaiveTime!
isPresent: Boolean!
```

---

### getAttendanceStreak
Retrieve attendance streak between date ranges.

#### GraphQL Query
```graphql
query {
getAttendanceStreak(startDate:"YYYY-MM-DD",endDate:"YYYY-MM-DD"){
id
memberId
month
streak
}
}
```

#### Arguments
- `startDate` (required): A date in the format `YYYY-MM-DD`.
- `endDate` (required): A date in the format `YYYY-MM-DD`.

#### Fields
```graphql
id: Int!
memberId: Int!
month: NaiveDate!
streak: Int!
```

---

### getAttendanceSummary
Retrieve attendance summary between date ranges.

#### GraphQL Query
```graphql
query {
getAttendanceSummary(startDate:"YYYY-MM-DD",endDate:"YYYY-MM-DD") {
maxDays
memberAttendance {
id
presentDays
}
dailyCount {
date
count
}
}
}
```

#### Arguments
- `startDate` (required): A date in the format `YYYY-MM-DD`.
- `endDate` (required): A date in the format `YYYY-MM-DD`.

#### Fields
Type: AttendanceSummary!
```graphql
maxDays: Int!
memberAttendance: [MemberAttendance!]!
dailyCount: [DailyCount!]!
```

Type: MemberAttendance!
```graphql
id: Int!
presentDays: Int!
```

Type: DailyCount!
```graphql
date: NaiveDate!
count: Int!
```

---

### getNonWorkingDays
Retrieve Non Working Days from root.

#### GraphQL Query
```graphql
query {
getNonWorkingDays
}
```

#### Fields
```graphql
[NaiveDate!]!
```

---

### getProjects
Retrieve active project details for all members.

#### GraphQL Query
```graphql
query {
getProjects {
id
memberId
projectTitle
}
}
```

#### Fields
```graphql
id: Int!
memberId: Int!
projectTitle: String
```

---

### getUpdateStreak
Retrieve Update streaks for all members.

#### GraphQL Query
```graphql
query {
getUpdateStreak {
id
streak
maxStreak
}
}
```

#### Fields
```graphql
id: Int!
streak: Int
maxStreak: Int
```
14 changes: 14 additions & 0 deletions migrations/20241226065211_add_attendance_strak_and_projects.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
CREATE TABLE AttendanceStreak (
id SERIAL PRIMARY KEY,
member_id INT NOT NULL,
month DATE,
streak INT NOT NULL DEFAULT 0,
CONSTRAINT fkey_member FOREIGN KEY (member_id) REFERENCES Member(id) ON DELETE CASCADE
);

CREATE TABLE ActiveProjects (
id SERIAL PRIMARY KEY,
member_id INT NOT NULL,
project_title TEXT,
CONSTRAINT fkey_member FOREIGN KEY (member_id) REFERENCES Member(id) ON DELETE CASCADE
);
1 change: 1 addition & 0 deletions migrations/20241226074423_attendance_streak_constraint.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE AttendanceStreak ADD CONSTRAINT unique_member_month UNIQUE (member_id, month);
83 changes: 82 additions & 1 deletion src/attendance/scheduled_task.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use chrono::{Local, NaiveTime};
use chrono::{Datelike, Local, NaiveTime};
use chrono_tz::Asia::Kolkata;
use sqlx::PgPool;
use std::sync::Arc;
Expand Down Expand Up @@ -93,8 +93,89 @@ pub async fn scheduled_task(pool: Arc<PgPool>) {
Ok(_) => println!("Leaderboard updated."),
Err(e) => eprintln!("Failed to update leaderboard: {:?}", e),
}

// Update attendance streak
update_attendance_streak(member.id, pool.as_ref()).await;
}
}
Err(e) => eprintln!("Failed to fetch members: {:?}", e),
}
}

// Function to update attendance streak
async fn update_attendance_streak(member_id: i32, pool: &sqlx::PgPool) {
let today = chrono::Local::now().with_timezone(&chrono_tz::Asia::Kolkata).naive_local();
let yesterday = today.checked_sub_signed(chrono::Duration::hours(12)).unwrap().date();

if today.day() == 1 {
let _ = sqlx::query(
r#"
INSERT INTO AttendanceStreak (member_id, month, streak)
VALUES ($1, date_trunc('month', $2::date AT TIME ZONE 'Asia/Kolkata'), 0)
"#,
)
.bind(member_id)
.bind(today)
.execute(pool)
.await;
println!("Attendance streak created for member ID: {}", member_id);
}

let present_attendance = sqlx::query_scalar::<_, i64>(
r#"
SELECT COUNT(*)
FROM Attendance
WHERE id = $1
AND is_present = true
AND date = $2
"#,
)
.bind(member_id)
.bind(yesterday)
.fetch_one(pool)
.await;

match present_attendance {
Ok(1) => {
let existing_streak = sqlx::query_scalar::<_, i32>(
r#"
SELECT streak
FROM AttendanceStreak
WHERE member_id = $1
AND month = date_trunc('month', $2::date AT TIME ZONE 'Asia/Kolkata')
"#,
)
.bind(member_id)
.bind(today)
.fetch_optional(pool)
.await;

match existing_streak {
Ok(Some(streak)) => {
let _ = sqlx::query(
r#"
UPDATE AttendanceStreak
SET streak = $1
WHERE member_id = $2
AND month = date_trunc('month', $3::date AT TIME ZONE 'Asia/Kolkata')
"#,
)
.bind(streak + 1)
.bind(member_id)
.bind(today)
.execute(pool)
.await;
}
Ok(None) => {
println!("No streak found for member ID: {}", member_id);
}
Err(e) => eprintln!("Error checking streak for member ID {}: {:?}", member_id, e),
}
}
Ok(0) => {
println!("Sreak not incremented for member ID: {}", member_id);
}
Ok(_) => eprintln!("Unexpected attendance value for member ID: {}", member_id),
Err(e) => eprintln!("Error checking attendance for member ID {}: {:?}", member_id, e),
}
}
27 changes: 27 additions & 0 deletions src/db/attendance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,30 @@ pub struct Attendance {
pub timeout: NaiveTime,
pub is_present: bool,
}

#[derive(FromRow, SimpleObject)]
pub struct AttendanceStreak {
pub id: i32,
pub member_id: i32,
pub month: NaiveDate,
pub streak: i32,
}

#[derive(FromRow, SimpleObject)]
pub struct AttendanceSummary {
pub max_days:i64,
pub member_attendance: Vec<MemberAttendance>,
pub daily_count: Vec<DailyCount>,
}

#[derive(FromRow, SimpleObject)]
pub struct MemberAttendance {
pub id:i32,
pub present_days:i64,
}

#[derive(FromRow, SimpleObject)]
pub struct DailyCount {
pub date: NaiveDate,
pub count: i64,
}
10 changes: 9 additions & 1 deletion src/db/member.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,15 @@ pub struct Member {
pub year: i32,
pub macaddress: String,
pub discord_id: Option<String>,
pub group_id: i32,
pub group_id: Option<i32>,
}

#[derive(FromRow, SimpleObject)]
pub struct MemberExtended {
pub member: Member,
pub project_title: Option<String>,
pub attendance_count: Option<String>,
pub update_count: Option<String>,
}

#[derive(FromRow, SimpleObject)]
Expand Down
2 changes: 1 addition & 1 deletion src/db/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub mod attendance;
pub mod leaderboard;
pub mod member;

pub mod projects;
9 changes: 9 additions & 0 deletions src/db/projects.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use sqlx::FromRow;
use async_graphql::SimpleObject;

#[derive(FromRow, SimpleObject)]
pub struct ActiveProjects {
id: i32,
member_id: i32,
project_title: Option<String>,
}
Loading
Loading