admin panel cleanup
All checks were successful
Deploy to VPS / deploy (push) Successful in 1m26s

This commit is contained in:
Tihon
2026-03-18 13:15:08 +02:00
parent 955c6d1c01
commit 90efdf1f59
11 changed files with 64 additions and 58 deletions

View File

@@ -2,11 +2,9 @@ package com.honey.honey.controller;
import com.honey.honey.model.Payment;
import com.honey.honey.model.Payout;
import com.honey.honey.model.SupportTicket;
import com.honey.honey.model.UserA;
import com.honey.honey.repository.PaymentRepository;
import com.honey.honey.repository.PayoutRepository;
import com.honey.honey.repository.SupportTicketRepository;
import com.honey.honey.repository.UserARepository;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
@@ -30,7 +28,6 @@ public class AdminDashboardController {
private final UserARepository userARepository;
private final PaymentRepository paymentRepository;
private final PayoutRepository payoutRepository;
private final SupportTicketRepository supportTicketRepository;
@GetMapping("/stats")
public ResponseEntity<Map<String, Object>> getDashboardStats() {
@@ -103,15 +100,6 @@ public class AdminDashboardController {
BigDecimal cryptoNetRevenueWeek = cryptoRevenueWeek.subtract(cryptoPayoutsWeek);
BigDecimal cryptoNetRevenueMonth = cryptoRevenueMonth.subtract(cryptoPayoutsMonth);
// Support Tickets
long openTickets = supportTicketRepository.countByStatus(SupportTicket.TicketStatus.OPENED);
// Count tickets closed today
long ticketsResolvedToday = supportTicketRepository.findAll().stream()
.filter(t -> t.getStatus() == SupportTicket.TicketStatus.CLOSED &&
t.getUpdatedAt() != null &&
t.getUpdatedAt().isAfter(todayStart))
.count();
// Build response
stats.put("users", Map.of(
"total", totalUsers,
@@ -162,19 +150,6 @@ public class AdminDashboardController {
crypto.put("profitUsdMonth", cryptoNetRevenueMonth);
stats.put("crypto", crypto);
stats.put("rounds", Map.of(
"total", 0L,
"today", 0L,
"week", 0L,
"month", 0L,
"avgPool", 0
));
stats.put("supportTickets", Map.of(
"open", openTickets,
"resolvedToday", ticketsResolvedToday
));
return ResponseEntity.ok(stats);
}
}

View File

@@ -124,6 +124,7 @@ public class AdminPaymentController {
.orderId(payment.getOrderId())
.starsAmount(payment.getStarsAmount())
.ticketsAmount(payment.getTicketsAmount())
.usdAmount(payment.getUsdAmount())
.status(payment.getStatus().name())
.telegramPaymentChargeId(payment.getTelegramPaymentChargeId())
.telegramProviderPaymentChargeId(payment.getTelegramProviderPaymentChargeId())

View File

@@ -135,6 +135,7 @@ public class AdminPayoutController {
.type(payout.getType().name())
.giftName(payout.getGiftName() != null ? payout.getGiftName().name() : null)
.total(payout.getTotal())
.usdAmount(payout.getUsdAmount())
.starsAmount(payout.getStarsAmount())
.quantity(payout.getQuantity())
.status(payout.getStatus().name())

View File

@@ -58,8 +58,10 @@ public class AdminUserController {
@RequestParam(required = false) String languageCode,
@RequestParam(required = false) Integer dateRegFrom,
@RequestParam(required = false) Integer dateRegTo,
@RequestParam(required = false) Long balanceMin,
@RequestParam(required = false) Long balanceMax,
@RequestParam(required = false) Long balanceAMin,
@RequestParam(required = false) Long balanceAMax,
@RequestParam(required = false) Long balanceBMin,
@RequestParam(required = false) Long balanceBMax,
@RequestParam(required = false) Integer referralCountMin,
@RequestParam(required = false) Integer referralCountMax,
@RequestParam(required = false) Integer referrerId,
@@ -81,9 +83,11 @@ public class AdminUserController {
}
Pageable pageable = PageRequest.of(page, size, sort);
// Convert balance filters from tickets (divide by 1000000) to bigint format
Long balanceMinBigint = balanceMin != null ? balanceMin * 1000000L : null;
Long balanceMaxBigint = balanceMax != null ? balanceMax * 1000000L : null;
// Convert balance filters from display value to bigint format
Long balanceAMinBigint = balanceAMin != null ? balanceAMin * 1000000L : null;
Long balanceAMaxBigint = balanceAMax != null ? balanceAMax * 1000000L : null;
Long balanceBMinBigint = balanceBMin != null ? balanceBMin * 1000000L : null;
Long balanceBMaxBigint = balanceBMax != null ? balanceBMax * 1000000L : null;
boolean excludeMasters = isSupport();
Page<AdminUserDto> dtoPage = adminUserService.getUsers(
@@ -94,8 +98,10 @@ public class AdminUserController {
languageCode,
dateRegFrom,
dateRegTo,
balanceMinBigint,
balanceMaxBigint,
balanceAMinBigint,
balanceAMaxBigint,
balanceBMinBigint,
balanceBMaxBigint,
referralCountMin,
referralCountMax,
referrerId,

View File

@@ -5,6 +5,7 @@ import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.time.Instant;
@Data
@@ -18,6 +19,8 @@ public class AdminPaymentDto {
private String orderId;
private Integer starsAmount;
private Long ticketsAmount;
/** USD amount (e.g. 1.25). */
private BigDecimal usdAmount;
private String status;
private String telegramPaymentChargeId;
private String telegramProviderPaymentChargeId;

View File

@@ -5,6 +5,7 @@ import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.time.Instant;
@Data
@@ -19,6 +20,8 @@ public class AdminPayoutDto {
private String type;
private String giftName;
private Long total;
/** USD amount (e.g. 1.25). */
private BigDecimal usdAmount;
private Integer starsAmount;
private Integer quantity;
private String status;

View File

@@ -30,6 +30,7 @@ public class AdminUserDetailDto {
// Balance Info
private Long balanceA;
private Long balanceB;
private Long depositTotal;
private Integer depositCount;
private Long withdrawTotal;

View File

@@ -6,7 +6,6 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.NotBlank;
@Data
@Builder
@@ -17,13 +16,12 @@ public class BalanceAdjustmentRequest {
private BalanceType balanceType; // A or B
@NotNull(message = "Amount is required")
private Long amount; // In bigint format (tickets * 1,000,000)
private Long amount; // In bigint format (display value * 1,000,000)
@NotNull(message = "Operation is required")
private OperationType operation; // ADD or SUBTRACT
@NotBlank(message = "Reason is required")
private String reason; // Reason for adjustment (for audit log)
private String reason; // Optional reason for adjustment (for audit log)
public enum BalanceType {
A, B

View File

@@ -56,8 +56,10 @@ public class AdminUserService {
String languageCode,
Integer dateRegFrom,
Integer dateRegTo,
Long balanceMin,
Long balanceMax,
Long balanceAMin,
Long balanceAMax,
Long balanceBMin,
Long balanceBMax,
Integer referralCountMin,
Integer referralCountMax,
Integer referrerId,
@@ -137,20 +139,16 @@ public class AdminUserService {
predicates.add(cb.lessThanOrEqualTo(root.get("dateReg"), endOfDayTimestamp));
}
// Balance / referral filters via subqueries so DB handles pagination
if (balanceMin != null || balanceMax != null) {
// Balance A / Balance B filters via subqueries
if (balanceAMin != null || balanceAMax != null || balanceBMin != null || balanceBMax != null) {
Subquery<Integer> subB = query.subquery(Integer.class);
Root<UserB> br = subB.from(UserB.class);
subB.select(br.get("id"));
List<Predicate> subPreds = new ArrayList<>();
if (balanceMin != null) {
subPreds.add(cb.greaterThanOrEqualTo(
cb.sum(br.get("balanceA"), br.get("balanceB")), balanceMin));
}
if (balanceMax != null) {
subPreds.add(cb.lessThanOrEqualTo(
cb.sum(br.get("balanceA"), br.get("balanceB")), balanceMax));
}
if (balanceAMin != null) subPreds.add(cb.greaterThanOrEqualTo(br.get("balanceA"), balanceAMin));
if (balanceAMax != null) subPreds.add(cb.lessThanOrEqualTo(br.get("balanceA"), balanceAMax));
if (balanceBMin != null) subPreds.add(cb.greaterThanOrEqualTo(br.get("balanceB"), balanceBMin));
if (balanceBMax != null) subPreds.add(cb.lessThanOrEqualTo(br.get("balanceB"), balanceBMax));
subB.where(cb.and(subPreds.toArray(new Predicate[0])));
predicates.add(cb.in(root.get("id")).value(subB));
}
@@ -186,7 +184,7 @@ public class AdminUserService {
return cb.and(predicates.toArray(new Predicate[0]));
};
Set<String> sortRequiresJoin = Set.of("balanceA", "depositTotal", "withdrawTotal", "referralCount", "profit");
Set<String> sortRequiresJoin = Set.of("balanceA", "balanceB", "depositTotal", "withdrawTotal", "referralCount", "profit");
boolean useJoinSort = sortBy != null && sortRequiresJoin.contains(sortBy);
List<UserA> userList;
long totalElements;
@@ -194,7 +192,7 @@ public class AdminUserService {
if (useJoinSort) {
List<Integer> orderedIds = getOrderedUserIdsForAdminList(
search, banned, countryCode, languageCode,
dateRegFrom, dateRegTo, balanceMin, balanceMax,
dateRegFrom, dateRegTo, balanceAMin, balanceAMax, balanceBMin, balanceBMax,
referralCountMin, referralCountMax,
referrerId, referralLevel, ipFilter,
sortBy, sortDir != null ? sortDir : "desc",
@@ -301,8 +299,10 @@ public class AdminUserService {
String languageCode,
Integer dateRegFrom,
Integer dateRegTo,
Long balanceMin,
Long balanceMax,
Long balanceAMin,
Long balanceAMax,
Long balanceBMin,
Long balanceBMax,
Integer referralCountMin,
Integer referralCountMax,
Integer referrerId,
@@ -374,14 +374,24 @@ public class AdminUserService {
params.add(dateRegTo);
paramIndex++;
}
if (balanceMin != null) {
sql.append(" AND (b.balance_a + b.balance_b) >= ?");
params.add(balanceMin);
if (balanceAMin != null) {
sql.append(" AND b.balance_a >= ?");
params.add(balanceAMin);
paramIndex++;
}
if (balanceMax != null) {
sql.append(" AND (b.balance_a + b.balance_b) <= ?");
params.add(balanceMax);
if (balanceAMax != null) {
sql.append(" AND b.balance_a <= ?");
params.add(balanceAMax);
paramIndex++;
}
if (balanceBMin != null) {
sql.append(" AND b.balance_b >= ?");
params.add(balanceBMin);
paramIndex++;
}
if (balanceBMax != null) {
sql.append(" AND b.balance_b <= ?");
params.add(balanceBMax);
paramIndex++;
}
if (referralCountMin != null || referralCountMax != null) {
@@ -417,6 +427,7 @@ public class AdminUserService {
String orderColumn = switch (sortBy != null ? sortBy : "") {
case "balanceA" -> "b.balance_a";
case "balanceB" -> "b.balance_b";
case "depositTotal" -> "b.deposit_total";
case "withdrawTotal" -> "b.withdraw_total";
case "referralCount" -> "(d.referals_1 + d.referals_2 + d.referals_3 + d.referals_4 + d.referals_5)";
@@ -579,6 +590,7 @@ public class AdminUserService {
.banned(userA.getBanned())
.ipAddress(IpUtils.bytesToIp(userA.getIp()))
.balanceA(userB.getBalanceA())
.balanceB(userB.getBalanceB())
.depositTotal(userB.getDepositTotal())
.depositCount(userB.getDepositCount())
.withdrawTotal(userB.getWithdrawTotal())

View File

@@ -0,0 +1,4 @@
-- Ensure payment_enabled and payout_enabled feature switches exist (for admin panel and runtime).
INSERT INTO feature_switches (`key`, `enabled`, `updated_at`)
VALUES ('payment_enabled', 1, CURRENT_TIMESTAMP), ('payout_enabled', 1, CURRENT_TIMESTAMP)
ON DUPLICATE KEY UPDATE `updated_at` = CURRENT_TIMESTAMP;

View File

@@ -0,0 +1,2 @@
-- Index for admin users list: filter and sort by Balance B
CREATE INDEX idx_users_b_balance_b ON db_users_b(balance_b);