Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package org.patinanetwork.patchats.api.match.db.repos;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.Instant;
import java.util.List;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.patinanetwork.patchats.api.match.db.models.MatchCycle;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.stereotype.Repository;

@Repository
@RequiredArgsConstructor
public class MatchCycleSqlRepo implements MatchCycleRepo {
private final JdbcClient jdbc;

private MatchCycle parseResultSetToMatchCycle(final ResultSet rs) throws SQLException {
return MatchCycle.builder()
.id(rs.getInt("id"))
.period(rs.getString("period"))

Check failure on line 22 in src/main/java/org/patinanetwork/patchats/api/match/db/repos/MatchCycleSqlRepo.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "period" 4 times.

See more on https://sonarcloud.io/project/issues?id=Patina-Network_patchats&issues=AaABxpx9E2CEp0L91YEA&open=AaABxpx9E2CEp0L91YEA&pullRequest=74
.runAt(rs.getObject("run_at", Instant.class))

Check failure on line 23 in src/main/java/org/patinanetwork/patchats/api/match/db/repos/MatchCycleSqlRepo.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "run_at" 3 times.

See more on https://sonarcloud.io/project/issues?id=Patina-Network_patchats&issues=AaABxpx9E2CEp0L91YD-&open=AaABxpx9E2CEp0L91YD-&pullRequest=74
.totalMembers(rs.getInt("total_members"))

Check failure on line 24 in src/main/java/org/patinanetwork/patchats/api/match/db/repos/MatchCycleSqlRepo.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "total_members" 3 times.

See more on https://sonarcloud.io/project/issues?id=Patina-Network_patchats&issues=AaABxpx9E2CEp0L91YD9&open=AaABxpx9E2CEp0L91YD9&pullRequest=74

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically, we can calculate this by looking at the match table and then counting the rows right?

One issue with this is that if we have a new pending MatchCycle, then the count could be changing as we add more matches. So then we would have to update this sychronously with adding matches to the match table. Having the same information in two different places is a huge pain to keep synced.

Potentially we can fill these numbers in when we change a MatchCycle from pending to live, so that they're cached, so we don't have to compute them each time. If it's not like read only though, it would still require syncing tho. Like if we edit matches after it goes live.

We should also make a new column for the table that is like: isLive, which we flip when we go send the emails out.

.totalMatched(rs.getInt("total_matched"))

Check failure on line 25 in src/main/java/org/patinanetwork/patchats/api/match/db/repos/MatchCycleSqlRepo.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "total_matched" 3 times.

See more on https://sonarcloud.io/project/issues?id=Patina-Network_patchats&issues=AaABxpx9E2CEp0L91YD_&open=AaABxpx9E2CEp0L91YD_&pullRequest=74
.build();
}

@Override
public MatchCycle createMatchCycle(MatchCycle matchCycle) {
String sql = """
INSERT INTO "match_cycles" (
"period",
"run_at",
"total_members",
"total_matched"
)
VALUES(
:period,
:run_at,
:total_members,
:total_matched
)
RETURNING
*
""";

return jdbc.sql(sql)
.param("period", matchCycle.getPeriod())
.param("run_at", matchCycle.getRunAt())
.param("total_members", matchCycle.getTotalMembers())
.param("total_matched", matchCycle.getTotalMatched())
.query((rs, rowNum) -> parseResultSetToMatchCycle(rs))
.single();
}

@Override
public Optional<MatchCycle> updateMatchCycle(MatchCycle matchCycle) {
String sql = """
UPDATE "match_cycles" SET
"period" = :period,
"run_at" = :run_at,
"total_members" = :total_members,
"total_matched" = :total_matched
WHERE "id" = :id
RETURNING *
""";

return jdbc.sql(sql)
.param("id", matchCycle.getId())
.param("period", matchCycle.getPeriod())
.param("run_at", matchCycle.getRunAt())
.param("total_members", matchCycle.getTotalMembers())
.param("total_matched", matchCycle.getTotalMatched())
.query((rs, rowNum) -> parseResultSetToMatchCycle(rs))
.optional();
}

@Override
public Optional<MatchCycle> getMatchCycleById(Integer id) {
String sql = "SELECT * FROM match_cycles WHERE id = :id";
return jdbc.sql(sql)
.param("id", id)
.query((rs, rowNum) -> parseResultSetToMatchCycle(rs))
.optional();
}

@Override
public Optional<MatchCycle> deleteMatchCycleById(Integer id) {
String sql = "DELETE FROM match_cycles WHERE id = :id RETURNING *";
return jdbc.sql(sql)
.param("id", id)
.query((rs, rowNum) -> parseResultSetToMatchCycle(rs))
.optional();
}

@Override
public List<MatchCycle> filterMatchCycles(MatchCycleFilterCriteria criteria) {
StringBuilder sql = new StringBuilder("SELECT * FROM match_cycles WHERE 1=1");
MapSqlParameterSource params = new MapSqlParameterSource();

criteria.period().ifPresent(period -> {
sql.append(" AND period = :period");
params.addValue("period", period);
});

criteria.startTime().ifPresent(start -> {
sql.append(" AND run_at >= :start_time");
params.addValue("start_time", start);
});

criteria.endTime().ifPresent(end -> {
sql.append(" AND run_at <= :end_time");
params.addValue("end_time", end);
});

return jdbc.sql(sql.toString())
.paramSource(params)
.query((rs, rowNum) -> parseResultSetToMatchCycle(rs))
.list();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
package org.patinanetwork.patchats.api.match.db.repos;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.Instant;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.patinanetwork.patchats.api.match.db.models.Match;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.stereotype.Repository;

@Repository
@RequiredArgsConstructor
public class MatchSqlRepo implements MatchRepo {
private final JdbcClient jdbc;

private Match parseResultSetToMatch(final ResultSet rs) throws SQLException {
return Match.builder()
.id(UUID.fromString(rs.getString("id")))
.memberAId(UUID.fromString(rs.getString("member_a_id")))

Check failure on line 23 in src/main/java/org/patinanetwork/patchats/api/match/db/repos/MatchSqlRepo.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "member_a_id" 3 times.

See more on https://sonarcloud.io/project/issues?id=Patina-Network_patchats&issues=AaABxpvcE2CEp0L91YD2&open=AaABxpvcE2CEp0L91YD2&pullRequest=74
.memberBId(UUID.fromString(rs.getString("member_b_id")))

Check failure on line 24 in src/main/java/org/patinanetwork/patchats/api/match/db/repos/MatchSqlRepo.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "member_b_id" 3 times.

See more on https://sonarcloud.io/project/issues?id=Patina-Network_patchats&issues=AaABxpvcE2CEp0L91YD6&open=AaABxpvcE2CEp0L91YD6&pullRequest=74
.matchCycleId(rs.getInt("cycle_id"))

Check failure on line 25 in src/main/java/org/patinanetwork/patchats/api/match/db/repos/MatchSqlRepo.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "cycle_id" 4 times.

See more on https://sonarcloud.io/project/issues?id=Patina-Network_patchats&issues=AaABxpvcE2CEp0L91YD4&open=AaABxpvcE2CEp0L91YD4&pullRequest=74
.matchScore(rs.getObject("match_score", Double.class))

Check failure on line 26 in src/main/java/org/patinanetwork/patchats/api/match/db/repos/MatchSqlRepo.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "match_score" 3 times.

See more on https://sonarcloud.io/project/issues?id=Patina-Network_patchats&issues=AaABxpvcE2CEp0L91YD5&open=AaABxpvcE2CEp0L91YD5&pullRequest=74
.status(rs.getString("status"))

Check failure on line 27 in src/main/java/org/patinanetwork/patchats/api/match/db/repos/MatchSqlRepo.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "status" 5 times.

See more on https://sonarcloud.io/project/issues?id=Patina-Network_patchats&issues=AaABxpvcE2CEp0L91YD8&open=AaABxpvcE2CEp0L91YD8&pullRequest=74
.feedbackA(rs.getString("feedback_a"))

Check failure on line 28 in src/main/java/org/patinanetwork/patchats/api/match/db/repos/MatchSqlRepo.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "feedback_a" 3 times.

See more on https://sonarcloud.io/project/issues?id=Patina-Network_patchats&issues=AaABxpvcE2CEp0L91YD7&open=AaABxpvcE2CEp0L91YD7&pullRequest=74
.feedbackB(rs.getString("feedback_b"))

Check failure on line 29 in src/main/java/org/patinanetwork/patchats/api/match/db/repos/MatchSqlRepo.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "feedback_b" 3 times.

See more on https://sonarcloud.io/project/issues?id=Patina-Network_patchats&issues=AaABxpvcE2CEp0L91YD3&open=AaABxpvcE2CEp0L91YD3&pullRequest=74
.createdAt(rs.getObject("created_at", Instant.class))
.build();
}

@Override
public Match createMatch(Match match) {
String sql = """
INSERT INTO "matches" (
"id",
"member_a_id",
"member_b_id",
"cycle_id",
"match_score",
"status",
"feedback_a",
"feedback_b"
)
VALUES(
:id,
:member_a_id,
:member_b_id,
:cycle_id,
:match_score,
:status,
:feedback_a,
:feedback_b
)
RETURNING
*
""";
return jdbc.sql(sql)
.param("id", match.getId())
.param("member_a_id", match.getMemberAId())
.param("member_b_id", match.getMemberBId())
.param("cycle_id", match.getMatchCycleId())
.param("match_score", match.getMatchScore())
.param("status", match.getStatus())
.param("feedback_a", match.getFeedbackA())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd actually remove feedback from this table as well, and make a table for feedback specifically.

It'd be:
feedback_id
match_id
member_id
...feedback content

feedback content could be like 1-5 stars, text field for written things or whatever else we think of. But that leaves it to be a lot more flexible.

.param("feedback_b", match.getFeedbackB())
.query((rs, rowNum) -> parseResultSetToMatch(rs))
.single();
}

@Override
public Optional<Match> updateMatch(Match match) {
String sql = """
UPDATE "matches" SET
"member_a_id" = :member_a_id,
"member_b_id" = :member_b_id,
"cycle_id" = :cycle_id,
"match_score" = :match_score,
"status" = :status,
"feedback_a" = :feedback_a,
"feedback_b" = :feedback_b
WHERE "id" = :id
RETURNING *
""";
return jdbc.sql(sql)
.param("id", match.getId())
.param("member_a_id", match.getMemberAId())
.param("member_b_id", match.getMemberBId())
.param("cycle_id", match.getMatchCycleId())
.param("match_score", match.getMatchScore())
.param("status", match.getStatus())
.param("feedback_a", match.getFeedbackA())
.param("feedback_b", match.getFeedbackB())
.query((rs, rowNum) -> parseResultSetToMatch(rs))
.optional();
}

@Override
public Optional<Match> getMatchById(UUID id) {
String sql = "SELECT * FROM matches WHERE id = :id";
Comment thread
rootandroo marked this conversation as resolved.
return jdbc.sql(sql)
.param("id", id)
.query((rs, rowNum) -> parseResultSetToMatch(rs))
.optional();
}

@Override
public Optional<Match> setMatchStatus(UUID id, String status) {
String sql = """
UPDATE "matches" SET "status" = :status
WHERE "id" = :id
RETURNING *
""";
return jdbc.sql(sql)
.param("id", id)
.param("status", status)
.query((rs, rowNum) -> parseResultSetToMatch(rs))
.optional();
}

@Override
public Optional<Match> deleteMatchById(UUID id) {
String sql = "DELETE FROM matches WHERE id = :id RETURNING *";
return jdbc.sql(sql)
.param("id", id)
.query((rs, rowNum) -> parseResultSetToMatch(rs))
.optional();
}

@Override
public Optional<Match> recordFeedback(UUID id, UUID memberId, String feedback) {
String sql = """
UPDATE "matches" SET
"feedback_a" = CASE WHEN "member_a_id" = :member_id THEN :feedback ELSE "feedback_a" END,
"feedback_b" = CASE WHEN "member_b_id" = :member_id THEN :feedback ELSE "feedback_b" END
WHERE "id" = :id AND ("member_a_id" = :member_id OR "member_b_id" = :member_id)
RETURNING *
""";
return jdbc.sql(sql)
.param("id", id)
.param("member_id", memberId)
.param("feedback", feedback)
.query((rs, rowNum) -> parseResultSetToMatch(rs))
.optional();
}

@Override
public List<Match> filterMatches(MatchFilterCriteria criteria) {
StringBuilder sql = new StringBuilder("SELECT * FROM matches WHERE 1=1");
MapSqlParameterSource params = new MapSqlParameterSource();

criteria.status().ifPresent(status -> {
sql.append(" AND status = :status");
params.addValue("status", status);
});

criteria.memberId().ifPresent(memberId -> {
sql.append(" AND (member_a_id = :member_id OR member_b_id = :member_id)");
params.addValue("member_id", memberId);
});

criteria.matchCycleId().ifPresent(cycleId -> {
sql.append(" AND cycle_id = :cycle_id");
params.addValue("cycle_id", cycleId);
});

criteria.startTime().ifPresent(start -> {
sql.append(" AND created_at >= :start_time");
params.addValue("start_time", start);
});

criteria.endTime().ifPresent(end -> {
sql.append(" AND created_at <= :end_time");
params.addValue("end_time", end);
});

criteria.period().ifPresent(period -> {
sql.append(" AND cycle_id IN (SELECT id FROM match_cycles WHERE period = :period)");
params.addValue("period", period);
});

criteria.memberIndustry().ifPresent(memberIndustry -> {
sql.append(" AND (");
sql.append("member_a_id IN (SELECT id FROM members WHERE industry_pref = :member_industry)");
sql.append(" OR ");
sql.append("member_b_id IN (SELECT id FROM members WHERE industry_pref = :member_industry)");
sql.append(")");
params.addValue("member_industry", memberIndustry);
});
Comment thread
rootandroo marked this conversation as resolved.

return jdbc.sql(sql.toString())
.paramSource(params)
.query((rs, rowNum) -> parseResultSetToMatch(rs))
.list();
}
}
Loading