diff --git a/finance-backend/src/main/kotlin/dev/zrdzn/finance/backend/transaction/application/TransactionService.kt b/finance-backend/src/main/kotlin/dev/zrdzn/finance/backend/transaction/application/TransactionService.kt index 2b89071..779ed95 100644 --- a/finance-backend/src/main/kotlin/dev/zrdzn/finance/backend/transaction/application/TransactionService.kt +++ b/finance-backend/src/main/kotlin/dev/zrdzn/finance/backend/transaction/application/TransactionService.kt @@ -53,6 +53,7 @@ import java.time.Instant import java.time.LocalDate import java.time.Month import java.time.format.DateTimeFormatter +import java.time.format.TextStyle import java.time.temporal.ChronoUnit import java.util.Locale import org.apache.commons.codec.binary.Base64 @@ -610,33 +611,38 @@ class TransactionService( val results = transactionRepository.getMonthlyTransactionSums(vaultId) val today = LocalDate.now(clock) - val currentYear = today.year - val currentMonth = today.monthValue - val categories = Array(12) { index -> - val month = (currentMonth - index - 1).mod(12) + 1 - val year = currentYear - if (month > currentMonth) 1 else 0 - "${Month.of(month).name.substring(0, 3)} ${year}'" + val monthsData = mutableMapOf>() + + val categories = mutableListOf() + for (monthIndex in 11 downTo 0) { + val monthDate = today.minusMonths(monthIndex.toLong()) + val monthDisplayName = "${monthDate.month.getDisplayName(TextStyle.SHORT, Locale.ENGLISH)} ${monthDate.year}" + + categories.add(monthDisplayName) + monthsData[monthDisplayName] = Triple(BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO) } - val incomingData = Array(12) { BigDecimal.ZERO } - val outgoingData = Array(12) { BigDecimal.ZERO } - val differenceData = Array(12) { BigDecimal.ZERO } - - results.forEach { row -> - val month = row[0] as Int - val incoming = row[1] as BigDecimal - val outgoing = row[2] as BigDecimal - - categories[month - 1] = Month.of(month).name - incomingData[month - 1] = incoming - outgoingData[month - 1] = outgoing - differenceData[month - 1] = incoming.minus(outgoing) + + results.forEach { + val month = it[0] as Int + val year = it[1] as Int + val incoming = it[2] as BigDecimal + val outgoing = it[3] as BigDecimal + + val key = "${Month.of(month).getDisplayName(TextStyle.SHORT, Locale.ENGLISH)} $year" + if (key in monthsData) { + monthsData[key] = Triple(incoming, outgoing, incoming.minus(outgoing)) + } } - when (transactionType) { - TransactionType.INCOMING -> return FlowsChartResponse(categories.reversed(), listOf(FlowsChartSeries("Income", incomingData.reversed()))) - TransactionType.OUTGOING -> return FlowsChartResponse(categories.reversed(), listOf(FlowsChartSeries("Spent", outgoingData.reversed()))) - else -> return FlowsChartResponse(categories.reversed(), listOf(FlowsChartSeries("Balance", differenceData.reversed()))) + val incomingData = categories.map { monthsData[it]?.first ?: BigDecimal.ZERO } + val outgoingData = categories.map { monthsData[it]?.second ?: BigDecimal.ZERO } + val differenceData = categories.map { monthsData[it]?.third ?: BigDecimal.ZERO } + + return when (transactionType) { + TransactionType.INCOMING -> FlowsChartResponse(categories, listOf(FlowsChartSeries("Income", incomingData))) + TransactionType.OUTGOING -> FlowsChartResponse(categories, listOf(FlowsChartSeries("Spent", outgoingData))) + else -> FlowsChartResponse(categories, listOf(FlowsChartSeries("Balance", differenceData))) } } diff --git a/finance-backend/src/main/kotlin/dev/zrdzn/finance/backend/transaction/infrastructure/JpaTransactionRepository.kt b/finance-backend/src/main/kotlin/dev/zrdzn/finance/backend/transaction/infrastructure/JpaTransactionRepository.kt index b79a171..83df44d 100644 --- a/finance-backend/src/main/kotlin/dev/zrdzn/finance/backend/transaction/infrastructure/JpaTransactionRepository.kt +++ b/finance-backend/src/main/kotlin/dev/zrdzn/finance/backend/transaction/infrastructure/JpaTransactionRepository.kt @@ -56,6 +56,7 @@ interface JpaTransactionRepository : TransactionRepository, Repository= CURRENT_DATE - INTERVAL '12 months' GROUP BY - CAST(EXTRACT(MONTH FROM transaction.created_at) AS INTEGER) + CAST(EXTRACT(MONTH FROM transaction.created_at) AS INTEGER), + CAST(EXTRACT(YEAR FROM transaction.created_at) AS INTEGER) ORDER BY - CAST(EXTRACT(MONTH FROM transaction.created_at) AS INTEGER) + CAST(EXTRACT(MONTH FROM transaction.created_at) AS INTEGER), + CAST(EXTRACT(YEAR FROM transaction.created_at) AS INTEGER) """, nativeQuery = true) override fun getMonthlyTransactionSums( @Param("vaultId") vaultId: Int