feat(#3): implement recurring interactors
This commit is contained in:
@@ -5,6 +5,10 @@ import dev.achmad.ledgerr.domain.category.interactor.GetCategories
|
|||||||
import dev.achmad.ledgerr.domain.category.interactor.SeedDefaultCategories
|
import dev.achmad.ledgerr.domain.category.interactor.SeedDefaultCategories
|
||||||
import dev.achmad.ledgerr.domain.category.interactor.UpsertCategory
|
import dev.achmad.ledgerr.domain.category.interactor.UpsertCategory
|
||||||
import dev.achmad.ledgerr.domain.expense.interactor.ReassignExpenseCategory
|
import dev.achmad.ledgerr.domain.expense.interactor.ReassignExpenseCategory
|
||||||
|
import dev.achmad.ledgerr.domain.recurring.interactor.DeleteRecurringExpense
|
||||||
|
import dev.achmad.ledgerr.domain.recurring.interactor.GetRecurringExpenses
|
||||||
|
import dev.achmad.ledgerr.domain.recurring.interactor.ProcessDueRecurringExpenses
|
||||||
|
import dev.achmad.ledgerr.domain.recurring.interactor.UpsertRecurringExpense
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
val domainModule = module {
|
val domainModule = module {
|
||||||
@@ -14,4 +18,9 @@ val domainModule = module {
|
|||||||
factory { SeedDefaultCategories(get()) }
|
factory { SeedDefaultCategories(get()) }
|
||||||
|
|
||||||
factory { ReassignExpenseCategory(get()) }
|
factory { ReassignExpenseCategory(get()) }
|
||||||
|
|
||||||
|
factory { GetRecurringExpenses(get()) }
|
||||||
|
factory { UpsertRecurringExpense(get()) }
|
||||||
|
factory { DeleteRecurringExpense(get()) }
|
||||||
|
factory { ProcessDueRecurringExpenses(get(), get()) }
|
||||||
}
|
}
|
||||||
|
|||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
package dev.achmad.ledgerr.domain.recurring.interactor
|
||||||
|
|
||||||
|
import dev.achmad.ledgerr.data.local.dao.RecurringExpenseDao
|
||||||
|
|
||||||
|
class DeleteRecurringExpense(
|
||||||
|
private val dao: RecurringExpenseDao,
|
||||||
|
) {
|
||||||
|
suspend fun await(id: Long) {
|
||||||
|
dao.deleteById(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
package dev.achmad.ledgerr.domain.recurring.interactor
|
||||||
|
|
||||||
|
import dev.achmad.ledgerr.data.local.dao.RecurringExpenseDao
|
||||||
|
import dev.achmad.ledgerr.data.local.mapper.toModel
|
||||||
|
import dev.achmad.ledgerr.domain.recurring.model.RecurringExpense
|
||||||
|
import dev.achmad.ledgerr.domain.recurring.model.RecurringExpenseWithCategory
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
||||||
|
class GetRecurringExpenses(
|
||||||
|
private val recurringDao: RecurringExpenseDao,
|
||||||
|
) {
|
||||||
|
fun subscribeAll(): Flow<List<RecurringExpenseWithCategory>> =
|
||||||
|
recurringDao.subscribeAll().map { rows ->
|
||||||
|
rows.map { row ->
|
||||||
|
RecurringExpenseWithCategory(
|
||||||
|
recurring = row.recurring.toModel(),
|
||||||
|
category = row.category.toModel(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun awaitOne(id: Long): RecurringExpense? =
|
||||||
|
recurringDao.getById(id)?.toModel()
|
||||||
|
}
|
||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
package dev.achmad.ledgerr.domain.recurring.interactor
|
||||||
|
|
||||||
|
import dev.achmad.ledgerr.data.local.dao.ExpenseDao
|
||||||
|
import dev.achmad.ledgerr.data.local.dao.RecurringExpenseDao
|
||||||
|
import dev.achmad.ledgerr.data.local.mapper.toEntity
|
||||||
|
import dev.achmad.ledgerr.data.local.mapper.toModel
|
||||||
|
import dev.achmad.ledgerr.domain.expense.model.Expense
|
||||||
|
import java.time.LocalDate
|
||||||
|
|
||||||
|
class ProcessDueRecurringExpenses(
|
||||||
|
private val recurringDao: RecurringExpenseDao,
|
||||||
|
private val expenseDao: ExpenseDao,
|
||||||
|
) {
|
||||||
|
suspend fun await(today: LocalDate = LocalDate.now()): List<Expense> {
|
||||||
|
val dueTemplates = recurringDao.getDue(today.toEpochDay())
|
||||||
|
if (dueTemplates.isEmpty()) return emptyList()
|
||||||
|
val created = mutableListOf<Expense>()
|
||||||
|
for (templateEntity in dueTemplates) {
|
||||||
|
val template = templateEntity.toModel()
|
||||||
|
val expense = Expense(
|
||||||
|
amount = template.amount,
|
||||||
|
categoryId = template.categoryId,
|
||||||
|
date = template.nextDueDate,
|
||||||
|
note = template.note,
|
||||||
|
recurringExpenseId = template.id,
|
||||||
|
)
|
||||||
|
val newId = expenseDao.insert(expense.toEntity())
|
||||||
|
created += expense.copy(id = newId)
|
||||||
|
val advanced = template.copy(
|
||||||
|
nextDueDate = template.interval.advance(template.nextDueDate),
|
||||||
|
)
|
||||||
|
recurringDao.update(advanced.toEntity())
|
||||||
|
}
|
||||||
|
return created
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
package dev.achmad.ledgerr.domain.recurring.interactor
|
||||||
|
|
||||||
|
import dev.achmad.ledgerr.data.local.dao.RecurringExpenseDao
|
||||||
|
import dev.achmad.ledgerr.data.local.mapper.toEntity
|
||||||
|
import dev.achmad.ledgerr.domain.recurring.model.RecurringExpense
|
||||||
|
|
||||||
|
class UpsertRecurringExpense(
|
||||||
|
private val dao: RecurringExpenseDao,
|
||||||
|
) {
|
||||||
|
suspend fun await(recurring: RecurringExpense): Long {
|
||||||
|
val entity = recurring.toEntity()
|
||||||
|
return if (recurring.id == 0L) {
|
||||||
|
dao.insert(entity)
|
||||||
|
} else {
|
||||||
|
dao.update(entity)
|
||||||
|
recurring.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user