goldenChat base source add

This commit is contained in:
aidev
2026-05-23 15:11:48 +09:00
commit a4ea7762b5
2081 changed files with 1155760 additions and 0 deletions
@@ -0,0 +1,145 @@
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);
}
}
}