Browse Source

add create snapshots

Daniel Bohry 8 months ago
parent
commit
feee7271b3

+ 3 - 1
src/main/java/com/danielbohry/stocks/App.java

@@ -3,9 +3,11 @@ package com.danielbohry.stocks;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.scheduling.annotation.EnableScheduling;
 
-@SpringBootApplication
+@EnableScheduling
 @EnableFeignClients
+@SpringBootApplication
 public class App {
 
     public static void main(String[] args) {

+ 0 - 7
src/main/java/com/danielbohry/stocks/api/portfolio/PortfolioController.java

@@ -27,13 +27,6 @@ public class PortfolioController {
         return ResponseEntity.ok(response);
     }
 
-    @GetMapping("{id}")
-    public ResponseEntity<Portfolio> get(@PathVariable String id,
-                                         @RequestParam(required = false, defaultValue = "usd") String currency) {
-        Portfolio response = service.get(id, currency.toUpperCase());
-        return ResponseEntity.ok(response);
-    }
-
     @PostMapping
     public ResponseEntity<Portfolio> create() {
         Portfolio response = service.create();

+ 19 - 0
src/main/java/com/danielbohry/stocks/domain/Snapshot.java

@@ -0,0 +1,19 @@
+package com.danielbohry.stocks.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+import java.time.Instant;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Document("snapshots")
+public class Snapshot {
+
+    private Portfolio portfolio;
+    private Instant createdAt;
+
+}

+ 6 - 0
src/main/java/com/danielbohry/stocks/repository/PortfolioRepository.java

@@ -1,6 +1,7 @@
 package com.danielbohry.stocks.repository;
 
 import com.danielbohry.stocks.domain.Portfolio;
+import org.springframework.data.mongodb.repository.Aggregation;
 import org.springframework.data.mongodb.repository.MongoRepository;
 import org.springframework.data.mongodb.repository.Query;
 import org.springframework.stereotype.Repository;
@@ -15,4 +16,9 @@ public interface PortfolioRepository extends MongoRepository<Portfolio, String>
 
     List<Portfolio> findAllByUsername(String username);
 
+    @Aggregation(pipeline = {
+        "{ '$project': { '_id': 1 } }"
+    })
+    List<String> findAllPortfolioIds();
+
 }

+ 9 - 0
src/main/java/com/danielbohry/stocks/repository/SnapshotRepository.java

@@ -0,0 +1,9 @@
+package com.danielbohry.stocks.repository;
+
+import com.danielbohry.stocks.domain.Snapshot;
+import org.springframework.data.mongodb.repository.MongoRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface SnapshotRepository extends MongoRepository<Snapshot, String> {
+}

+ 8 - 8
src/main/java/com/danielbohry/stocks/service/PortfolioService.java

@@ -6,7 +6,6 @@ import com.danielbohry.stocks.domain.Quote;
 import com.danielbohry.stocks.domain.Stock;
 import com.danielbohry.stocks.exception.BadRequestException;
 import com.danielbohry.stocks.exception.NotFoundException;
-import com.danielbohry.stocks.exception.UnauthorizedException;
 import com.danielbohry.stocks.repository.PortfolioRepository;
 import com.danielbohry.stocks.service.ExchangeService.ExchangeRateResponse;
 import lombok.AllArgsConstructor;
@@ -15,10 +14,11 @@ import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
-import java.util.*;
-import java.util.stream.Collectors;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
 
-import static java.math.RoundingMode.HALF_UP;
 import static java.time.LocalDateTime.now;
 import static java.util.Collections.emptyList;
 
@@ -35,6 +35,10 @@ public class PortfolioService {
         return repository.findAll();
     }
 
+    public List<String> getAllIds() {
+        return repository.findAllPortfolioIds();
+    }
+
     public List<Portfolio> getByUser(String username, String currency) {
         List<Portfolio> portfolios = repository.findAllByUsername(username);
 
@@ -47,10 +51,6 @@ public class PortfolioService {
         Portfolio portfolio = repository.findById(id)
             .orElseThrow(() -> new NotFoundException("No portfolio found with id: " + id));
 
-        if (portfolio.getUsername() != null && !Objects.equals(portfolio.getUsername(), UserContextHolder.get().getUsername())) {
-            throw new UnauthorizedException("You do not have permission to access this portfolio");
-        }
-
         ExchangeRateResponse exchangeRate = exchangeService.getCurrentRate(currency);
         Map<String, BigDecimal> rates = exchangeRate.getConversionRates();
         BigDecimal targetRate = rates.getOrDefault(currency, BigDecimal.ONE);

+ 46 - 0
src/main/java/com/danielbohry/stocks/service/SnapshotService.java

@@ -0,0 +1,46 @@
+package com.danielbohry.stocks.service;
+
+import com.danielbohry.stocks.domain.Portfolio;
+import com.danielbohry.stocks.domain.Snapshot;
+import com.danielbohry.stocks.repository.SnapshotRepository;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+import static java.time.Instant.now;
+
+@Slf4j
+@Service
+@AllArgsConstructor
+public class SnapshotService {
+
+    private final PortfolioService service;
+    private final SnapshotRepository repository;
+
+    public static final String ONCE_PER_MONTH = "0 0 0 1 * *";
+    public static final String DEFAULT_CURRENCY = "USD";
+
+    @Scheduled(cron = ONCE_PER_MONTH)
+    public void createSnapshots() {
+        List<Portfolio> portfolios = service.getAllIds().stream()
+            .map(portfolioId -> service.get(portfolioId, DEFAULT_CURRENCY))
+            .toList();
+
+        saveSnapshots(portfolios);
+    }
+
+    public void saveSnapshots(List<Portfolio> portfolios) {
+        if (portfolios.isEmpty()) return;
+
+        List<Snapshot> snapshots = portfolios.stream()
+            .filter(portfolio -> !portfolio.getStocks().isEmpty())
+            .map(portfolio -> new Snapshot(portfolio, now()))
+            .toList();
+
+        repository.saveAll(snapshots);
+    }
+
+}