StockController.java 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package com.danielbohry.stocks.api.stock;
  2. import com.danielbohry.stocks.context.UserContextHolder;
  3. import com.danielbohry.stocks.domain.Quote;
  4. import com.danielbohry.stocks.domain.StockInfo;
  5. import com.danielbohry.stocks.service.StockInfoService;
  6. import com.danielbohry.stocks.service.StockService;
  7. import io.swagger.v3.oas.annotations.Hidden;
  8. import lombok.AllArgsConstructor;
  9. import lombok.extern.slf4j.Slf4j;
  10. import org.springframework.http.ResponseEntity;
  11. import org.springframework.web.bind.annotation.*;
  12. import org.springframework.web.multipart.MultipartFile;
  13. import java.io.BufferedReader;
  14. import java.io.InputStreamReader;
  15. import java.math.BigDecimal;
  16. import java.util.List;
  17. import java.util.Objects;
  18. import static java.nio.charset.StandardCharsets.UTF_8;
  19. import static java.time.LocalDateTime.now;
  20. @Slf4j
  21. @RestController
  22. @RequestMapping("api/stocks")
  23. @AllArgsConstructor
  24. @CrossOrigin
  25. public class StockController {
  26. private final StockService service;
  27. private final StockInfoService infoService;
  28. @GetMapping
  29. public ResponseEntity<List<Quote>> find(@RequestParam(value = "q", required = false) String query) {
  30. List<Quote> response = (query == null || query.isBlank())
  31. ? service.getAll()
  32. : service.get(query);
  33. return ResponseEntity.ok(response);
  34. }
  35. @GetMapping("{code}")
  36. public ResponseEntity<Quote> getByCode(@PathVariable String code) {
  37. Quote response = service.getByCode(code.toUpperCase());
  38. return ResponseEntity.ok(response);
  39. }
  40. @GetMapping("{code}/info")
  41. public ResponseEntity<StockInfo> getStockInfo(@PathVariable String code) {
  42. StockInfo response = infoService.get(code);
  43. return ResponseEntity.ok(response);
  44. }
  45. @Hidden
  46. @PostMapping("/upload-csv")
  47. public ResponseEntity<StockUploadCSVResponse> uploadCsvFile(@RequestParam("file") MultipartFile file, @RequestParam("currency") String currency) {
  48. if (file.isEmpty()) {
  49. return ResponseEntity.badRequest().build();
  50. }
  51. try (BufferedReader reader = new BufferedReader(new InputStreamReader(file.getInputStream(), UTF_8))) {
  52. List<Quote> quotes = reader.lines()
  53. .map(r -> convert(r, currency))
  54. .filter(Objects::nonNull)
  55. .toList();
  56. List<Quote> response = service.update(quotes);
  57. return ResponseEntity.ok(new StockUploadCSVResponse(response.size() + " entries updated."));
  58. } catch (Exception e) {
  59. log.error("Failed to import csv", e);
  60. return ResponseEntity.status(400).build();
  61. }
  62. }
  63. @Hidden
  64. @PostMapping("/generate")
  65. public ResponseEntity<Void> generateStockInfo() {
  66. if (UserContextHolder.isAdmin()) {
  67. infoService.generate();
  68. }
  69. return ResponseEntity.ok().build();
  70. }
  71. private Quote convert(String input, String currency) {
  72. String[] value = input.split(",");
  73. log.info("Importing [{}]", (Object) value);
  74. if (value[3] != null && !value[3].equals("#N/A")) {
  75. BigDecimal price = new BigDecimal(value[3]);
  76. return price.compareTo(BigDecimal.ZERO) > 0
  77. ? new Quote(value[0], value[1], currency, price, now())
  78. : null;
  79. } else if (value[0] != null && Objects.equals(value[3], "#N/A")) {
  80. return null;
  81. } else {
  82. return null;
  83. }
  84. }
  85. }