commit 225bc67cbecee0f031bf3dfb4d1288235d0720da
parent 036598c3f3ae999ed3be17f60e53ac436f845799
Author: ms <ms@taler.net>
Date: Sun, 9 Jan 2022 16:15:47 +0100
implement history API
Diffstat:
2 files changed, 48 insertions(+), 7 deletions(-)
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt
@@ -338,10 +338,21 @@ object BankAccountTransactionsTable : LongIdTable() {
class BankAccountTransactionEntity(id: EntityID<Long>) : LongEntity(id) {
companion object : LongEntityClass<BankAccountTransactionEntity>(BankAccountTransactionsTable) {
override fun new(init: BankAccountTransactionEntity.() -> Unit): BankAccountTransactionEntity {
+ /**
+ * Fresh transactions are those that wait to be included in a
+ * "history" report, likely a Camt.5x message. The "fresh transactions"
+ * table keeps a list of such transactions.
+ */
val freshTx = super.new(init)
BankAccountFreshTransactionsTable.insert {
it[transactionRef] = freshTx.id
}
+ /**
+ * The bank account involved in this transaction points to
+ * it as the "last known" transaction, to make it easier to
+ * build histories that depend on such record.
+ */
+ freshTx.account.lastTransaction = freshTx
return freshTx
}
}
@@ -384,6 +395,13 @@ object BankAccountsTable : IntIdTable() {
val owner = text("owner")
val isPublic = bool("isPublic").default(false)
val demoBank = reference("demoBank", DemobankConfigsTable)
+
+ /**
+ * Point to the last transaction related to this account, regardless
+ * of it being credit or debit. This reference helps to construct
+ * history results that start from / depend on the last transaction.
+ */
+ val lastTransaction = reference("lastTransaction", BankAccountTransactionsTable).nullable()
}
class BankAccountEntity(id: EntityID<Int>) : IntEntity(id) {
@@ -395,6 +413,7 @@ class BankAccountEntity(id: EntityID<Int>) : IntEntity(id) {
var owner by BankAccountsTable.owner
var isPublic by BankAccountsTable.isPublic
var demoBank by DemobankConfigEntity referencedOn BankAccountsTable.demoBank
+ var lastTransaction by BankAccountTransactionEntity optionalReferencedOn BankAccountsTable.lastTransaction
}
object BankAccountStatementsTable : IntIdTable() {
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
@@ -1279,8 +1279,7 @@ val sandboxApp: Application.() -> Unit = {
})
return@get
}
- // This endpoint is being called "GET /transaction" in the docs.
- get("/accounts/{account_name}/history") {
+ get("/accounts/{account_name}/transactions") {
val demobank = ensureDemobank(call)
val bankAccount = getBankAccountFromLabel(
call.getUriComponent("account_name"),
@@ -1290,13 +1289,36 @@ val sandboxApp: Application.() -> Unit = {
if (!authOk && (call.request.basicAuth() != bankAccount.owner)) throw forbidden(
"Cannot access bank account ${bankAccount.label}"
)
+
+ val page: Int = Integer.decode(call.request.queryParameters["page"] ?: "1")
+ val size: Int = Integer.decode(call.request.queryParameters["size"] ?: "5")
+
val ret = mutableListOf<RawPayment>()
+ /**
+ * Case where page number wasn't given,
+ * therefore the results starts from the last transaction. */
transaction {
- BankAccountTransactionEntity.find {
- BankAccountTransactionsTable.account eq bankAccount.id
- // FIXME: more criteria to come.
- }.forEach {
- ret.add(getHistoryElementFromTransactionRow(it))
+ /**
+ * Get a history page - from the calling bank account - having
+ * 'firstElementId' as the latest transaction in it. */
+ fun getPage(firstElementId: Long): Iterable<BankAccountTransactionEntity> {
+ return BankAccountTransactionEntity.find {
+ (BankAccountTransactionsTable.id lessEq firstElementId) and
+ (BankAccountTransactionsTable.account eq bankAccount.id)
+ }.take(size)
+ }
+ val lt: BankAccountTransactionEntity? = bankAccount.lastTransaction
+ if (lt == null) return@transaction
+ var firstElement: BankAccountTransactionEntity = lt
+ /**
+ * This loop fetches (and discards) pages until the
+ * desired one is found. */
+ for (i in 0..(page)) {
+ val pageBuf = getPage(firstElement.id.value)
+ firstElement = pageBuf.last()
+ if (i == page) pageBuf.forEach {
+ ret.add(getHistoryElementFromTransactionRow(it))
+ }
}
}
call.respond(ret)