diff --git a/src/main/java/com/l2/shots/auth/AdminResetPasswordRequest.java b/src/main/java/com/l2/shots/auth/AdminResetPasswordRequest.java index 789b71b..bcb1f32 100644 --- a/src/main/java/com/l2/shots/auth/AdminResetPasswordRequest.java +++ b/src/main/java/com/l2/shots/auth/AdminResetPasswordRequest.java @@ -1,6 +1,4 @@ package com.l2.shots.auth; -public class AdminResetPasswordRequest { - public String username; - public String newPassword; +public record AdminResetPasswordRequest(String username, String newPassword) { } diff --git a/src/main/java/com/l2/shots/auth/AdminUserSummary.java b/src/main/java/com/l2/shots/auth/AdminUserSummary.java index 35181f8..587a311 100644 --- a/src/main/java/com/l2/shots/auth/AdminUserSummary.java +++ b/src/main/java/com/l2/shots/auth/AdminUserSummary.java @@ -3,22 +3,21 @@ package com.l2.shots.auth; import java.time.Instant; import java.util.UUID; -public class AdminUserSummary { - public UUID id; - public String username; - public Instant createdAt; - public Instant lastLoginAt; - public boolean isAdmin; - public boolean mustChangePassword; +public record AdminUserSummary( + UUID id, + String username, + Instant createdAt, + Instant lastLoginAt, + boolean isAdmin, + boolean mustChangePassword) { - public AdminUserSummary() {} - - public AdminUserSummary(User u) { - this.id = u.id; - this.username = u.username; - this.createdAt = u.createdAt; - this.lastLoginAt = u.lastLoginAt; - this.isAdmin = u.isAdmin; - this.mustChangePassword = u.mustChangePassword; + public static AdminUserSummary from(User u) { + return new AdminUserSummary( + u.id, + u.username, + u.createdAt, + u.lastLoginAt, + u.isAdmin, + u.mustChangePassword); } } diff --git a/src/main/java/com/l2/shots/auth/AuthMeResponse.java b/src/main/java/com/l2/shots/auth/AuthMeResponse.java index 2c925bb..40184a1 100644 --- a/src/main/java/com/l2/shots/auth/AuthMeResponse.java +++ b/src/main/java/com/l2/shots/auth/AuthMeResponse.java @@ -3,20 +3,10 @@ package com.l2.shots.auth; import java.time.Instant; import java.util.UUID; -public class AuthMeResponse { - public UUID id; - public String username; - public Instant createdAt; - public boolean mustChangePassword; - public boolean isAdmin; - - public AuthMeResponse() {} - - public AuthMeResponse(UUID id, String username, Instant createdAt, boolean mustChangePassword, boolean isAdmin) { - this.id = id; - this.username = username; - this.createdAt = createdAt; - this.mustChangePassword = mustChangePassword; - this.isAdmin = isAdmin; - } +public record AuthMeResponse( + UUID id, + String username, + Instant createdAt, + boolean mustChangePassword, + boolean isAdmin) { } diff --git a/src/main/java/com/l2/shots/auth/AuthResource.java b/src/main/java/com/l2/shots/auth/AuthResource.java index e8fc729..e41585f 100644 --- a/src/main/java/com/l2/shots/auth/AuthResource.java +++ b/src/main/java/com/l2/shots/auth/AuthResource.java @@ -42,7 +42,7 @@ public class AuthResource { @POST @Path("/register") public Response register(Credentials creds) { - Optional result = authService.register(creds.username, creds.password); + Optional result = authService.register(creds.username(), creds.password()); if (result.isEmpty()) { return Response.status(409) .entity(new ErrorBody("username no disponible o datos inválidos")) @@ -58,7 +58,7 @@ public class AuthResource { @POST @Path("/login") public Response login(Credentials creds) { - Optional result = authService.authenticate(creds.username, creds.password); + Optional result = authService.authenticate(creds.username(), creds.password()); if (result.isEmpty()) { return Response.status(401) .entity(new ErrorBody("credenciales inválidas")) @@ -83,7 +83,7 @@ public class AuthResource { @Path("/change-password") @Authenticated public Response changePassword(@Context HttpHeaders headers, ChangePasswordRequest body) { - if (body == null || body.currentPassword == null || body.newPassword == null) { + if (body == null || body.currentPassword() == null || body.newPassword() == null) { return Response.status(400).entity(new ErrorBody("Faltan campos requeridos")).build(); } Optional jwt = jwtCookieAuth.extractToken(headers); @@ -91,7 +91,7 @@ public class AuthResource { Optional user = authService.getEntityFromToken(jwt.get()); if (user.isEmpty()) return Response.status(401).build(); AuthService.ChangePasswordResult result = authService.changePassword( - user.get().id, body.currentPassword, body.newPassword); + user.get().id, body.currentPassword(), body.newPassword()); switch (result) { case OK: User refreshed = User.findById(user.get().id); @@ -116,7 +116,7 @@ public class AuthResource { @Path("/admin/reset-password") @RolesAllowed("admin") public Response adminResetPassword(AdminResetPasswordRequest body) { - if (body == null || body.username == null || body.newPassword == null) { + if (body == null || body.username() == null || body.newPassword() == null) { return Response.status(400).entity(new ErrorBody("Faltan campos requeridos")).build(); } UUID requesterId; @@ -125,7 +125,7 @@ public class AuthResource { } catch (Exception e) { return Response.status(401).build(); } - boolean ok = authService.resetPasswordAsAdmin(requesterId, body.username, body.newPassword); + boolean ok = authService.resetPasswordAsAdmin(requesterId, body.username(), body.newPassword()); if (!ok) { return Response.status(400).entity(new ErrorBody("Usuario no encontrado o contraseña inválida")).build(); } @@ -180,9 +180,6 @@ public class AuthResource { .build(); } - public static class ErrorBody { - public String error; - public ErrorBody() {} - public ErrorBody(String error) { this.error = error; } + public record ErrorBody(String error) { } } diff --git a/src/main/java/com/l2/shots/auth/AuthService.java b/src/main/java/com/l2/shots/auth/AuthService.java index 15349c7..395d94e 100644 --- a/src/main/java/com/l2/shots/auth/AuthService.java +++ b/src/main/java/com/l2/shots/auth/AuthService.java @@ -77,7 +77,7 @@ public class AuthService { public java.util.List listUsersForAdmin() { return User.listAll().stream() - .map(AdminUserSummary::new) + .map(AdminUserSummary::from) .collect(java.util.stream.Collectors.toList()); } diff --git a/src/main/java/com/l2/shots/auth/ChangePasswordRequest.java b/src/main/java/com/l2/shots/auth/ChangePasswordRequest.java index cc66d9b..817f9db 100644 --- a/src/main/java/com/l2/shots/auth/ChangePasswordRequest.java +++ b/src/main/java/com/l2/shots/auth/ChangePasswordRequest.java @@ -1,6 +1,4 @@ package com.l2.shots.auth; -public class ChangePasswordRequest { - public String currentPassword; - public String newPassword; +public record ChangePasswordRequest(String currentPassword, String newPassword) { } diff --git a/src/main/java/com/l2/shots/auth/Credentials.java b/src/main/java/com/l2/shots/auth/Credentials.java index 21f7dcd..369d3d2 100644 --- a/src/main/java/com/l2/shots/auth/Credentials.java +++ b/src/main/java/com/l2/shots/auth/Credentials.java @@ -1,6 +1,4 @@ package com.l2.shots.auth; -public class Credentials { - public String username; - public String password; +public record Credentials(String username, String password) { } diff --git a/src/main/java/com/l2/shots/auth/MustChangePasswordFilter.java b/src/main/java/com/l2/shots/auth/MustChangePasswordFilter.java index d2dfcf1..699d44f 100644 --- a/src/main/java/com/l2/shots/auth/MustChangePasswordFilter.java +++ b/src/main/java/com/l2/shots/auth/MustChangePasswordFilter.java @@ -60,8 +60,9 @@ public class MustChangePasswordFilter implements ContainerRequestFilter { .build()); } - public static class MustChangeBody { - public String error = "Debe cambiar la contraseña antes de continuar"; - public boolean mustChangePassword = true; + public record MustChangeBody(String error, boolean mustChangePassword) { + public MustChangeBody() { + this("Debe cambiar la contraseña antes de continuar", true); + } } } diff --git a/src/main/java/com/l2/shots/history/HistoryResource.java b/src/main/java/com/l2/shots/history/HistoryResource.java index 0cdd162..ffc4d2c 100644 --- a/src/main/java/com/l2/shots/history/HistoryResource.java +++ b/src/main/java/com/l2/shots/history/HistoryResource.java @@ -36,16 +36,16 @@ public class HistoryResource { Optional userId = extractUserId(headers); if (userId.isEmpty()) return Response.status(401).build(); - if (input == null || input.items == null || input.snapshot == null) { + if (input == null || input.items() == null || input.snapshot() == null) { return Response.status(400).entity("{\"error\":\"payload inválido\"}").build(); } - if (input.items.size() > 100) { + if (input.items().size() > 100) { return Response.status(400).entity("{\"error\":\"demasiados items\"}").build(); } - if (input.label != null && input.label.length() > 100) { + if (input.label() != null && input.label().length() > 100) { return Response.status(400).entity("{\"error\":\"label demasiado largo\"}").build(); } - if (input.totalCristalesUsed <= 0) { + if (input.totalCristalesUsed() <= 0) { return Response.status(400).entity("{\"error\":\"no hay cristales usados\"}").build(); } diff --git a/src/main/java/com/l2/shots/history/HistoryService.java b/src/main/java/com/l2/shots/history/HistoryService.java index 9f48f69..9db887d 100644 --- a/src/main/java/com/l2/shots/history/HistoryService.java +++ b/src/main/java/com/l2/shots/history/HistoryService.java @@ -18,7 +18,7 @@ public class HistoryService { public List listForUser(UUID userId) { return ProductionRun.list("userId = ?1 ORDER BY createdAt DESC", userId) .stream() - .map(RunSummary::new) + .map(RunSummary::from) .toList(); } @@ -29,7 +29,7 @@ public class HistoryService { List items = mapper.readValue(entity.itemsJson, mapper.getTypeFactory() .constructCollectionType(List.class, RunItem.class)); RunSnapshot snapshot = mapper.readValue(entity.snapshotJson, RunSnapshot.class); - return Optional.of(new RunDetails(entity, items, snapshot)); + return Optional.of(RunDetails.of(entity, items, snapshot)); } catch (JsonProcessingException e) { return Optional.empty(); } @@ -41,21 +41,21 @@ public class HistoryService { entity.id = UUID.randomUUID(); entity.userId = userId; entity.createdAt = Instant.now(); - entity.label = input.label; - entity.totalCost = input.totalCost; - entity.totalSale = input.totalSale; - entity.totalProfit = input.totalProfit; - entity.totalShots = input.totalShots; - entity.totalCristalesUsed = input.totalCristalesUsed; - entity.totalOreUsed = input.totalOreUsed; + entity.label = input.label(); + entity.totalCost = input.totalCost(); + entity.totalSale = input.totalSale(); + entity.totalProfit = input.totalProfit(); + entity.totalShots = input.totalShots(); + entity.totalCristalesUsed = input.totalCristalesUsed(); + entity.totalOreUsed = input.totalOreUsed(); try { - entity.itemsJson = mapper.writeValueAsString(input.items); - entity.snapshotJson = mapper.writeValueAsString(input.snapshot); + entity.itemsJson = mapper.writeValueAsString(input.items()); + entity.snapshotJson = mapper.writeValueAsString(input.snapshot()); } catch (JsonProcessingException e) { throw new RuntimeException("Failed to serialize run payload", e); } entity.persist(); - return new RunSummary(entity); + return RunSummary.from(entity); } @Transactional @@ -67,22 +67,8 @@ public class HistoryService { List runs = ProductionRun.list( "userId = ?1 ORDER BY createdAt DESC", userId); - HistoryStats stats = new HistoryStats(); - stats.totalRuns = runs.size(); - if (runs.isEmpty()) { - stats.totalCost = 0; - stats.totalSale = 0; - stats.totalProfit = 0; - stats.totalShots = 0; - stats.avgProfit = 0; - stats.avgCost = 0; - stats.avgSale = 0; - stats.bestRun = null; - stats.worstRun = null; - stats.last5Avg = 0; - stats.last10Avg = 0; - return stats; + return new HistoryStats(0, 0, 0, 0, 0, 0, 0, 0, null, null, 0, 0); } long totalCost = 0; @@ -101,27 +87,28 @@ public class HistoryService { if (r.totalProfit < worst.totalProfit) worst = r; } - stats.totalCost = totalCost; - stats.totalSale = totalSale; - stats.totalProfit = totalProfit; - stats.totalShots = totalShots; - stats.avgProfit = totalProfit / runs.size(); - stats.avgCost = totalCost / runs.size(); - stats.avgSale = totalSale / runs.size(); - stats.bestRun = new RunSummary(best); - stats.worstRun = new RunSummary(worst); - - int n5 = Math.min(5, runs.size()); - int n10 = Math.min(10, runs.size()); + int n = runs.size(); + int n5 = Math.min(5, n); + int n10 = Math.min(10, n); long sum5 = 0; long sum10 = 0; for (int i = 0; i < n10; i++) { sum10 += runs.get(i).totalProfit; if (i < n5) sum5 += runs.get(i).totalProfit; } - stats.last5Avg = n5 > 0 ? sum5 / n5 : 0; - stats.last10Avg = n10 > 0 ? sum10 / n10 : 0; - return stats; + return new HistoryStats( + n, + totalCost, + totalSale, + totalProfit, + totalShots, + totalProfit / n, + totalCost / n, + totalSale / n, + RunSummary.from(best), + RunSummary.from(worst), + n5 > 0 ? sum5 / n5 : 0, + n10 > 0 ? sum10 / n10 : 0); } } diff --git a/src/main/java/com/l2/shots/history/HistoryStats.java b/src/main/java/com/l2/shots/history/HistoryStats.java index 2b7b2a1..72a6ed9 100644 --- a/src/main/java/com/l2/shots/history/HistoryStats.java +++ b/src/main/java/com/l2/shots/history/HistoryStats.java @@ -1,16 +1,16 @@ package com.l2.shots.history; -public class HistoryStats { - public int totalRuns; - public long totalCost; - public long totalSale; - public long totalProfit; - public long totalShots; - public long avgProfit; - public long avgCost; - public long avgSale; - public RunSummary bestRun; - public RunSummary worstRun; - public long last5Avg; - public long last10Avg; +public record HistoryStats( + int totalRuns, + long totalCost, + long totalSale, + long totalProfit, + long totalShots, + long avgProfit, + long avgCost, + long avgSale, + RunSummary bestRun, + RunSummary worstRun, + long last5Avg, + long last10Avg) { } diff --git a/src/main/java/com/l2/shots/history/RunDetails.java b/src/main/java/com/l2/shots/history/RunDetails.java index 4980b55..5a0fac0 100644 --- a/src/main/java/com/l2/shots/history/RunDetails.java +++ b/src/main/java/com/l2/shots/history/RunDetails.java @@ -1,16 +1,34 @@ package com.l2.shots.history; +import java.time.Instant; import java.util.List; +import java.util.UUID; -public class RunDetails extends RunSummary { - public List items; - public RunSnapshot snapshot; +public record RunDetails( + UUID id, + Instant createdAt, + String label, + long totalCost, + long totalSale, + long totalProfit, + long totalShots, + long totalCristalesUsed, + long totalOreUsed, + List items, + RunSnapshot snapshot) { - public RunDetails() {} - - public RunDetails(ProductionRun r, List items, RunSnapshot snapshot) { - super(r); - this.items = items; - this.snapshot = snapshot; + public static RunDetails of(ProductionRun r, List items, RunSnapshot snapshot) { + return new RunDetails( + r.id, + r.createdAt, + r.label, + r.totalCost, + r.totalSale, + r.totalProfit, + r.totalShots, + r.totalCristalesUsed, + r.totalOreUsed, + items, + snapshot); } } diff --git a/src/main/java/com/l2/shots/history/RunIn.java b/src/main/java/com/l2/shots/history/RunIn.java index f758e06..21649fc 100644 --- a/src/main/java/com/l2/shots/history/RunIn.java +++ b/src/main/java/com/l2/shots/history/RunIn.java @@ -2,14 +2,14 @@ package com.l2.shots.history; import java.util.List; -public class RunIn { - public String label; - public long totalCost; - public long totalSale; - public long totalProfit; - public long totalShots; - public long totalCristalesUsed; - public long totalOreUsed; - public List items; - public RunSnapshot snapshot; +public record RunIn( + String label, + long totalCost, + long totalSale, + long totalProfit, + long totalShots, + long totalCristalesUsed, + long totalOreUsed, + List items, + RunSnapshot snapshot) { } diff --git a/src/main/java/com/l2/shots/history/RunItem.java b/src/main/java/com/l2/shots/history/RunItem.java index 4e50daf..e578332 100644 --- a/src/main/java/com/l2/shots/history/RunItem.java +++ b/src/main/java/com/l2/shots/history/RunItem.java @@ -1,31 +1,14 @@ package com.l2.shots.history; -public class RunItem { - public String tipo; - public String grado; - public int cristalesDisponibles; - public int cristalesUsados; - public int oreNecesario; - public int crafteosPosibles; - public int shotsObtenidos; - public long costoTotal; - public long valorVenta; - public long ganancia; - - public RunItem() {} - - public RunItem(String tipo, String grado, int cristalesDisponibles, int cristalesUsados, - int oreNecesario, int crafteosPosibles, int shotsObtenidos, - long costoTotal, long valorVenta, long ganancia) { - this.tipo = tipo; - this.grado = grado; - this.cristalesDisponibles = cristalesDisponibles; - this.cristalesUsados = cristalesUsados; - this.oreNecesario = oreNecesario; - this.crafteosPosibles = crafteosPosibles; - this.shotsObtenidos = shotsObtenidos; - this.costoTotal = costoTotal; - this.valorVenta = valorVenta; - this.ganancia = ganancia; - } +public record RunItem( + String tipo, + String grado, + int cristalesDisponibles, + int cristalesUsados, + int oreNecesario, + int crafteosPosibles, + int shotsObtenidos, + long costoTotal, + long valorVenta, + long ganancia) { } diff --git a/src/main/java/com/l2/shots/history/RunSnapshot.java b/src/main/java/com/l2/shots/history/RunSnapshot.java index 0243d2a..8bbaf46 100644 --- a/src/main/java/com/l2/shots/history/RunSnapshot.java +++ b/src/main/java/com/l2/shots/history/RunSnapshot.java @@ -3,14 +3,7 @@ package com.l2.shots.history; import java.util.List; import java.util.Map; -public class RunSnapshot { - public Map insumos; - public List> formulas; - - public RunSnapshot() {} - - public RunSnapshot(Map insumos, List> formulas) { - this.insumos = insumos; - this.formulas = formulas; - } +public record RunSnapshot( + Map insumos, + List> formulas) { } diff --git a/src/main/java/com/l2/shots/history/RunSummary.java b/src/main/java/com/l2/shots/history/RunSummary.java index 4b219c1..e0ef5c2 100644 --- a/src/main/java/com/l2/shots/history/RunSummary.java +++ b/src/main/java/com/l2/shots/history/RunSummary.java @@ -3,28 +3,27 @@ package com.l2.shots.history; import java.time.Instant; import java.util.UUID; -public class RunSummary { - public UUID id; - public Instant createdAt; - public String label; - public long totalCost; - public long totalSale; - public long totalProfit; - public long totalShots; - public long totalCristalesUsed; - public long totalOreUsed; +public record RunSummary( + UUID id, + Instant createdAt, + String label, + long totalCost, + long totalSale, + long totalProfit, + long totalShots, + long totalCristalesUsed, + long totalOreUsed) { - public RunSummary() {} - - public RunSummary(ProductionRun r) { - this.id = r.id; - this.createdAt = r.createdAt; - this.label = r.label; - this.totalCost = r.totalCost; - this.totalSale = r.totalSale; - this.totalProfit = r.totalProfit; - this.totalShots = r.totalShots; - this.totalCristalesUsed = r.totalCristalesUsed; - this.totalOreUsed = r.totalOreUsed; + public static RunSummary from(ProductionRun r) { + return new RunSummary( + r.id, + r.createdAt, + r.label, + r.totalCost, + r.totalSale, + r.totalProfit, + r.totalShots, + r.totalCristalesUsed, + r.totalOreUsed); } } diff --git a/src/main/java/com/l2/shots/state/AppState.java b/src/main/java/com/l2/shots/state/AppState.java index 64268a5..f137392 100644 --- a/src/main/java/com/l2/shots/state/AppState.java +++ b/src/main/java/com/l2/shots/state/AppState.java @@ -3,57 +3,25 @@ package com.l2.shots.state; import java.util.List; import java.util.Map; -public class AppState { +public record AppState( + Insumos insumos, + List formulas, + Map> disponibles) { - public Insumos insumos; - public List formulas; - public Map> disponibles; - - public AppState() {} - - public AppState(Insumos insumos, List formulas, Map> disponibles) { - this.insumos = insumos; - this.formulas = formulas; - this.disponibles = disponibles; + public record Insumos( + Map cristales, + int soulOre, + int spiritOre, + Map> venta) { } - public static class Insumos { - public Map cristales; - public int soulOre; - public int spiritOre; - public Map> venta; - - public Insumos() {} - - public Insumos(Map cristales, int soulOre, int spiritOre, - Map> venta) { - this.cristales = cristales; - this.soulOre = soulOre; - this.spiritOre = spiritOre; - this.venta = venta; - } - } - - public static class FormulaDto { - public String id; - public String tipo; - public String grado; - public int cristalesReq; - public Integer soulOreReq; - public Integer spiritOreReq; - public int shotsObtenidos; - - public FormulaDto() {} - - public FormulaDto(String id, String tipo, String grado, int cristalesReq, - Integer soulOreReq, Integer spiritOreReq, int shotsObtenidos) { - this.id = id; - this.tipo = tipo; - this.grado = grado; - this.cristalesReq = cristalesReq; - this.soulOreReq = soulOreReq; - this.spiritOreReq = spiritOreReq; - this.shotsObtenidos = shotsObtenidos; - } + public record FormulaDto( + String id, + String tipo, + String grado, + int cristalesReq, + Integer soulOreReq, + Integer spiritOreReq, + int shotsObtenidos) { } } diff --git a/src/main/java/com/l2/shots/state/StateResource.java b/src/main/java/com/l2/shots/state/StateResource.java index b0b14fd..b64d7e2 100644 --- a/src/main/java/com/l2/shots/state/StateResource.java +++ b/src/main/java/com/l2/shots/state/StateResource.java @@ -43,10 +43,10 @@ public class StateResource { Optional userId = extractUserId(headers); if (userId.isEmpty()) return Response.status(401).build(); - if (state == null || state.insumos == null || state.formulas == null || state.disponibles == null) { + if (state == null || state.insumos() == null || state.formulas() == null || state.disponibles() == null) { return Response.status(400).entity("{\"error\":\"estado inválido\"}").build(); } - if (state.formulas.size() > 200) { + if (state.formulas().size() > 200) { return Response.status(400).entity("{\"error\":\"estado demasiado grande\"}").build(); } stateService.saveForUser(userId.get(), state);