feat: websocket events update payment db
This commit is contained in:
@@ -36,6 +36,40 @@ class PaymentCacheRepository(context: Context) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a page of payments from the DB.
|
||||
* Returns empty list if nothing cached yet.
|
||||
*/
|
||||
suspend fun loadCachedPage(offset: Int, limit: Int): List<PaymentRecord> {
|
||||
return dao.getPage(limit = limit, offset = offset)
|
||||
.map { it.toDomain() }
|
||||
.also {
|
||||
if (it.isNotEmpty())
|
||||
Log.d(TAG, "PAYMENTS [CACHE HIT ] offset=$offset got ${it.size} rows from Room")
|
||||
else
|
||||
Log.d(TAG, "PAYMENTS [CACHE MISS] offset=$offset — no rows in Room")
|
||||
}
|
||||
}
|
||||
|
||||
/** Total number of payment rows in the DB. */
|
||||
suspend fun countCached(): Int = dao.count()
|
||||
|
||||
/**
|
||||
* Merge a fetched page into the DB.
|
||||
* Uses INSERT OR REPLACE — never deletes existing rows.
|
||||
* Safe to call for any page, not just the first.
|
||||
*/
|
||||
suspend fun mergePayments(payments: List<PaymentRecord>) {
|
||||
if (payments.isEmpty()) return
|
||||
val now = System.currentTimeMillis()
|
||||
runCatching {
|
||||
dao.insertAll(payments.map { it.toEntity(now) })
|
||||
Log.d(TAG, "PAYMENTS [MERGE ] upserted ${payments.size} payments (total: ${dao.count()})")
|
||||
}.onFailure {
|
||||
Log.w(TAG, "PAYMENTS [MERGE ERR] ${it.message}")
|
||||
}
|
||||
}
|
||||
|
||||
/** Persist the first page of payments to the database. */
|
||||
suspend fun savePayments(payments: List<PaymentRecord>) {
|
||||
val now = System.currentTimeMillis()
|
||||
@@ -62,6 +96,28 @@ class PaymentCacheRepository(context: Context) {
|
||||
Log.d(TAG, "PAYMENTS [DETAIL SET] $checkingId")
|
||||
}
|
||||
|
||||
/** Upsert PaymentRecord to database. */
|
||||
suspend fun upsertPayment(payment: PaymentRecord) {
|
||||
val entity = payment.toEntity(savedAt = System.currentTimeMillis())
|
||||
dao.insert(entity)
|
||||
Log.d(TAG, "PAYMENTS [UPSERT ] ${payment.checkingId}")
|
||||
}
|
||||
|
||||
/** Check the DB for a stored payment record and return it as a detail response.
|
||||
* Returns null if not found. Never hits the network. */
|
||||
suspend fun getDetailFromDb(checkingId: String): PaymentDetailResponse? {
|
||||
val entity = dao.getByCheckingId(checkingId) ?: return null
|
||||
Log.d(TAG, "PAYMENTS [DETAIL DB ] $checkingId — found in Room")
|
||||
return PaymentDetailResponse(
|
||||
paid = entity.status == "success",
|
||||
details = entity.toDomain()
|
||||
)
|
||||
}
|
||||
|
||||
/** Returns true if this checkingId is already stored in the DB. */
|
||||
suspend fun containsPayment(checkingId: String): Boolean =
|
||||
dao.getByCheckingId(checkingId) != null
|
||||
|
||||
/** Clear everything — useful for testing and logout. */
|
||||
suspend fun clearAll() {
|
||||
detailCache.clear()
|
||||
|
||||
@@ -11,14 +11,28 @@ interface PaymentDao {
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insertAll(payments: List<PaymentRecordEntity>)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insert(payment: PaymentRecordEntity)
|
||||
|
||||
/** Returns all rows ordered by time descending. */
|
||||
@Query("SELECT * FROM payment_records ORDER BY time DESC")
|
||||
suspend fun getAll(): List<PaymentRecordEntity>
|
||||
|
||||
/** A single page, ordered newest-first. */
|
||||
@Query("SELECT * FROM payment_records ORDER BY time DESC LIMIT :limit OFFSET :offset")
|
||||
suspend fun getPage(limit: Int, offset: Int): List<PaymentRecordEntity>
|
||||
|
||||
/** Total number of rows — used to know if we have a full page cached. */
|
||||
@Query("SELECT COUNT(*) FROM payment_records")
|
||||
suspend fun count(): Int
|
||||
|
||||
/** Returns the savedAt timestamp of the most recently written row, or null if table is empty. */
|
||||
@Query("SELECT savedAt FROM payment_records ORDER BY savedAt DESC LIMIT 1")
|
||||
suspend fun getLatestSavedAt(): Long?
|
||||
|
||||
@Query("SELECT * FROM payment_records WHERE checkingId = :checkingId LIMIT 1")
|
||||
suspend fun getByCheckingId(checkingId: String): PaymentRecordEntity?
|
||||
|
||||
@Query("DELETE FROM payment_records")
|
||||
suspend fun deleteAll()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user