Skip to content

Commit 4291d38

Browse files
committed
feat: add member-specific status breaks
1 parent 4a9fdcd commit 4291d38

4 files changed

Lines changed: 57 additions & 13 deletions

File tree

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
ALTER TABLE statusbreaks ADD COLUMN member_id INT;
2+
3+
ALTER TABLE statusbreaks
4+
ADD CONSTRAINT fk_statusbreaks_member
5+
FOREIGN KEY (member_id)
6+
REFERENCES member(member_id)
7+
ON DELETE CASCADE;
8+
9+
-- Make year nullable since member-specific breaks don't need it
10+
ALTER TABLE statusbreaks ALTER COLUMN year DROP NOT NULL;
11+
12+
-- Add index for member_id lookups
13+
CREATE INDEX idx_statusbreaks_member_id ON statusbreaks(member_id);
14+

src/graphql/mutations/status_mutations.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,35 @@ impl StatusMutations {
4343
input: CreateStatusBreakInput,
4444
) -> Result<StatusBreakRecord> {
4545
let pool = ctx.data::<Arc<PgPool>>().expect("Pool must be in context");
46-
let status = sqlx::query_as::<_, StatusBreakRecord>(
47-
"INSERT INTO StatusBreaks (start_date, end_date, year, reason)
48-
VALUES ($1, $2, $3, $4)
46+
47+
match (&input.year, &input.member_id) {
48+
(Some(_), Some(_)) => {
49+
return Err("Cannot specify both year and member_id. A status break must apply to either a year or a member, not both.".into());
50+
}
51+
(None, None) => {
52+
return Err("Must specify either year or member_id. A status break must apply to either a year or a member.".into());
53+
}
54+
_ => {}
55+
}
56+
57+
if input.start_date >= input.end_date {
58+
return Err("start_date must be before end_date".into());
59+
}
60+
61+
let status_break = sqlx::query_as::<_, StatusBreakRecord>(
62+
"INSERT INTO StatusBreaks (start_date, end_date, year, member_id, reason)
63+
VALUES ($1, $2, $3, $4, $5)
4964
RETURNING *
5065
",
5166
)
5267
.bind(input.start_date)
5368
.bind(input.end_date)
5469
.bind(input.year)
70+
.bind(input.member_id)
5571
.bind(&input.reason)
5672
.fetch_one(pool.as_ref())
5773
.await?;
5874

59-
Ok(status)
75+
Ok(status_break)
6076
}
6177
}

src/graphql/queries/member_queries.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -191,9 +191,15 @@ impl StatusInfo {
191191
AND (
192192
is_sent = TRUE
193193
OR NOT EXISTS (
194-
SELECT * FROM StatusBreaks sb
195-
WHERE year = (SELECT year from Member where member_id=$1)
196-
AND suh.date BETWEEN sb.start_date AND sb.end_date
194+
SELECT 1 FROM StatusBreaks sb
195+
WHERE suh.date BETWEEN sb.start_date AND sb.end_date
196+
AND (
197+
-- Year-wide break
198+
sb.year = (SELECT year FROM Member WHERE member_id = $1)
199+
OR
200+
-- Member-specific break
201+
sb.member_id = $1
202+
)
197203
)
198204
)
199205
)
@@ -235,13 +241,19 @@ impl StatusUpdateRecord {
235241

236242
let is_on_break = sqlx::query_scalar(
237243
"SELECT EXISTS (
238-
SELECT 1 from StatusBreaks
239-
WHERE year = (SELECT year FROM Member WHERE member_id = $1)
240-
AND $2 BETWEEN start_date AND end_date
244+
SELECT 1 FROM StatusBreaks
245+
WHERE $1 BETWEEN start_date AND end_date
246+
AND (
247+
-- Year-wide break
248+
year = (SELECT year FROM Member WHERE member_id = $2)
249+
OR
250+
-- Member-specific break
251+
member_id = $2
252+
)
241253
)",
242254
)
243-
.bind(self.member_id)
244255
.bind(self.date)
256+
.bind(self.member_id)
245257
.fetch_optional(pool.as_ref())
246258
.await?;
247259

src/models/status_update.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,16 @@ pub struct StatusBreakRecord {
2222
pub id: i32,
2323
pub start_date: NaiveDate,
2424
pub end_date: NaiveDate,
25-
pub year: i32,
25+
pub year: Option<i32>,
26+
pub member_id: Option<i32>,
2627
pub reason: Option<String>,
2728
}
2829

2930
#[derive(InputObject)]
3031
pub struct CreateStatusBreakInput {
3132
pub start_date: NaiveDate,
3233
pub end_date: NaiveDate,
33-
pub year: i32,
34+
pub year: Option<i32>,
35+
pub member_id: Option<i32>,
3436
pub reason: Option<String>,
3537
}

0 commit comments

Comments
 (0)