Skip to content

Commit 9dd4ccb

Browse files
authored
Merge pull request #34 from he1senbrg/home_fn
Added necessary queries and mutations for home
2 parents 00cefe3 + 300630f commit 9dd4ccb

File tree

11 files changed

+507
-10
lines changed

11 files changed

+507
-10
lines changed

docs/mutations.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
- [editMember](#editmember)
66
- [markAttendance](#markattendance)
77
- [addAttendance](#addattendance)
8+
- [setActiveProject](#setactiveproject)
9+
- [removeActiveProject](#re)
810

911
---
1012

@@ -141,4 +143,46 @@ date: NaiveDate!
141143
timein: NaiveTime!
142144
timeout: NaiveTime!
143145
isPresent: Boolean!
146+
```
147+
---
148+
149+
### setActiveProject
150+
Set active project for a member.
151+
152+
#### GraphQL Mutation
153+
```graphql
154+
mutation {
155+
setActiveProject(id:0,projectName:"project_name") {
156+
id
157+
memberId
158+
projectTitle
159+
}
160+
}
161+
```
162+
163+
#### Arguments (all required)
164+
```graphql
165+
id: Int!
166+
projectName: String!
167+
```
168+
169+
---
170+
171+
### removeActiveProject
172+
Remove active project for a member.
173+
174+
#### GraphQL Mutation
175+
```graphql
176+
mutation {
177+
removeActiveProject(projectId:0) {
178+
id
179+
memberId
180+
projectTitle
181+
}
182+
}
183+
```
184+
185+
#### Arguments (all required)
186+
```graphql
187+
projectId: Int!
144188
```

docs/queries.md

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
## Contents
44
- [getMember](#getmember)
55
- [getAttendance](#getattendance)
6+
- [getAttendanceStreak](#getattendancestreak)
7+
- [getAttendanceSummary](#getattendancesummary)
8+
- [getNonWorkingDays](#getnonworkingdays)
9+
- [getProjects](#getprojects)
10+
- [getUpdateStreak](#getupdatestreak)
611

712
---
813

@@ -62,3 +67,141 @@ timein: NaiveTime!
6267
timeout: NaiveTime!
6368
isPresent: Boolean!
6469
```
70+
71+
---
72+
73+
### getAttendanceStreak
74+
Retrieve attendance streak between date ranges.
75+
76+
#### GraphQL Query
77+
```graphql
78+
query {
79+
getAttendanceStreak(startDate:"YYYY-MM-DD",endDate:"YYYY-MM-DD"){
80+
id
81+
memberId
82+
month
83+
streak
84+
}
85+
}
86+
```
87+
88+
#### Arguments
89+
- `startDate` (required): A date in the format `YYYY-MM-DD`.
90+
- `endDate` (required): A date in the format `YYYY-MM-DD`.
91+
92+
#### Fields
93+
```graphql
94+
id: Int!
95+
memberId: Int!
96+
month: NaiveDate!
97+
streak: Int!
98+
```
99+
100+
---
101+
102+
### getAttendanceSummary
103+
Retrieve attendance summary between date ranges.
104+
105+
#### GraphQL Query
106+
```graphql
107+
query {
108+
getAttendanceSummary(startDate:"YYYY-MM-DD",endDate:"YYYY-MM-DD") {
109+
maxDays
110+
memberAttendance {
111+
id
112+
presentDays
113+
}
114+
dailyCount {
115+
date
116+
count
117+
}
118+
}
119+
}
120+
```
121+
122+
#### Arguments
123+
- `startDate` (required): A date in the format `YYYY-MM-DD`.
124+
- `endDate` (required): A date in the format `YYYY-MM-DD`.
125+
126+
#### Fields
127+
Type: AttendanceSummary!
128+
```graphql
129+
maxDays: Int!
130+
memberAttendance: [MemberAttendance!]!
131+
dailyCount: [DailyCount!]!
132+
```
133+
134+
Type: MemberAttendance!
135+
```graphql
136+
id: Int!
137+
presentDays: Int!
138+
```
139+
140+
Type: DailyCount!
141+
```graphql
142+
date: NaiveDate!
143+
count: Int!
144+
```
145+
146+
---
147+
148+
### getNonWorkingDays
149+
Retrieve Non Working Days from root.
150+
151+
#### GraphQL Query
152+
```graphql
153+
query {
154+
getNonWorkingDays
155+
}
156+
```
157+
158+
#### Fields
159+
```graphql
160+
[NaiveDate!]!
161+
```
162+
163+
---
164+
165+
### getProjects
166+
Retrieve active project details for all members.
167+
168+
#### GraphQL Query
169+
```graphql
170+
query {
171+
getProjects {
172+
id
173+
memberId
174+
projectTitle
175+
}
176+
}
177+
```
178+
179+
#### Fields
180+
```graphql
181+
id: Int!
182+
memberId: Int!
183+
projectTitle: String
184+
```
185+
186+
---
187+
188+
### getUpdateStreak
189+
Retrieve Update streaks for all members.
190+
191+
#### GraphQL Query
192+
```graphql
193+
query {
194+
getUpdateStreak {
195+
id
196+
streak
197+
maxStreak
198+
}
199+
}
200+
```
201+
202+
#### Fields
203+
```graphql
204+
id: Int!
205+
streak: Int
206+
maxStreak: Int
207+
```
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CREATE TABLE AttendanceStreak (
2+
id SERIAL PRIMARY KEY,
3+
member_id INT NOT NULL,
4+
month DATE,
5+
streak INT NOT NULL DEFAULT 0,
6+
CONSTRAINT fkey_member FOREIGN KEY (member_id) REFERENCES Member(id) ON DELETE CASCADE
7+
);
8+
9+
CREATE TABLE ActiveProjects (
10+
id SERIAL PRIMARY KEY,
11+
member_id INT NOT NULL,
12+
project_title TEXT,
13+
CONSTRAINT fkey_member FOREIGN KEY (member_id) REFERENCES Member(id) ON DELETE CASCADE
14+
);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TABLE AttendanceStreak ADD CONSTRAINT unique_member_month UNIQUE (member_id, month);

src/attendance/scheduled_task.rs

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use chrono::{Local, NaiveTime};
1+
use chrono::{Datelike, Local, NaiveTime};
22
use chrono_tz::Asia::Kolkata;
33
use sqlx::PgPool;
44
use std::sync::Arc;
@@ -93,8 +93,89 @@ pub async fn scheduled_task(pool: Arc<PgPool>) {
9393
Ok(_) => println!("Leaderboard updated."),
9494
Err(e) => eprintln!("Failed to update leaderboard: {:?}", e),
9595
}
96+
97+
// Update attendance streak
98+
update_attendance_streak(member.id, pool.as_ref()).await;
9699
}
97100
}
98101
Err(e) => eprintln!("Failed to fetch members: {:?}", e),
99102
}
100103
}
104+
105+
// Function to update attendance streak
106+
async fn update_attendance_streak(member_id: i32, pool: &sqlx::PgPool) {
107+
let today = chrono::Local::now().with_timezone(&chrono_tz::Asia::Kolkata).naive_local();
108+
let yesterday = today.checked_sub_signed(chrono::Duration::hours(12)).unwrap().date();
109+
110+
if today.day() == 1 {
111+
let _ = sqlx::query(
112+
r#"
113+
INSERT INTO AttendanceStreak (member_id, month, streak)
114+
VALUES ($1, date_trunc('month', $2::date AT TIME ZONE 'Asia/Kolkata'), 0)
115+
"#,
116+
)
117+
.bind(member_id)
118+
.bind(today)
119+
.execute(pool)
120+
.await;
121+
println!("Attendance streak created for member ID: {}", member_id);
122+
}
123+
124+
let present_attendance = sqlx::query_scalar::<_, i64>(
125+
r#"
126+
SELECT COUNT(*)
127+
FROM Attendance
128+
WHERE id = $1
129+
AND is_present = true
130+
AND date = $2
131+
"#,
132+
)
133+
.bind(member_id)
134+
.bind(yesterday)
135+
.fetch_one(pool)
136+
.await;
137+
138+
match present_attendance {
139+
Ok(1) => {
140+
let existing_streak = sqlx::query_scalar::<_, i32>(
141+
r#"
142+
SELECT streak
143+
FROM AttendanceStreak
144+
WHERE member_id = $1
145+
AND month = date_trunc('month', $2::date AT TIME ZONE 'Asia/Kolkata')
146+
"#,
147+
)
148+
.bind(member_id)
149+
.bind(today)
150+
.fetch_optional(pool)
151+
.await;
152+
153+
match existing_streak {
154+
Ok(Some(streak)) => {
155+
let _ = sqlx::query(
156+
r#"
157+
UPDATE AttendanceStreak
158+
SET streak = $1
159+
WHERE member_id = $2
160+
AND month = date_trunc('month', $3::date AT TIME ZONE 'Asia/Kolkata')
161+
"#,
162+
)
163+
.bind(streak + 1)
164+
.bind(member_id)
165+
.bind(today)
166+
.execute(pool)
167+
.await;
168+
}
169+
Ok(None) => {
170+
println!("No streak found for member ID: {}", member_id);
171+
}
172+
Err(e) => eprintln!("Error checking streak for member ID {}: {:?}", member_id, e),
173+
}
174+
}
175+
Ok(0) => {
176+
println!("Sreak not incremented for member ID: {}", member_id);
177+
}
178+
Ok(_) => eprintln!("Unexpected attendance value for member ID: {}", member_id),
179+
Err(e) => eprintln!("Error checking attendance for member ID {}: {:?}", member_id, e),
180+
}
181+
}

src/db/attendance.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,30 @@ pub struct Attendance {
1111
pub timeout: NaiveTime,
1212
pub is_present: bool,
1313
}
14+
15+
#[derive(FromRow, SimpleObject)]
16+
pub struct AttendanceStreak {
17+
pub id: i32,
18+
pub member_id: i32,
19+
pub month: NaiveDate,
20+
pub streak: i32,
21+
}
22+
23+
#[derive(FromRow, SimpleObject)]
24+
pub struct AttendanceSummary {
25+
pub max_days:i64,
26+
pub member_attendance: Vec<MemberAttendance>,
27+
pub daily_count: Vec<DailyCount>,
28+
}
29+
30+
#[derive(FromRow, SimpleObject)]
31+
pub struct MemberAttendance {
32+
pub id:i32,
33+
pub present_days:i64,
34+
}
35+
36+
#[derive(FromRow, SimpleObject)]
37+
pub struct DailyCount {
38+
pub date: NaiveDate,
39+
pub count: i64,
40+
}

src/db/member.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,15 @@ pub struct Member {
1414
pub year: i32,
1515
pub macaddress: String,
1616
pub discord_id: Option<String>,
17-
pub group_id: i32,
17+
pub group_id: Option<i32>,
18+
}
19+
20+
#[derive(FromRow, SimpleObject)]
21+
pub struct MemberExtended {
22+
pub member: Member,
23+
pub project_title: Option<String>,
24+
pub attendance_count: Option<String>,
25+
pub update_count: Option<String>,
1826
}
1927

2028
#[derive(FromRow, SimpleObject)]

src/db/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
pub mod attendance;
22
pub mod leaderboard;
33
pub mod member;
4-
4+
pub mod projects;

src/db/projects.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
use sqlx::FromRow;
2+
use async_graphql::SimpleObject;
3+
4+
#[derive(FromRow, SimpleObject)]
5+
pub struct ActiveProjects {
6+
id: i32,
7+
member_id: i32,
8+
project_title: Option<String>,
9+
}

0 commit comments

Comments
 (0)