diff --git a/src/main/java/com/honey/honey/controller/AdminDashboardController.java b/src/main/java/com/honey/honey/controller/AdminDashboardController.java index 2e39814..2e3a1af 100644 --- a/src/main/java/com/honey/honey/controller/AdminDashboardController.java +++ b/src/main/java/com/honey/honey/controller/AdminDashboardController.java @@ -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> 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); } } diff --git a/src/main/java/com/honey/honey/controller/AdminPaymentController.java b/src/main/java/com/honey/honey/controller/AdminPaymentController.java index a9d2afa..51949ba 100644 --- a/src/main/java/com/honey/honey/controller/AdminPaymentController.java +++ b/src/main/java/com/honey/honey/controller/AdminPaymentController.java @@ -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()) diff --git a/src/main/java/com/honey/honey/controller/AdminPayoutController.java b/src/main/java/com/honey/honey/controller/AdminPayoutController.java index 3d1afee..51ecfec 100644 --- a/src/main/java/com/honey/honey/controller/AdminPayoutController.java +++ b/src/main/java/com/honey/honey/controller/AdminPayoutController.java @@ -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()) diff --git a/src/main/java/com/honey/honey/controller/AdminUserController.java b/src/main/java/com/honey/honey/controller/AdminUserController.java index 907ebc3..1722a35 100644 --- a/src/main/java/com/honey/honey/controller/AdminUserController.java +++ b/src/main/java/com/honey/honey/controller/AdminUserController.java @@ -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 dtoPage = adminUserService.getUsers( @@ -94,8 +98,10 @@ public class AdminUserController { languageCode, dateRegFrom, dateRegTo, - balanceMinBigint, - balanceMaxBigint, + balanceAMinBigint, + balanceAMaxBigint, + balanceBMinBigint, + balanceBMaxBigint, referralCountMin, referralCountMax, referrerId, diff --git a/src/main/java/com/honey/honey/dto/AdminPaymentDto.java b/src/main/java/com/honey/honey/dto/AdminPaymentDto.java index 54e7016..7a79245 100644 --- a/src/main/java/com/honey/honey/dto/AdminPaymentDto.java +++ b/src/main/java/com/honey/honey/dto/AdminPaymentDto.java @@ -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; diff --git a/src/main/java/com/honey/honey/dto/AdminPayoutDto.java b/src/main/java/com/honey/honey/dto/AdminPayoutDto.java index 17edbe2..03e6283 100644 --- a/src/main/java/com/honey/honey/dto/AdminPayoutDto.java +++ b/src/main/java/com/honey/honey/dto/AdminPayoutDto.java @@ -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; diff --git a/src/main/java/com/honey/honey/dto/AdminUserDetailDto.java b/src/main/java/com/honey/honey/dto/AdminUserDetailDto.java index 0230a5e..e2db557 100644 --- a/src/main/java/com/honey/honey/dto/AdminUserDetailDto.java +++ b/src/main/java/com/honey/honey/dto/AdminUserDetailDto.java @@ -30,6 +30,7 @@ public class AdminUserDetailDto { // Balance Info private Long balanceA; + private Long balanceB; private Long depositTotal; private Integer depositCount; private Long withdrawTotal; diff --git a/src/main/java/com/honey/honey/dto/BalanceAdjustmentRequest.java b/src/main/java/com/honey/honey/dto/BalanceAdjustmentRequest.java index 914a13f..0b46d32 100644 --- a/src/main/java/com/honey/honey/dto/BalanceAdjustmentRequest.java +++ b/src/main/java/com/honey/honey/dto/BalanceAdjustmentRequest.java @@ -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 diff --git a/src/main/java/com/honey/honey/service/AdminUserService.java b/src/main/java/com/honey/honey/service/AdminUserService.java index 83b4b4c..e6c0ec4 100644 --- a/src/main/java/com/honey/honey/service/AdminUserService.java +++ b/src/main/java/com/honey/honey/service/AdminUserService.java @@ -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 subB = query.subquery(Integer.class); Root br = subB.from(UserB.class); subB.select(br.get("id")); List 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 sortRequiresJoin = Set.of("balanceA", "depositTotal", "withdrawTotal", "referralCount", "profit"); + Set sortRequiresJoin = Set.of("balanceA", "balanceB", "depositTotal", "withdrawTotal", "referralCount", "profit"); boolean useJoinSort = sortBy != null && sortRequiresJoin.contains(sortBy); List userList; long totalElements; @@ -194,7 +192,7 @@ public class AdminUserService { if (useJoinSort) { List 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()) diff --git a/src/main/resources/db/migration/V73__feature_switch_payment_payout_enabled.sql b/src/main/resources/db/migration/V73__feature_switch_payment_payout_enabled.sql new file mode 100644 index 0000000..756808e --- /dev/null +++ b/src/main/resources/db/migration/V73__feature_switch_payment_payout_enabled.sql @@ -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; diff --git a/src/main/resources/db/migration/V74__admin_users_b_balance_b_index.sql b/src/main/resources/db/migration/V74__admin_users_b_balance_b_index.sql new file mode 100644 index 0000000..80742b7 --- /dev/null +++ b/src/main/resources/db/migration/V74__admin_users_b_balance_b_index.sql @@ -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);