Fix monthly recurring transactions not being created when the year changes

The previous implementation only checked that at least one month had passed between the last run date and now by subtracting the ordinal values. If it were February (month 2) and the previous run date were in January (month 1), then 2 - 1 would equal 1, so it would have been one month since the previous run and we would create the recurring transaction. If it were December however (month 12), the following month would be January (month 1), and 1 - 12 would be -11, so it would appear that we had already created a transaction 11 months in the future. The new implementation also takes the year into account to avoid this situation.
This commit is contained in:
William Brawner 2022-02-02 21:21:20 -07:00
parent f8c970eb68
commit 2a7d674204
2 changed files with 45 additions and 20 deletions

View file

@ -40,7 +40,8 @@ class RecurringTransactionProcessingJob(
is Frequency.Monthly -> {
it.lastRun?.let { last ->
val zonedLastRun = last.atZone(ZoneId.of("UTC"))
if (zonedNow.monthValue - zonedLastRun.monthValue < it.frequency.count)
val monthsPassed = ((zonedNow.year * 12) + zonedNow.monthValue) - ((zonedLastRun.year * 12) + zonedLastRun.monthValue)
if (monthsPassed < it.frequency.count)
return@forEach
}
val frequency = (it.frequency as Frequency.Monthly).dayOfMonth
@ -63,7 +64,6 @@ class RecurringTransactionProcessingJob(
return@forEach
}
}
}
}
is Frequency.Yearly -> {

View file

@ -231,19 +231,19 @@ class RecurringTransactionProcessingJobTest {
fun `monthly transactions are created every last friday`() = runBlockingTest {
val start = Instant.parse("1970-01-01T00:00:00Z")
recurringTransactionRepository.save(
RecurringTransaction(
title = "Monthly transaction",
amount = 123,
frequency = Frequency.Monthly(
1,
DayOfMonth.positionalDayOfWeek(Position.LAST, DayOfWeek.FRIDAY),
Time(9, 0, 0)
),
expense = true,
start = start,
createdBy = "tester",
budgetId = "budgetId"
)
RecurringTransaction(
title = "Monthly transaction",
amount = 123,
frequency = Frequency.Monthly(
1,
DayOfMonth.positionalDayOfWeek(Position.LAST, DayOfWeek.FRIDAY),
Time(9, 0, 0)
),
expense = true,
start = start,
createdBy = "tester",
budgetId = "budgetId"
)
)
loopFor(start, 120)
val createdTransactions = transactionRepository.findAll()
@ -254,15 +254,40 @@ class RecurringTransactionProcessingJobTest {
assertEquals("1970-04-24T09:00:00Z", createdTransactions[3].date.toString())
}
@Test
fun `monthly transactions are created in the new year`() = runBlockingTest {
val start = Instant.parse("1971-01-01T00:00:00Z")
recurringTransactionRepository.save(
RecurringTransaction(
title = "Monthly transaction",
amount = 123,
frequency = Frequency.Monthly(
1,
DayOfMonth.day(1),
Time(9, 0, 0)
),
expense = true,
start = start,
createdBy = "tester",
budgetId = "budgetId",
lastRun = Instant.parse("1970-12-01T09:00:00Z")
)
)
loopFor(start, 1)
val createdTransactions = transactionRepository.findAll()
assertEquals(1, createdTransactions.size)
assertEquals("1971-01-01T09:00:00Z", createdTransactions[0].date.toString())
}
@Test
fun `yearly transactions are created every march 31st`() = runBlockingTest {
val start = Instant.parse("1970-01-01T00:00:00Z")
recurringTransactionRepository.save(
RecurringTransaction(
title = "Yearly transaction",
amount = 123,
frequency = Frequency.Yearly(1, MonthDay.of(3, 31), Time(9, 0, 0)),
expense = true,
RecurringTransaction(
title = "Yearly transaction",
amount = 123,
frequency = Frequency.Yearly(1, MonthDay.of(3, 31), Time(9, 0, 0)),
expense = true,
start = start,
createdBy = "tester",
budgetId = "budgetId"