Skip to content

Commit

Permalink
RetentionPeriod support
Browse files Browse the repository at this point in the history
  • Loading branch information
frogggias committed May 3, 2021
1 parent ae1186f commit b1e51a5
Show file tree
Hide file tree
Showing 7 changed files with 217 additions and 3 deletions.
3 changes: 3 additions & 0 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 18 additions & 2 deletions .idea/markdown-navigator.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ plugins {

val kotlinVersion: String by extra("1.4.21")
val projectGroup: String by extra("com.dotypos.lib.migration")
val projectVersion: String by extra("0.5.4")
val projectVersion: String by extra("0.5.5")

allprojects {
repositories {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
@file:UseSerializers(
BigDecimalSerializer::class,
DateSerializer::class,
RetentionPeriodSerializer::class,
)

package com.dotypos.lib.migration.dto.config

import com.dotypos.lib.migration.dto.config.PosConfigurationDto.DocumentNumberingConfiguration.Companion.NUMBERING_FORMAT_REGEX
import com.dotypos.lib.migration.dto.entity.iface.WithCountry
import com.dotypos.lib.migration.dto.entity.iface.WithName
import com.dotypos.lib.migration.dto.enumerate.PaymentMethod
import com.dotypos.lib.migration.serialization.BigDecimalSerializer
import com.dotypos.lib.migration.serialization.DateSerializer
import com.dotypos.lib.migration.serialization.RetentionPeriodSerializer
import com.dotypos.validator.validation.matches
import com.dotypos.validator.validation.matchesOrNull
import com.dotypos.validator.validationOf
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers

@Serializable
data class PosConfigurationDto(
Expand Down Expand Up @@ -144,6 +154,9 @@ data class PosConfigurationDto(
*/
@SerialName("defaultWarehouseId")
val defaultWarehouseId: Long,

@SerialName("retentionPeriod")
val retentionPeriod: RetentionPeriod = RetentionPeriod.DEFAULT_RETENTION_PERIOD,
) : WithName, WithCountry {

@Serializable
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.dotypos.lib.migration.dto.config

data class RetentionPeriod(
val value: Long,
val unit: RetentionPeriod.RetentionUnit,
) {

override fun toString() = "$value${unit.abbreviation}"

enum class RetentionUnit(val abbreviation: String) {
DAY(abbreviation = "d"),
WEEK(abbreviation = "w"),
MONTH(abbreviation = "m"),
QUARTER(abbreviation = "q");
}

companion object {
val DEFAULT_RETENTION_PERIOD = RetentionPeriod(value = 2, unit = RetentionUnit.WEEK)

fun parse(value: String): RetentionPeriod {
return kotlin.runCatching {
val periodUnit = RetentionUnit.values().first { value.endsWith(it.abbreviation) }
RetentionPeriod(
value = value.substringBefore(periodUnit.abbreviation).toLong(),
unit = periodUnit,
)
}.getOrNull() ?: DEFAULT_RETENTION_PERIOD
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.dotypos.lib.migration.serialization

import com.dotypos.lib.migration.dto.config.RetentionPeriod
import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder

object RetentionPeriodSerializer : KSerializer<RetentionPeriod> {

override val descriptor = PrimitiveSerialDescriptor("RetentionPeriod", PrimitiveKind.STRING)

override fun deserialize(decoder: Decoder): RetentionPeriod {
return decoder.decodeString().let(RetentionPeriod.Companion::parse)
?: RetentionPeriod.DEFAULT_RETENTION_PERIOD
}

override fun serialize(encoder: Encoder, value: RetentionPeriod) {
encoder.encodeString(value.toString())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
@file:UseSerializers(RetentionPeriodSerializer::class)

package serialization

import com.dotypos.lib.migration.dto.config.RetentionPeriod
import com.dotypos.lib.migration.serialization.RetentionPeriodSerializer
import kotlinx.serialization.*
import kotlinx.serialization.json.Json
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import kotlin.test.assertEquals

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class RetentionPeriodSerializationDeserializationTest {

@Nested
inner class Serialization {

@Test
fun `Valid serialization of 2 weeks retention`() {
val period = RetentionPeriod(value = 2, unit = RetentionPeriod.RetentionUnit.WEEK)
val string = period.toString()
assertEquals("2w", string)
}

@Test
fun `Valid serialization of 3 month retention`() {
val period = RetentionPeriod(value = 3, unit = RetentionPeriod.RetentionUnit.MONTH)
val string = period.toString()
assertEquals("3m", string)
}
}

@Nested
inner class Deserialization {

@Test
fun `Valid deserialization of 3 weeks retention`() {
val string = "3w"
val period = RetentionPeriod.parse(string)
assertEquals(3L, period.value)
assertEquals(RetentionPeriod.RetentionUnit.WEEK, period.unit)
}

@Test
fun `Fallback deserialization of invalid input`() {
val string = "asdf"
val period = RetentionPeriod.parse(string)
assertEquals(RetentionPeriod.DEFAULT_RETENTION_PERIOD.value, period.value)
assertEquals(RetentionPeriod.DEFAULT_RETENTION_PERIOD.unit, period.unit)
}

@Test
fun `Fallback deserialization of invalid input 2`() {
val string = "8ew"
val period = RetentionPeriod.parse(string)
assertEquals(RetentionPeriod.DEFAULT_RETENTION_PERIOD.value, period.value)
assertEquals(RetentionPeriod.DEFAULT_RETENTION_PERIOD.unit, period.unit)
}
}

@Nested
inner class Serializer {

private val json = Json

@Test
fun `Valid serialization 4 months`() {
val retention = RetentionPeriod(value = 4, unit = RetentionPeriod.RetentionUnit.WEEK)
val string = json.encodeToString(RetentionWrapper(retention))
assertEquals(
expected = """
{"value":"4w"}
""".trimIndent(),
actual = string
)
}

@Test
fun `Valid serialization 1 quarter`() {
val retention = RetentionPeriod(value = 1, unit = RetentionPeriod.RetentionUnit.QUARTER)
val string = json.encodeToString(RetentionWrapper(retention))
assertEquals(
expected = """
{"value":"1q"}
""".trimIndent(),
actual = string
)
}

@Test
fun `Valid deserialization 4 weeks`() {
val string = """{"value":"4w"}""".trimIndent()
val wrapper = json.decodeFromString<RetentionWrapper>(string)
assertEquals(4L, wrapper.value.value)
assertEquals(RetentionPeriod.RetentionUnit.WEEK, wrapper.value.unit)
}

@Test
fun `Fallback deserialization of invalid value`() {
val string = """{"value":"4ew"}""".trimIndent()
val wrapper = json.decodeFromString<RetentionWrapper>(string)
assertEquals(RetentionPeriod.DEFAULT_RETENTION_PERIOD.value, wrapper.value.value)
assertEquals(RetentionPeriod.DEFAULT_RETENTION_PERIOD.unit, wrapper.value.unit)
assertEquals(RetentionPeriod.DEFAULT_RETENTION_PERIOD, wrapper.value)
}

@Test
fun `Fallback deserialization of missing value`() {
val string = """{}""".trimIndent()
val wrapper = json.decodeFromString<RetentionWrapperWithDefaultValue>(string)
assertEquals(RetentionPeriod.DEFAULT_RETENTION_PERIOD.value, wrapper.value.value)
assertEquals(RetentionPeriod.DEFAULT_RETENTION_PERIOD.unit, wrapper.value.unit)
assertEquals(RetentionPeriod.DEFAULT_RETENTION_PERIOD, wrapper.value)
}
}

@Serializable
private data class RetentionWrapper(
@SerialName(value = "value")
val value: RetentionPeriod,
)

@Serializable
private data class RetentionWrapperWithDefaultValue(
@SerialName(value = "value")
val value: RetentionPeriod = RetentionPeriod.DEFAULT_RETENTION_PERIOD,
)
}

0 comments on commit b1e51a5

Please sign in to comment.