알림삭제 기능 추가

This commit is contained in:
Macbook
2026-05-27 17:39:33 +09:00
parent 701a9b2881
commit 9cee6387c3
7 changed files with 344 additions and 4 deletions
@@ -12,8 +12,11 @@ import java.util.List;
* 매매 시그널 이력 REST API.
*
* <pre>
* GET /api/trade-signals → 전체 이력
* GET /api/trade-signals?market= → 종목별 이력
* GET /api/trade-signals → 전체 이력
* GET /api/trade-signals?market= → 종목별 이력
* DELETE /api/trade-signals/{id} → 단건 삭제
* DELETE /api/trade-signals → 전체 삭제
* POST /api/trade-signals/delete-batch → ID 목록 삭제
* </pre>
*/
@RestController
@@ -36,6 +39,32 @@ public class TradeSignalController {
return ResponseEntity.ok(result);
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteOne(
@PathVariable Long id,
@RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
@RequestHeader(value = "X-Device-Id", required = false) String deviceId) {
service.deleteOne(id, parseUserId(userIdHeader), deviceId);
return ResponseEntity.noContent().build();
}
@DeleteMapping
public ResponseEntity<java.util.Map<String, Integer>> deleteAll(
@RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
@RequestHeader(value = "X-Device-Id", required = false) String deviceId) {
int deleted = service.deleteAll(parseUserId(userIdHeader), deviceId);
return ResponseEntity.ok(java.util.Map.of("deleted", deleted));
}
@PostMapping("/delete-batch")
public ResponseEntity<java.util.Map<String, Integer>> deleteBatch(
@RequestBody java.util.List<Long> ids,
@RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
@RequestHeader(value = "X-Device-Id", required = false) String deviceId) {
int deleted = service.deleteBatch(ids, parseUserId(userIdHeader), deviceId);
return ResponseEntity.ok(java.util.Map.of("deleted", deleted));
}
private Long parseUserId(String h) {
if (h == null || h.isBlank()) return null;
try { return Long.parseLong(h); } catch (NumberFormatException e) { return null; }
@@ -2,6 +2,9 @@ package com.goldenchart.repository;
import com.goldenchart.entity.GcTradeSignal;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
@@ -10,4 +13,13 @@ public interface GcTradeSignalRepository extends JpaRepository<GcTradeSignal, Lo
List<GcTradeSignal> findByDeviceIdOrderByCreatedAtDesc(String deviceId);
List<GcTradeSignal> findByUserIdOrderByCreatedAtDesc(Long userId);
List<GcTradeSignal> findByDeviceIdAndMarketOrderByCreatedAtDesc(String deviceId, String market);
@Modifying
@Query("DELETE FROM GcTradeSignal e WHERE e.userId = :userId")
void deleteByUserId(@Param("userId") Long userId);
@Modifying
@Query("DELETE FROM GcTradeSignal e WHERE e.deviceId = :deviceId AND (e.userId IS NULL OR e.userId = 0)")
void deleteByDeviceId(@Param("deviceId") String deviceId);
}
@@ -69,6 +69,52 @@ public class TradeSignalService {
.stream().map(this::toDto).toList();
}
// ── 삭제 ─────────────────────────────────────────────────────────────────
public void deleteOne(Long id, Long userId, String deviceId) {
if (id == null) return;
repo.findById(id).ifPresent(entity -> {
if (!owns(entity, userId, deviceId)) return;
repo.delete(entity);
log.info("[TradeSignal] deleted id={} market={}", id, entity.getMarket());
});
}
public int deleteBatch(List<Long> ids, Long userId, String deviceId) {
if (ids == null || ids.isEmpty()) return 0;
List<GcTradeSignal> toDelete = ids.stream()
.distinct()
.map(repo::findById)
.filter(java.util.Optional::isPresent)
.map(java.util.Optional::get)
.filter(e -> owns(e, userId, deviceId))
.toList();
if (toDelete.isEmpty()) return 0;
repo.deleteAll(toDelete);
log.info("[TradeSignal] batch deleted count={}", toDelete.size());
return toDelete.size();
}
public int deleteAll(Long userId, String deviceId) {
if (userId != null) {
long count = repo.findByUserIdOrderByCreatedAtDesc(userId).size();
repo.deleteByUserId(userId);
log.info("[TradeSignal] deleted all for userId={} count≈{}", userId, count);
return (int) count;
}
String dev = deviceId != null ? deviceId : "";
long count = repo.findByDeviceIdOrderByCreatedAtDesc(dev).size();
repo.deleteByDeviceId(dev);
log.info("[TradeSignal] deleted all for deviceId={} count≈{}", dev, count);
return (int) count;
}
private static boolean owns(GcTradeSignal entity, Long userId, String deviceId) {
if (userId != null && userId.equals(entity.getUserId())) return true;
if (deviceId == null || deviceId.isBlank()) return false;
return deviceId.equals(entity.getDeviceId());
}
// ── 변환 ─────────────────────────────────────────────────────────────────
private TradeSignalDto toDto(GcTradeSignal e) {