From 4bf7ebb6bfbfac19b9a4093e925101a6866e2449 Mon Sep 17 00:00:00 2001 From: dasha Date: Sun, 24 Dec 2023 17:28:56 +0400 Subject: [PATCH] =?UTF-8?q?=D0=B7=D0=B0=D0=BA=D0=B0=D0=B7=D1=8B=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20=D0=B0=D0=B4=D0=BC=D0=B8=D0=BD=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../myapplication/api/MyServerService.kt | 7 ++++ .../myapplication/api/order/OrderRemote.kt | 2 +- .../api/order/OrderRemoteMediator.kt | 34 ++++++++++++++----- .../api/order/OrderWithUserRemote.kt | 22 ++++++++++++ .../api/order/RestOrderRepository.kt | 6 +++- .../myapplication/database/AppContainer.kt | 1 + .../database/entities/composeui/OrderList.kt | 19 ++++++++--- .../entities/composeui/OrderListViewModel.kt | 3 +- .../database/entities/dao/OrderDao.kt | 7 +++- .../database/entities/model/Order.kt | 2 +- .../database/entities/model/OrderWithUser.kt | 18 ++++++++++ .../repository/OfflineOrderRepository.kt | 13 ++++--- .../entities/repository/OrderRepository.kt | 3 +- 13 files changed, 113 insertions(+), 24 deletions(-) create mode 100644 app/src/main/java/com/example/myapplication/api/order/OrderWithUserRemote.kt create mode 100644 app/src/main/java/com/example/myapplication/database/entities/model/OrderWithUser.kt diff --git a/app/src/main/java/com/example/myapplication/api/MyServerService.kt b/app/src/main/java/com/example/myapplication/api/MyServerService.kt index 5830d50..4cca3f3 100644 --- a/app/src/main/java/com/example/myapplication/api/MyServerService.kt +++ b/app/src/main/java/com/example/myapplication/api/MyServerService.kt @@ -3,6 +3,7 @@ package com.example.myapplication.api import com.example.myapplication.api.cinema.CinemaRemote import com.example.myapplication.api.cinema.CinemaWithSessionsRemote import com.example.myapplication.api.order.OrderRemote +import com.example.myapplication.api.order.OrderWithUserRemote import com.example.myapplication.api.session.ReportRemote import com.example.myapplication.api.session.SessionFromCinemaRemote import com.example.myapplication.api.session.SessionRemote @@ -137,6 +138,12 @@ interface MyServerService { @Query("_limit") limit: Int, ): List + @GET("orders?_expand=user") + suspend fun getOrders( + @Query("_page") page: Int, + @Query("_limit") limit: Int, + ): List + @GET("orders/{id}") suspend fun getOrder( @Path("id") id: Int, diff --git a/app/src/main/java/com/example/myapplication/api/order/OrderRemote.kt b/app/src/main/java/com/example/myapplication/api/order/OrderRemote.kt index 71a6105..def55c7 100644 --- a/app/src/main/java/com/example/myapplication/api/order/OrderRemote.kt +++ b/app/src/main/java/com/example/myapplication/api/order/OrderRemote.kt @@ -20,5 +20,5 @@ fun OrderRemote.toOrder(): Order = Order( ) fun Order.toOrderRemote(): OrderRemote = OrderRemote( - uid, userId!!, dateTime, sessions = emptyList() + uid, userId, dateTime, sessions = emptyList() ) \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/api/order/OrderRemoteMediator.kt b/app/src/main/java/com/example/myapplication/api/order/OrderRemoteMediator.kt index a355b88..adae753 100644 --- a/app/src/main/java/com/example/myapplication/api/order/OrderRemoteMediator.kt +++ b/app/src/main/java/com/example/myapplication/api/order/OrderRemoteMediator.kt @@ -7,9 +7,14 @@ import androidx.paging.RemoteMediator import androidx.room.withTransaction import com.example.myapplication.LiveStore import com.example.myapplication.api.MyServerService +import com.example.myapplication.api.user.toUser import com.example.myapplication.database.AppDatabase import com.example.myapplication.database.entities.model.Order +import com.example.myapplication.database.entities.model.OrderWithUser +import com.example.myapplication.database.entities.model.User +import com.example.myapplication.database.entities.model.UserRole import com.example.myapplication.database.entities.repository.OfflineOrderRepository +import com.example.myapplication.database.entities.repository.OfflineUserRepository import com.example.myapplication.database.remotekeys.model.RemoteKeyType import com.example.myapplication.database.remotekeys.model.RemoteKeys import com.example.myapplication.database.remotekeys.repository.OfflineRemoteKeyRepository @@ -20,9 +25,10 @@ import java.io.IOException class OrderRemoteMediator( private val service: MyServerService, private val dbOrderRepository: OfflineOrderRepository, + private val dbUserRepository: OfflineUserRepository, private val dbRemoteKeyRepository: OfflineRemoteKeyRepository, private val database: AppDatabase -) : RemoteMediator() { +) : RemoteMediator() { override suspend fun initialize(): InitializeAction { return InitializeAction.LAUNCH_INITIAL_REFRESH @@ -30,7 +36,7 @@ class OrderRemoteMediator( override suspend fun load( loadType: LoadType, - state: PagingState + state: PagingState ): MediatorResult { val page = when (loadType) { LoadType.REFRESH -> { @@ -52,14 +58,23 @@ class OrderRemoteMediator( } try { - val orders = service.getOrders( - userId = LiveStore.user.value?.uid ?: 0, - page = page, limit = state.config.pageSize - ).map { it.toOrder() } + val user = LiveStore.user + var users: List = emptyList() + val orders: List = if (user.value?.role == UserRole.ADMIN) { + val temp = service.getOrders(page = page, limit = state.config.pageSize) + users = temp.map { it.user.toUser() } + temp.map { it.toOrder() } + } else { + service.getOrders( + userId = user.value?.uid ?: 0, page = page, limit = state.config.pageSize + ).map { it.toOrder() } + } + val endOfPaginationReached = orders.isEmpty() database.withTransaction { if (loadType == LoadType.REFRESH) { dbRemoteKeyRepository.deleteRemoteKey(RemoteKeyType.ORDER) + dbUserRepository.clearUsers() dbOrderRepository.clearOrders() } val prevKey = if (page == 1) null else page - 1 @@ -74,6 +89,7 @@ class OrderRemoteMediator( } dbRemoteKeyRepository.createRemoteKeys(keys) dbOrderRepository.insertOrders(orders) + dbUserRepository.insertUsers(users) } return MediatorResult.Success(endOfPaginationReached = endOfPaginationReached) } catch (exception: IOException) { @@ -83,14 +99,14 @@ class OrderRemoteMediator( } } - private suspend fun getRemoteKeyForLastItem(state: PagingState): RemoteKeys? { + private suspend fun getRemoteKeyForLastItem(state: PagingState): RemoteKeys? { return state.pages.lastOrNull { it.data.isNotEmpty() }?.data?.lastOrNull() ?.let { order -> dbRemoteKeyRepository.getAllRemoteKeys(order.uid, RemoteKeyType.ORDER) } } - private suspend fun getRemoteKeyForFirstItem(state: PagingState): RemoteKeys? { + private suspend fun getRemoteKeyForFirstItem(state: PagingState): RemoteKeys? { return state.pages.firstOrNull { it.data.isNotEmpty() }?.data?.firstOrNull() ?.let { order -> dbRemoteKeyRepository.getAllRemoteKeys(order.uid, RemoteKeyType.ORDER) @@ -98,7 +114,7 @@ class OrderRemoteMediator( } private suspend fun getRemoteKeyClosestToCurrentPosition( - state: PagingState + state: PagingState ): RemoteKeys? { return state.anchorPosition?.let { position -> state.closestItemToPosition(position)?.uid?.let { orderUid -> diff --git a/app/src/main/java/com/example/myapplication/api/order/OrderWithUserRemote.kt b/app/src/main/java/com/example/myapplication/api/order/OrderWithUserRemote.kt new file mode 100644 index 0000000..e67c5ed --- /dev/null +++ b/app/src/main/java/com/example/myapplication/api/order/OrderWithUserRemote.kt @@ -0,0 +1,22 @@ +package com.example.myapplication.api.order + +import com.example.myapplication.api.session.SessionFromOrderRemote +import com.example.myapplication.api.user.UserRemote +import com.example.myapplication.database.entities.model.Order +import kotlinx.serialization.Contextual +import kotlinx.serialization.Serializable +import org.threeten.bp.LocalDateTime + +@Serializable +data class OrderWithUserRemote( + val id: Int = 0, + val userId: Int = 0, + val user: UserRemote, + @Contextual + val dateTime: LocalDateTime = LocalDateTime.now(), + var sessions: List = emptyList() +) + +fun OrderWithUserRemote.toOrder(): Order = Order( + id, userId, dateTime +) \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/api/order/RestOrderRepository.kt b/app/src/main/java/com/example/myapplication/api/order/RestOrderRepository.kt index 3a4b92a..9310f38 100644 --- a/app/src/main/java/com/example/myapplication/api/order/RestOrderRepository.kt +++ b/app/src/main/java/com/example/myapplication/api/order/RestOrderRepository.kt @@ -10,9 +10,11 @@ import com.example.myapplication.database.AppContainer import com.example.myapplication.database.AppDatabase import com.example.myapplication.database.entities.model.Order import com.example.myapplication.database.entities.model.OrderSessionCrossRef +import com.example.myapplication.database.entities.model.OrderWithUser import com.example.myapplication.database.entities.model.SessionFromOrder import com.example.myapplication.database.entities.repository.OfflineOrderRepository import com.example.myapplication.database.entities.repository.OfflineOrderSessionRepository +import com.example.myapplication.database.entities.repository.OfflineUserRepository import com.example.myapplication.database.entities.repository.OrderRepository import com.example.myapplication.database.remotekeys.repository.OfflineRemoteKeyRepository import kotlinx.coroutines.flow.Flow @@ -20,11 +22,12 @@ import kotlinx.coroutines.flow.Flow class RestOrderRepository( private val service: MyServerService, private val dbOrderRepository: OfflineOrderRepository, + private val dbUserRepository: OfflineUserRepository, private val dbOrderSessionRepository: OfflineOrderSessionRepository, private val dbRemoteKeyRepository: OfflineRemoteKeyRepository, private val database: AppDatabase ) : OrderRepository { - override fun getAllOrders(): Flow> { + override fun getAllOrders(): Flow> { val pagingSourceFactory = { dbOrderRepository.getAllOrdersPagingSource() } @OptIn(ExperimentalPagingApi::class) return Pager( @@ -35,6 +38,7 @@ class RestOrderRepository( remoteMediator = OrderRemoteMediator( service, dbOrderRepository, + dbUserRepository, dbRemoteKeyRepository, database, ), diff --git a/app/src/main/java/com/example/myapplication/database/AppContainer.kt b/app/src/main/java/com/example/myapplication/database/AppContainer.kt index 92fce85..e6c5f3c 100644 --- a/app/src/main/java/com/example/myapplication/database/AppContainer.kt +++ b/app/src/main/java/com/example/myapplication/database/AppContainer.kt @@ -80,6 +80,7 @@ class AppDataContainer(private val context: Context) : AppContainer { RestOrderRepository( MyServerService.getInstance(), orderRepository, + userRepository, orderSessionRepository, remoteKeyRepository, AppDatabase.getInstance(context) diff --git a/app/src/main/java/com/example/myapplication/database/entities/composeui/OrderList.kt b/app/src/main/java/com/example/myapplication/database/entities/composeui/OrderList.kt index 77bedb7..1acbea8 100644 --- a/app/src/main/java/com/example/myapplication/database/entities/composeui/OrderList.kt +++ b/app/src/main/java/com/example/myapplication/database/entities/composeui/OrderList.kt @@ -24,7 +24,9 @@ import androidx.navigation.NavController import androidx.paging.compose.collectAsLazyPagingItems import androidx.paging.compose.itemContentType import androidx.paging.compose.itemKey +import com.example.myapplication.LiveStore import com.example.myapplication.composeui.navigation.Screen +import com.example.myapplication.database.entities.model.UserRole import com.example.myapplication.ui.theme.PmudemoTheme import org.threeten.bp.format.DateTimeFormatter @@ -34,7 +36,7 @@ fun OrderList( viewModel: OrderListViewModel = viewModel(factory = AppViewModelProvider.Factory) ) { val ordersUiState = viewModel.orderListUiState.collectAsLazyPagingItems() - + LazyColumn( modifier = Modifier .fillMaxSize() @@ -66,10 +68,17 @@ fun OrderList( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp) ) { - Text( - "Заказ №${order.uid}, ${formattedDate}", - color = MaterialTheme.colorScheme.onSecondary - ) + if (LiveStore.user.value?.role == UserRole.ADMIN) + Text( + "Заказ №${order.uid}, ${formattedDate}\n" + + "Пользователь: ${order.user?.login ?: "Неизвестно"}", + color = MaterialTheme.colorScheme.onSecondary + ) + else + Text( + "Заказ №${order.uid}, $formattedDate", + color = MaterialTheme.colorScheme.onSecondary + ) } } } diff --git a/app/src/main/java/com/example/myapplication/database/entities/composeui/OrderListViewModel.kt b/app/src/main/java/com/example/myapplication/database/entities/composeui/OrderListViewModel.kt index b1d46bf..8b1df7d 100644 --- a/app/src/main/java/com/example/myapplication/database/entities/composeui/OrderListViewModel.kt +++ b/app/src/main/java/com/example/myapplication/database/entities/composeui/OrderListViewModel.kt @@ -3,11 +3,12 @@ package com.example.myapplication.database.entities.composeui import androidx.paging.PagingData import com.example.myapplication.composeui.MyViewModel import com.example.myapplication.database.entities.model.Order +import com.example.myapplication.database.entities.model.OrderWithUser import com.example.myapplication.database.entities.repository.OrderRepository import kotlinx.coroutines.flow.Flow class OrderListViewModel( orderRepository: OrderRepository ) : MyViewModel() { - var orderListUiState: Flow> = orderRepository.getAllOrders() + val orderListUiState: Flow> = orderRepository.getAllOrders() } \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/database/entities/dao/OrderDao.kt b/app/src/main/java/com/example/myapplication/database/entities/dao/OrderDao.kt index 8fa144f..e035115 100644 --- a/app/src/main/java/com/example/myapplication/database/entities/dao/OrderDao.kt +++ b/app/src/main/java/com/example/myapplication/database/entities/dao/OrderDao.kt @@ -8,12 +8,17 @@ import androidx.room.OnConflictStrategy import androidx.room.Query import androidx.room.Update import com.example.myapplication.database.entities.model.Order +import com.example.myapplication.database.entities.model.OrderWithUser import com.example.myapplication.database.entities.model.SessionFromOrder @Dao interface OrderDao { @Query("select * from orders where user_id = :userId") - fun getAll(userId: Int?): PagingSource + fun getAll(userId: Int?): PagingSource + + @Query("select * from orders " + + "left join users on orders.user_id = users.uid") + fun getAll(): PagingSource @Query( "SELECT o.*, s.*, os.count, os.frozen_price " + diff --git a/app/src/main/java/com/example/myapplication/database/entities/model/Order.kt b/app/src/main/java/com/example/myapplication/database/entities/model/Order.kt index bd032cb..b6d51ea 100644 --- a/app/src/main/java/com/example/myapplication/database/entities/model/Order.kt +++ b/app/src/main/java/com/example/myapplication/database/entities/model/Order.kt @@ -12,7 +12,7 @@ data class Order( @PrimaryKey(autoGenerate = true) val uid: Int, @ColumnInfo(name = "user_id", index = true) - val userId: Int?, + val userId: Int = 0, @ColumnInfo(name = "date_time") val dateTime: LocalDateTime, ) { diff --git a/app/src/main/java/com/example/myapplication/database/entities/model/OrderWithUser.kt b/app/src/main/java/com/example/myapplication/database/entities/model/OrderWithUser.kt new file mode 100644 index 0000000..fdf5c49 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/database/entities/model/OrderWithUser.kt @@ -0,0 +1,18 @@ +package com.example.myapplication.database.entities.model + +import androidx.room.ColumnInfo +import androidx.room.Relation +import org.threeten.bp.LocalDateTime + +data class OrderWithUser( + val uid: Int, + @ColumnInfo(name = "user_id", index = true) + val userId: Int = 0, + @ColumnInfo(name = "date_time") + val dateTime: LocalDateTime, + @Relation( + parentColumn = "user_id", + entity = User::class, + entityColumn = "uid" + ) val user: User? +) \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/database/entities/repository/OfflineOrderRepository.kt b/app/src/main/java/com/example/myapplication/database/entities/repository/OfflineOrderRepository.kt index 804f654..1db8e36 100644 --- a/app/src/main/java/com/example/myapplication/database/entities/repository/OfflineOrderRepository.kt +++ b/app/src/main/java/com/example/myapplication/database/entities/repository/OfflineOrderRepository.kt @@ -8,24 +8,29 @@ import com.example.myapplication.LiveStore import com.example.myapplication.database.AppContainer import com.example.myapplication.database.entities.dao.OrderDao import com.example.myapplication.database.entities.model.Order +import com.example.myapplication.database.entities.model.OrderWithUser import com.example.myapplication.database.entities.model.SessionFromOrder +import com.example.myapplication.database.entities.model.UserRole import kotlinx.coroutines.flow.Flow class OfflineOrderRepository(private val orderDao: OrderDao) : OrderRepository { - override fun getAllOrders(): Flow> = Pager( + override fun getAllOrders(): Flow> = Pager( config = PagingConfig( pageSize = AppContainer.LIMIT, enablePlaceholders = false ), - pagingSourceFactory = { orderDao.getAll(LiveStore.user.value?.uid ?: 0) } + pagingSourceFactory = { getAllOrdersPagingSource() } ).flow override suspend fun getOrder(uid: Int): List = orderDao.getByUid(uid) override suspend fun insertOrder(order: Order): Long = orderDao.insert(order).first() - fun getAllOrdersPagingSource(): PagingSource { - return orderDao.getAll(LiveStore.user.value?.uid ?: 0) + fun getAllOrdersPagingSource(): PagingSource { + val user = LiveStore.user.value + if (user?.role == UserRole.ADMIN) + return orderDao.getAll() + return orderDao.getAll(user?.uid ?: 0) } suspend fun clearOrders() = orderDao.deleteAll() diff --git a/app/src/main/java/com/example/myapplication/database/entities/repository/OrderRepository.kt b/app/src/main/java/com/example/myapplication/database/entities/repository/OrderRepository.kt index 19ccd9c..f83f02b 100644 --- a/app/src/main/java/com/example/myapplication/database/entities/repository/OrderRepository.kt +++ b/app/src/main/java/com/example/myapplication/database/entities/repository/OrderRepository.kt @@ -2,11 +2,12 @@ package com.example.myapplication.database.entities.repository import androidx.paging.PagingData import com.example.myapplication.database.entities.model.Order +import com.example.myapplication.database.entities.model.OrderWithUser import com.example.myapplication.database.entities.model.SessionFromOrder import kotlinx.coroutines.flow.Flow interface OrderRepository { - fun getAllOrders(): Flow> + fun getAllOrders(): Flow> suspend fun getOrder(uid: Int): List suspend fun insertOrder(order: Order): Long } \ No newline at end of file