Skip to content

Commit

Permalink
Fixed local database queries for medicines. Now taking subquery and l…
Browse files Browse the repository at this point in the history
…ocation into account.

Better updating of pharmacy on resume, and real time updates with Room.
  • Loading branch information
Nyckoka committed May 23, 2024
1 parent 3b2eb37 commit d9e41f8
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,43 +28,50 @@ interface MedicineDao {
suspend fun upsertPharmacyMedicineList(pharmacyMedicineList: List<PharmacyMedicineEntity>)

@Query("UPDATE medicines SET notificationsActive = :notificationsActive WHERE medicineId = :medicineId")
fun updateMedicineNotificationStatus(
suspend fun updateMedicineNotificationStatus(
medicineId: Long,
notificationsActive: Boolean
)

@Query("SELECT * FROM medicines ORDER BY medicineId ASC")
fun pagingSource(): PagingSource<Int, MedicineEntity>

@Query("SELECT * FROM medicines WHERE name LIKE :query")
@Query("SELECT * FROM medicines WHERE name LIKE '%' || :query || '%'")
fun pagingSource(query: String): PagingSource<Int, MedicineEntity>

@Query(
"""
SELECT medicines.medicineId, medicines.name, medicines.description, medicines.boxPhotoUrl,
pharmacy_medicine.pharmacyId AS closestPharmacyId, pharmacies.name AS closestPharmacyName
pharmacy_medicine.pharmacyId AS closestPharmacyId, pharmacies.name AS closestPharmacyName
FROM medicines
LEFT JOIN pharmacy_medicine ON medicines.medicineId = pharmacy_medicine.medicineId
INNER JOIN pharmacies ON pharmacy_medicine.pharmacyId = pharmacies.pharmacyId
WHERE pharmacy_medicine.pharmacyId = (
SELECT pharmacyId FROM pharmacies
ORDER BY (ABS(pharmacies.latitude - :latitude) + ABS(pharmacies.longitude - :longitude)) ASC
LIMIT 1
LEFT JOIN pharmacies ON pharmacy_medicine.pharmacyId = pharmacies.pharmacyId
WHERE (pharmacies.pharmacyId = (
-- Closest pharmacy to each medicine
SELECT p.pharmacyId
FROM pharmacy_medicine pm
JOIN pharmacies p ON pm.pharmacyId = p.pharmacyId
WHERE pm.medicineId = medicines.medicineId
ORDER BY ABS(p.latitude - :latitude) + ABS(p.longitude - :longitude) ASC
LIMIT 1
) OR pharmacy_medicine.pharmacyId IS NULL
)
AND medicines.name LIKE "%" || :query || "%"
ORDER BY medicines.medicineId ASC
"""
)
fun medicineWithClosestPharmacyPagingSource(
fun pagingSourceMedicineWithClosestPharmacy(
latitude: Double,
longitude: Double
longitude: Double,
query: String
): PagingSource<Int, MedicineWithClosestPharmacyEntity>

@Query(
"""
SELECT * FROM medicines
WHERE medicineId NOT IN (
SELECT medicineId FROM pharmacy_medicine WHERE pharmacyId = :pharmacyId
) AND name LIKE :query
) AND name LIKE "%" || :query || "%"
"""
)
fun pagingSourceMedicineNotInPharmacy(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package pt.ulisboa.ist.pharmacist.repository.local.pharmacies
import androidx.paging.PagingSource
import androidx.room.Dao
import androidx.room.Query
import androidx.room.Update
import androidx.room.Upsert

@Dao
Expand All @@ -14,6 +15,28 @@ interface PharmacyDao {
@Upsert
suspend fun upsertPharmacy(pharmacy: PharmacyEntity)

@Query("UPDATE pharmacies SET userRating = :userRating WHERE pharmacyId = :pharmacyId")
suspend fun updateUserRating(pharmacyId: Long, userRating: Int)

@Update(entity = PharmacyEntity::class)
suspend fun updateGlobalRating(pharmacyEntityGlobalRating: PharmacyEntityGlobalRating)

suspend fun updateGlobalRating(pharmacyId: Long, globalRating: Double, numberOfRatings: Array<Int>) {
updateGlobalRating(PharmacyEntityGlobalRating(pharmacyId, globalRating, numberOfRatings))
}

data class PharmacyEntityGlobalRating(
val pharmacyId: Long,
val globalRating: Double,
val numberOfRatings: Array<Int>
)

@Query("UPDATE pharmacies SET userFlagged = :isFlagged WHERE pharmacyId = :pharmacyId")
suspend fun updateUserFlagged(pharmacyId: Long, isFlagged: Boolean)

@Query("UPDATE pharmacies SET userMarkedAsFavorite = :isFavorite WHERE pharmacyId = :pharmacyId")
suspend fun updateUserMarkedAsFavorite(pharmacyId: Long, isFavorite: Boolean)

@Query(
"""
SELECT pharmacies.pharmacyId, pharmacies.name, pharmacies.latitude, pharmacies.longitude, pharmacies.pictureUrl, pharmacies.globalRating, pharmacies.numberOfRatings,
Expand All @@ -24,10 +47,7 @@ interface PharmacyDao {
WHERE pharmacy_medicine.medicineId = :medicineId
"""
)
fun getPagingSourceByMedicineId(medicineId: Long): PagingSource<Int, PharmacyEntity>

@Query("UPDATE pharmacies SET userMarkedAsFavorite = :isFavorite WHERE pharmacyId = :pharmacyId")
fun updatePharmacyFavoriteStatus(pharmacyId: Long, isFavorite: Boolean)
fun pagingSourceByMedicineId(medicineId: Long): PagingSource<Int, PharmacyEntity>

@Query("SELECT * FROM pharmacies")
suspend fun getAllPharmacies(): List<PharmacyEntity>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ class MedicineWithClosestPharmacyRemoteMediator(

val limit = state.config.pageSize

Log.d("MedicineRemoteMediator", "LoadType: $loadType")
Log.d("MedicineWithClosestPharmacyRemoteMediator", "LoadType: $loadType")
Log.d(
"MedicineRemoteMediator",
"MedicineWithClosestPharmacyRemoteMediator",
"Item count: ${state.pages.flatten().map { it.medicineId }}"
)
Log.d("MedicineRemoteMediator", "Offset: $offset, Limit: $limit")
Log.d("MedicineWithClosestPharmacyRemoteMediator", "Offset: $offset, Limit: $limit")

return try {
val result = medicineApi.getMedicinesWithClosestPharmacy(
Expand All @@ -54,7 +54,7 @@ class MedicineWithClosestPharmacyRemoteMediator(
return MediatorResult.Error(Exception("Error loading data"))
}

Log.d("MedicineRemoteMediator", "Result: ${result.data.medicines.size}")
Log.d("MedicineWithClosestPharmacyRemoteMediator", "Result: ${result.data.medicines.size}")

pharmacistDb.withTransaction {
if (loadType == LoadType.REFRESH)
Expand All @@ -71,7 +71,7 @@ class MedicineWithClosestPharmacyRemoteMediator(
}

Log.d(
"MedicineRemoteMediator",
"MedicineWithClosestPharmacyRemoteMediator",
"Reached end of pagination: ${result.data.medicines.isEmpty() || result.data.medicines.size < limit}"
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ class RealTimeUpdatesService(
super.onOpen(webSocket, response)
Log.d(TAG, "WebSocket opened")

Log.d(TAG, "Sending subscriptions to WebSocket")
/*Log.d(TAG, "Sending subscriptions to WebSocket")
val json = Gson().toJson(currentSubscriptions.map { it.toDto() }.toTypedArray())
val sent = webSocket.send(json)
Log.d(TAG, "Successfully sent subscriptions to WebSocket: $sent")
Log.d(TAG, "Successfully sent subscriptions to WebSocket: $sent")*/
}

override fun onMessage(webSocket: WebSocket, text: String) {
Expand Down Expand Up @@ -111,7 +111,7 @@ class RealTimeUpdatesService(

override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
super.onClosed(webSocket, code, reason)
Log.d(TAG, "WebSocket closed")
Log.d(TAG, "WebSocket closed: reason: $reason")
close()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,10 @@ class AddMedicineToPharmacyViewModel @AssistedInject constructor(
query = query,
location = location
),
pagingSourceFactory = { pharmacistDb.medicineDao().pagingSource() }
pagingSourceFactory = {
pharmacistDb.medicineDao()
.pagingSourceMedicineNotInPharmacy(query, pharmacyId)
}
)
.flow
.map { pagingData ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class MedicineViewModel @AssistedInject constructor(
location = location
),
pagingSourceFactory = {
pharmacistDb.pharmacyDao().getPagingSourceByMedicineId(medicineId = medicineId)
pharmacistDb.pharmacyDao().pagingSourceByMedicineId(medicineId = medicineId)
}
)
.flow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import pt.ulisboa.ist.pharmacist.domain.pharmacies.Location
import pt.ulisboa.ist.pharmacist.repository.local.PharmacistDatabase
import pt.ulisboa.ist.pharmacist.repository.mappers.toMedicineWithClosestPharmacy
import pt.ulisboa.ist.pharmacist.repository.remote.medicines.MedicineApi
import pt.ulisboa.ist.pharmacist.repository.remote.medicines.MedicineRemoteMediator
import pt.ulisboa.ist.pharmacist.repository.remote.medicines.MedicineWithClosestPharmacyRemoteMediator
import pt.ulisboa.ist.pharmacist.session.SessionManager
import pt.ulisboa.ist.pharmacist.ui.screens.PharmacistViewModel
import javax.inject.Inject
Expand Down Expand Up @@ -76,19 +76,18 @@ class MedicineSearchViewModel @Inject constructor(
enablePlaceholders = false,
initialLoadSize = PAGE_SIZE
),
remoteMediator = //MedicineWithClosestPharmacyRemoteMediator(
MedicineRemoteMediator(
remoteMediator = MedicineWithClosestPharmacyRemoteMediator(
pharmacistDb = pharmacistDb,
medicineApi = medicineApi,
query = query,
location = location
),
pagingSourceFactory = {
pharmacistDb.medicineDao().pagingSource()
/*pharmacistDb.medicineDao().medicineWithClosestPharmacyPagingSource(
pharmacistDb.medicineDao().pagingSourceMedicineWithClosestPharmacy(
latitude = location.lat,
longitude = location.lon,
)*/
query = query
)
}
)
.flow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ class PharmacyActivity : PharmacistActivity() {
}
}

override fun onResume() {
super.onResume()

Log.d("PharmacyActivity", "Loading pharmacy")
viewModel.loadPharmacy(pharmacyId)
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,20 +202,41 @@ class PharmacyViewModel @AssistedInject constructor(
fun listenForRealTimeUpdates() = viewModelScope.launch {
realTimeUpdatesService.listenForRealTimeUpdates(
onPharmacyUserRating = { pharmacyUserRatingData ->
pharmacy = pharmacy?.copy(userRating = pharmacyUserRatingData.userRating)
viewModelScope.launch {
pharmacistDb.pharmacyDao().updateUserRating(
pharmacyId = pharmacyId,
userRating = pharmacyUserRatingData.userRating
)
pharmacy = pharmacistDb.pharmacyDao().getPharmacyById(pharmacyId).toPharmacy()
}
},
onPharmacyGlobalRating = { pharmacyGlobalRatingData ->
pharmacy = pharmacy?.copy(
globalRating = pharmacyGlobalRatingData.globalRating,
numberOfRatings = pharmacyGlobalRatingData.numberOfRatings.toTypedArray()
)
viewModelScope.launch {
pharmacistDb.pharmacyDao().updateGlobalRating(
pharmacyId = pharmacyId,
globalRating = pharmacyGlobalRatingData.globalRating,
numberOfRatings = pharmacyGlobalRatingData.numberOfRatings.toTypedArray()
)
pharmacy = pharmacistDb.pharmacyDao().getPharmacyById(pharmacyId).toPharmacy()
}
},
onPharmacyUserFlagged = { pharmacyUserFlaggedData ->
pharmacy = pharmacy?.copy(userFlagged = pharmacyUserFlaggedData.flagged)
viewModelScope.launch {
pharmacistDb.pharmacyDao().updateUserFlagged(
pharmacyId = pharmacyId,
isFlagged = pharmacyUserFlaggedData.flagged
)
pharmacy = pharmacistDb.pharmacyDao().getPharmacyById(pharmacyId).toPharmacy()
}
},
onPharmacyUserFavorited = { pharmacyUserFavoritedData ->
pharmacy =
pharmacy?.copy(userMarkedAsFavorite = pharmacyUserFavoritedData.favorited)
viewModelScope.launch {
pharmacistDb.pharmacyDao().updateUserMarkedAsFavorite(
pharmacyId = pharmacyId,
isFavorite = pharmacyUserFavoritedData.favorited
)
pharmacy = pharmacistDb.pharmacyDao().getPharmacyById(pharmacyId).toPharmacy()
}
},
onMedicineStock = { medicineStockData ->
Log.d(
Expand Down

0 comments on commit d9e41f8

Please sign in to comment.