diff --git a/comixed-services/src/main/java/org/comixedproject/service/scraping/ScrapingService.java b/comixed-services/src/main/java/org/comixedproject/service/scraping/ScrapingService.java index 8d8fabff6..43785a306 100644 --- a/comixed-services/src/main/java/org/comixedproject/service/scraping/ScrapingService.java +++ b/comixed-services/src/main/java/org/comixedproject/service/scraping/ScrapingService.java @@ -22,8 +22,10 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import java.util.ArrayList; -import java.util.List; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.util.*; import lombok.extern.log4j.Log4j2; import org.apache.commons.lang.StringUtils; import org.comixedproject.model.comicbooks.Comic; @@ -226,11 +228,11 @@ public Comic scrapeComic(final Long comicId, final Integer issueId, final boolea List encodedDetails = new ArrayList<>(); try { encodedDetails.add(this.objectMapper.writeValueAsString(issueDetails)); + log.debug("Caching fetched issue details"); + this.scrapingCacheService.saveToCache(source, key, encodedDetails); } catch (JsonProcessingException error) { - throw new ScrapingException("failed to encode issue details", error); + log.error("Failed to cache issue details", error); } - log.debug("Caching fetched issue details"); - this.scrapingCacheService.saveToCache(source, key, encodedDetails); } } @@ -243,8 +245,8 @@ public Comic scrapeComic(final Long comicId, final Integer issueId, final boolea comic.setSeries(issueDetails.getSeries()); comic.setVolume(issueDetails.getVolume()); comic.setIssueNumber(issueDetails.getIssueNumber()); - comic.setCoverDate(issueDetails.getCoverDate()); - comic.setStoreDate(issueDetails.getStoreDate()); + comic.setCoverDate(this.adjustForTimezone(issueDetails.getCoverDate())); + comic.setStoreDate(this.adjustForTimezone(issueDetails.getStoreDate())); comic.setTitle(issueDetails.getTitle()); comic.setDescription(issueDetails.getDescription()); comic.getCharacters().clear(); @@ -274,6 +276,12 @@ public Comic scrapeComic(final Long comicId, final Integer issueId, final boolea } } + Date adjustForTimezone(final Date date) { + final LocalDateTime localDateTime = + LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); + return new Date(localDateTime.atOffset(ZoneOffset.UTC).toInstant().toEpochMilli()); + } + private ScrapingIssueDetails doLoadIssueDetails(final String source, final String key) throws ScrapingException { final List cachedEntries = this.scrapingCacheService.getFromCache(source, key); diff --git a/comixed-services/src/test/java/org/comixedproject/service/scraping/ScrapingServiceTest.java b/comixed-services/src/test/java/org/comixedproject/service/scraping/ScrapingServiceTest.java index 7adb749d8..f62d1e010 100644 --- a/comixed-services/src/test/java/org/comixedproject/service/scraping/ScrapingServiceTest.java +++ b/comixed-services/src/test/java/org/comixedproject/service/scraping/ScrapingServiceTest.java @@ -525,6 +525,33 @@ public void testScrapeComicNothingCached() this.verifyComicScraping(loadedComic); } + @Test + public void testScrapeComicCachingError() + throws ComicException, ScrapingException, JsonProcessingException { + Mockito.when(comicService.getComic(Mockito.anyLong())).thenReturn(loadedComic, savedComic); + Mockito.when(scrapingCacheService.getFromCache(Mockito.anyString(), Mockito.anyString())) + .thenReturn(cachedEntryList); + Mockito.when(scrapingAdaptor.getIssueDetails(Mockito.anyString(), Mockito.anyInt())) + .thenReturn(scrapingIssueDetails); + Mockito.when(objectMapper.writeValueAsString(Mockito.any(ScrapingIssueDetails.class))) + .thenThrow(JsonProcessingException.class); + + final Comic result = scrapingService.scrapeComic(TEST_COMIC_ID, TEST_ISSUE_ID, false); + + assertNotNull(result); + assertSame(savedComic, result); + + Mockito.verify(comicService, Mockito.times(2)).getComic(TEST_COMIC_ID); + Mockito.verify(scrapingCacheService, Mockito.times(1)) + .getFromCache(TEST_CACHE_SOURCE, TEST_ISSUE_DETAILS_KEY); + Mockito.verify(scrapingAdaptor, Mockito.times(1)).getIssueDetails(TEST_API_KEY, TEST_ISSUE_ID); + Mockito.verify(comicStateHandler, Mockito.times(1)).fireEvent(loadedComic, ComicEvent.scraped); + Mockito.verify(scrapingCacheService, Mockito.never()) + .saveToCache(Mockito.anyString(), Mockito.anyString(), Mockito.anyList()); + + this.verifyComicScraping(loadedComic); + } + @Test public void testScrapeComicCachedDate() throws ComicException, JsonProcessingException, ScrapingException { @@ -567,8 +594,10 @@ private void verifyComicScraping(final Comic comic) { Mockito.verify(this.loadedComic, Mockito.times(1)).setPublisher(TEST_PUBLISHER); Mockito.verify(this.loadedComic, Mockito.times(1)).setSeries(TEST_SERIES_NAME); Mockito.verify(this.loadedComic, Mockito.times(1)).setVolume(TEST_VOLUME); - Mockito.verify(this.loadedComic, Mockito.times(1)).setCoverDate(TEST_COVER_DATE); - Mockito.verify(this.loadedComic, Mockito.times(1)).setStoreDate(TEST_STORE_DATE); + Mockito.verify(this.loadedComic, Mockito.times(1)) + .setCoverDate(this.scrapingService.adjustForTimezone(TEST_COVER_DATE)); + Mockito.verify(this.loadedComic, Mockito.times(1)) + .setStoreDate(this.scrapingService.adjustForTimezone(TEST_STORE_DATE)); Mockito.verify(this.loadedComic, Mockito.times(1)).setTitle(TEST_TITLE); Mockito.verify(this.loadedComic, Mockito.times(1)).setDescription(TEST_DESCRIPTION); Mockito.verify(this.imprintService, Mockito.times(1)).update(comic); diff --git a/comixed-webui/src/app/comic-books/comic-books.fixtures.ts b/comixed-webui/src/app/comic-books/comic-books.fixtures.ts index 3a18e8310..85a08eab8 100644 --- a/comixed-webui/src/app/comic-books/comic-books.fixtures.ts +++ b/comixed-webui/src/app/comic-books/comic-books.fixtures.ts @@ -88,6 +88,7 @@ export const COMIC_1: Comic = { addedDate: new Date().getTime(), deletedDate: null, coverDate: new Date().getTime(), + storeDate: new Date().getTime(), yearPublished: 2019, pageCount: 32, characters: ['character1', 'character2', 'character3'], @@ -125,6 +126,7 @@ export const COMIC_2: Comic = { addedDate: new Date().getTime(), deletedDate: null, coverDate: new Date().getTime(), + storeDate: new Date().getTime(), yearPublished: 2018, pageCount: 32, characters: ['character2', 'character3', 'character4'], @@ -162,6 +164,7 @@ export const COMIC_3: Comic = { addedDate: new Date().getTime(), deletedDate: null, coverDate: new Date().getTime(), + storeDate: new Date().getTime(), yearPublished: 1953, pageCount: 32, characters: ['character3', 'character4', 'character5'], @@ -199,6 +202,7 @@ export const COMIC_4: Comic = { addedDate: new Date().getTime(), deletedDate: null, coverDate: new Date().getTime(), + storeDate: new Date().getTime(), yearPublished: 1972, pageCount: 32, characters: [], @@ -236,6 +240,7 @@ export const COMIC_5: Comic = { addedDate: new Date().getTime(), deletedDate: null, coverDate: new Date().getTime(), + storeDate: new Date().getTime(), yearPublished: 2000, pageCount: 32, characters: [], diff --git a/comixed-webui/src/app/comic-books/components/comic-overview/comic-overview.component.html b/comixed-webui/src/app/comic-books/components/comic-overview/comic-overview.component.html index 0b15f34b2..a9f8d7962 100644 --- a/comixed-webui/src/app/comic-books/components/comic-overview/comic-overview.component.html +++ b/comixed-webui/src/app/comic-books/components/comic-overview/comic-overview.component.html @@ -74,7 +74,20 @@ - {{ comic.coverDate | date: "MM/yyyy" }} + {{ comic.coverDate | date: "MMMM yyyy" }} + + + + + + {{ "comic-book.label.store-date" | translate }} + + + + + {{ comic.storeDate | date: "longDate" }} diff --git a/comixed-webui/src/app/comic-books/models/comic.ts b/comixed-webui/src/app/comic-books/models/comic.ts index b09b2ba46..e82e7ca44 100644 --- a/comixed-webui/src/app/comic-books/models/comic.ts +++ b/comixed-webui/src/app/comic-books/models/comic.ts @@ -38,6 +38,7 @@ export interface Comic { volume: string; issueNumber: string; coverDate: number; + storeDate: number; yearPublished: number; title: string; sortableIssueNumber: string; diff --git a/comixed-webui/src/assets/i18n/de/comic-books.json b/comixed-webui/src/assets/i18n/de/comic-books.json index aaf9400c8..98a56c618 100644 --- a/comixed-webui/src/assets/i18n/de/comic-books.json +++ b/comixed-webui/src/assets/i18n/de/comic-books.json @@ -52,6 +52,7 @@ "show-next-comic-page": "Go to next page...", "show-previous-comic-page": "Go to previous page...", "sort-name": "Sort Name", + "store-date": "Store Date", "stories": "Story Arcs In This Issue ({count})", "teams": "Teams In This Issue ({count})", "title": "Title", diff --git a/comixed-webui/src/assets/i18n/en/comic-books.json b/comixed-webui/src/assets/i18n/en/comic-books.json index b8fdf6127..6b9a2cf14 100644 --- a/comixed-webui/src/assets/i18n/en/comic-books.json +++ b/comixed-webui/src/assets/i18n/en/comic-books.json @@ -50,6 +50,7 @@ "scraping-notes": "Scraping Notes", "series": "Series Name", "sort-name": "Sort Name", + "store-date": "Store Date", "stories": "Story Arcs In This Issue ({count})", "teams": "Teams In This Issue ({count})", "title": "Title", diff --git a/comixed-webui/src/assets/i18n/es/comic-books.json b/comixed-webui/src/assets/i18n/es/comic-books.json index b1d0839fe..8125c1192 100644 --- a/comixed-webui/src/assets/i18n/es/comic-books.json +++ b/comixed-webui/src/assets/i18n/es/comic-books.json @@ -50,6 +50,7 @@ "scraping-notes": "Notas de raspado", "series": "Nombre de la serie", "sort-name": "Nombre de ordenación", + "store-date": "Store Date", "stories": "Arcos argumentales en esta edición ({count})", "teams": "Equipos en esta edición ({count})", "title": "Title", diff --git a/comixed-webui/src/assets/i18n/fr/comic-books.json b/comixed-webui/src/assets/i18n/fr/comic-books.json index 47276a7fa..196ab8206 100644 --- a/comixed-webui/src/assets/i18n/fr/comic-books.json +++ b/comixed-webui/src/assets/i18n/fr/comic-books.json @@ -50,6 +50,7 @@ "scraping-notes": "Notes de récupération", "series": "Nom de série", "sort-name": "Nom pour le tri", + "store-date": "Store Date", "stories": "Arcs naratifs dans ce numéro ({count})", "teams": "Équipes dans ce numéro ({count})", "title": "Titre", diff --git a/comixed-webui/src/assets/i18n/pt/comic-books.json b/comixed-webui/src/assets/i18n/pt/comic-books.json index b8fdf6127..6b9a2cf14 100644 --- a/comixed-webui/src/assets/i18n/pt/comic-books.json +++ b/comixed-webui/src/assets/i18n/pt/comic-books.json @@ -50,6 +50,7 @@ "scraping-notes": "Scraping Notes", "series": "Series Name", "sort-name": "Sort Name", + "store-date": "Store Date", "stories": "Story Arcs In This Issue ({count})", "teams": "Teams In This Issue ({count})", "title": "Title",