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,23 @@
ALTER TABLE "Achievement"
ADD COLUMN "leaderboardId" UUID,
ADD CONSTRAINT "fk_leaderboard" FOREIGN KEY ("leaderboardId") REFERENCES "Leaderboard"(id);

-- backfill
-- all current `Achievement.name` is either
-- "<leaderboard name> - <school> - <Nth> Place" (tag leaderboards)
-- "<leaderboard name> - <Nth> Place" (global leaderboard)
DO $$
BEGIN
CASE current_database()
WHEN 'codebloom-prod' THEN
UPDATE "Achievement" a
SET "leaderboardId" = l.id
FROM "Leaderboard" l
WHERE l.name = split_part(a.title, ' - ', 1);
ELSE
RAISE NOTICE 'Skipping prod only backfill: Current database is %', current_database();
END CASE;
END $$;

ALTER TABLE "Achievement"
ALTER COLUMN "leaderboardId" SET NOT NULL;
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
DO $$
BEGIN
INSERT INTO "Achievement"
(id, "userId", title, description, "isActive", place, leaderboard, "createdAt")
INSERT INTO "Achievement"
(id, "userId", title, description, "isActive", place, leaderboard, "leaderboardId", "createdAt")
VALUES
(
'265dd000-c310-11f0-8d3a-461b1b1abee9',
'1717a2dc-ce77-4853-a620-82177799ad26',
'October Overflow',
'Not expired leaderboard',
'Achieved first place on the Patina Network leaderboard',
true,
'ONE',
'Patina',
'39bc2def-669f-4383-8ea3-7202efd613f2',
'2025-11-11 00:00:00+00'
);

INSERT INTO "Achievement"
(id, "userId", title, description, "isActive", place, leaderboard, "createdAt")
INSERT INTO "Achievement"
(id, "userId", title, description, "isActive", place, leaderboard, "leaderboardId", "createdAt")
VALUES
(
'365dd000-c310-11f0-8d3a-461b1b1abeea',
'1717a2dc-ce77-4853-a620-82177799ad26',
'auto november = nullptr;',
'Expired leaderboard',
'Secured first place on the global leaderboard',
true,
'ONE',
NULL,
'8fc363b2-b5be-4f1a-9e0e-ea4844fc919c',
'2025-12-06 00:00:00+00'
);

END $$;
END $$;
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ public class Achievement {
@NotNullColumn
private String userId;

@NotNullColumn
private String leaderboardId;

@NotNullColumn
private AchievementPlaceEnum place;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public interface AchievementRepository {
* <li>title
* <li>description
* <li>isActive
* <li>leaderboardId
* </ul>
*/
void createAchievement(Achievement achievement);
Expand All @@ -29,6 +30,7 @@ public interface AchievementRepository {
* <li>description
* <li>isActive
* <li>deletedAt
* <li>leaderboardId
* </ul>
*
* @return updated achievement if successful
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
var title = rs.getString("title");
var description = rs.getString("description");
var isActive = rs.getBoolean("isActive");
var leaderboardId = rs.getString("leaderboardId");

Check failure on line 29 in src/main/java/org/patinanetwork/codebloom/common/db/repos/achievements/AchievementSqlRepository.java

View check run for this annotation

SonarQubeCloud / [codebloom_backend] SonarCloud Code Analysis

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

See more on https://sonarcloud.io/project/issues?id=Patina-Network_codebloom_backend&issues=AZ_AzdWP_sm3M2mr6TTm&open=AZ_AzdWP_sm3M2mr6TTm&pullRequest=953
var createdAt = StandardizedOffsetDateTime.normalize(rs.getObject("createdAt", OffsetDateTime.class));
OffsetDateTime deletedAt =
StandardizedOffsetDateTime.normalize(rs.getObject("deletedAt", OffsetDateTime.class));
Expand All @@ -34,6 +35,7 @@
.userId(userId)
.place(place)
.leaderboard(leaderboard)
.leaderboardId(leaderboardId)
.title(title)
.description(description)
.isActive(isActive)
Expand All @@ -53,9 +55,9 @@
achievement.setId(UUID.randomUUID().toString());
String sql = """
INSERT INTO "Achievement"
(id, "userId", place, leaderboard, title, description, "isActive", "deletedAt")
(id, "userId", place, leaderboard, title, description, "isActive", "deletedAt", "leaderboardId")
VALUES
(:id, :userId, :place, :leaderboard, :title, :description, :isActive, :deletedAt)
(:id, :userId, :place, :leaderboard, :title, :description, :isActive, :deletedAt, :leaderboardId)
RETURNING
"createdAt"
""";
Expand All @@ -71,6 +73,7 @@
.map(Enum::name)
.orElse(null),
Types.OTHER)
.param("leaderboardId", UUID.fromString(achievement.getLeaderboardId()))
.param("title", achievement.getTitle())
.param("description", achievement.getDescription())
.param("isActive", achievement.isActive())
Expand All @@ -94,7 +97,8 @@
title = :title,
description = :description,
"isActive" = :isActive,
"deletedAt" = :deletedAt
"deletedAt" = :deletedAt,
"leaderboardId" = :leaderboardId
WHERE
id = :id
""";
Expand All @@ -108,10 +112,12 @@
.map(Enum::name)
.orElse(null),
Types.OTHER)
.param("leaderboardId", achievement.getLeaderboardId())
.param("title", achievement.getTitle())
.param("description", achievement.getDescription())
.param("isActive", achievement.isActive())
.param("deletedAt", achievement.getDeletedAt())
.param("leaderboardId", UUID.fromString(achievement.getLeaderboardId()))
.param("id", UUID.fromString(achievement.getId()))
.update();

Expand Down Expand Up @@ -150,7 +156,8 @@
description,
"isActive",
"createdAt",
"deletedAt"
"deletedAt",
"leaderboardId"
FROM
"Achievement"
WHERE
Expand Down Expand Up @@ -178,7 +185,8 @@
description,
"isActive",
"createdAt",
"deletedAt"
"deletedAt",
"leaderboardId"
FROM
"Achievement"
WHERE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ public class AchievementDto {
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, nullable = true)
private Tag leaderboard;

@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
private String leaderboardId;

@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
private String title;

Expand All @@ -52,6 +55,7 @@ public static AchievementDto fromAchievement(final Achievement achievement) {
.leaderboard(achievement.getLeaderboard())
.place(achievement.getPlace())
.title(achievement.getTitle())
.leaderboardId(achievement.getLeaderboardId())
.description(achievement.getDescription())
.isActive(achievement.isActive())
.createdAt(achievement.getCreatedAt())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public class AchievementRepositoryTest extends BaseRepositoryTest {
private Achievement testAchievement;
private Achievement deletableAchievement;
private String mockUserId = "ed3bfe18-e42a-467f-b4fa-07e8da4d2555";
// Not expired leaderboard
private String mockLeaderboardId = "39bc2def-669f-4383-8ea3-7202efd613f2";

@Autowired
public AchievementRepositoryTest(final AchievementRepository repo) {
Expand All @@ -34,6 +36,7 @@ void createAchievement() {
.userId(mockUserId)
.place(AchievementPlaceEnum.ONE)
.leaderboard(null)
.leaderboardId(mockLeaderboardId)
.title("Test Achievement")
.description("Integration test achievement")
.isActive(true)
Expand Down Expand Up @@ -78,6 +81,7 @@ void testUpdateAchievement() {
.userId(testAchievement.getUserId())
.place(AchievementPlaceEnum.THREE)
.leaderboard(Tag.Patina)
.leaderboardId(mockLeaderboardId)
.title("Updated Title")
.description("Updated Description")
.isActive(false)
Expand All @@ -101,6 +105,7 @@ void testDeleteAchievementById() {
.userId(mockUserId)
.place(AchievementPlaceEnum.ONE)
.leaderboard(null)
.leaderboardId(mockLeaderboardId)
.title("Deletable Achievement")
.description("Should be deleted")
.isActive(true)
Expand Down
Loading