알림 시간봉 오류 수정
This commit is contained in:
@@ -6,6 +6,7 @@ import com.goldenchart.entity.GcAppSettings;
|
||||
import com.goldenchart.entity.GcLiveStrategySettings;
|
||||
import com.goldenchart.entity.GcWatchlist;
|
||||
import com.goldenchart.repository.GcLiveStrategySettingsRepository;
|
||||
import com.goldenchart.repository.GcStrategyRepository;
|
||||
import com.goldenchart.repository.GcWatchlistRepository;
|
||||
import com.goldenchart.websocket.DynamicSubscriptionManager;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -26,6 +27,7 @@ import java.util.Optional;
|
||||
public class LiveStrategySettingsService {
|
||||
|
||||
private final GcLiveStrategySettingsRepository repo;
|
||||
private final GcStrategyRepository strategyRepo;
|
||||
private final GcWatchlistRepository watchlistRepo;
|
||||
private final AppSettingsService appSettingsService;
|
||||
private final DynamicSubscriptionManager subscriptionManager;
|
||||
@@ -35,10 +37,11 @@ public class LiveStrategySettingsService {
|
||||
|
||||
// ── 조회 ──────────────────────────────────────────────────────────────────
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
@Transactional
|
||||
public LiveStrategySettingsDto get(Long userId, String deviceId, String market) {
|
||||
GcAppSettings app = appSettingsService.getEntity(userId, deviceId);
|
||||
Optional<GcLiveStrategySettings> entity = findEntity(userId, deviceId, market);
|
||||
entity.ifPresent(this::reconcileOneRow);
|
||||
LiveStrategySettingsDto dto = entity.isPresent()
|
||||
? toDto(entity.get())
|
||||
: defaultDtoFromApp(market, app);
|
||||
@@ -48,12 +51,15 @@ public class LiveStrategySettingsService {
|
||||
return dto;
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
@Transactional
|
||||
public List<LiveStrategySettingsDto> listActive(Long userId, String deviceId) {
|
||||
List<GcLiveStrategySettings> rows = userId != null
|
||||
? repo.findByUserIdAndIsLiveCheckTrue(userId)
|
||||
: repo.findByDeviceIdAndIsLiveCheckTrue(
|
||||
deviceId != null && !deviceId.isBlank() ? deviceId : "anonymous");
|
||||
for (GcLiveStrategySettings row : rows) {
|
||||
reconcileOneRow(row);
|
||||
}
|
||||
if (rows.isEmpty()) {
|
||||
return List.of();
|
||||
}
|
||||
@@ -116,6 +122,61 @@ public class LiveStrategySettingsService {
|
||||
|
||||
// ── 저장/갱신 — 전역 템플릿 + 관심종목 전체 동기화 ─────────────────────────
|
||||
|
||||
/**
|
||||
* 기동·설정 조회 시 — strategy_id 누락·삭제 전략·회원 전역 전략 불일치 보정.
|
||||
*
|
||||
* @return 수정된 행 수
|
||||
*/
|
||||
@Transactional
|
||||
public int reconcileOrphanAndStaleSettings() {
|
||||
int fixed = 0;
|
||||
for (GcLiveStrategySettings row : repo.findAllByIsLiveCheckTrue()) {
|
||||
if (reconcileOneRow(row)) {
|
||||
fixed++;
|
||||
}
|
||||
}
|
||||
if (fixed > 0) {
|
||||
log.info("[LiveStrategySettings] reconcile fixed {} active row(s)", fixed);
|
||||
}
|
||||
return fixed;
|
||||
}
|
||||
|
||||
private boolean reconcileOneRow(GcLiveStrategySettings row) {
|
||||
boolean changed = false;
|
||||
GcAppSettings app = appSettingsService.getEntity(row.getUserId(), row.getDeviceId());
|
||||
|
||||
if (row.getStrategyId() == null) {
|
||||
row.setIsLiveCheck(false);
|
||||
changed = true;
|
||||
} else if (!strategyRepo.existsById(row.getStrategyId())) {
|
||||
if (row.getUserId() != null
|
||||
&& Boolean.TRUE.equals(app.getLiveStrategyCheck())
|
||||
&& app.getLiveStrategyId() != null
|
||||
&& strategyRepo.existsById(app.getLiveStrategyId())) {
|
||||
row.setStrategyId(app.getLiveStrategyId());
|
||||
} else {
|
||||
row.setIsLiveCheck(false);
|
||||
}
|
||||
changed = true;
|
||||
} else if (row.getUserId() != null
|
||||
&& Boolean.TRUE.equals(app.getLiveStrategyCheck())
|
||||
&& app.getLiveStrategyId() != null
|
||||
&& !app.getLiveStrategyId().equals(row.getStrategyId())
|
||||
&& strategyRepo.existsById(app.getLiveStrategyId())) {
|
||||
row.setStrategyId(app.getLiveStrategyId());
|
||||
conditionTimeframes.invalidate(app.getLiveStrategyId());
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
repo.save(row);
|
||||
if (row.getMarket() != null) {
|
||||
liveStrategyEvaluator.invalidateCache(row.getMarket());
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
public LiveStrategySettingsDto save(Long userId, String deviceId,
|
||||
LiveStrategySettingsDto dto) {
|
||||
if (!Boolean.TRUE.equals(dto.getSkipGlobalTemplate())) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.goldenchart.service;
|
||||
|
||||
import com.goldenchart.dto.TradeSignalDto;
|
||||
import com.goldenchart.entity.GcTradeSignal;
|
||||
import com.goldenchart.repository.GcStrategyRepository;
|
||||
import com.goldenchart.repository.GcTradeSignalRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -22,6 +23,7 @@ import java.util.List;
|
||||
public class TradeSignalService {
|
||||
|
||||
private final GcTradeSignalRepository repo;
|
||||
private final GcStrategyRepository strategyRepo;
|
||||
private final FcmPushService fcmPushService;
|
||||
|
||||
// ── 저장 ─────────────────────────────────────────────────────────────────
|
||||
@@ -31,12 +33,13 @@ public class TradeSignalService {
|
||||
String signalType, double price,
|
||||
long candleTime, String candleType,
|
||||
String executionType) {
|
||||
String resolvedName = resolveStrategyName(strategyId, strategyName);
|
||||
GcTradeSignal entity = GcTradeSignal.builder()
|
||||
.deviceId(deviceId)
|
||||
.userId(userId)
|
||||
.market(market)
|
||||
.strategyId(strategyId)
|
||||
.strategyName(strategyName)
|
||||
.strategyName(resolvedName)
|
||||
.signalType(signalType)
|
||||
.price(price)
|
||||
.candleTime(candleTime)
|
||||
@@ -49,7 +52,7 @@ public class TradeSignalService {
|
||||
// 로그인 사용자는 live 설정에 userId만 있고 deviceId가 null — FCM은 userId 기준으로 발송
|
||||
if (userId != null || (deviceId != null && !deviceId.isBlank())) {
|
||||
fcmPushService.sendTradeSignalIfEnabled(
|
||||
deviceId, userId, market, signalType, price, strategyName, saved.getId());
|
||||
deviceId, userId, market, signalType, price, resolvedName, saved.getId());
|
||||
}
|
||||
return toDto(saved);
|
||||
}
|
||||
@@ -66,9 +69,11 @@ public class TradeSignalService {
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<TradeSignalDto> listByMarket(Long userId, String deviceId, String market) {
|
||||
return repo.findByDeviceIdAndMarketOrderByCreatedAtDesc(
|
||||
deviceId != null ? deviceId : "", market)
|
||||
.stream().map(this::toDto).toList();
|
||||
List<GcTradeSignal> list = userId != null
|
||||
? repo.findByUserIdAndMarketOrderByCreatedAtDesc(userId, market)
|
||||
: repo.findByDeviceIdAndMarketOrderByCreatedAtDesc(
|
||||
deviceId != null ? deviceId : "", market);
|
||||
return list.stream().map(this::toDto).toList();
|
||||
}
|
||||
|
||||
// ── 삭제 ─────────────────────────────────────────────────────────────────
|
||||
@@ -117,6 +122,14 @@ public class TradeSignalService {
|
||||
return deviceId.equals(entity.getDeviceId());
|
||||
}
|
||||
|
||||
private String resolveStrategyName(Long strategyId, String strategyName) {
|
||||
if (strategyName != null && !strategyName.isBlank()) return strategyName;
|
||||
if (strategyId == null) return null;
|
||||
return strategyRepo.findById(strategyId)
|
||||
.map(s -> s.getName())
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
// ── 변환 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
private TradeSignalDto toDto(GcTradeSignal e) {
|
||||
|
||||
Reference in New Issue
Block a user