Browse Source

Add concept of currency to the Quote object

Daniel Bohry 1 year ago
parent
commit
7a81f45f13

+ 6 - 6
src/main/java/com/danielbohry/stocks/controller/stock/StockController.java

@@ -12,11 +12,11 @@ import org.springframework.web.multipart.MultipartFile;
 import java.io.BufferedReader;
 import java.io.InputStreamReader;
 import java.math.BigDecimal;
-import java.nio.charset.StandardCharsets;
 import java.util.List;
 import java.util.Objects;
 import java.util.regex.Pattern;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.time.LocalDateTime.now;
 import static java.util.Collections.emptyList;
 
@@ -51,14 +51,14 @@ public class StockController {
 
     @Hidden
     @PostMapping("/upload-csv")
-    public ResponseEntity<StockUploadCSVResponse> uploadCsvFile(@RequestParam("file") MultipartFile file) {
+    public ResponseEntity<StockUploadCSVResponse> uploadCsvFile(@RequestParam("file") MultipartFile file, @RequestParam("currency") String currency) {
         if (file.isEmpty()) {
             return ResponseEntity.badRequest().build();
         }
 
-        try (BufferedReader reader = new BufferedReader(new InputStreamReader(file.getInputStream(), StandardCharsets.UTF_8))) {
+        try (BufferedReader reader = new BufferedReader(new InputStreamReader(file.getInputStream(), UTF_8))) {
             List<Quote> quotes = reader.lines()
-                    .map(this::convert)
+                    .map(r -> convert(r, currency))
                     .filter(Objects::nonNull)
                     .toList();
 
@@ -71,7 +71,7 @@ public class StockController {
         }
     }
 
-    private Quote convert(String input) {
+    private Quote convert(String input, String currency) {
         String[] value = input.split(",");
 
         log.info("Importing [{}]", (Object) value);
@@ -79,7 +79,7 @@ public class StockController {
         if (value[3] != null && !value[3].equals("#N/A")) {
             BigDecimal price = new BigDecimal(value[3]);
             return price.compareTo(BigDecimal.ZERO) > 0
-                    ? new Quote(value[0], value[1], price, now())
+                    ? new Quote(value[0], value[1], currency, price, now())
                     : null;
         } else if (value[0] != null && Objects.equals(value[3], "#N/A")) {
             return null;

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

@@ -17,12 +17,14 @@ public class Quote {
     private String id;
     private String code;
     private String name;
+    private String currency;
     private BigDecimal price;
     private LocalDateTime updatedAt;
 
-    public Quote(String code, String name, BigDecimal price, LocalDateTime updatedAt) {
+    public Quote(String code, String name, String currency, BigDecimal price, LocalDateTime updatedAt) {
         this.code = code;
         this.name = name;
+        this.currency = currency;
         this.price = price;
         this.updatedAt = updatedAt;
     }

+ 2 - 0
src/main/java/com/danielbohry/stocks/repository/QuoteRepository.java

@@ -16,4 +16,6 @@ public interface QuoteRepository extends MongoRepository<Quote, String> {
 
     Optional<Quote> findByCode(String code);
 
+    List<Quote> findByCodeIn(List<String> codes);
+
 }

+ 31 - 10
src/main/java/com/danielbohry/stocks/repository/StockRepository.java

@@ -13,13 +13,13 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Repository;
 
 import java.math.BigDecimal;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
+import java.time.Instant;
+import java.util.*;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 import static java.time.LocalDateTime.now;
+import static java.util.stream.Collectors.toList;
 
 @Slf4j
 @Repository
@@ -48,11 +48,32 @@ public class StockRepository {
         return quote.orElseGet(() -> repository.save(getStockQuote(code)));
     }
 
-    public List<Quote> update(List<Quote> quote) {
-        return repository.saveAll(quote.stream().peek(i -> {
-            Quote current = repository.findByCode(i.getCode()).orElse(i);
-            i.setId(current.getId());
-        }).toList());
+    public List<Quote> update(List<Quote> quotes) {
+        log.info("Updating [{}] quotes [{}]", quotes.size(), Instant.now());
+        List<String> codes = quotes.stream()
+                .map(Quote::getCode)
+                .collect(toList());
+        Map<String, Quote> existingQuotesMap = repository.findByCodeIn(codes)
+                .stream()
+                .collect(Collectors.toMap(Quote::getCode, Function.identity()));
+
+        log.info("Found [{}] quotes by codes [{}]", existingQuotesMap.size(), Instant.now());
+
+        List<Quote> updatedQuotes = quotes.stream()
+                .map(quote -> {
+                    Quote existingQuote = existingQuotesMap.get(quote.getCode());
+                    if (existingQuote != null) {
+                        quote.setId(existingQuote.getId());
+                    }
+                    return quote;
+                })
+                .collect(toList());
+
+        log.info("Updating [{}] quotes [{}]", updatedQuotes.size(), Instant.now());
+        List<Quote> result = repository.saveAll(updatedQuotes);
+        log.info("Update complete for [{}] quotes [{}]", quotes.size(), Instant.now());
+
+        return result;
     }
 
     public boolean isValid(String code) {
@@ -70,7 +91,7 @@ public class StockRepository {
     }
 
     public Quote getStockQuote(String code) {
-        Quote quote = repository.findByCode(code).stream().findFirst().orElse(new Quote(code, null, null, now()));
+        Quote quote = repository.findByCode(code).stream().findFirst().orElse(new Quote(code, null, null, null, now()));
         quote.setPrice(getLastPrice(quote));
 
         if (quote.getName() == null || quote.getPrice() == null) {

+ 1 - 1
src/test/java/service/StockServiceTest.java

@@ -34,7 +34,7 @@ public class StockServiceTest {
     public void shouldGetStockByCode() {
         //given
         String code = "AAPL";
-        Quote expected = new Quote(code, "Apple Inc.", null, null);
+        Quote expected = new Quote(code, "Apple Inc.", "USD", null, null);
 
         //when
         Quote result = service.getByCode(code);