refactoring network layer

This commit is contained in:
2026-02-17 09:23:25 +03:00
parent d64f2b5b8f
commit 7b40f336cd
24 changed files with 204 additions and 119 deletions

View File

@@ -2,10 +2,12 @@ package ru.fincode.tsudesk.core.database
import androidx.room.Database import androidx.room.Database
import androidx.room.RoomDatabase import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import ru.fincode.tsudesk.core.database.schedule.LessonCacheEntity import ru.fincode.tsudesk.core.database.schedule.LessonCacheEntity
import ru.fincode.tsudesk.core.database.schedule.ScheduleCacheEntity import ru.fincode.tsudesk.core.database.schedule.ScheduleCacheEntity
import ru.fincode.tsudesk.core.database.schedule.ScheduleDao import ru.fincode.tsudesk.core.database.schedule.ScheduleDao
@TypeConverters(StringListConverter::class)
@Database( @Database(
entities = [ entities = [
// schedule feature // schedule feature

View File

@@ -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>?): String =
list
?.joinToString(separator = separator)
.orEmpty()
@TypeConverter
fun toList(value: String?): List<String> =
value
?.takeIf { it.isNotBlank() }
?.split(separator)
.orEmpty()
}

View File

@@ -1,6 +1,6 @@
package ru.fincode.tsudesk.core.database.schedule package ru.fincode.tsudesk.core.database.schedule
object ScheduleDbConstants { object Constants {
const val SCHEDULE_TABLE = "schedule_cache" const val SCHEDULE_TABLE = "schedule_cache"
const val LESSON_TABLE = "lesson_cache" const val LESSON_TABLE = "lesson_cache"

View File

@@ -3,8 +3,8 @@ package ru.fincode.tsudesk.core.database.schedule
import androidx.room.Entity import androidx.room.Entity
import androidx.room.Index import androidx.room.Index
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import ru.fincode.tsudesk.core.database.schedule.ScheduleDbConstants.COL_SCHEDULE_KEY import ru.fincode.tsudesk.core.database.schedule.Constants.COL_SCHEDULE_KEY
import ru.fincode.tsudesk.core.database.schedule.ScheduleDbConstants.LESSON_TABLE import ru.fincode.tsudesk.core.database.schedule.Constants.LESSON_TABLE
@Entity( @Entity(
tableName = LESSON_TABLE, indices = [Index(value = [COL_SCHEDULE_KEY])] tableName = LESSON_TABLE, indices = [Index(value = [COL_SCHEDULE_KEY])]
@@ -19,6 +19,6 @@ data class LessonCacheEntity(
val typeName: String, val typeName: String,
val room: String, val room: String,
val teacher: String, val teacher: String,
val groupId: String, val groupIds: List<String>,
val type: String val type: String
) )

View File

@@ -1,13 +1,21 @@
package ru.fincode.tsudesk.core.database.schedule 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 { object Query {
const val SELECT_LESSON_BY_KEY_QUERY = const val SELECT_LESSONS_BY_KEY_QUERY =
"SELECT * FROM lesson_cache WHERE scheduleKey = :key" "SELECT * FROM $LESSON_TABLE WHERE $COL_SCHEDULE_KEY = :key"
const val SELECT_SCHEDULE_BY_KEY_QUERY = 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 = const val DELETE_LESSONS_BY_KEY =
"DELETE FROM lesson_cache WHERE scheduleKey = :key" "DELETE FROM $LESSON_TABLE WHERE $COL_SCHEDULE_KEY = :key"
const val DELETE_SCHEDULE_BY_KEY =
"DELETE FROM $SCHEDULE_TABLE WHERE $COL_KEY = :key"
} }

View File

@@ -2,7 +2,7 @@ package ru.fincode.tsudesk.core.database.schedule
import androidx.room.Entity import androidx.room.Entity
import androidx.room.PrimaryKey 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) @Entity(tableName = SCHEDULE_TABLE)
data class ScheduleCacheEntity( data class ScheduleCacheEntity(

View File

@@ -6,22 +6,25 @@ import androidx.room.OnConflictStrategy
import androidx.room.Query import androidx.room.Query
import androidx.room.Transaction import androidx.room.Transaction
import kotlinx.coroutines.flow.Flow 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 import ru.fincode.tsudesk.core.database.schedule.Query.SELECT_SCHEDULE_BY_KEY_QUERY
@Dao @Dao
interface ScheduleDao { interface ScheduleDao {
@Query(SELECT_SCHEDULE_BY_KEY_QUERY) @Query(SELECT_SCHEDULE_BY_KEY_QUERY)
fun observeSchedule(key: String): Flow<ScheduleCacheEntity?> fun observeSchedule(key: String): Flow<ScheduleCacheEntity?>
@Query(SELECT_LESSON_BY_KEY_QUERY) @Query(SELECT_LESSONS_BY_KEY_QUERY)
fun observeLessons(key: String): Flow<List<LessonCacheEntity>> fun observeLessons(key: String): Flow<List<LessonCacheEntity>>
@Query("SELECT * FROM schedule_cache WHERE `key` = :key LIMIT 1") @Query(SELECT_SCHEDULE_BY_KEY_QUERY)
suspend fun getSchedule(key: String): ScheduleCacheEntity? 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<LessonCacheEntity> suspend fun getLessons(key: String): List<LessonCacheEntity>
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
@@ -30,10 +33,10 @@ interface ScheduleDao {
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertLessons(lessons: List<LessonCacheEntity>) suspend fun insertLessons(lessons: List<LessonCacheEntity>)
@Query("DELETE FROM lesson_cache WHERE scheduleKey = :key") @Query(DELETE_LESSONS_BY_KEY)
suspend fun deleteLessonsByKey(key: String) suspend fun deleteLessonsByKey(key: String)
@Query("DELETE FROM schedule_cache WHERE `key` = :key") @Query(DELETE_SCHEDULE_BY_KEY)
suspend fun deleteScheduleByKey(key: String) suspend fun deleteScheduleByKey(key: String)
@Transaction @Transaction
@@ -48,7 +51,7 @@ interface ScheduleDao {
} }
@Transaction @Transaction
suspend fun clearSchedule(key: String) { suspend fun removeSchedule(key: String) {
deleteLessonsByKey(key) deleteLessonsByKey(key)
deleteScheduleByKey(key) deleteScheduleByKey(key)
} }

View File

@@ -9,8 +9,8 @@ import ru.fincode.tsudesk.core.network.model.NetworkResult
import ru.fincode.tsudesk.core.network.model.map 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.ScheduleLocalDataSource
import ru.fincode.tsudesk.feature.schedule.data.datasource.ScheduleRemoteDataSource 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.local.ScheduleCacheKey
import ru.fincode.tsudesk.feature.schedule.data.mapper.ScheduleNetworkMapper 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.ScheduleEntity
import ru.fincode.tsudesk.feature.schedule.domain.model.ScheduleType import ru.fincode.tsudesk.feature.schedule.domain.model.ScheduleType
import ru.fincode.tsudesk.feature.schedule.domain.repository.ScheduleRepository import ru.fincode.tsudesk.feature.schedule.domain.repository.ScheduleRepository
@@ -33,6 +33,7 @@ class ScheduleRepositoryImpl @Inject constructor(
emit(DataResult.Data(cached, refreshedFromNetwork = false)) emit(DataResult.Data(cached, refreshedFromNetwork = false))
} }
// if (cached?.timestamp != updated.timestamp) { ... }
val networkResult: NetworkResult<ScheduleEntity> = when (type) { val networkResult: NetworkResult<ScheduleEntity> = when (type) {
is ScheduleType.Group -> is ScheduleType.Group ->
remote.loadScheduleByGroup(type.number).map(mapper::invoke) remote.loadScheduleByGroup(type.number).map(mapper::invoke)
@@ -43,7 +44,6 @@ class ScheduleRepositoryImpl @Inject constructor(
when (networkResult) { when (networkResult) {
is NetworkResult.Success -> { is NetworkResult.Success -> {
// Важно: timestamp должен обновляться при записи из сети (либо приходить новым)
local.saveSchedule(key, networkResult.data) 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() val updated: ScheduleEntity = local.observeSchedule(key).filterNotNull().first()
// Если не хочешь дублировать, когда данные те же — включи проверку:
// if (cached?.timestamp != updated.timestamp) { ... }
emit(DataResult.Data(updated, refreshedFromNetwork = true)) emit(DataResult.Data(updated, refreshedFromNetwork = true))
} }

View File

@@ -1,7 +1,7 @@
package ru.fincode.tsudesk.feature.schedule.data.datasource package ru.fincode.tsudesk.feature.schedule.data.datasource
import ru.fincode.tsudesk.core.network.model.NetworkResult 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 { interface ScheduleRemoteDataSource {
suspend fun loadScheduleByGroup(number: String): NetworkResult<ScheduleDto> suspend fun loadScheduleByGroup(number: String): NetworkResult<ScheduleDto>

View File

@@ -6,8 +6,6 @@ import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.onStart
import ru.fincode.tsudesk.core.database.schedule.ScheduleDao import ru.fincode.tsudesk.core.database.schedule.ScheduleDao
import ru.fincode.tsudesk.feature.schedule.data.datasource.ScheduleLocalDataSource 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 ru.fincode.tsudesk.feature.schedule.domain.model.ScheduleEntity
import javax.inject.Inject import javax.inject.Inject

View File

@@ -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.LessonCacheEntity
import ru.fincode.tsudesk.core.database.schedule.ScheduleCacheEntity 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.LessonEntity
import ru.fincode.tsudesk.feature.schedule.domain.model.LessonType
import ru.fincode.tsudesk.feature.schedule.domain.model.ScheduleEntity import ru.fincode.tsudesk.feature.schedule.domain.model.ScheduleEntity
object ScheduleCacheKey { object ScheduleCacheKey {
fun group(number: String) = "$GROUP_PRE_KEY$number" fun group(number: String) = "$GROUP_PRE_KEY$number"
fun teacher(name: String) = "$TEACHER_PRE_KEY$name" fun teacher(name: String) = "$TEACHER_PRE_KEY$name"
@@ -34,8 +33,8 @@ fun ScheduleEntity.toCache(
typeName = lesson.typeName, typeName = lesson.typeName,
room = lesson.room, room = lesson.room,
teacher = lesson.teacher, teacher = lesson.teacher,
groupId = lesson.groupId, groupIds = lesson.groupIds,
type = lesson.type type = lesson.type.toString()
) )
} }
@@ -58,6 +57,6 @@ private fun LessonCacheEntity.toDomain(): LessonEntity =
typeName = typeName, typeName = typeName,
room = room, room = room,
teacher = teacher, teacher = teacher,
groupId = groupId, groupIds = groupIds,
type = type type = LessonType.fromApi(type)
) )

View File

@@ -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"
}
}
}

View File

@@ -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<ScheduleDto>
}

View File

@@ -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"
}
}

View File

@@ -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<LessonDto>
@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<GroupDto>,
@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"
}
}

View File

@@ -3,7 +3,7 @@ package ru.fincode.tsudesk.feature.schedule.data.remote
import com.squareup.moshi.Moshi import com.squareup.moshi.Moshi
import com.squareup.moshi.Types import com.squareup.moshi.Types
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory 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 { class ScheduleJsonParser {

View File

@@ -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.core.network.model.NetworkMeta
import ru.fincode.tsudesk.feature.schedule.data.remote.model.LessonDto import ru.fincode.tsudesk.feature.schedule.data.remote.dto.LessonDto
import ru.fincode.tsudesk.feature.schedule.data.remote.model.ScheduleDto 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.LessonEntity
import ru.fincode.tsudesk.feature.schedule.domain.model.LessonType
import ru.fincode.tsudesk.feature.schedule.domain.model.ScheduleEntity import ru.fincode.tsudesk.feature.schedule.domain.model.ScheduleEntity
import javax.inject.Inject import javax.inject.Inject
@@ -19,11 +20,11 @@ class ScheduleNetworkMapper @Inject constructor() {
LessonEntity( LessonEntity(
date = item.date.trim(), date = item.date.trim(),
time = item.time.trim(), time = item.time.trim(),
name = item.discipline.trim(), name = item.name.trim(),
typeName = item.typeName.trim(), typeName = item.typeName.trim(),
room = item.room.trim(), room = item.room.trim(),
teacher = item.teacher.trim(), teacher = item.teacher.trim(),
groupId = item.groups.firstOrNull()?.groupCode.orEmpty(), groupIds = item.groups.map { it.groupCode.trim() },
type = item.type.trim() type = LessonType.Companion.fromApi(item.type)
) )
} }

View File

@@ -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.model.NetworkResult
import ru.fincode.tsudesk.core.network.apiCall import ru.fincode.tsudesk.core.network.apiCall
import ru.fincode.tsudesk.feature.schedule.data.datasource.ScheduleRemoteDataSource 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 import javax.inject.Inject
class ScheduleRemoteDataSourceImpl @Inject constructor( class ScheduleRemoteDataSourceImpl @Inject constructor(

View File

@@ -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<ScheduleDto>
}

View File

@@ -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
)

View File

@@ -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<GroupDto>,
@Json(name = FIELD_TYPE)
val type: String
)

View File

@@ -0,0 +1,3 @@
package ru.fincode.tsudesk.feature.schedule.data.remote.dto
typealias ScheduleDto = List<LessonDto>

View File

@@ -5,7 +5,7 @@ import dagger.Provides
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent import dagger.hilt.components.SingletonComponent
import retrofit2.Retrofit 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 import javax.inject.Singleton
@Module @Module

View File

@@ -1,5 +1,10 @@
package ru.fincode.tsudesk.feature.schedule.domain.model 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( data class LessonEntity(
val date: String, // "12.01.2026" val date: String, // "12.01.2026"
val time: String, // "11:00 - 13:55" val time: String, // "11:00 - 13:55"
@@ -7,6 +12,24 @@ data class LessonEntity(
val typeName: String, // "Лекции", "Лабораторные занятия" и т.д. val typeName: String, // "Лекции", "Лабораторные занятия" и т.д.
val room: String, val room: String,
val teacher: String, val teacher: String,
val groupId: String, val groupIds: List<String>,
val type: String // "lecture" / "lab" / "practice" / "default" 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
}
}
}