알림삭제 기능 추가
This commit is contained in:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user