diff --git a/komga/src/flyway/resources/db/migration/sqlite/V20210729173532__series_metadata_total_book_count.sql b/komga/src/flyway/resources/db/migration/sqlite/V20210729173532__series_metadata_total_book_count.sql new file mode 100644 index 000000000..237c2175f --- /dev/null +++ b/komga/src/flyway/resources/db/migration/sqlite/V20210729173532__series_metadata_total_book_count.sql @@ -0,0 +1,4 @@ +alter table series_metadata + add column TOTAL_BOOK_COUNT int NULL; +alter table series_metadata + add column TOTAL_BOOK_COUNT_LOCK boolean NOT NULL DEFAULT 0; diff --git a/komga/src/main/kotlin/org/gotson/komga/domain/model/SeriesMetadata.kt b/komga/src/main/kotlin/org/gotson/komga/domain/model/SeriesMetadata.kt index 2a7365bab..2ce3dbb13 100644 --- a/komga/src/main/kotlin/org/gotson/komga/domain/model/SeriesMetadata.kt +++ b/komga/src/main/kotlin/org/gotson/komga/domain/model/SeriesMetadata.kt @@ -13,6 +13,7 @@ class SeriesMetadata( val language: String = "", genres: Set = emptySet(), tags: Set = emptySet(), + val totalBookCount: Int? = null, val statusLock: Boolean = false, val titleLock: Boolean = false, @@ -24,6 +25,7 @@ class SeriesMetadata( val languageLock: Boolean = false, val genresLock: Boolean = false, val tagsLock: Boolean = false, + val totalBookCountLock: Boolean = false, val seriesId: String = "", @@ -48,6 +50,7 @@ class SeriesMetadata( language: String = this.language, genres: Set = this.genres, tags: Set = this.tags, + totalBookCount: Int? = this.totalBookCount, statusLock: Boolean = this.statusLock, titleLock: Boolean = this.titleLock, titleSortLock: Boolean = this.titleSortLock, @@ -58,6 +61,7 @@ class SeriesMetadata( languageLock: Boolean = this.languageLock, genresLock: Boolean = this.genresLock, tagsLock: Boolean = this.tagsLock, + totalBookCountLock: Boolean = this.totalBookCountLock, seriesId: String = this.seriesId, createdDate: LocalDateTime = this.createdDate, lastModifiedDate: LocalDateTime = this.lastModifiedDate @@ -73,6 +77,7 @@ class SeriesMetadata( language = language, genres = genres, tags = tags, + totalBookCount = totalBookCount, statusLock = statusLock, titleLock = titleLock, titleSortLock = titleSortLock, @@ -83,6 +88,7 @@ class SeriesMetadata( languageLock = languageLock, genresLock = genresLock, tagsLock = tagsLock, + totalBookCountLock = totalBookCountLock, seriesId = seriesId, createdDate = createdDate, lastModifiedDate = lastModifiedDate @@ -100,6 +106,6 @@ class SeriesMetadata( } override fun toString(): String { - return "SeriesMetadata(status=$status, readingDirection=$readingDirection, ageRating=$ageRating, language=$language, genres=$genres, statusLock=$statusLock, titleLock=$titleLock, titleSortLock=$titleSortLock, readingDirectionLock=$readingDirectionLock, publisherLock=$publisherLock, ageRatingLock=$ageRatingLock, languageLock=$languageLock, genresLock=$genresLock, seriesId='$seriesId', createdDate=$createdDate, lastModifiedDate=$lastModifiedDate, title='$title', titleSort='$titleSort', summary='$summary', publisher='$publisher')" + return "SeriesMetadata(status=$status, readingDirection=$readingDirection, ageRating=$ageRating, language='$language', totalBookCount=$totalBookCount, statusLock=$statusLock, titleLock=$titleLock, titleSortLock=$titleSortLock, summaryLock=$summaryLock, readingDirectionLock=$readingDirectionLock, publisherLock=$publisherLock, ageRatingLock=$ageRatingLock, languageLock=$languageLock, genresLock=$genresLock, tagsLock=$tagsLock, totalBookCountLock=$totalBookCountLock, seriesId='$seriesId', createdDate=$createdDate, lastModifiedDate=$lastModifiedDate, title='$title', titleSort='$titleSort', summary='$summary', publisher='$publisher', tags=$tags, genres=$genres)" } } diff --git a/komga/src/main/kotlin/org/gotson/komga/infrastructure/jooq/SeriesDtoDao.kt b/komga/src/main/kotlin/org/gotson/komga/infrastructure/jooq/SeriesDtoDao.kt index 100c7de09..866aca078 100644 --- a/komga/src/main/kotlin/org/gotson/komga/infrastructure/jooq/SeriesDtoDao.kt +++ b/komga/src/main/kotlin/org/gotson/komga/infrastructure/jooq/SeriesDtoDao.kt @@ -365,7 +365,9 @@ class SeriesDtoDao( genres = genres, genresLock = genresLock, tags = tags, - tagsLock = tagsLock + tagsLock = tagsLock, + totalBookCount = totalBookCount, + totalBookCountLock = totalBookCountLock, ) private fun BookMetadataAggregationRecord.toDto(authors: List) = diff --git a/komga/src/main/kotlin/org/gotson/komga/infrastructure/jooq/SeriesMetadataDao.kt b/komga/src/main/kotlin/org/gotson/komga/infrastructure/jooq/SeriesMetadataDao.kt index 9c1aa35a4..5d72dac9f 100644 --- a/komga/src/main/kotlin/org/gotson/komga/infrastructure/jooq/SeriesMetadataDao.kt +++ b/komga/src/main/kotlin/org/gotson/komga/infrastructure/jooq/SeriesMetadataDao.kt @@ -68,6 +68,8 @@ class SeriesMetadataDao( .set(d.LANGUAGE_LOCK, metadata.languageLock) .set(d.GENRES_LOCK, metadata.genresLock) .set(d.TAGS_LOCK, metadata.tagsLock) + .set(d.TOTAL_BOOK_COUNT, metadata.totalBookCount) + .set(d.TOTAL_BOOK_COUNT_LOCK, metadata.totalBookCountLock) .execute() insertGenres(metadata) @@ -95,6 +97,8 @@ class SeriesMetadataDao( .set(d.LANGUAGE_LOCK, metadata.languageLock) .set(d.GENRES_LOCK, metadata.genresLock) .set(d.TAGS_LOCK, metadata.tagsLock) + .set(d.TOTAL_BOOK_COUNT, metadata.totalBookCount) + .set(d.TOTAL_BOOK_COUNT_LOCK, metadata.totalBookCountLock) .set(d.LAST_MODIFIED_DATE, LocalDateTime.now(ZoneId.of("Z"))) .where(d.SERIES_ID.eq(metadata.seriesId)) .execute() @@ -167,6 +171,7 @@ class SeriesMetadataDao( language = language, genres = genres, tags = tags, + totalBookCount = totalBookCount, statusLock = statusLock, titleLock = titleLock, @@ -178,6 +183,7 @@ class SeriesMetadataDao( languageLock = languageLock, genresLock = genresLock, tagsLock = tagsLock, + totalBookCountLock = totalBookCountLock, seriesId = seriesId, diff --git a/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/SeriesController.kt b/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/SeriesController.kt index e172c2198..6c1d21592 100644 --- a/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/SeriesController.kt +++ b/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/SeriesController.kt @@ -443,7 +443,9 @@ class SeriesController( tags = if (isSet("tags")) { if (tags != null) tags!! else emptySet() } else existing.tags, - tagsLock = tagsLock ?: existing.tagsLock + tagsLock = tagsLock ?: existing.tagsLock, + totalBookCount = if (isSet("totalBookCount")) totalBookCount else existing.totalBookCount, + totalBookCountLock = totalBookCountLock ?: existing.totalBookCountLock, ) } seriesMetadataRepository.update(updated) diff --git a/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/dto/SeriesDto.kt b/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/dto/SeriesDto.kt index 86f84b58e..f63f4822a 100644 --- a/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/dto/SeriesDto.kt +++ b/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/dto/SeriesDto.kt @@ -49,6 +49,8 @@ data class SeriesMetadataDto( val genresLock: Boolean, val tags: Set, val tagsLock: Boolean, + val totalBookCount: Int?, + val totalBookCountLock: Boolean, @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") val created: LocalDateTime, diff --git a/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/dto/SeriesMetadataUpdateDto.kt b/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/dto/SeriesMetadataUpdateDto.kt index 244eb7b25..750eeff97 100644 --- a/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/dto/SeriesMetadataUpdateDto.kt +++ b/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/dto/SeriesMetadataUpdateDto.kt @@ -3,6 +3,7 @@ package org.gotson.komga.interfaces.rest.dto import org.gotson.komga.domain.model.SeriesMetadata import org.gotson.komga.infrastructure.validation.NullOrBlankOrBCP47 import org.gotson.komga.infrastructure.validation.NullOrNotBlank +import javax.validation.constraints.Positive import javax.validation.constraints.PositiveOrZero import kotlin.properties.Delegates @@ -33,7 +34,7 @@ class SeriesMetadataUpdateDto { var publisherLock: Boolean? = null var readingDirection: SeriesMetadata.ReadingDirection? - by Delegates.observable(null) { prop, _, _ -> + by Delegates.observable(null) { prop, _, _ -> isSet[prop.name] = true } @@ -41,7 +42,7 @@ class SeriesMetadataUpdateDto { @get:PositiveOrZero var ageRating: Int? - by Delegates.observable(null) { prop, _, _ -> + by Delegates.observable(null) { prop, _, _ -> isSet[prop.name] = true } @@ -53,16 +54,24 @@ class SeriesMetadataUpdateDto { var languageLock: Boolean? = null var genres: Set? - by Delegates.observable?>(null) { prop, _, _ -> + by Delegates.observable(null) { prop, _, _ -> isSet[prop.name] = true } var genresLock: Boolean? = null var tags: Set? - by Delegates.observable?>(null) { prop, _, _ -> + by Delegates.observable(null) { prop, _, _ -> isSet[prop.name] = true } var tagsLock: Boolean? = null + + @get:Positive + var totalBookCount: Int? + by Delegates.observable(null) { prop, _, _ -> + isSet[prop.name] = true + } + + var totalBookCountLock: Boolean? = null } diff --git a/komga/src/test/kotlin/org/gotson/komga/infrastructure/jooq/SeriesMetadataDaoTest.kt b/komga/src/test/kotlin/org/gotson/komga/infrastructure/jooq/SeriesMetadataDaoTest.kt index a83cf2c5c..31946709c 100644 --- a/komga/src/test/kotlin/org/gotson/komga/infrastructure/jooq/SeriesMetadataDaoTest.kt +++ b/komga/src/test/kotlin/org/gotson/komga/infrastructure/jooq/SeriesMetadataDaoTest.kt @@ -61,6 +61,7 @@ class SeriesMetadataDaoTest( genres = setOf("Action", "Adventure"), tags = setOf("tag", "another"), language = "en", + totalBookCount = 5, titleLock = true, titleSortLock = true, summaryLock = true, @@ -70,6 +71,7 @@ class SeriesMetadataDaoTest( genresLock = true, languageLock = true, tagsLock = true, + totalBookCountLock = true, seriesId = series.id ) @@ -90,6 +92,7 @@ class SeriesMetadataDaoTest( assertThat(created.language).isEqualTo(metadata.language) assertThat(created.genres).containsAll(metadata.genres) assertThat(created.tags).containsAll(metadata.tags) + assertThat(created.totalBookCount).isEqualTo(metadata.totalBookCount) assertThat(created.titleLock).isEqualTo(metadata.titleLock) assertThat(created.titleSortLock).isEqualTo(metadata.titleSortLock) @@ -101,6 +104,7 @@ class SeriesMetadataDaoTest( assertThat(created.genresLock).isEqualTo(metadata.genresLock) assertThat(created.languageLock).isEqualTo(metadata.languageLock) assertThat(created.tagsLock).isEqualTo(metadata.tagsLock) + assertThat(created.totalBookCountLock).isEqualTo(metadata.totalBookCountLock) } @Test @@ -122,25 +126,27 @@ class SeriesMetadataDaoTest( assertThat(created.title).isEqualTo(metadata.title) assertThat(created.titleSort).isEqualTo(metadata.title) - assertThat(created.summary).isBlank() + assertThat(created.summary).isBlank assertThat(created.status).isEqualTo(SeriesMetadata.Status.ONGOING) assertThat(created.readingDirection).isNull() - assertThat(created.publisher).isBlank() - assertThat(created.language).isBlank() + assertThat(created.publisher).isBlank + assertThat(created.language).isBlank assertThat(created.ageRating).isNull() assertThat(created.genres).isEmpty() assertThat(created.tags).isEmpty() + assertThat(created.totalBookCount).isNull() - assertThat(created.titleLock).isFalse() - assertThat(created.titleSortLock).isFalse() - assertThat(created.statusLock).isFalse() - assertThat(created.summaryLock).isFalse() - assertThat(created.readingDirectionLock).isFalse() - assertThat(created.publisherLock).isFalse() - assertThat(created.ageRatingLock).isFalse() - assertThat(created.genresLock).isFalse() - assertThat(created.languageLock).isFalse() - assertThat(created.tagsLock).isFalse() + assertThat(created.titleLock).isFalse + assertThat(created.titleSortLock).isFalse + assertThat(created.statusLock).isFalse + assertThat(created.summaryLock).isFalse + assertThat(created.readingDirectionLock).isFalse + assertThat(created.publisherLock).isFalse + assertThat(created.ageRatingLock).isFalse + assertThat(created.genresLock).isFalse + assertThat(created.languageLock).isFalse + assertThat(created.tagsLock).isFalse + assertThat(created.totalBookCountLock).isFalse } @Test @@ -191,6 +197,7 @@ class SeriesMetadataDaoTest( language = "en", genres = setOf("Action"), tags = setOf("tag"), + totalBookCount = 3, seriesId = series.id ) seriesMetadataDao.insert(metadata) @@ -210,6 +217,7 @@ class SeriesMetadataDaoTest( language = "jp", genres = setOf("Adventure"), tags = setOf("Another"), + totalBookCount = 8, statusLock = true, titleLock = true, titleSortLock = true, @@ -219,7 +227,8 @@ class SeriesMetadataDaoTest( ageRatingLock = true, languageLock = true, genresLock = true, - tagsLock = true + tagsLock = true, + totalBookCountLock = true, ) } @@ -241,16 +250,18 @@ class SeriesMetadataDaoTest( assertThat(modified.language).isEqualTo(updated.language) assertThat(modified.genres).containsAll(updated.genres) assertThat(modified.tags).containsAll(updated.tags) + assertThat(modified.totalBookCount).isEqualTo(updated.totalBookCount) - assertThat(modified.titleLock).isTrue() - assertThat(modified.titleSortLock).isTrue() - assertThat(modified.statusLock).isTrue() - assertThat(modified.summaryLock).isTrue() - assertThat(modified.readingDirectionLock).isTrue() - assertThat(modified.ageRatingLock).isTrue() - assertThat(modified.languageLock).isTrue() - assertThat(modified.genresLock).isTrue() - assertThat(modified.publisherLock).isTrue() - assertThat(modified.tagsLock).isTrue() + assertThat(modified.titleLock).isTrue + assertThat(modified.titleSortLock).isTrue + assertThat(modified.statusLock).isTrue + assertThat(modified.summaryLock).isTrue + assertThat(modified.readingDirectionLock).isTrue + assertThat(modified.ageRatingLock).isTrue + assertThat(modified.languageLock).isTrue + assertThat(modified.genresLock).isTrue + assertThat(modified.publisherLock).isTrue + assertThat(modified.tagsLock).isTrue + assertThat(modified.totalBookCountLock).isTrue } } diff --git a/komga/src/test/kotlin/org/gotson/komga/interfaces/rest/SeriesControllerTest.kt b/komga/src/test/kotlin/org/gotson/komga/interfaces/rest/SeriesControllerTest.kt index 26127766e..1eed01ee6 100644 --- a/komga/src/test/kotlin/org/gotson/komga/interfaces/rest/SeriesControllerTest.kt +++ b/komga/src/test/kotlin/org/gotson/komga/interfaces/rest/SeriesControllerTest.kt @@ -419,6 +419,7 @@ class SeriesControllerTest( """{"title":""}""", """{"titleSort":""}""", """{"ageRating":-1}""", + """{"totalBookCount":0}""", """{"language":"japanese"}""" ] ) @@ -463,7 +464,9 @@ class SeriesControllerTest( "genres":["Action"], "genresLock":true, "tags":["tag"], - "tagsLock":true + "tagsLock":true, + "totalBookCount":5, + "totalBookCountLock":true } """.trimIndent() @@ -486,6 +489,7 @@ class SeriesControllerTest( assertThat(ageRating).isEqualTo(12) assertThat(genres).containsExactly("action") assertThat(tags).containsExactly("tag") + assertThat(totalBookCount).isEqualTo(5) assertThat(titleLock).isEqualTo(true) assertThat(titleSortLock).isEqualTo(true) @@ -497,6 +501,7 @@ class SeriesControllerTest( assertThat(summaryLock).isEqualTo(true) assertThat(genresLock).isEqualTo(true) assertThat(tagsLock).isEqualTo(true) + assertThat(totalBookCountLock).isEqualTo(true) } } @@ -515,7 +520,8 @@ class SeriesControllerTest( ageRating = 12, readingDirection = SeriesMetadata.ReadingDirection.LEFT_TO_RIGHT, genres = setOf("Action"), - tags = setOf("tag") + tags = setOf("tag"), + totalBookCount = 5, ) seriesMetadataRepository.update(updated) @@ -533,7 +539,8 @@ class SeriesControllerTest( "readingDirection":null, "ageRating":null, "genres":null, - "tags":null + "tags":null, + "totalBookCount":null } """.trimIndent() @@ -550,6 +557,7 @@ class SeriesControllerTest( assertThat(ageRating).isNull() assertThat(genres).isEmpty() assertThat(tags).isEmpty() + assertThat(totalBookCount).isNull() } } }