146 lines
6.6 KiB
Java
146 lines
6.6 KiB
Java
package com.goldenchart.service;
|
|
|
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
import com.goldenchart.entity.GcChartSlot;
|
|
import com.goldenchart.entity.GcChartWorkspace;
|
|
import com.goldenchart.repository.GcChartWorkspaceRepository;
|
|
import lombok.RequiredArgsConstructor;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* 차트 워크스페이스·슬롯 설정 저장/조회 서비스.
|
|
* userId 또는 deviceId 중 하나를 식별자로 사용한다.
|
|
*/
|
|
@Service
|
|
@RequiredArgsConstructor
|
|
@Slf4j
|
|
@Transactional
|
|
public class ChartSettingsService {
|
|
|
|
private final GcChartWorkspaceRepository workspaceRepo;
|
|
private final ObjectMapper objectMapper;
|
|
|
|
// ── 워크스페이스 조회 ──────────────────────────────────────────────────────
|
|
|
|
@Transactional(readOnly = true)
|
|
public GcChartWorkspace getWorkspace(Long userId, String deviceId) {
|
|
return findWorkspace(userId, deviceId).orElse(null);
|
|
}
|
|
|
|
@Transactional(readOnly = true)
|
|
public GcChartWorkspace getWorkspaceWithSlots(Long userId, String deviceId) {
|
|
if (userId != null) {
|
|
return workspaceRepo.findWithSlotsByUserId(userId).orElse(null);
|
|
}
|
|
return workspaceRepo.findWithSlotsByDeviceId(deviceId).orElse(null);
|
|
}
|
|
|
|
// ── 워크스페이스 저장 (생성 또는 전체 업데이트) ────────────────────────────
|
|
|
|
public GcChartWorkspace saveWorkspace(Long userId, String deviceId,
|
|
String layoutId, String syncOptionsJson) {
|
|
GcChartWorkspace ws = findWorkspace(userId, deviceId)
|
|
.orElseGet(() -> GcChartWorkspace.builder()
|
|
.userId(userId)
|
|
.deviceId(deviceId)
|
|
.layoutId(layoutId)
|
|
.slots(new ArrayList<>())
|
|
.build());
|
|
ws.setLayoutId(layoutId);
|
|
ws.setSyncOptionsJson(syncOptionsJson);
|
|
return workspaceRepo.save(ws);
|
|
}
|
|
|
|
// ── 슬롯 설정 저장 ─────────────────────────────────────────────────────────
|
|
|
|
public GcChartSlot saveSlot(Long userId, String deviceId, int slotIndex,
|
|
Map<String, Object> slotData) {
|
|
GcChartWorkspace ws = findOrCreateWorkspace(userId, deviceId);
|
|
|
|
GcChartSlot slot = ws.getSlots().stream()
|
|
.filter(s -> s.getSlotIndex() == slotIndex)
|
|
.findFirst()
|
|
.orElseGet(() -> {
|
|
GcChartSlot newSlot = GcChartSlot.builder()
|
|
.workspace(ws)
|
|
.slotIndex(slotIndex)
|
|
.build();
|
|
ws.getSlots().add(newSlot);
|
|
return newSlot;
|
|
});
|
|
|
|
applySlotData(slot, slotData);
|
|
workspaceRepo.save(ws);
|
|
return slot;
|
|
}
|
|
|
|
// ── 전체 워크스페이스 + 슬롯 일괄 저장 (프론트 최초 로드 또는 전체 저장) ──
|
|
|
|
public GcChartWorkspace saveAll(Long userId, String deviceId,
|
|
String layoutId, String syncOptionsJson,
|
|
List<Map<String, Object>> slotsData) {
|
|
GcChartWorkspace ws = findOrCreateWorkspace(userId, deviceId);
|
|
ws.setLayoutId(layoutId);
|
|
ws.setSyncOptionsJson(syncOptionsJson);
|
|
|
|
// 슬롯 동기화
|
|
List<GcChartSlot> existing = ws.getSlots();
|
|
for (int i = 0; i < slotsData.size(); i++) {
|
|
final int idx = i;
|
|
GcChartSlot slot = existing.stream()
|
|
.filter(s -> s.getSlotIndex() == idx)
|
|
.findFirst()
|
|
.orElseGet(() -> {
|
|
GcChartSlot ns = GcChartSlot.builder()
|
|
.workspace(ws).slotIndex(idx).build();
|
|
existing.add(ns);
|
|
return ns;
|
|
});
|
|
applySlotData(slot, slotsData.get(i));
|
|
}
|
|
// 초과 슬롯 제거
|
|
existing.removeIf(s -> s.getSlotIndex() >= slotsData.size());
|
|
|
|
return workspaceRepo.save(ws);
|
|
}
|
|
|
|
// ── private helpers ────────────────────────────────────────────────────────
|
|
|
|
private java.util.Optional<GcChartWorkspace> findWorkspace(Long userId, String deviceId) {
|
|
if (userId != null) return workspaceRepo.findByUserId(userId);
|
|
return workspaceRepo.findByDeviceId(deviceId);
|
|
}
|
|
|
|
private GcChartWorkspace findOrCreateWorkspace(Long userId, String deviceId) {
|
|
return findWorkspace(userId, deviceId)
|
|
.orElseGet(() -> workspaceRepo.save(GcChartWorkspace.builder()
|
|
.userId(userId).deviceId(deviceId).layoutId("1").build()));
|
|
}
|
|
|
|
private void applySlotData(GcChartSlot slot, Map<String, Object> d) {
|
|
if (d.containsKey("symbol")) slot.setSymbol((String) d.get("symbol"));
|
|
if (d.containsKey("timeframe")) slot.setTimeframe((String) d.get("timeframe"));
|
|
if (d.containsKey("chartType")) slot.setChartType((String) d.get("chartType"));
|
|
if (d.containsKey("theme")) slot.setTheme((String) d.get("theme"));
|
|
if (d.containsKey("mode")) slot.setMode((String) d.get("mode"));
|
|
if (d.containsKey("logScale")) slot.setLogScale(Boolean.parseBoolean(d.get("logScale").toString()));
|
|
if (d.containsKey("drawingsLocked")) slot.setDrawingsLocked(Boolean.parseBoolean(d.get("drawingsLocked").toString()));
|
|
if (d.containsKey("drawingsVisible"))slot.setDrawingsVisible(Boolean.parseBoolean(d.get("drawingsVisible").toString()));
|
|
try {
|
|
if (d.containsKey("indicators")) slot.setIndicatorsJson(objectMapper.writeValueAsString(d.get("indicators")));
|
|
if (d.containsKey("drawings")) slot.setDrawingsJson(objectMapper.writeValueAsString(d.get("drawings")));
|
|
if (d.containsKey("paneLayout")) slot.setPaneLayoutJson(objectMapper.writeValueAsString(d.get("paneLayout")));
|
|
if (d.containsKey("mainChartStyle")) slot.setMainChartStyleJson(objectMapper.writeValueAsString(d.get("mainChartStyle")));
|
|
} catch (JsonProcessingException e) {
|
|
log.error("슬롯 JSON 직렬화 실패", e);
|
|
}
|
|
}
|
|
}
|