From 7b40f336cdfe3f6fc4f761768742ae69e4325662 Mon Sep 17 00:00:00 2001 From: Shcherbatykh Oleg Date: Tue, 17 Feb 2026 09:23:25 +0300 Subject: [PATCH] refactoring network layer --- .../tsudesk/core/database/AppDatabase.kt | 2 + .../core/database/StringListConverter.kt | 21 ++++++++++ .../core/database/schedule/Constants.kt | 2 +- .../database/schedule/LessonCacheEntity.kt | 6 +-- .../tsudesk/core/database/schedule/Query.kt | 18 ++++++--- .../database/schedule/ScheduleCacheEntity.kt | 2 +- .../core/database/schedule/ScheduleDao.kt | 17 ++++---- .../schedule/data/ScheduleRepositoryImpl.kt | 9 ++--- .../datasource/ScheduleRemoteDataSource.kt | 2 +- .../data/local/ScheduleLocalDataSourceImpl.kt | 2 - .../ScheduleStorageMapper.kt | 17 ++++---- .../feature/schedule/data/remote/Constants.kt | 33 +++++++++++++++ .../schedule/data/remote/ScheduleApi.kt | 18 --------- .../data/remote/ScheduleApiContract.kt | 16 -------- .../schedule/data/remote/ScheduleDto.kt | 38 ------------------ .../data/remote/ScheduleJsonParser.kt | 2 +- .../ScheduleNetworkMapper.kt | 13 +++--- .../remote/ScheduleRemoteDataSourceImpl.kt | 3 +- .../schedule/data/remote/api/ScheduleApi.kt | 16 ++++++++ .../schedule/data/remote/dto/GroupDto.kt | 12 ++++++ .../schedule/data/remote/dto/LessonDto.kt | 40 +++++++++++++++++++ .../schedule/data/remote/dto/ScheduleDto.kt | 3 ++ .../schedule/di/ScheduleNetworkModule.kt | 2 +- .../schedule/domain/model/LessonEntity.kt | 29 ++++++++++++-- 24 files changed, 204 insertions(+), 119 deletions(-) create mode 100644 core/database/src/main/java/ru/fincode/tsudesk/core/database/StringListConverter.kt rename feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/{mapper => local}/ScheduleStorageMapper.kt (77%) create mode 100644 feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/Constants.kt delete mode 100644 feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/ScheduleApi.kt delete mode 100644 feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/ScheduleApiContract.kt delete mode 100644 feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/ScheduleDto.kt rename feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/{mapper => remote}/ScheduleNetworkMapper.kt (65%) create mode 100644 feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/api/ScheduleApi.kt create mode 100644 feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/dto/GroupDto.kt create mode 100644 feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/dto/LessonDto.kt create mode 100644 feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/dto/ScheduleDto.kt diff --git a/core/database/src/main/java/ru/fincode/tsudesk/core/database/AppDatabase.kt b/core/database/src/main/java/ru/fincode/tsudesk/core/database/AppDatabase.kt index 081d722..75f3f7d 100644 --- a/core/database/src/main/java/ru/fincode/tsudesk/core/database/AppDatabase.kt +++ b/core/database/src/main/java/ru/fincode/tsudesk/core/database/AppDatabase.kt @@ -2,10 +2,12 @@ package ru.fincode.tsudesk.core.database import androidx.room.Database import androidx.room.RoomDatabase +import androidx.room.TypeConverters import ru.fincode.tsudesk.core.database.schedule.LessonCacheEntity import ru.fincode.tsudesk.core.database.schedule.ScheduleCacheEntity import ru.fincode.tsudesk.core.database.schedule.ScheduleDao +@TypeConverters(StringListConverter::class) @Database( entities = [ // schedule feature diff --git a/core/database/src/main/java/ru/fincode/tsudesk/core/database/StringListConverter.kt b/core/database/src/main/java/ru/fincode/tsudesk/core/database/StringListConverter.kt new file mode 100644 index 0000000..15905e7 --- /dev/null +++ b/core/database/src/main/java/ru/fincode/tsudesk/core/database/StringListConverter.kt @@ -0,0 +1,21 @@ +package ru.fincode.tsudesk.core.database + +import androidx.room.TypeConverter + +class StringListConverter { + + private val separator = "||" + + @TypeConverter + fun fromList(list: List?): String = + list + ?.joinToString(separator = separator) + .orEmpty() + + @TypeConverter + fun toList(value: String?): List = + value + ?.takeIf { it.isNotBlank() } + ?.split(separator) + .orEmpty() +} diff --git a/core/database/src/main/java/ru/fincode/tsudesk/core/database/schedule/Constants.kt b/core/database/src/main/java/ru/fincode/tsudesk/core/database/schedule/Constants.kt index fc8e423..3865c86 100644 --- a/core/database/src/main/java/ru/fincode/tsudesk/core/database/schedule/Constants.kt +++ b/core/database/src/main/java/ru/fincode/tsudesk/core/database/schedule/Constants.kt @@ -1,6 +1,6 @@ package ru.fincode.tsudesk.core.database.schedule -object ScheduleDbConstants { +object Constants { const val SCHEDULE_TABLE = "schedule_cache" const val LESSON_TABLE = "lesson_cache" diff --git a/core/database/src/main/java/ru/fincode/tsudesk/core/database/schedule/LessonCacheEntity.kt b/core/database/src/main/java/ru/fincode/tsudesk/core/database/schedule/LessonCacheEntity.kt index 47dc271..53b598d 100644 --- a/core/database/src/main/java/ru/fincode/tsudesk/core/database/schedule/LessonCacheEntity.kt +++ b/core/database/src/main/java/ru/fincode/tsudesk/core/database/schedule/LessonCacheEntity.kt @@ -3,8 +3,8 @@ package ru.fincode.tsudesk.core.database.schedule import androidx.room.Entity import androidx.room.Index import androidx.room.PrimaryKey -import ru.fincode.tsudesk.core.database.schedule.ScheduleDbConstants.COL_SCHEDULE_KEY -import ru.fincode.tsudesk.core.database.schedule.ScheduleDbConstants.LESSON_TABLE +import ru.fincode.tsudesk.core.database.schedule.Constants.COL_SCHEDULE_KEY +import ru.fincode.tsudesk.core.database.schedule.Constants.LESSON_TABLE @Entity( tableName = LESSON_TABLE, indices = [Index(value = [COL_SCHEDULE_KEY])] @@ -19,6 +19,6 @@ data class LessonCacheEntity( val typeName: String, val room: String, val teacher: String, - val groupId: String, + val groupIds: List, val type: String ) diff --git a/core/database/src/main/java/ru/fincode/tsudesk/core/database/schedule/Query.kt b/core/database/src/main/java/ru/fincode/tsudesk/core/database/schedule/Query.kt index ac95a90..49945a1 100644 --- a/core/database/src/main/java/ru/fincode/tsudesk/core/database/schedule/Query.kt +++ b/core/database/src/main/java/ru/fincode/tsudesk/core/database/schedule/Query.kt @@ -1,13 +1,21 @@ package ru.fincode.tsudesk.core.database.schedule +import ru.fincode.tsudesk.core.database.schedule.Constants.COL_KEY +import ru.fincode.tsudesk.core.database.schedule.Constants.COL_SCHEDULE_KEY +import ru.fincode.tsudesk.core.database.schedule.Constants.LESSON_TABLE +import ru.fincode.tsudesk.core.database.schedule.Constants.SCHEDULE_TABLE + object Query { - const val SELECT_LESSON_BY_KEY_QUERY = - "SELECT * FROM lesson_cache WHERE scheduleKey = :key" + const val SELECT_LESSONS_BY_KEY_QUERY = + "SELECT * FROM $LESSON_TABLE WHERE $COL_SCHEDULE_KEY = :key" const val SELECT_SCHEDULE_BY_KEY_QUERY = - "SELECT * FROM schedule_cache WHERE `key` = :key LIMIT 1" + "SELECT * FROM $SCHEDULE_TABLE WHERE $COL_KEY = :key LIMIT 1" - const val DELETE_LESSON_BY_GROUP_KEY_QUERY = - "DELETE FROM lesson_cache WHERE scheduleKey = :key" + const val DELETE_LESSONS_BY_KEY = + "DELETE FROM $LESSON_TABLE WHERE $COL_SCHEDULE_KEY = :key" + + const val DELETE_SCHEDULE_BY_KEY = + "DELETE FROM $SCHEDULE_TABLE WHERE $COL_KEY = :key" } diff --git a/core/database/src/main/java/ru/fincode/tsudesk/core/database/schedule/ScheduleCacheEntity.kt b/core/database/src/main/java/ru/fincode/tsudesk/core/database/schedule/ScheduleCacheEntity.kt index 7482f81..66a147e 100644 --- a/core/database/src/main/java/ru/fincode/tsudesk/core/database/schedule/ScheduleCacheEntity.kt +++ b/core/database/src/main/java/ru/fincode/tsudesk/core/database/schedule/ScheduleCacheEntity.kt @@ -2,7 +2,7 @@ package ru.fincode.tsudesk.core.database.schedule import androidx.room.Entity import androidx.room.PrimaryKey -import ru.fincode.tsudesk.core.database.schedule.ScheduleDbConstants.SCHEDULE_TABLE +import ru.fincode.tsudesk.core.database.schedule.Constants.SCHEDULE_TABLE @Entity(tableName = SCHEDULE_TABLE) data class ScheduleCacheEntity( diff --git a/core/database/src/main/java/ru/fincode/tsudesk/core/database/schedule/ScheduleDao.kt b/core/database/src/main/java/ru/fincode/tsudesk/core/database/schedule/ScheduleDao.kt index ddf475c..806a4ea 100644 --- a/core/database/src/main/java/ru/fincode/tsudesk/core/database/schedule/ScheduleDao.kt +++ b/core/database/src/main/java/ru/fincode/tsudesk/core/database/schedule/ScheduleDao.kt @@ -6,22 +6,25 @@ import androidx.room.OnConflictStrategy import androidx.room.Query import androidx.room.Transaction import kotlinx.coroutines.flow.Flow -import ru.fincode.tsudesk.core.database.schedule.Query.SELECT_LESSON_BY_KEY_QUERY +import ru.fincode.tsudesk.core.database.schedule.Query.DELETE_LESSONS_BY_KEY +import ru.fincode.tsudesk.core.database.schedule.Query.DELETE_SCHEDULE_BY_KEY +import ru.fincode.tsudesk.core.database.schedule.Query.SELECT_LESSONS_BY_KEY_QUERY import ru.fincode.tsudesk.core.database.schedule.Query.SELECT_SCHEDULE_BY_KEY_QUERY + @Dao interface ScheduleDao { @Query(SELECT_SCHEDULE_BY_KEY_QUERY) fun observeSchedule(key: String): Flow - @Query(SELECT_LESSON_BY_KEY_QUERY) + @Query(SELECT_LESSONS_BY_KEY_QUERY) fun observeLessons(key: String): Flow> - @Query("SELECT * FROM schedule_cache WHERE `key` = :key LIMIT 1") + @Query(SELECT_SCHEDULE_BY_KEY_QUERY) suspend fun getSchedule(key: String): ScheduleCacheEntity? - @Query("SELECT * FROM lesson_cache WHERE scheduleKey = :key") + @Query(SELECT_LESSONS_BY_KEY_QUERY) suspend fun getLessons(key: String): List @Insert(onConflict = OnConflictStrategy.REPLACE) @@ -30,10 +33,10 @@ interface ScheduleDao { @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertLessons(lessons: List) - @Query("DELETE FROM lesson_cache WHERE scheduleKey = :key") + @Query(DELETE_LESSONS_BY_KEY) suspend fun deleteLessonsByKey(key: String) - @Query("DELETE FROM schedule_cache WHERE `key` = :key") + @Query(DELETE_SCHEDULE_BY_KEY) suspend fun deleteScheduleByKey(key: String) @Transaction @@ -48,7 +51,7 @@ interface ScheduleDao { } @Transaction - suspend fun clearSchedule(key: String) { + suspend fun removeSchedule(key: String) { deleteLessonsByKey(key) deleteScheduleByKey(key) } diff --git a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/ScheduleRepositoryImpl.kt b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/ScheduleRepositoryImpl.kt index 78385ad..0767a88 100644 --- a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/ScheduleRepositoryImpl.kt +++ b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/ScheduleRepositoryImpl.kt @@ -9,8 +9,8 @@ import ru.fincode.tsudesk.core.network.model.NetworkResult import ru.fincode.tsudesk.core.network.model.map import ru.fincode.tsudesk.feature.schedule.data.datasource.ScheduleLocalDataSource import ru.fincode.tsudesk.feature.schedule.data.datasource.ScheduleRemoteDataSource -import ru.fincode.tsudesk.feature.schedule.data.mapper.ScheduleCacheKey -import ru.fincode.tsudesk.feature.schedule.data.mapper.ScheduleNetworkMapper +import ru.fincode.tsudesk.feature.schedule.data.local.ScheduleCacheKey +import ru.fincode.tsudesk.feature.schedule.data.remote.ScheduleNetworkMapper import ru.fincode.tsudesk.feature.schedule.domain.model.ScheduleEntity import ru.fincode.tsudesk.feature.schedule.domain.model.ScheduleType import ru.fincode.tsudesk.feature.schedule.domain.repository.ScheduleRepository @@ -33,6 +33,7 @@ class ScheduleRepositoryImpl @Inject constructor( emit(DataResult.Data(cached, refreshedFromNetwork = false)) } + // if (cached?.timestamp != updated.timestamp) { ... } val networkResult: NetworkResult = when (type) { is ScheduleType.Group -> remote.loadScheduleByGroup(type.number).map(mapper::invoke) @@ -43,7 +44,6 @@ class ScheduleRepositoryImpl @Inject constructor( when (networkResult) { is NetworkResult.Success -> { - // Важно: timestamp должен обновляться при записи из сети (либо приходить новым) local.saveSchedule(key, networkResult.data) } @@ -53,11 +53,8 @@ class ScheduleRepositoryImpl @Inject constructor( } } - // 3) DB snapshot после записи — эмитим второй раз (NETWORK) val updated: ScheduleEntity = local.observeSchedule(key).filterNotNull().first() - // Если не хочешь дублировать, когда данные те же — включи проверку: - // if (cached?.timestamp != updated.timestamp) { ... } emit(DataResult.Data(updated, refreshedFromNetwork = true)) } diff --git a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/datasource/ScheduleRemoteDataSource.kt b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/datasource/ScheduleRemoteDataSource.kt index 4c7b75b..73e588b 100644 --- a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/datasource/ScheduleRemoteDataSource.kt +++ b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/datasource/ScheduleRemoteDataSource.kt @@ -1,7 +1,7 @@ package ru.fincode.tsudesk.feature.schedule.data.datasource import ru.fincode.tsudesk.core.network.model.NetworkResult -import ru.fincode.tsudesk.feature.schedule.data.remote.model.ScheduleDto +import ru.fincode.tsudesk.feature.schedule.data.remote.dto.ScheduleDto interface ScheduleRemoteDataSource { suspend fun loadScheduleByGroup(number: String): NetworkResult diff --git a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/local/ScheduleLocalDataSourceImpl.kt b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/local/ScheduleLocalDataSourceImpl.kt index 34570b6..6199584 100644 --- a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/local/ScheduleLocalDataSourceImpl.kt +++ b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/local/ScheduleLocalDataSourceImpl.kt @@ -6,8 +6,6 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.onStart import ru.fincode.tsudesk.core.database.schedule.ScheduleDao import ru.fincode.tsudesk.feature.schedule.data.datasource.ScheduleLocalDataSource -import ru.fincode.tsudesk.feature.schedule.data.mapper.toCache -import ru.fincode.tsudesk.feature.schedule.data.mapper.toDomain import ru.fincode.tsudesk.feature.schedule.domain.model.ScheduleEntity import javax.inject.Inject diff --git a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/mapper/ScheduleStorageMapper.kt b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/local/ScheduleStorageMapper.kt similarity index 77% rename from feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/mapper/ScheduleStorageMapper.kt rename to feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/local/ScheduleStorageMapper.kt index 3266da9..c84d72d 100644 --- a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/mapper/ScheduleStorageMapper.kt +++ b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/local/ScheduleStorageMapper.kt @@ -1,15 +1,14 @@ -package ru.fincode.tsudesk.feature.schedule.data.mapper +package ru.fincode.tsudesk.feature.schedule.data.local +import ru.fincode.tsudesk.core.database.schedule.Constants.GROUP_PRE_KEY +import ru.fincode.tsudesk.core.database.schedule.Constants.TEACHER_PRE_KEY import ru.fincode.tsudesk.core.database.schedule.LessonCacheEntity import ru.fincode.tsudesk.core.database.schedule.ScheduleCacheEntity -import ru.fincode.tsudesk.core.database.schedule.ScheduleDbConstants.GROUP_PRE_KEY -import ru.fincode.tsudesk.core.database.schedule.ScheduleDbConstants.TEACHER_PRE_KEY import ru.fincode.tsudesk.feature.schedule.domain.model.LessonEntity +import ru.fincode.tsudesk.feature.schedule.domain.model.LessonType import ru.fincode.tsudesk.feature.schedule.domain.model.ScheduleEntity - - object ScheduleCacheKey { fun group(number: String) = "$GROUP_PRE_KEY$number" fun teacher(name: String) = "$TEACHER_PRE_KEY$name" @@ -34,8 +33,8 @@ fun ScheduleEntity.toCache( typeName = lesson.typeName, room = lesson.room, teacher = lesson.teacher, - groupId = lesson.groupId, - type = lesson.type + groupIds = lesson.groupIds, + type = lesson.type.toString() ) } @@ -58,6 +57,6 @@ private fun LessonCacheEntity.toDomain(): LessonEntity = typeName = typeName, room = room, teacher = teacher, - groupId = groupId, - type = type + groupIds = groupIds, + type = LessonType.fromApi(type) ) diff --git a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/Constants.kt b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/Constants.kt new file mode 100644 index 0000000..eb6464e --- /dev/null +++ b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/Constants.kt @@ -0,0 +1,33 @@ +package ru.fincode.tsudesk.feature.schedule.data.remote + +object ScheduleApiContract { + + object Path { + const val GET_SCHEDULE_METHOD = "GetSchedule.php" + } + + object Query { + const val FIELD_SEARCH = "search_field" + const val VALUE_SEARCH = "search_value" + + const val FIELD_GROUP = "GROUP_P" + const val FIELD_TEACHER = "PREP" + + const val FIELD_DATE = "DATE_Z" + const val FIELD_TIME = "TIME_Z" + const val FIELD_NAME = "DISCIP" + const val FIELD_TYPE_NAME = "KOW" + const val FIELD_ROOM = "AUD" + + const val FIELD_GROUPS = "GROUPS" + const val FIELD_TYPE = "CLASS" + + object LessonType { + const val VALUE_LECTURE = "lecture" + const val VALUE_LAB = "lab" + const val VALUE_PRACTICE = "practice" + const val VALUE_DEFAULT = "default" + } + } + +} \ No newline at end of file diff --git a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/ScheduleApi.kt b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/ScheduleApi.kt deleted file mode 100644 index 4ba0669..0000000 --- a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/ScheduleApi.kt +++ /dev/null @@ -1,18 +0,0 @@ -package ru.fincode.tsudesk.feature.schedule.data.remote - -import retrofit2.Response -import retrofit2.http.GET -import retrofit2.http.Query -import ru.fincode.tsudesk.feature.schedule.data.remote.ScheduleApiContract.Path.GET_SCHEDULE_METHOD -import ru.fincode.tsudesk.feature.schedule.data.remote.ScheduleApiContract.Query.SEARCH_FIELD -import ru.fincode.tsudesk.feature.schedule.data.remote.ScheduleApiContract.Query.SEARCH_VALUE -import ru.fincode.tsudesk.feature.schedule.data.remote.model.ScheduleDto - -interface ScheduleApi { - - @GET(GET_SCHEDULE_METHOD) - suspend fun getSchedule( - @Query(SEARCH_FIELD) searchField: String, - @Query(SEARCH_VALUE) searchValue: String - ): Response -} diff --git a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/ScheduleApiContract.kt b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/ScheduleApiContract.kt deleted file mode 100644 index 295885e..0000000 --- a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/ScheduleApiContract.kt +++ /dev/null @@ -1,16 +0,0 @@ -package ru.fincode.tsudesk.feature.schedule.data.remote - -object ScheduleApiContract { - - object Path { - const val GET_SCHEDULE_METHOD = "GetSchedule.php" - } - - object Query { - const val SEARCH_FIELD = "search_field" - const val SEARCH_VALUE = "search_value" - - const val FIELD_GROUP = "GROUP_P" - const val FIELD_TEACHER = "PREP" - } -} diff --git a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/ScheduleDto.kt b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/ScheduleDto.kt deleted file mode 100644 index 6cae659..0000000 --- a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/ScheduleDto.kt +++ /dev/null @@ -1,38 +0,0 @@ -package ru.fincode.tsudesk.feature.schedule.data.remote.model - -import com.squareup.moshi.Json -import com.squareup.moshi.JsonClass - -typealias ScheduleDto = List - -@JsonClass(generateAdapter = false) // reflection-адаптер через moshi-kotlin -data class LessonDto( - @Json(name = "DATE_Z") - val date: String, // "12.01.2026" - @Json(name = "TIME_Z") - val time: String, // "11:00 - 13:55" - @Json(name = "DISCIP") - val discipline: String, // предмет - @Json(name = "KOW") - val typeName: String, // "Лекции", "Лабораторные занятия", "Э", "зч", "КР", "ДЗ" и т.п. - @Json(name = "AUD") - val room: String, // можно назвать audience, но ключ в JSON "AUD" - @Json(name = "PREP") - val teacher: String, - @Json(name = "GROUPS") - val groups: List, - @Json(name = "CLASS") - val type: String // "lecture" / "lab" / "practice" / "default" -) { - - data class GroupDto( - @Json(name = "GROUP_P") - val groupCode: String - ) - object ScheduleSearchField { - const val GROUP_P = "GROUP_P" - const val PREP = "PREP" - } - -} - diff --git a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/ScheduleJsonParser.kt b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/ScheduleJsonParser.kt index 86ea07b..2d3703b 100644 --- a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/ScheduleJsonParser.kt +++ b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/ScheduleJsonParser.kt @@ -3,7 +3,7 @@ package ru.fincode.tsudesk.feature.schedule.data.remote import com.squareup.moshi.Moshi import com.squareup.moshi.Types import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory -import ru.fincode.tsudesk.feature.schedule.data.remote.model.LessonDto +import ru.fincode.tsudesk.feature.schedule.data.remote.dto.LessonDto class ScheduleJsonParser { diff --git a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/mapper/ScheduleNetworkMapper.kt b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/ScheduleNetworkMapper.kt similarity index 65% rename from feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/mapper/ScheduleNetworkMapper.kt rename to feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/ScheduleNetworkMapper.kt index a5662a0..09e2d04 100644 --- a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/mapper/ScheduleNetworkMapper.kt +++ b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/ScheduleNetworkMapper.kt @@ -1,9 +1,10 @@ -package ru.fincode.tsudesk.feature.schedule.data.mapper +package ru.fincode.tsudesk.feature.schedule.data.remote import ru.fincode.tsudesk.core.network.model.NetworkMeta -import ru.fincode.tsudesk.feature.schedule.data.remote.model.LessonDto -import ru.fincode.tsudesk.feature.schedule.data.remote.model.ScheduleDto +import ru.fincode.tsudesk.feature.schedule.data.remote.dto.LessonDto +import ru.fincode.tsudesk.feature.schedule.data.remote.dto.ScheduleDto import ru.fincode.tsudesk.feature.schedule.domain.model.LessonEntity +import ru.fincode.tsudesk.feature.schedule.domain.model.LessonType import ru.fincode.tsudesk.feature.schedule.domain.model.ScheduleEntity import javax.inject.Inject @@ -19,11 +20,11 @@ class ScheduleNetworkMapper @Inject constructor() { LessonEntity( date = item.date.trim(), time = item.time.trim(), - name = item.discipline.trim(), + name = item.name.trim(), typeName = item.typeName.trim(), room = item.room.trim(), teacher = item.teacher.trim(), - groupId = item.groups.firstOrNull()?.groupCode.orEmpty(), - type = item.type.trim() + groupIds = item.groups.map { it.groupCode.trim() }, + type = LessonType.Companion.fromApi(item.type) ) } \ No newline at end of file diff --git a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/ScheduleRemoteDataSourceImpl.kt b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/ScheduleRemoteDataSourceImpl.kt index 1f435b9..aa13eb9 100644 --- a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/ScheduleRemoteDataSourceImpl.kt +++ b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/ScheduleRemoteDataSourceImpl.kt @@ -3,7 +3,8 @@ package ru.fincode.tsudesk.feature.schedule.data.remote import ru.fincode.tsudesk.core.network.model.NetworkResult import ru.fincode.tsudesk.core.network.apiCall import ru.fincode.tsudesk.feature.schedule.data.datasource.ScheduleRemoteDataSource -import ru.fincode.tsudesk.feature.schedule.data.remote.model.ScheduleDto +import ru.fincode.tsudesk.feature.schedule.data.remote.api.ScheduleApi +import ru.fincode.tsudesk.feature.schedule.data.remote.dto.ScheduleDto import javax.inject.Inject class ScheduleRemoteDataSourceImpl @Inject constructor( diff --git a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/api/ScheduleApi.kt b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/api/ScheduleApi.kt new file mode 100644 index 0000000..50327e0 --- /dev/null +++ b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/api/ScheduleApi.kt @@ -0,0 +1,16 @@ +package ru.fincode.tsudesk.feature.schedule.data.remote.api + +import retrofit2.Response +import retrofit2.http.GET +import retrofit2.http.Query +import ru.fincode.tsudesk.feature.schedule.data.remote.ScheduleApiContract +import ru.fincode.tsudesk.feature.schedule.data.remote.dto.ScheduleDto + +interface ScheduleApi { + + @GET(ScheduleApiContract.Path.GET_SCHEDULE_METHOD) + suspend fun getSchedule( + @Query(ScheduleApiContract.Query.FIELD_SEARCH) searchField: String, + @Query(ScheduleApiContract.Query.VALUE_SEARCH) searchValue: String + ): Response +} \ No newline at end of file diff --git a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/dto/GroupDto.kt b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/dto/GroupDto.kt new file mode 100644 index 0000000..b828445 --- /dev/null +++ b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/dto/GroupDto.kt @@ -0,0 +1,12 @@ +package ru.fincode.tsudesk.feature.schedule.data.remote.dto + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass +import ru.fincode.tsudesk.feature.schedule.data.remote.ScheduleApiContract.Query.FIELD_GROUP + +@JsonClass(generateAdapter = false) +data class GroupDto( + + @Json(name = FIELD_GROUP) + val groupCode: String +) diff --git a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/dto/LessonDto.kt b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/dto/LessonDto.kt new file mode 100644 index 0000000..56d03f4 --- /dev/null +++ b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/dto/LessonDto.kt @@ -0,0 +1,40 @@ +package ru.fincode.tsudesk.feature.schedule.data.remote.dto + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass +import ru.fincode.tsudesk.feature.schedule.data.remote.ScheduleApiContract.Query.FIELD_DATE +import ru.fincode.tsudesk.feature.schedule.data.remote.ScheduleApiContract.Query.FIELD_GROUPS +import ru.fincode.tsudesk.feature.schedule.data.remote.ScheduleApiContract.Query.FIELD_NAME +import ru.fincode.tsudesk.feature.schedule.data.remote.ScheduleApiContract.Query.FIELD_ROOM +import ru.fincode.tsudesk.feature.schedule.data.remote.ScheduleApiContract.Query.FIELD_TEACHER +import ru.fincode.tsudesk.feature.schedule.data.remote.ScheduleApiContract.Query.FIELD_TIME +import ru.fincode.tsudesk.feature.schedule.data.remote.ScheduleApiContract.Query.FIELD_TYPE +import ru.fincode.tsudesk.feature.schedule.data.remote.ScheduleApiContract.Query.FIELD_TYPE_NAME + +@JsonClass(generateAdapter = false) +data class LessonDto( + + @Json(name = FIELD_DATE) + val date: String, + + @Json(name = FIELD_TIME) + val time: String, + + @Json(name = FIELD_NAME) + val name: String, + + @Json(name = FIELD_TYPE_NAME) + val typeName: String, + + @Json(name = FIELD_ROOM) + val room: String, + + @Json(name = FIELD_TEACHER) + val teacher: String, + + @Json(name = FIELD_GROUPS) + val groups: List, + + @Json(name = FIELD_TYPE) + val type: String +) diff --git a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/dto/ScheduleDto.kt b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/dto/ScheduleDto.kt new file mode 100644 index 0000000..488b591 --- /dev/null +++ b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/data/remote/dto/ScheduleDto.kt @@ -0,0 +1,3 @@ +package ru.fincode.tsudesk.feature.schedule.data.remote.dto + +typealias ScheduleDto = List \ No newline at end of file diff --git a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/di/ScheduleNetworkModule.kt b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/di/ScheduleNetworkModule.kt index 4f6b081..695e593 100644 --- a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/di/ScheduleNetworkModule.kt +++ b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/di/ScheduleNetworkModule.kt @@ -5,7 +5,7 @@ import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import retrofit2.Retrofit -import ru.fincode.tsudesk.feature.schedule.data.remote.ScheduleApi +import ru.fincode.tsudesk.feature.schedule.data.remote.api.ScheduleApi import javax.inject.Singleton @Module diff --git a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/domain/model/LessonEntity.kt b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/domain/model/LessonEntity.kt index dbf1294..ce77a56 100644 --- a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/domain/model/LessonEntity.kt +++ b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/domain/model/LessonEntity.kt @@ -1,5 +1,10 @@ package ru.fincode.tsudesk.feature.schedule.domain.model +import ru.fincode.tsudesk.feature.schedule.data.remote.ScheduleApiContract.Query.LessonType.VALUE_DEFAULT +import ru.fincode.tsudesk.feature.schedule.data.remote.ScheduleApiContract.Query.LessonType.VALUE_LAB +import ru.fincode.tsudesk.feature.schedule.data.remote.ScheduleApiContract.Query.LessonType.VALUE_LECTURE +import ru.fincode.tsudesk.feature.schedule.data.remote.ScheduleApiContract.Query.LessonType.VALUE_PRACTICE + data class LessonEntity( val date: String, // "12.01.2026" val time: String, // "11:00 - 13:55" @@ -7,6 +12,24 @@ data class LessonEntity( val typeName: String, // "Лекции", "Лабораторные занятия" и т.д. val room: String, val teacher: String, - val groupId: String, - val type: String // "lecture" / "lab" / "practice" / "default" -) \ No newline at end of file + val groupIds: List, + val type: LessonType +) + +enum class LessonType { + DEFAULT, + LECTURE, + LAB, + PRACTICE; + + companion object { + fun fromApi(value: String?): LessonType = + when (value?.lowercase()) { + VALUE_LECTURE -> LECTURE + VALUE_LAB -> LAB + VALUE_PRACTICE -> PRACTICE + VALUE_DEFAULT -> DEFAULT + else -> DEFAULT + } + } +} \ No newline at end of file